Skip to content

Commit

Permalink
Merge pull request #2 from parsilver/refactor-code
Browse files Browse the repository at this point in the history
Add supported PHP 8.3
  • Loading branch information
parsilver authored May 29, 2024
2 parents b42c059 + 5d662f2 commit 3d4423c
Show file tree
Hide file tree
Showing 11 changed files with 204 additions and 90 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
fail-fast: true
matrix:
os: [ubuntu-latest, windows-latest]
php: [8.2, 8.1, 8.0]
php: [8.3, 8.2, 8.1, 8.0]
stability: [prefer-lowest, prefer-stable]

name: P${{ matrix.php }} - ${{ matrix.stability }} - ${{ matrix.os }}
Expand All @@ -22,7 +22,7 @@ jobs:
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: dom, curl, libxml, mbstring, zip, pcntl, bcmath, soap, intl, gd, exif, iconv, fileinfo
extensions: dom, curl, libxml, mbstring, zip, pcntl, bcmath, soap, intl
coverage: pcov

- name: Setup problem matchers
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"authors": [
{
"name": "PA",
"role": "DevOps"
"role": "Developer"
}
],
"config": {
Expand Down
13 changes: 13 additions & 0 deletions src/Contracts/MessageParser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Farzai\TruemoneyWebhook\Contracts;

interface MessageParser
{
/**
* Parse the request from Truemoney webhook.
*
* @return mixed
*/
public function parse(array $data);
}
13 changes: 13 additions & 0 deletions src/Contracts/ServerRequestFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Farzai\TruemoneyWebhook\Contracts;

use Psr\Http\Message\ServerRequestInterface;

interface ServerRequestFactory
{
/**
* Create a new server request.
*/
public function create(): ServerRequestInterface;
}
21 changes: 0 additions & 21 deletions src/Entity/AbstractEntity.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
namespace Farzai\TruemoneyWebhook\Entity;

use JsonSerializable;
use Psr\Http\Message\ServerRequestInterface;

abstract class AbstractEntity implements JsonSerializable
{
Expand All @@ -14,26 +13,6 @@ abstract class AbstractEntity implements JsonSerializable
*/
protected $data;

/**
* Map data to entity from array.
*
* @return static
*/
public static function fromArray(array $data)
{
return new static($data);
}

/**
* Map data to entity from request.
*
* @return static
*/
public static function fromRequest(ServerRequestInterface $request)
{
return static::fromArray(@json_decode((string) $request->getBody(), true) ?: []);
}

/**
* Entity data
*/
Expand Down
44 changes: 44 additions & 0 deletions src/MessageParser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace Farzai\TruemoneyWebhook;

use Farzai\TruemoneyWebhook\Contracts\MessageParser as MessageParserContract;
use Farzai\TruemoneyWebhook\Entity\Message;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use RuntimeException;

class MessageParser implements MessageParserContract
{
private array $config = [
// The key used to sign
'secret' => null,

// Algorithm used to sign the token
'alg' => 'HS256',
];

/**
* Parser constructor.
*/
public function __construct(array $config)
{
$this->config = array_merge($this->config, $config);
}

/**
* Parse the request from Truemoney webhook.
*
* @return mixed
*/
public function parse(array $data)
{
if (! $data || ! $data['message']) {
throw new RuntimeException('Invalid request body.');
}

$data = JWT::decode($data['message'], new Key($this->config['secret'], $this->config['alg']));

return new Message((array) $data);
}
}
113 changes: 54 additions & 59 deletions src/Postman.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@

namespace Farzai\TruemoneyWebhook;

use Farzai\TruemoneyWebhook\Contracts\MessageParser as MessageParserContract;
use Farzai\TruemoneyWebhook\Contracts\ServerRequestFactory as ServerRequestFactoryContract;
use Farzai\TruemoneyWebhook\Entity\Message;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use InvalidArgumentException;
use Nyholm\Psr7\Factory\Psr17Factory;
use Nyholm\Psr7Server\ServerRequestCreator;
use Psr\Http\Message\ServerRequestInterface;
use RuntimeException;

Expand All @@ -21,23 +19,23 @@ class Postman
'alg' => 'HS256',
];

private ServerRequestFactoryContract $serverRequestFactory;

private MessageParserContract $messageParser;

/**
* Postman constructor.
*
* @param array $config
* Notes: Config are required keys: 'secret',
* Optional keys: 'alg',
* Notes: Config are required keys: 'secret',
* Optional keys: 'alg',
*/
public function __construct(array $config)
{
// Validate config
// Check secret key is required
if (! isset($config['secret']) || empty($config['secret'])) {
throw new InvalidArgumentException('Invalid config. "secret" is required.');
}

// Set config
$this->config = array_merge($this->config, $config);
$this->messageParser = new MessageParser($this->config);

$this->setServerRequestFactory(new ServerRequestFactory);
}

/**
Expand All @@ -47,70 +45,67 @@ public function __construct(array $config)
*
* @return Message
*/
public function capture(ServerRequestInterface $request = null)
public function capture(?ServerRequestInterface $request = null)
{
$this->validateConfig($this->getConfig());

if (! $request) {
$factory = new Psr17Factory();
$request = $this->serverRequestFactory->create();
}

$creator = new ServerRequestCreator(
$factory,
$factory,
$factory,
$factory
);
$this->validateRequest($request);

$request = $creator->fromGlobals();
}
$jsonData = @json_decode($request->getBody()->getContents(), true) ?: [];

if ($request->getMethod() !== 'POST') {
throw new RuntimeException('Invalid request method.');
}
return $this->messageParser->parse($jsonData);
}

