diff --git a/app/Lib/Axepta/AxeptaConfig.php b/app/Lib/Axepta/AxeptaConfig.php new file mode 100644 index 00000000..c29f324a --- /dev/null +++ b/app/Lib/Axepta/AxeptaConfig.php @@ -0,0 +1,35 @@ + $axeptaConfig */ + #[\SensitiveParameter] + public array $checkoutConfig = [] + ) { + if (empty(trim($endpoint))) { + throw new \DomainException('Endpoint cannot be empty'); + } + if (empty(trim($merchantId))) { + throw new \DomainException('Merchant ID cannot be empty'); + } + if (empty(trim($apiKey))) { + throw new \DomainException('API Key cannot be empty'); + } + if (empty(trim($hmac))) { + throw new \DomainException('HMAC cannot be empty'); + } + } +} diff --git a/app/Lib/Axepta/AxeptaPayment.php b/app/Lib/Axepta/AxeptaPayment.php index 8b7b8f87..d46e58c3 100644 --- a/app/Lib/Axepta/AxeptaPayment.php +++ b/app/Lib/Axepta/AxeptaPayment.php @@ -21,15 +21,13 @@ class AxeptaPayment /** * Guzzle Client instance - * - * @var GuzzleHttp\Client */ private \GuzzleHttp\Client $client; /** * Additionnal or Update Axepta configuration * - * @var array + * @var array */ private array $axeptaCheckoutConfig; @@ -40,35 +38,12 @@ class AxeptaPayment */ private string $cacheKey = "AxeptaBearerToken"; - /** - * Construct method - * - * @param string $endpoint Axepta Endpoint - * @param string $merchantId Axepta Merchant ID - * @param string $apiKey Axepta Secret API Key - * @param string $hmac Axepta HMAC - * @param array $axeptaConfig Additionnal or Update Axepta configuration - * @return void - */ public function __construct( private readonly LoggerInterface $logger, - #[\SensitiveParameter] - private string $endpoint, - #[\SensitiveParameter] - private string $merchantId, - #[\SensitiveParameter] - private string $apiKey, - #[\SensitiveParameter] - private string $hmac, - #[\SensitiveParameter] - private array $axeptaConfig = [] + private readonly AxeptaConfig $axeptaConfig ) { - $this->endpoint = $endpoint; - $this->merchantId = $merchantId; - $this->apiKey = $apiKey; - $this->hmac = $hmac; - $this->client = new Client([ - 'base_uri' => $this->endpoint, + $this->client = new Client([ + 'base_uri' => $this->axeptaConfig->endpoint, 'timeout' => 5.0, ]); $this->axeptaCheckoutConfig = [ @@ -89,7 +64,7 @@ class AxeptaPayment ], ] ], - ...$axeptaConfig + ...$axeptaConfig->checkoutConfig ]; } @@ -110,8 +85,8 @@ class AxeptaPayment $response = $this->client->post('/authorization/oauth/token', [ 'form_params' => [ 'grant_type' => 'client_credentials', - 'client_id' => $this->merchantId, - 'client_secret' => $this->apiKey + 'client_id' => $this->axeptaConfig->merchantId, + 'client_secret' => $this->axeptaConfig->apiKey ] ]); @@ -145,8 +120,12 @@ class AxeptaPayment * @return string * @throws \RuntimeException */ - public function getCheckoutUrl(AxeptaOrder $order, string $returnUrl, string $cancelUrl, string $webhookUrl): string - { + public function getCheckoutUrl( + #[\SensitiveParameter] AxeptaOrder $order, + #[\SensitiveParameter] string $returnUrl, + #[\SensitiveParameter] $cancelUrl, + #[\SensitiveParameter] string $webhookUrl + ): string { $payload = [ "transId" => $this->generateTransId(), "urls" => [ @@ -268,7 +247,8 @@ class AxeptaPayment $rawPayload = $request->getContent(false); $this->logger->debug( - 'Received an IPN call', [ + 'Received an IPN call', + [ 'request_signature_version' => $signatureVersion, 'request_signature' => $signature, 'request_timestamp' => $timestamp, @@ -347,8 +327,11 @@ class AxeptaPayment * @param string $rawPayload * @return boolean */ - private function isValidSignature(string $signature, CarbonInterface $timestamp, string $rawPayload): bool - { + private function isValidSignature( + #[\SensitiveParameter] string $signature, + CarbonInterface $timestamp, + #[\SensitiveParameter] string $rawPayload + ): bool { $providedSignature = $this->extractSignatureFromCurrentVersion($signature); if (!$providedSignature) { @@ -360,7 +343,7 @@ class AxeptaPayment } $signedPayload = "{$timestamp}.{$rawPayload}"; - $expectedSignature = hash_hmac('sha256', $signedPayload, $this->hmac); + $expectedSignature = hash_hmac('sha256', $signedPayload, $this->axeptaConfig->hmac); $signatureIsValid = hash_equals($expectedSignature, $providedSignature); if (!$signatureIsValid) { @@ -386,7 +369,7 @@ class AxeptaPayment * @param string $signature * @return string|null */ - private function extractSignatureFromCurrentVersion(string $signature): ?string + private function extractSignatureFromCurrentVersion(#[\SensitiveParameter] string $signature): ?string { $signatures = explode(',', $signature); $filteredSignatures = array_filter($signatures, function (string $key) { diff --git a/tests/Unit/Lib/Axepta/AxeptaConfigTest.php b/tests/Unit/Lib/Axepta/AxeptaConfigTest.php new file mode 100644 index 00000000..acc87f5c --- /dev/null +++ b/tests/Unit/Lib/Axepta/AxeptaConfigTest.php @@ -0,0 +1,116 @@ +assertInstanceOf(AxeptaConfig::class, $config); + } + + public function testCannotInstanciateWithEmptyEndpoint(): void + { + $this->assertThrows(function () { + // GIVEN + $endpoint = ''; + $merchantId = 'M_123'; + $apiKey = 'key'; + $hmac = 'hmac'; + + // WHEN + new AxeptaConfig( + $endpoint, + $merchantId, + $apiKey, + $hmac + ); + + // THEN + }, DomainException::class); + } + + public function testCannotInstanciateWithEmptyMerchantId(): void + { + $this->assertThrows(function () { + // GIVEN + $endpoint = 'https://api.axepta.com'; + $merchantId = ''; + $apiKey = 'key'; + $hmac = 'hmac'; + + // WHEN + new AxeptaConfig( + $endpoint, + $merchantId, + $apiKey, + $hmac + ); + + // THEN + }, DomainException::class); + } + + public function testCannotInstanciateWithEmptyApiKey(): void + { + $this->assertThrows(function () { + // GIVEN + $endpoint = 'https://api.axepta.com'; + $merchantId = 'M_123'; + $apiKey = ''; + $hmac = 'hmac'; + + // WHEN + new AxeptaConfig( + $endpoint, + $merchantId, + $apiKey, + $hmac + ); + + // THEN + }, DomainException::class); + } + + public function testCannotInstanciateWithEmptyHmac(): void + { + $this->assertThrows(function () { + // GIVEN + $endpoint = 'https://api.axepta.com'; + $merchantId = 'M_123'; + $apiKey = 'key'; + $hmac = ''; + + // WHEN + new AxeptaConfig( + $endpoint, + $merchantId, + $apiKey, + $hmac + ); + + // THEN + }, DomainException::class); + } +}