From 142c25c12806959cc4b5cae5c15238e6c384f613 Mon Sep 17 00:00:00 2001 From: "David.Owusu" Date: Wed, 7 Apr 2021 21:17:22 +0200 Subject: [PATCH 1/9] [change] (UMCS-181) Add ApplepayAdapter and ApplepaySession class. --- src/Adapter/ApplepayAdapter.php | 121 ++++++++++++++++++++ src/Adapter/ApplepaySession.php | 128 ++++++++++++++++++++++ test/unit/Adapter/ApplepaySessionTest.php | 43 ++++++++ 3 files changed, 292 insertions(+) create mode 100644 src/Adapter/ApplepayAdapter.php create mode 100644 src/Adapter/ApplepaySession.php create mode 100644 test/unit/Adapter/ApplepaySessionTest.php diff --git a/src/Adapter/ApplepayAdapter.php b/src/Adapter/ApplepayAdapter.php new file mode 100644 index 00000000..ce2194c4 --- /dev/null +++ b/src/Adapter/ApplepayAdapter.php @@ -0,0 +1,121 @@ + + * + * @package UnzerSDK\Adapter + */ +namespace UnzerSDK\Adapter; + +use UnzerSDK\Services\EnvironmentService; +use UnzerSDK\Exceptions\UnzerApiException; +use function in_array; + +class ApplepayAdapter +{ + private $request; + + /** + * @param string $merchantValidationURL + * @param ApplepaySession $applePaySession + * @param string $merchantValidationCertificatePath + * @param string $merchantValidationCertificateKeyChainPath + * + * @return string|null + * + * @throws UnzerApiException + */ + public function validateApplePayMerchant( + string $merchantValidationURL, + ApplepaySession $applePaySession, + string $merchantValidationCertificatePath + ): ?string { + $payload = $applePaySession->jsonSerialize(); + $this->init($merchantValidationURL, $payload, $merchantValidationCertificatePath); + try { + return $this->execute(); + } catch (\Exception $exception) { + return $exception; + } + } + + /** + * {@inheritDoc} + */ + public function init($url, $payload, $sslCert): void + { + $timeout = EnvironmentService::getTimeout(); + $curlVerbose = EnvironmentService::isCurlVerbose(); + + $this->request = curl_init(); + $this->setOption(CURLOPT_URL, $url); + $this->setOption(CURLOPT_HTTPHEADER, ['Content-Type: application/json']); + $this->setOption(CURLOPT_POST, 1); + $this->setOption(CURLOPT_DNS_USE_GLOBAL_CACHE, false); + $this->setOption(CURLOPT_POSTFIELDS, $payload); + $this->setOption(CURLOPT_SSLCERT, $sslCert); + + + $this->setOption(CURLOPT_FAILONERROR, false); + $this->setOption(CURLOPT_TIMEOUT, $timeout); + $this->setOption(CURLOPT_CONNECTTIMEOUT, $timeout); + $this->setOption(CURLOPT_HTTP200ALIASES, (array)400); + $this->setOption(CURLOPT_RETURNTRANSFER, 1); + $this->setOption(CURLOPT_SSL_VERIFYPEER, 1); + $this->setOption(CURLOPT_SSL_VERIFYHOST, 2); + $this->setOption(CURLOPT_VERBOSE, $curlVerbose); + $this->setOption(CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); + } + + /** + * {@inheritDoc} + */ + public function execute(): ?string + { + $response = curl_exec($this->request); + $error = curl_error($this->request); + $errorNo = curl_errno($this->request); + + switch ($errorNo) { + case 0: + return $response; + break; + case CURLE_OPERATION_TIMEDOUT: + $errorMessage = 'Timeout: The Payment API seems to be not available at the moment!'; + break; + default: + $errorMessage = $error . ' (curl_errno: '. $errorNo . ').'; + break; + } + throw new UnzerApiException($errorMessage); + } + + /** + * Sets curl option. + * + * @param $name + * @param $value + */ + private function setOption($name, $value): void + { + curl_setopt($this->request, $name, $value); + } +} diff --git a/src/Adapter/ApplepaySession.php b/src/Adapter/ApplepaySession.php new file mode 100644 index 00000000..e4d47e1d --- /dev/null +++ b/src/Adapter/ApplepaySession.php @@ -0,0 +1,128 @@ + + * + * @package UnzerSDK + * + */ + +namespace UnzerSDK\Adapter; + +class ApplepaySession +{ + /** + * This can be found in the Apple Developer Account + * + * @var string|null $merchantIdentifier + */ + private $merchantIdentifier; + + /** + * This is the Merchant-Name + * + * @var string|null $displayName + */ + private $displayName; + + /** + * This is the Domain Name which has been validated in the Apple Developer Account. + * + * @var string|null $domainName + */ + private $domainName; + + /** + * ApplepaySession constructor. + * + * @param string|null $merchantIdentifier + * @param string|null $displayName + * @param string|null $domainName + */ + public function __construct(string $merchantIdentifier, string $displayName, string $domainName) + { + $this->merchantIdentifier = $merchantIdentifier; + $this->displayName = $displayName; + $this->domainName = $domainName; + } + + public function jsonSerialize() + { + $properties = get_object_vars($this); + return json_encode($properties, JSON_UNESCAPED_SLASHES | JSON_PRESERVE_ZERO_FRACTION); + } + + /** + * @return string|null + */ + public function getMerchantIdentifier(): ?string + { + return $this->merchantIdentifier; + } + + /** + * @param string|null $merchantIdentifier + * + * @return ApplepaySession + */ + public function setMerchantIdentifier(?string $merchantIdentifier): ApplepaySession + { + $this->merchantIdentifier = $merchantIdentifier; + return $this; + } + + /** + * @return string|null + */ + public function getDisplayName(): ?string + { + return $this->displayName; + } + + /** + * @param string|null $displayName + * + * @return ApplepaySession + */ + public function setDisplayName(?string $displayName): ApplepaySession + { + $this->displayName = $displayName; + return $this; + } + + /** + * @return string|null + */ + public function getDomainName(): ?string + { + return $this->domainName; + } + + /** + * @param string|null $domainName + * + * @return ApplepaySession + */ + public function setDomainName(?string $domainName): ApplepaySession + { + $this->domainName = $domainName; + return $this; + } +} diff --git a/test/unit/Adapter/ApplepaySessionTest.php b/test/unit/Adapter/ApplepaySessionTest.php new file mode 100644 index 00000000..c4f8e281 --- /dev/null +++ b/test/unit/Adapter/ApplepaySessionTest.php @@ -0,0 +1,43 @@ + + * + * @package UnzerSDK + * + */ + +namespace UnzerSDK\test\Adapter; + +use UnzerSDK\Adapter\ApplepaySession; +use PHPUnit\Framework\TestCase; + +class ApplepaySessionTest extends TestCase +{ + public function testJsonSerialize() + { + $applepaySession = new ApplepaySession('merchantIdentifier', 'displayName', 'domainName'); + $expectedJson = '{"merchantIdentifier": "merchantIdentifier", "displayName": "displayName", "domainName": "domainName"}'; + + $jsonSerialize = $applepaySession->jsonSerialize(); + $this->assertJsonStringEqualsJsonString($expectedJson, $jsonSerialize); + echo $jsonSerialize; + } +} From 4a0f352c96a874a5327a981a4373f3cce29c659f Mon Sep 17 00:00:00 2001 From: "David.Owusu" Date: Tue, 13 Apr 2021 15:14:11 +0200 Subject: [PATCH 2/9] [change] (UMCS-181) Moved applepay session. --- .../ExternalResources}/ApplepaySession.php | 8 ++++---- test/unit/Adapter/ApplepaySessionTest.php | 7 +++---- 2 files changed, 7 insertions(+), 8 deletions(-) rename src/{Adapter => Resources/ExternalResources}/ApplepaySession.php (93%) diff --git a/src/Adapter/ApplepaySession.php b/src/Resources/ExternalResources/ApplepaySession.php similarity index 93% rename from src/Adapter/ApplepaySession.php rename to src/Resources/ExternalResources/ApplepaySession.php index e4d47e1d..d20caa57 100644 --- a/src/Adapter/ApplepaySession.php +++ b/src/Resources/ExternalResources/ApplepaySession.php @@ -1,8 +1,8 @@ + * @author David Owusu * * @package UnzerSDK * */ -namespace UnzerSDK\Adapter; +namespace UnzerSDK\Resources\ExternalResources; class ApplepaySession { diff --git a/test/unit/Adapter/ApplepaySessionTest.php b/test/unit/Adapter/ApplepaySessionTest.php index c4f8e281..39f06f39 100644 --- a/test/unit/Adapter/ApplepaySessionTest.php +++ b/test/unit/Adapter/ApplepaySessionTest.php @@ -2,7 +2,7 @@ /* * [DESCRIPTION] * - * Copyright (C) [ACTUAL YEAR] - today Unzer E-Com GmbH + * Copyright (C) 2021 - today Unzer E-Com GmbH * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,7 @@ * * @link https://docs.unzer.com/ * - * @author [AUTHOR] + * @author David Owusu * * @package UnzerSDK * @@ -26,8 +26,8 @@ namespace UnzerSDK\test\Adapter; -use UnzerSDK\Adapter\ApplepaySession; use PHPUnit\Framework\TestCase; +use UnzerSDK\Resources\ExternalResources\ApplepaySession; class ApplepaySessionTest extends TestCase { @@ -38,6 +38,5 @@ public function testJsonSerialize() $jsonSerialize = $applepaySession->jsonSerialize(); $this->assertJsonStringEqualsJsonString($expectedJson, $jsonSerialize); - echo $jsonSerialize; } } From dbc0e26b0d477ed247281ccefa17c9cb2d51e1be Mon Sep 17 00:00:00 2001 From: "David.Owusu" Date: Tue, 13 Apr 2021 15:27:37 +0200 Subject: [PATCH 3/9] [change] (UMCS-181) Add environment variables for applepay merchant validation certificate. --- src/Services/EnvironmentService.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/Services/EnvironmentService.php b/src/Services/EnvironmentService.php index fbfdbaa9..5244d8e2 100755 --- a/src/Services/EnvironmentService.php +++ b/src/Services/EnvironmentService.php @@ -41,6 +41,9 @@ class EnvironmentService public const ENV_VAR_TEST_PRIVATE_KEY_NON_3DS = 'UNZER_PAPI_TEST_PRIVATE_KEY_NON_3DS'; public const ENV_VAR_TEST_PUBLIC_KEY_NON_3DS = 'UNZER_PAPI_TEST_PUBLIC_KEY_NON_3DS'; + public const ENV_VAR_TEST_APPLE_MERCHANT_CERTIFICATE = 'UNZER_APPLE_MERCHANT_CERTIFICATE_PATH'; + public const ENV_VAR_TEST_APPLE_CA_CERTIFICATE = 'UNZER_APPLE_CA_CERTIFICATE_PATH'; + private const ENV_VAR_NAME_TIMEOUT = 'UNZER_PAPI_TIMEOUT'; private const DEFAULT_TIMEOUT = 60; @@ -137,4 +140,22 @@ public static function getTestPublicKey($non3ds = false): string $key = stripslashes($_SERVER[$variableName] ?? ''); return empty($key) ? '' : $key; } + + /** + * Returns the apple merchant certificate path set via environment variable. + * @return string + */ + public static function getAppleMerchantCertificatePath(): string + { + return $_SERVER[self::ENV_VAR_TEST_APPLE_MERCHANT_CERTIFICATE] ?? ''; + } + + /** + * Returns the CA certificate path set via environment variable. + * @return string + */ + public static function getAppleCaCertificatePath(): string + { + return $_SERVER[self::ENV_VAR_TEST_APPLE_CA_CERTIFICATE] ?? ''; + } } From 6ea4b6216507060acee927971fe41874742b50c1 Mon Sep 17 00:00:00 2001 From: "David.Owusu" Date: Tue, 13 Apr 2021 15:29:00 +0200 Subject: [PATCH 4/9] [change] (UMCS-181) Add Applepay adapter test. --- src/Adapter/ApplepayAdapter.php | 86 ++++++++++------ .../ApplepayMerchantValidationException.php | 33 +++++++ src/Services/EnvironmentService.php | 2 + test/integration/ApplepayAdapterTest.php | 98 +++++++++++++++++++ 4 files changed, 188 insertions(+), 31 deletions(-) create mode 100644 src/Exceptions/ApplepayMerchantValidationException.php create mode 100644 test/integration/ApplepayAdapterTest.php diff --git a/src/Adapter/ApplepayAdapter.php b/src/Adapter/ApplepayAdapter.php index ce2194c4..22fc76e8 100644 --- a/src/Adapter/ApplepayAdapter.php +++ b/src/Adapter/ApplepayAdapter.php @@ -1,5 +1,6 @@ jsonSerialize(); - $this->init($merchantValidationURL, $payload, $merchantValidationCertificatePath); - try { - return $this->execute(); - } catch (\Exception $exception) { - return $exception; - } + $this->init( + $merchantValidationURL, + $payload, + $merchantValidationCertificatePath, + $merchantValidationCertificateKeyChainPath + ); + $sessionResponse = $this->execute(); + $this->close(); + return $sessionResponse; } /** * {@inheritDoc} */ - public function init($url, $payload, $sslCert): void + public function init($url, $payload, $sslCert, $caCert = null): void { $timeout = EnvironmentService::getTimeout(); $curlVerbose = EnvironmentService::isCurlVerbose(); - $this->request = curl_init(); - $this->setOption(CURLOPT_URL, $url); + $this->request = curl_init($url); $this->setOption(CURLOPT_HTTPHEADER, ['Content-Type: application/json']); $this->setOption(CURLOPT_POST, 1); $this->setOption(CURLOPT_DNS_USE_GLOBAL_CACHE, false); $this->setOption(CURLOPT_POSTFIELDS, $payload); - $this->setOption(CURLOPT_SSLCERT, $sslCert); - - $this->setOption(CURLOPT_FAILONERROR, false); $this->setOption(CURLOPT_TIMEOUT, $timeout); $this->setOption(CURLOPT_CONNECTTIMEOUT, $timeout); @@ -83,39 +84,62 @@ public function init($url, $payload, $sslCert): void $this->setOption(CURLOPT_SSL_VERIFYHOST, 2); $this->setOption(CURLOPT_VERBOSE, $curlVerbose); $this->setOption(CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); + + $this->setOption(CURLOPT_SSLCERT, $sslCert); + if (isset($caCert)) { + $this->setOption(CURLOPT_CAINFO, $caCert); + } + } + + /** + * Sets curl option. + * + * @param $name + * @param $value + */ + private function setOption($name, $value): void + { + curl_setopt($this->request, $name, $value); } /** * {@inheritDoc} + * + * @throws ApplepayMerchantValidationException */ public function execute(): ?string { $response = curl_exec($this->request); - $error = curl_error($this->request); - $errorNo = curl_errno($this->request); + $error = curl_error($this->request); + $errorNo = curl_errno($this->request); switch ($errorNo) { case 0: return $response; break; case CURLE_OPERATION_TIMEDOUT: - $errorMessage = 'Timeout: The Payment API seems to be not available at the moment!'; + $errorMessage = 'Timeout: The Applepay API seems to be not available at the moment!'; break; default: - $errorMessage = $error . ' (curl_errno: '. $errorNo . ').'; + $errorMessage = $error . ' (curl_errno: ' . $errorNo . ').'; break; } - throw new UnzerApiException($errorMessage); + throw new ApplepayMerchantValidationException($errorMessage); } /** - * Sets curl option. - * - * @param $name - * @param $value + * @inheritDoc */ - private function setOption($name, $value): void + public function close(): void { - curl_setopt($this->request, $name, $value); + curl_close($this->request); + } + + /** + * @inheritDoc + */ + public function getResponseCode(): string + { + return curl_getinfo($this->request, CURLINFO_HTTP_CODE); } } diff --git a/src/Exceptions/ApplepayMerchantValidationException.php b/src/Exceptions/ApplepayMerchantValidationException.php new file mode 100644 index 00000000..ba61e821 --- /dev/null +++ b/src/Exceptions/ApplepayMerchantValidationException.php @@ -0,0 +1,33 @@ + + * + * @package UnzerSDK + * + */ + +namespace UnzerSDK\Exceptions; + +use Exception; + +class ApplepayMerchantValidationException extends Exception +{ +} diff --git a/src/Services/EnvironmentService.php b/src/Services/EnvironmentService.php index 5244d8e2..a6063039 100755 --- a/src/Services/EnvironmentService.php +++ b/src/Services/EnvironmentService.php @@ -143,6 +143,7 @@ public static function getTestPublicKey($non3ds = false): string /** * Returns the apple merchant certificate path set via environment variable. + * * @return string */ public static function getAppleMerchantCertificatePath(): string @@ -152,6 +153,7 @@ public static function getAppleMerchantCertificatePath(): string /** * Returns the CA certificate path set via environment variable. + * * @return string */ public static function getAppleCaCertificatePath(): string diff --git a/test/integration/ApplepayAdapterTest.php b/test/integration/ApplepayAdapterTest.php new file mode 100644 index 00000000..0aad0d6b --- /dev/null +++ b/test/integration/ApplepayAdapterTest.php @@ -0,0 +1,98 @@ + + * + * @package UnzerSDK + * + */ + +namespace UnzerSDK\test\integration; + +use UnzerSDK\Adapter\ApplepayAdapter; +use UnzerSDK\Resources\ExternalResources\ApplepaySession; +use UnzerSDK\Services\EnvironmentService; +use UnzerSDK\test\BaseIntegrationTest; + +class ApplepayAdapterTest extends BaseIntegrationTest +{ + private $merchantValidationUrl; + private $merchantValidationCertificatePath; + private $appleCaCertificatePath; + + /** + * @inheritDoc + */ + protected function setUp(): void + { + $this->merchantValidationUrl = 'https://apple-pay-gateway-cert.apple.com/paymentservices/startSession'; + $this->merchantValidationCertificatePath = EnvironmentService::getAppleMerchantCertificatePath(); + $this->appleCaCertificatePath = EnvironmentService::getAppleCaCertificatePath(); + } + + /** + * test merchant validation request. + * + * @test + */ + public function verifyMerchantValidationRequest(): void + { + $applepaySession = $this->createApplepaySession(); + $appleAdapter = new ApplepayAdapter(); + + $validationResponse = $appleAdapter->validateApplePayMerchant( + $this->merchantValidationUrl, + $applepaySession, + $this->merchantValidationCertificatePath, + $this->appleCaCertificatePath + ); + + $this->assertNotNull($validationResponse); + } + + /** + * test merchant validation request without ca certificate. + * + * @test + */ + public function merchantValidationWorksWithoutCaCert(): void + { + $merchantValidationCertificatePath = EnvironmentService::getAppleMerchantCertificatePath(); + + $applepaySession = $this->createApplepaySession(); + $appleAdapter = new ApplepayAdapter(); + + $validationResponse = $appleAdapter->validateApplePayMerchant( + $this->merchantValidationUrl, + $applepaySession, + $this->merchantValidationCertificatePath + ); + + $this->assertNotNull($validationResponse); + } + + /** + * @return ApplepaySession + */ + private function createApplepaySession(): ApplepaySession + { + return new ApplepaySession('merchantIdentifier', 'displayName', 'domainName'); + } +} From 4bedaa0fda8564d76173696d514267d1fa5ee1a0 Mon Sep 17 00:00:00 2001 From: "David.Owusu" Date: Thu, 15 Apr 2021 11:14:29 +0200 Subject: [PATCH 5/9] [change] (UMCS-181) Check domain merchantValidationUrl. --- src/Adapter/ApplepayAdapter.php | 18 +++++++ src/Constants/ApplepayValidationDomains.php | 52 +++++++++++++++++++ test/integration/ApplepayAdapterTest.php | 57 ++++++++++++++++++++- test/unit/Adapter/ApplepaySessionTest.php | 4 +- 4 files changed, 127 insertions(+), 4 deletions(-) create mode 100644 src/Constants/ApplepayValidationDomains.php diff --git a/src/Adapter/ApplepayAdapter.php b/src/Adapter/ApplepayAdapter.php index 22fc76e8..b7c9ad7d 100644 --- a/src/Adapter/ApplepayAdapter.php +++ b/src/Adapter/ApplepayAdapter.php @@ -26,6 +26,7 @@ */ namespace UnzerSDK\Adapter; +use UnzerSDK\Constants\ApplepayValidationDomains; use UnzerSDK\Exceptions\ApplepayMerchantValidationException; use UnzerSDK\Resources\ExternalResources\ApplepaySession; use UnzerSDK\Services\EnvironmentService; @@ -50,6 +51,9 @@ public function validateApplePayMerchant( string $merchantValidationCertificatePath, ?string $merchantValidationCertificateKeyChainPath = null ): ?string { + if (!$this->validMerchantValidationDomain($merchantValidationURL)) { + throw new ApplepayMerchantValidationException('Invalid URL used merchantValidation request.'); + } $payload = $applePaySession->jsonSerialize(); $this->init( $merchantValidationURL, @@ -62,6 +66,20 @@ public function validateApplePayMerchant( return $sessionResponse; } + /** + * Check whether domain of merchantValidationURL is allowed for validation request. + * + * @param string $merchantValidationURL URL used for merchant validation request. + * + */ + public function validMerchantValidationDomain(string $merchantValidationURL): bool + { + $domain = explode('/', $merchantValidationURL)[2] ?? ''; + + $UrlList = ApplepayValidationDomains::ALLOWED_VALIDATION_URLS; + return in_array($domain, $UrlList); + } + /** * {@inheritDoc} */ diff --git a/src/Constants/ApplepayValidationDomains.php b/src/Constants/ApplepayValidationDomains.php new file mode 100644 index 00000000..9f9824ab --- /dev/null +++ b/src/Constants/ApplepayValidationDomains.php @@ -0,0 +1,52 @@ + + * + * @package UnzerSDK\Constants + */ +namespace UnzerSDK\Constants; + +class ApplepayValidationDomains +{ + // URL list + public const ALLOWED_VALIDATION_URLS = [ + 'apple-pay-gateway.apple.com', + 'cn-apple-pay-gateway.apple.com', + 'apple-pay-gateway-nc-pod1.apple.com', + 'apple-pay-gateway-nc-pod2.apple.com', + 'apple-pay-gateway-nc-pod3.apple.com', + 'apple-pay-gateway-nc-pod4.apple.com', + 'apple-pay-gateway-nc-pod5.apple.com', + 'apple-pay-gateway-pr-pod1.apple.com', + 'apple-pay-gateway-pr-pod2.apple.com', + 'apple-pay-gateway-pr-pod3.apple.com', + 'apple-pay-gateway-pr-pod4.apple.com', + 'apple-pay-gateway-pr-pod5.apple.com', + 'cn-apple-pay-gateway-sh-pod1.apple.com', + 'cn-apple-pay-gateway-sh-pod2.apple.com', + 'cn-apple-pay-gateway-sh-pod3.apple.com', + 'cn-apple-pay-gateway-tj-pod1.apple.com', + 'cn-apple-pay-gateway-tj-pod2.apple.com', + 'cn-apple-pay-gateway-tj-pod3.apple.com', + 'apple-pay-gateway-cert.apple.com', + 'cn-apple-pay-gateway-cert.apple.com' + ]; +} diff --git a/test/integration/ApplepayAdapterTest.php b/test/integration/ApplepayAdapterTest.php index 0aad0d6b..57fc5462 100644 --- a/test/integration/ApplepayAdapterTest.php +++ b/test/integration/ApplepayAdapterTest.php @@ -27,6 +27,7 @@ namespace UnzerSDK\test\integration; use UnzerSDK\Adapter\ApplepayAdapter; +use UnzerSDK\Exceptions\ApplepayMerchantValidationException; use UnzerSDK\Resources\ExternalResources\ApplepaySession; use UnzerSDK\Services\EnvironmentService; use UnzerSDK\test\BaseIntegrationTest; @@ -37,6 +38,17 @@ class ApplepayAdapterTest extends BaseIntegrationTest private $merchantValidationCertificatePath; private $appleCaCertificatePath; + public function domainShouldBeValidatedCorrectlyDP() + { + return [ + 'invalid: example.domain.com' => ['https://example.domain.com', false], + 'valid: https://apple-pay-gateway.apple.com/some/path' => ['https://apple-pay-gateway.apple.com/some/path', true], + 'valid: https://cn-apple-pay-gateway.apple.com' => ['https://cn-apple-pay-gateway.apple.com', true], + 'invalid: apple-pay-gateway-nc-pod1.apple.com' => ['apple-pay-gateway-nc-pod1.apple.com', false], + 'invalid: (empty)' => ['', false], + ]; + } + /** * @inheritDoc */ @@ -51,6 +63,8 @@ protected function setUp(): void * test merchant validation request. * * @test + * + * @throws \UnzerSDK\Exceptions\ApplepayMerchantValidationException */ public function verifyMerchantValidationRequest(): void { @@ -71,11 +85,11 @@ public function verifyMerchantValidationRequest(): void * test merchant validation request without ca certificate. * * @test + * + * @throws \UnzerSDK\Exceptions\ApplepayMerchantValidationException */ public function merchantValidationWorksWithoutCaCert(): void { - $merchantValidationCertificatePath = EnvironmentService::getAppleMerchantCertificatePath(); - $applepaySession = $this->createApplepaySession(); $appleAdapter = new ApplepayAdapter(); @@ -88,6 +102,45 @@ public function merchantValidationWorksWithoutCaCert(): void $this->assertNotNull($validationResponse); } + /** + * Merchant validation call should throw Exception if domain of Validation url is invalid. + * + * @test + * + */ + public function merchantValidationThrowsErrorForInvalidDomain(): void + { + $applepaySession = $this->createApplepaySession(); + $appleAdapter = new ApplepayAdapter(); + + $this->expectException(ApplepayMerchantValidationException::class); + $this->expectExceptionMessage('Invalid URL used merchantValidation request.'); + + $appleAdapter->validateApplePayMerchant( + 'https://invalid.domain.com/some/path', + $applepaySession, + $this->merchantValidationCertificatePath + ); + } + + /** + * test merchant validation request without ca certificate. + * + * @dataProvider domainShouldBeValidatedCorrectlyDP + * @test + * + * @param mixed $validationUrl + * @param mixed $expectedResult + * + */ + public function domainShouldBeValidatedCorrectly($validationUrl, $expectedResult): void + { + $appleAdapter = new ApplepayAdapter(); + + $domainValidation = $appleAdapter->validMerchantValidationDomain($validationUrl); + $this->assertEquals($expectedResult, $domainValidation); + } + /** * @return ApplepaySession */ diff --git a/test/unit/Adapter/ApplepaySessionTest.php b/test/unit/Adapter/ApplepaySessionTest.php index 39f06f39..0fc7e529 100644 --- a/test/unit/Adapter/ApplepaySessionTest.php +++ b/test/unit/Adapter/ApplepaySessionTest.php @@ -24,14 +24,14 @@ * */ -namespace UnzerSDK\test\Adapter; +namespace UnzerSDK\test\unit\Adapter; use PHPUnit\Framework\TestCase; use UnzerSDK\Resources\ExternalResources\ApplepaySession; class ApplepaySessionTest extends TestCase { - public function testJsonSerialize() + public function testJsonSerialize(): void { $applepaySession = new ApplepaySession('merchantIdentifier', 'displayName', 'domainName'); $expectedJson = '{"merchantIdentifier": "merchantIdentifier", "displayName": "displayName", "domainName": "domainName"}'; From 68368e1d869fabfa7f99e1a1b54b63d1c623bf0a Mon Sep 17 00:00:00 2001 From: "David.Owusu" Date: Thu, 15 Apr 2021 11:36:15 +0200 Subject: [PATCH 6/9] [change] (UMCS-181) Check domain merchantValidationUrl. --- src/Adapter/ApplepayAdapter.php | 2 +- test/integration/ApplepayAdapterTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Adapter/ApplepayAdapter.php b/src/Adapter/ApplepayAdapter.php index b7c9ad7d..cd33937a 100644 --- a/src/Adapter/ApplepayAdapter.php +++ b/src/Adapter/ApplepayAdapter.php @@ -52,7 +52,7 @@ public function validateApplePayMerchant( ?string $merchantValidationCertificateKeyChainPath = null ): ?string { if (!$this->validMerchantValidationDomain($merchantValidationURL)) { - throw new ApplepayMerchantValidationException('Invalid URL used merchantValidation request.'); + throw new ApplepayMerchantValidationException('Invalid URL used for merchantValidation request.'); } $payload = $applePaySession->jsonSerialize(); $this->init( diff --git a/test/integration/ApplepayAdapterTest.php b/test/integration/ApplepayAdapterTest.php index 57fc5462..98f002b7 100644 --- a/test/integration/ApplepayAdapterTest.php +++ b/test/integration/ApplepayAdapterTest.php @@ -114,7 +114,7 @@ public function merchantValidationThrowsErrorForInvalidDomain(): void $appleAdapter = new ApplepayAdapter(); $this->expectException(ApplepayMerchantValidationException::class); - $this->expectExceptionMessage('Invalid URL used merchantValidation request.'); + $this->expectExceptionMessage('Invalid URL used for merchantValidation request.'); $appleAdapter->validateApplePayMerchant( 'https://invalid.domain.com/some/path', From 6f803a67c638c41c8cfa8bdda6049ca9572f9009 Mon Sep 17 00:00:00 2001 From: "David.Owusu" Date: Thu, 15 Apr 2021 13:34:31 +0200 Subject: [PATCH 7/9] [change] (UMCS-181) strip slashes of env vars. --- src/Services/EnvironmentService.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Services/EnvironmentService.php b/src/Services/EnvironmentService.php index a6063039..f505492b 100755 --- a/src/Services/EnvironmentService.php +++ b/src/Services/EnvironmentService.php @@ -148,7 +148,7 @@ public static function getTestPublicKey($non3ds = false): string */ public static function getAppleMerchantCertificatePath(): string { - return $_SERVER[self::ENV_VAR_TEST_APPLE_MERCHANT_CERTIFICATE] ?? ''; + return stripslashes($_SERVER[self::ENV_VAR_TEST_APPLE_MERCHANT_CERTIFICATE]) ?? ''; } /** @@ -158,6 +158,6 @@ public static function getAppleMerchantCertificatePath(): string */ public static function getAppleCaCertificatePath(): string { - return $_SERVER[self::ENV_VAR_TEST_APPLE_CA_CERTIFICATE] ?? ''; + return stripslashes($_SERVER[self::ENV_VAR_TEST_APPLE_CA_CERTIFICATE]) ?? ''; } } From 92d4476508ff8070f8c50077985085fc16d90104 Mon Sep 17 00:00:00 2001 From: "David.Owusu" Date: Thu, 15 Apr 2021 15:21:08 +0200 Subject: [PATCH 8/9] [change] (UMCS-181) -code style. --- src/Services/EnvironmentService.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Services/EnvironmentService.php b/src/Services/EnvironmentService.php index f505492b..4888a8d2 100755 --- a/src/Services/EnvironmentService.php +++ b/src/Services/EnvironmentService.php @@ -148,7 +148,7 @@ public static function getTestPublicKey($non3ds = false): string */ public static function getAppleMerchantCertificatePath(): string { - return stripslashes($_SERVER[self::ENV_VAR_TEST_APPLE_MERCHANT_CERTIFICATE]) ?? ''; + return stripslashes($_SERVER[self::ENV_VAR_TEST_APPLE_MERCHANT_CERTIFICATE] ?? ''); } /** @@ -158,6 +158,6 @@ public static function getAppleMerchantCertificatePath(): string */ public static function getAppleCaCertificatePath(): string { - return stripslashes($_SERVER[self::ENV_VAR_TEST_APPLE_CA_CERTIFICATE]) ?? ''; + return stripslashes($_SERVER[self::ENV_VAR_TEST_APPLE_CA_CERTIFICATE] ?? ''); } } From be297c654cf76154e729bd416b4e6a2a756aa193 Mon Sep 17 00:00:00 2001 From: "David.Owusu" Date: Fri, 16 Apr 2021 12:02:13 +0200 Subject: [PATCH 9/9] [change] (UMCS-181) - fix PR comments. --- src/Resources/ExternalResources/ApplepaySession.php | 11 ++++++++--- test/unit/Adapter/ApplepaySessionTest.php | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Resources/ExternalResources/ApplepaySession.php b/src/Resources/ExternalResources/ApplepaySession.php index d20caa57..8fb4a416 100644 --- a/src/Resources/ExternalResources/ApplepaySession.php +++ b/src/Resources/ExternalResources/ApplepaySession.php @@ -52,9 +52,9 @@ class ApplepaySession /** * ApplepaySession constructor. * - * @param string|null $merchantIdentifier - * @param string|null $displayName - * @param string|null $domainName + * @param string $merchantIdentifier + * @param string $displayName + * @param string $domainName */ public function __construct(string $merchantIdentifier, string $displayName, string $domainName) { @@ -63,6 +63,11 @@ public function __construct(string $merchantIdentifier, string $displayName, str $this->domainName = $domainName; } + /** + * Returns the json representation of this object's properties. + * + * @return false|string + */ public function jsonSerialize() { $properties = get_object_vars($this); diff --git a/test/unit/Adapter/ApplepaySessionTest.php b/test/unit/Adapter/ApplepaySessionTest.php index 0fc7e529..84dfa01a 100644 --- a/test/unit/Adapter/ApplepaySessionTest.php +++ b/test/unit/Adapter/ApplepaySessionTest.php @@ -1,6 +1,6 @@