public function setServerRequestFactory(ServerRequestFactoryContract $serverRequestFactory)
{
$this->serverRequestFactory = $serverRequestFactory;

return $this->parseMessageFromRequest($request);
return $this;
}

/**
* Decode jwt and return message entity.
*
*
* @return Message
*
* @throws RuntimeException
*/
public function parseMessageFromRequest(ServerRequestInterface $request)
public function getServerRequestFactory(): ServerRequestFactoryContract
{
if (count($request->getHeader('Content-Type')) === 0 || $request->getHeader('Content-Type')[0] !== 'application/json') {
throw new RuntimeException('Invalid content type.');
}
return $this->serverRequestFactory;
}

if (! $request->getBody()->getContents()) {
throw new RuntimeException('Invalid request body.');
}
public function setConfig(array $config)
{
$this->config = array_merge($this->config, $config);

$jsonData = @json_decode($request->getBody()->getContents(), true) ?: [];
return $this;
}

return $this->parseMessageFromJsonArray($jsonData);
public function getConfig(): array
{
return $this->config;
}

/**
* Parse all input data to message entity.
*
*
* @return Message
*
* @throws RuntimeException
*/
public function parseMessageFromJsonArray(array $jsonData)
private function validateConfig(array $config)
{
if (! $jsonData || ! $jsonData['message']) {
throw new RuntimeException('Invalid request body.');
// Check secret key is required
if (! isset($config['secret']) || empty($config['secret'])) {
throw new InvalidArgumentException('Invalid config. "secret" is required.');
}
}

$data = JWT::decode($jsonData['message'], new Key($this->config['secret'], $this->config['alg']));
private function validateRequest(ServerRequestInterface $request)
{
if ($request->getMethod() !== 'POST') {
throw new RuntimeException('Invalid request method.');
}

$contentType = $request->getHeader('Content-Type')[0] ?? '';

// Convert to array
$data = (array) $data;
if ($contentType !== 'application/json') {
throw new RuntimeException('Invalid content type.');
}

return Message::fromArray($data);
if (empty($request->getBody()->getContents())) {
throw new RuntimeException('Invalid request body.');
}
}
}
28 changes: 28 additions & 0 deletions src/ServerRequestFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Farzai\TruemoneyWebhook;

use Farzai\TruemoneyWebhook\Contracts\ServerRequestFactory as ServerRequestFactoryContract;
use Nyholm\Psr7\Factory\Psr17Factory;
use Nyholm\Psr7Server\ServerRequestCreator;
use Psr\Http\Message\ServerRequestInterface;

class ServerRequestFactory implements ServerRequestFactoryContract
{
/**
* Create a new server request.
*/
public function create(): ServerRequestInterface
{
$factory = new Psr17Factory();

$creator = new ServerRequestCreator(
$factory,
$factory,
$factory,
$factory
);

return $creator->fromGlobals();
}
}
Loading

0 comments on commit 3d4423c

Please sign in to comment.