From 15eeab2421c776644567c8e20b7644a728ea6199 Mon Sep 17 00:00:00 2001 From: woutse Date: Mon, 27 Jan 2025 12:22:38 +0100 Subject: [PATCH 01/18] Updated composer.json --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index e59e88d..f41907c 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,8 @@ "ext-curl": "*", "ext-json": "*", "psr/container": "^2 || ^1", - "psr/http-message": "^2 || ^1" + "psr/http-message": "^2 || ^1", + "guzzlehttp/guzzle": "^7" }, "license": "MIT", "support": { @@ -22,7 +23,6 @@ ], "require-dev": { "ext-simplexml": "*", - "guzzlehttp/guzzle": "^7", "phpmd/phpmd": "^2", "phpstan/phpstan": "^2", "phpunit/phpunit": "^11", From e2194b14c64e51c4e62b0edae06fd538aa368ad7 Mon Sep 17 00:00:00 2001 From: woutse Date: Mon, 27 Jan 2025 16:59:09 +0100 Subject: [PATCH 02/18] Updates for unit tests --- composer.json | 5 + src/Config/Config.php | 1042 +++++++++----------------- src/Request/RequestData.php | 20 +- tests/TerminalsBrowseRequestTest.php | 41 + 4 files changed, 399 insertions(+), 709 deletions(-) create mode 100644 tests/TerminalsBrowseRequestTest.php diff --git a/composer.json b/composer.json index f41907c..ad7f6d3 100644 --- a/composer.json +++ b/composer.json @@ -39,6 +39,11 @@ "./src/Resources/functions/vat.php" ] }, + "autoload-dev": { + "psr-4": { + "Tests\\": "tests/" + } + }, "minimum-stability": "dev", "prefer-stable": true, "repositories": [ diff --git a/src/Config/Config.php b/src/Config/Config.php index a334f0f..c2270ff 100644 --- a/src/Config/Config.php +++ b/src/Config/Config.php @@ -8,779 +8,405 @@ use Iterator; use ArrayAccess; -if (PHP_VERSION_ID >= 80000) { - /** - * Class Config - * - * @package PayNL\Sdk - * - * @SuppressWarnings(PHPMD.TooManyPublicMethods) - */ - class Config implements Countable, Iterator, ArrayAccess - { - const TGU1 = 'https://connect.pay.nl'; - const TGU2 = 'https://connect.payments.nl'; - const TGU3 = 'https://connect.achterelkebetaling.nl'; - - protected array $data = []; - private static Config $configObject; - - /** - * Config constructor. - * - * @param array $data - */ - public function __construct(array $data = []) - { - foreach ($data as $key => $value) { - if (true === is_array($value)) { - $value = new self($value); - } - $this->data[$key] = $value; - } - } - - /** - * @return void - */ - public function __clone() - { - $data = []; - - foreach ($this->data as $key => $value) { - if ($value instanceof self) { - $value = clone $value; - } - $data[$key] = $value; - } - $this->data = $data; - } +/** + * Class Config + * + * @package PayNL\Sdk + * + * @SuppressWarnings(PHPMD.TooManyPublicMethods) + */ +class Config implements Countable, Iterator, ArrayAccess +{ + const TGU1 = 'https://connect.pay.nl'; + const TGU2 = 'https://connect.payments.nl'; + const TGU3 = 'https://connect.achterelkebetaling.nl'; + + protected array $data = []; + private static Config $configObject; - /** - * @param $key - * @param null $default - */ - public function get($key, $default = null) - { - return $this->data[$key] ?? $default; - } - - /** - * @param string|int $key - */ - public function __get($key) - { - return $this->get($key); - } - - /** - * @param string|int $key - * @param $value - * - * @return void - */ - public function set($key, $value): void - { + /** + * Config constructor. + * + * @param array $data + */ + public function __construct(array $data = []) + { + foreach ($data as $key => $value) { if (true === is_array($value)) { $value = new self($value); } - $this->data[$key] = $value; } + } - /** - * @param string|int $key - * @param $value - * - * @return void - */ - public function __set($key, $value): void - { - $this->set($key, $value); - } + /** + * @return void + */ + public function __clone() + { + $data = []; - /** - * @param string|int $key - * - * @return void - */ - public function remove($key): void - { - if (true === $this->has($key)) { - unset($this->data[$key]); + foreach ($this->data as $key => $value) { + if ($value instanceof self) { + $value = clone $value; } + $data[$key] = $value; } - /** - * @param string|int $key - * - * @return void - */ - public function __unset($key): void - { - $this->remove($key); - } - - /** - * @param string|int $key - * - * @return bool - */ - public function has($key): bool - { - return isset($this->data[$key]); - } - - /** - * @param string|int $key - * - * @return bool - */ - public function __isset($key): bool - { - return $this->has($key); - } - - /** - * @return array - */ - public function toArray(): array - { - $array = []; - $data = $this->data; - - foreach ($data as $key => $value) { - if ($value instanceof self) { - $value = $value->toArray(); - } - $array[$key] = $value; - } - - return $array; - } - - /** - * @inheritDoc - */ - public function current(): mixed - { - return current($this->data); - } + $this->data = $data; + } + /** + * @param $key + * @param null $default + */ + public function get($key, $default = null) + { + return $this->data[$key] ?? $default; + } - /** - * @inheritDoc - * - * @return void - */ - public function next(): void - { - next($this->data); - } + /** + * @param string|int $key + */ + public function __get($key) + { + return $this->get($key); + } - /** - * @inheritDoc - * - * @return - */ - public function key(): mixed - { - return key($this->data); + /** + * @param string|int $key + * @param $value + * + * @return void + */ + public function set($key, $value): void + { + if (true === is_array($value)) { + $value = new self($value); } - /** - * @inheritDoc - * - * @return bool - */ - public function valid(): bool - { - return null !== $this->key(); - } + $this->data[$key] = $value; + } - /** - * @inheritDoc - * - * @return void - */ - public function rewind(): void - { - reset($this->data); - } + /** + * @param string|int $key + * @param $value + * + * @return void + */ + public function __set($key, $value): void + { + $this->set($key, $value); + } - /** - * @inheritDoc - * - * @return bool - */ - public function offsetExists($offset): bool - { - return $this->has($offset); + /** + * @param string|int $key + * + * @return void + */ + public function remove($key): void + { + if (true === $this->has($key)) { + unset($this->data[$key]); } + } - /** - * @inheritDoc - * - * @return - */ - public function offsetGet($offset): mixed - { - return $this->get($offset); - } + /** + * @param string|int $key + * + * @return void + */ + public function __unset($key): void + { + $this->remove($key); + } - /** - * @inheritDoc - * - * @return void - */ - public function offsetSet($offset, $value): void - { - $this->set($offset, $value); - } + /** + * @param string|int $key + * + * @return bool + */ + public function has($key): bool + { + return isset($this->data[$key]); + } - /** - * @inheritDoc - * - * @return void - */ - public function offsetUnset($offset): void - { - $this->remove($offset); - } + /** + * @param string|int $key + * + * @return bool + */ + public function __isset($key): bool + { + return $this->has($key); + } - /** - * @inheritDoc - */ - public function count(): int - { - return count($this->data); - } + /** + * @return array + */ + public function toArray(): array + { + $array = []; + $data = $this->data; - /** - * Merge the current config object with the given one - * - * @param Config $mergeConfig - * - * @return Config - */ - public function merge(Config $mergeConfig): self - { - foreach ($mergeConfig as $key => $value) { - $currentValue = $this->get($key); - if ($value instanceof self && $currentValue instanceof self) { - $value = $currentValue->merge($value); - } - if (is_array($value)) { - foreach ($value as $k => $v) { - $currentValue[$k] = $v; - } - $value = $currentValue; - } - $this->set($key, $value); + foreach ($data as $key => $value) { + if ($value instanceof self) { + $value = $value->toArray(); } - return $this; + $array[$key] = $value; } - /** - * @param bool $debug - * @return $this - */ - public function setDebug(bool $debug): self - { - $this->data['debug'] = $debug; - return $this; - } + return $array; + } - /** - * @return bool - */ - public function getDebug(): bool - { - return $this->data['debug'] == 1; - } + /** + * @inheritDoc + */ + public function current(): mixed + { + return current($this->data); + } - /** - * @return string - */ - public function getFailoverUrl(): string - { - if (!empty($this->data['failoverUrl'])) { - return trim($this->data['failoverUrl']); - } - return ''; - } - /** - * Set destination(core) url - * - * @param string $url - * @return void - */ - public function setCore(string $url): self - { - if (!empty($url)) { - $this->data['api']['url'] = $url; - } - return $this; - } + /** + * @inheritDoc + * + * @return void + */ + public function next(): void + { + next($this->data); + } - /** - * Set version of API URL - * - * @param integer $version - * @return $this - */ - public function setVersion(int $version): self - { - $this->data['api']['version'] = $version; - return $this; - } + /** + * @inheritDoc + * + * @return + */ + public function key(): mixed + { + return key($this->data); + } - /** - * @return string - */ - public function getCore(): string - { - return $this->data['api']['url'] ?? ''; - } + /** + * @inheritDoc + * + * @return bool + */ + public function valid(): bool + { + return null !== $this->key(); + } - /** - * @param string $username - * @return $this - */ - public function setUsername(string $username): self - { - $this->data['authentication']['username'] = $username; - return $this; - } + /** + * @inheritDoc + * + * @return void + */ + public function rewind(): void + { + reset($this->data); + } - /** - * @return string - */ - public function getUsername() - { - return $this->data['authentication']['username'] ?? ''; - } + /** + * @inheritDoc + * + * @return bool + */ + public function offsetExists($offset): bool + { + return $this->has($offset); + } - /** - * @param string $password - * @return $this - */ - public function setPassword(string $password): self - { - $this->data['authentication']['password'] = $password; - return $this; - } + /** + * @inheritDoc + * + * @return + */ + public function offsetGet($offset): mixed + { + return $this->get($offset); + } - /** - * @return string - */ - public function getPassword() - { - return $this->data['authentication']['password'] ?? ''; - } + /** + * @inheritDoc + * + * @return void + */ + public function offsetSet($offset, $value): void + { + $this->set($offset, $value); + } - /** - * Get global config - * - * @return Config - */ - public static function getConfig() - { - if (empty(self::$configObject)) { - self::$configObject = (new Config(require __DIR__ . '/../../config/config.global.php')); - } - return self::$configObject; - } + /** + * @inheritDoc + * + * @return void + */ + public function offsetUnset($offset): void + { + $this->remove($offset); + } + /** + * @inheritDoc + */ + public function count(): int + { + return count($this->data); } -} else { + /** - * Class Config + * Merge the current config object with the given one * - * @package PayNL\Sdk + * @param Config $mergeConfig * - * @SuppressWarnings(PHPMD.TooManyPublicMethods) - */ - class Config implements Countable, Iterator, ArrayAccess - { - const TGU1 = 'https://connect.pay.nl'; - const TGU2 = 'https://connect.payments.nl'; - const TGU3 = 'https://connect.achterelkebetaling.nl'; - - protected array $data = []; - private static Config $configObject; - - /** - * Config constructor. - * - * @param array $data - */ - public function __construct(array $data = []) - { - foreach ($data as $key => $value) { - if (true === is_array($value)) { - $value = new self($value); - } - $this->data[$key] = $value; + * @return Config + */ + public function merge(Config $mergeConfig): self + { + foreach ($mergeConfig as $key => $value) { + $currentValue = $this->get($key); + if ($value instanceof self && $currentValue instanceof self) { + $value = $currentValue->merge($value); } - } - - /** - * @return void - */ - public function __clone() - { - $data = []; - - foreach ($this->data as $key => $value) { - if ($value instanceof self) { - $value = clone $value; + if (is_array($value)) { + foreach ($value as $k => $v) { + $currentValue[$k] = $v; } - $data[$key] = $value; + $value = $currentValue; } - - $this->data = $data; - } - - /** - * @param $key - * @param null $default - */ - public function get($key, $default = null) - { - return $this->data[$key] ?? $default; - } - - /** - * @param string|int $key - */ - public function __get($key) - { - return $this->get($key); - } - - /** - * @param string|int $key - * @param $value - * - * @return void - */ - public function set($key, $value): void - { - if (true === is_array($value)) { - $value = new self($value); - } - - $this->data[$key] = $value; - } - - /** - * @param string|int $key - * @param $value - * - * @return void - */ - public function __set($key, $value): void - { $this->set($key, $value); } + return $this; + } - /** - * @param string|int $key - * - * @return void - */ - public function remove($key): void - { - if (true === $this->has($key)) { - unset($this->data[$key]); - } - } - - /** - * @param string|int $key - * - * @return void - */ - public function __unset($key): void - { - $this->remove($key); - } - - /** - * @param string|int $key - * - * @return bool - */ - public function has($key): bool - { - return isset($this->data[$key]); - } - - /** - * @param string|int $key - * - * @return bool - */ - public function __isset($key): bool - { - return $this->has($key); - } - - /** - * @return array - */ - public function toArray(): array - { - $array = []; - $data = $this->data; - - foreach ($data as $key => $value) { - if ($value instanceof self) { - $value = $value->toArray(); - } - $array[$key] = $value; - } - - return $array; - } - - /** - * @inheritDoc - */ - public function current() - { - return current($this->data); - } - - - /** - * @inheritDoc - * - * @return void - */ - public function next(): void - { - next($this->data); - } - - /** - * @inheritDoc - * - * @return - */ - public function key() - { - return key($this->data); - } - - /** - * @inheritDoc - * - * @return bool - */ - public function valid(): bool - { - return null !== $this->key(); - } - - /** - * @inheritDoc - * - * @return void - */ - public function rewind(): void - { - reset($this->data); - } - - /** - * @inheritDoc - * - * @return bool - */ - public function offsetExists($offset): bool - { - return $this->has($offset); - } - - /** - * @inheritDoc - * - * @return - */ - public function offsetGet($offset) - { - return $this->get($offset); - } - - /** - * @inheritDoc - * - * @return void - */ - public function offsetSet($offset, $value): void - { - $this->set($offset, $value); - } - - /** - * @inheritDoc - * - * @return void - */ - public function offsetUnset($offset): void - { - $this->remove($offset); - } + /** + * @param bool $debug + * @return $this + */ + public function setDebug(bool $debug): self + { + $this->data['debug'] = $debug; + return $this; + } - /** - * @inheritDoc - */ - public function count(): int - { - return count($this->data); - } + /** + * @return bool + */ + public function getDebug(): bool + { + return $this->data['debug'] == 1; + } - /** - * Merge the current config object with the given one - * - * @param Config $mergeConfig - * - * @return Config - */ - public function merge(Config $mergeConfig): self - { - foreach ($mergeConfig as $key => $value) { - $currentValue = $this->get($key); - if ($value instanceof self && $currentValue instanceof self) { - $value = $currentValue->merge($value); - } - if (is_array($value)) { - foreach ($value as $k => $v) { - $currentValue[$k] = $v; - } - $value = $currentValue; - } - $this->set($key, $value); - } - return $this; + /** + * @return string + */ + public function getFailoverUrl(): string + { + if (!empty($this->data['failoverUrl'])) { + return trim($this->data['failoverUrl']); } + return ''; + } - /** - * @param bool $debug - * @return $this - */ - public function setDebug(bool $debug): self - { - $this->data['debug'] = $debug; - return $this; + /** + * Set destination(core) url + * + * @param string $url + * @return void + */ + public function setCore(string $url): self + { + if (!empty($url)) { + $this->data['api']['url'] = $url; } + return $this; + } - /** - * @return bool - */ - public function getDebug(): bool - { - return $this->data['debug'] == 1; - } + /** + * Set version of API URL + * + * @param integer $version + * @return $this + */ + public function setVersion(int $version): self + { + $this->data['api']['version'] = $version; + return $this; + } - /** - * @return string - */ - public function getFailoverUrl(): string - { - if (!empty($this->data['failoverUrl'])) { - return trim($this->data['failoverUrl']); - } - return ''; - } + /** + * @return string + */ + public function getCore(): string + { + return $this->data['api']['url'] ?? ''; + } - /** - * Set destination(core) url - * - * @param string $url - * @return void - */ - public function setCore(string $url): self - { - if (!empty($url)) { - $this->data['api']['url'] = $url; - } - return $this; - } + /** + * @param string $username + * @return $this + */ + public function setUsername(string $username): self + { + $this->data['authentication']['username'] = $username; + return $this; + } - /** - * Set version of API URL - * - * @param integer $version - * @return $this - */ - public function setVersion(int $version): self - { - $this->data['api']['version'] = $version; - return $this; + /** + * @return bool + */ + public function isEmpty() + { + if (empty($this->data['authentication']['password']) || + empty($this->data['authentication']['username'])) { + return true; } + return false; + } - /** - * @return string - */ - public function getCore(): string - { - return $this->data['api']['url'] ?? ''; - } + /** + * @return string + */ + public function getUsername() + { + return $this->data['authentication']['username'] ?? ''; + } - /** - * @param string $username - * @return $this - */ - public function setUsername(string $username): self - { - $this->data['authentication']['username'] = $username; - return $this; - } + /** + * @param string $password + * @return $this + */ + public function setPassword(string $password): self + { + $this->data['authentication']['password'] = $password; + return $this; + } - /** - * @return string - */ - public function getUsername() - { - return $this->data['authentication']['username'] ?? ''; - } + /** + * @return string + */ + public function getPassword() + { + return $this->data['authentication']['password'] ?? ''; + } - /** - * @param string $password - * @return $this - */ - public function setPassword(string $password): self - { - $this->data['authentication']['password'] = $password; - return $this; + /** + * Get global config + * + * @return Config + */ + public static function getConfig() + { + if (empty(self::$configObject)) { + self::$configObject = (new Config(require __DIR__ . '/../../config/config.global.php')); } + return self::$configObject; + } - /** - * @return string - */ - public function getPassword() - { - return $this->data['authentication']['password'] ?? ''; - } +} - /** - * Get global config - * - * @return Config - */ - public static function getConfig() - { - if (empty(self::$configObject)) { - self::$configObject = (new Config(require __DIR__ . '/../../config/config.global.php')); - } - return self::$configObject; - } - } -} diff --git a/src/Request/RequestData.php b/src/Request/RequestData.php index 83a5220..cd72147 100644 --- a/src/Request/RequestData.php +++ b/src/Request/RequestData.php @@ -18,6 +18,7 @@ */ abstract class RequestData implements RequestDataInterface { + protected $application; protected string $mapperName = ''; protected string $uri = ''; protected string $methodType = 'GET'; @@ -46,6 +47,15 @@ public function setConfig(Config $config): self return $this; } + /** + * @param $application + * @return void + */ + public function setApplication($application) + { + $this->application = $application; + } + /** * @return mixed * @throws PayException @@ -62,8 +72,16 @@ public function start() $config->setCore($config->getFailoverUrl()); } + if ($config->isEmpty()) { + throw new PayException('Please check your config', 0, 0); + } + try { - $response = (Application::init($config))->request($this)->run(); + if (empty($this->application)) { + $this->application = Application::init($config); + } + + $response = $this->application->request($this)->run(); } catch (\Throwable $e) { throw (new PayException('Could not initiate API call:' . $e->getMessage(), 0, 0)) ->setFriendlyMessage(Text::getFriendlyMessage($e->getMessage())); diff --git a/tests/TerminalsBrowseRequestTest.php b/tests/TerminalsBrowseRequestTest.php new file mode 100644 index 0000000..ad1f41b --- /dev/null +++ b/tests/TerminalsBrowseRequestTest.php @@ -0,0 +1,41 @@ +createMock(Application::class); + + $mockApplication->expects($this->never())->method('request'); + + $request = new TerminalsBrowseRequest(); + $request->setApplication($mockApplication); + + $this->expectException(PayException::class); + $this->expectExceptionMessage('Please check your config'); + + $request->start(); + } + + public function testStartWrongConfig() + { + $mockApplication = $this->createMock(Application::class); + + $request = new TerminalsBrowseRequest(); + $request->setApplication($mockApplication); + + $config = (new Config())->setUsername('test')->setPassword('test'); + + try { + $request->setConfig($config)->start(); + } catch (PayException $e) { + $this->assertEquals('Wrong credentials', $e->getFriendlyMessage()); + } + } +} \ No newline at end of file From 84b4ddce77ae03a97283259190f0396814a4121a Mon Sep 17 00:00:00 2001 From: woutse Date: Tue, 28 Jan 2025 15:52:35 +0100 Subject: [PATCH 03/18] Updates for unit tests --- tests/OrderCreateRequestTest.php | 150 +++++++++++++++++++++++++++++++ tests/OrderStatusRequestTest.php | 52 +++++++++++ 2 files changed, 202 insertions(+) create mode 100644 tests/OrderCreateRequestTest.php create mode 100644 tests/OrderStatusRequestTest.php diff --git a/tests/OrderCreateRequestTest.php b/tests/OrderCreateRequestTest.php new file mode 100644 index 0000000..aa3c8e5 --- /dev/null +++ b/tests/OrderCreateRequestTest.php @@ -0,0 +1,150 @@ +enableFastCheckout(false, true, false); + + $reflection = new \ReflectionClass($request); + $optimizeProperty = $reflection->getProperty('optimize'); + $optimizeProperty->setAccessible(true); + + $this->assertEquals([ + 'flow' => 'fastCheckout', + 'shippingAddress' => false, + 'billingAddress' => true, + 'contactDetails' => false, + ], $optimizeProperty->getValue($request)); + } + + public function testSetReturnUrl(): void + { + $request = new OrderCreateRequest(); + $request->setReturnurl('https://example.com/return'); + + $reflection = new \ReflectionClass($request); + $returnUrlProperty = $reflection->getProperty('returnUrl'); + $returnUrlProperty->setAccessible(true); + + $this->assertEquals('https://example.com/return', $returnUrlProperty->getValue($request)); + } + + public function testSetAmount(): void + { + $request = new OrderCreateRequest(); + $request->setAmount(123.45); + + $reflection = new \ReflectionClass($request); + $amountProperty = $reflection->getProperty('amount'); + $amountProperty->setAccessible(true); + + $this->assertEquals(12345, $amountProperty->getValue($request)); + } + + public function testSetReference(): void + { + $request = new OrderCreateRequest(); + + $request->setReference('Order123'); + + $reflection = new \ReflectionClass($request); + $referenceProperty = $reflection->getProperty('reference'); + $referenceProperty->setAccessible(true); + + $this->assertEquals('Order123', $referenceProperty->getValue($request)); + } + + public function testSetReferenceThrowsExceptionForInvalidReference(): void + { + $this->expectException(\Exception::class); + $this->expectExceptionMessage('Reference should consist of all letters or digits'); + + $request = new OrderCreateRequest(); + $request->setReference('Order#123'); + } + + public function testSetNotification(): void + { + $request = new OrderCreateRequest(); + + $request->setNotification('email', 'test@example.com'); + + $reflection = new \ReflectionClass($request); + $notificationTypeProperty = $reflection->getProperty('notificationType'); + $notificationTypeProperty->setAccessible(true); + $notificationRecipientProperty = $reflection->getProperty('notificationRecipient'); + $notificationRecipientProperty->setAccessible(true); + + $this->assertEquals('email', $notificationTypeProperty->getValue($request)); + $this->assertEquals('test@example.com', $notificationRecipientProperty->getValue($request)); + } + + public function testSetNotificationThrowsExceptionForInvalidEmail(): void + { + $this->expectException(\Exception::class); + $this->expectExceptionMessage('Valid email format expected as notification recipient'); + + $request = new OrderCreateRequest(); + $request->setNotification('email', 'invalid-email'); + } + + public function testSetNotificationThrowsExceptionForInvalidPushRecipient(): void + { + $this->expectException(\Exception::class); + $this->expectExceptionMessage('Recepient expected to be AD-####-#### code'); + + $request = new OrderCreateRequest(); + $request->setNotification('push', '1234'); + } + + public function testSetCustomer(): void + { + $mockCustomer = $this->createMock(Customer::class); + $request = new OrderCreateRequest(); + $request->setCustomer($mockCustomer); + + $reflection = new \ReflectionClass($request); + $customerProperty = $reflection->getProperty('customer'); + $customerProperty->setAccessible(true); + + $this->assertSame($mockCustomer, $customerProperty->getValue($request)); + } + + public function testSetOrder(): void + { + $mockOrder = $this->createMock(Order::class); + $request = new OrderCreateRequest(); + $request->setOrder($mockOrder); + + $reflection = new \ReflectionClass($request); + $orderProperty = $reflection->getProperty('order'); + $orderProperty->setAccessible(true); + + $this->assertSame($mockOrder, $orderProperty->getValue($request)); + } + + public function testSetStats(): void + { + $mockStats = $this->createMock(Stats::class); + $request = new OrderCreateRequest(); + $request->setStats($mockStats); + + $reflection = new \ReflectionClass($request); + $statsProperty = $reflection->getProperty('stats'); + $statsProperty->setAccessible(true); + + $this->assertSame($mockStats, $statsProperty->getValue($request)); + } +} diff --git a/tests/OrderStatusRequestTest.php b/tests/OrderStatusRequestTest.php new file mode 100644 index 0000000..44e4c27 --- /dev/null +++ b/tests/OrderStatusRequestTest.php @@ -0,0 +1,52 @@ +assertEquals(['transactionId' => $orderId], $request->getPathParameters()); + } + + public function testGetPathParameters(): void + { + $orderId = '67890'; + $request = new OrderStatusRequest($orderId); + + $expected = ['transactionId' => $orderId]; + $this->assertEquals($expected, $request->getPathParameters()); + } + + public function testGetBodyParametersReturnsEmptyArray(): void + { + $orderId = '67890'; + $request = new OrderStatusRequest($orderId); + + $this->assertEquals([], $request->getBodyParameters()); + } + + public function testStartReturnsPayOrder(): void + { + $orderId = '12345'; + + $mockPayOrder = $this->createMock(PayOrder::class); + + $request = $this->getMockBuilder(OrderStatusRequest::class) + ->setConstructorArgs([$orderId]) + ->onlyMethods(['start']) + ->getMock(); + + $request->method('start')->willReturn($mockPayOrder); + + $result = $request->start(); + + $this->assertInstanceOf(PayOrder::class, $result); + } +} From d988ae4d5376372d4a442f78a7e4d3b2600d9272 Mon Sep 17 00:00:00 2001 From: woutse Date: Tue, 28 Jan 2025 16:07:15 +0100 Subject: [PATCH 04/18] Updates for unit tests --- tests/OrderAbortRequestTest.php | 58 +++++++++++++++ tests/OrderApproveRequestTest.php | 58 +++++++++++++++ tests/OrderCaptureRequestTest.php | 102 ++++++++++++++++++++++++++ tests/ServiceGetConfigRequestTest.php | 70 ++++++++++++++++++ tests/TerminalsBrowseRequestTest.php | 2 +- 5 files changed, 289 insertions(+), 1 deletion(-) create mode 100644 tests/OrderAbortRequestTest.php create mode 100644 tests/OrderApproveRequestTest.php create mode 100644 tests/OrderCaptureRequestTest.php create mode 100644 tests/ServiceGetConfigRequestTest.php diff --git a/tests/OrderAbortRequestTest.php b/tests/OrderAbortRequestTest.php new file mode 100644 index 0000000..3c45fa4 --- /dev/null +++ b/tests/OrderAbortRequestTest.php @@ -0,0 +1,58 @@ +assertInstanceOf(OrderAbortRequest::class, $orderAbortRequest); + } + + public function testGetPathParameters(): void + { + $transactionId = '123456'; + $orderAbortRequest = new OrderAbortRequest($transactionId); + + $pathParameters = $orderAbortRequest->getPathParameters(); + + $this->assertIsArray($pathParameters); + $this->assertArrayHasKey('transactionId', $pathParameters); + $this->assertSame($transactionId, $pathParameters['transactionId']); + } + + public function testGetBodyParameters(): void + { + $transactionId = '123456'; + $orderAbortRequest = new OrderAbortRequest($transactionId); + + $bodyParameters = $orderAbortRequest->getBodyParameters(); + + $this->assertIsArray($bodyParameters); + $this->assertEmpty($bodyParameters); + } + + public function testStart(): void + { + $transactionId = '123456'; + $orderAbortRequest = $this->getMockBuilder(OrderAbortRequest::class) + ->setConstructorArgs([$transactionId]) + ->onlyMethods(['start']) + ->getMock(); + + $mockPayOrder = $this->createMock(PayOrder::class); + + $orderAbortRequest->method('start')->willReturn($mockPayOrder); + + $result = $orderAbortRequest->start(); + + $this->assertInstanceOf(PayOrder::class, $result); + } + +} \ No newline at end of file diff --git a/tests/OrderApproveRequestTest.php b/tests/OrderApproveRequestTest.php new file mode 100644 index 0000000..0adb60a --- /dev/null +++ b/tests/OrderApproveRequestTest.php @@ -0,0 +1,58 @@ +assertInstanceOf(OrderApproveRequest::class, $orderApproveRequest); + } + + public function testGetPathParameters(): void + { + $transactionId = '123456'; + $orderApproveRequest = new OrderApproveRequest($transactionId); + + $pathParameters = $orderApproveRequest->getPathParameters(); + + $this->assertIsArray($pathParameters); + $this->assertArrayHasKey('transactionId', $pathParameters); + $this->assertSame($transactionId, $pathParameters['transactionId']); + } + + public function testGetBodyParameters(): void + { + $transactionId = '123456'; + $orderApproveRequest = new OrderApproveRequest($transactionId); + + $bodyParameters = $orderApproveRequest->getBodyParameters(); + + $this->assertIsArray($bodyParameters); + $this->assertEmpty($bodyParameters); + } + + public function testStart(): void + { + $transactionId = '123456'; + $orderApproveRequest = $this->getMockBuilder(OrderApproveRequest::class) + ->setConstructorArgs([$transactionId]) + ->onlyMethods(['start']) + ->getMock(); + + $mockPayOrder = $this->createMock(PayOrder::class); + + $orderApproveRequest->method('start')->willReturn($mockPayOrder); + + $result = $orderApproveRequest->start(); + + $this->assertInstanceOf(PayOrder::class, $result); + } + +} \ No newline at end of file diff --git a/tests/OrderCaptureRequestTest.php b/tests/OrderCaptureRequestTest.php new file mode 100644 index 0000000..bebffce --- /dev/null +++ b/tests/OrderCaptureRequestTest.php @@ -0,0 +1,102 @@ +assertInstanceOf(OrderCaptureRequest::class, $orderCaptureRequest); + } + + public function testGetPathParameters(): void + { + $transactionId = '123456'; + $orderCaptureRequest = new OrderCaptureRequest($transactionId); + + $pathParameters = $orderCaptureRequest->getPathParameters(); + + $this->assertIsArray($pathParameters); + $this->assertArrayHasKey('transactionId', $pathParameters); + $this->assertSame($transactionId, $pathParameters['transactionId']); + } + + public function testGetBodyParametersWithAmount(): void + { + $transactionId = '123456'; + $amount = 150.75; + $orderCaptureRequest = new OrderCaptureRequest($transactionId, $amount); + + $bodyParameters = $orderCaptureRequest->getBodyParameters(); + + $this->assertIsArray($bodyParameters); + $this->assertArrayHasKey('amount', $bodyParameters); + $this->assertSame((int)round($amount * 100), $bodyParameters['amount']); + } + + public function testSetProduct(): void + { + $transactionId = '123456'; + $orderCaptureRequest = new OrderCaptureRequest($transactionId); + + $productId = 'prod-001'; + $quantity = 2; + + $orderCaptureRequest->setProduct($productId, $quantity); + + $bodyParameters = $orderCaptureRequest->getBodyParameters(); + + $this->assertIsArray($bodyParameters); + $this->assertArrayHasKey('products', $bodyParameters); + $this->assertCount(1, $bodyParameters['products']); + $this->assertSame($productId, $bodyParameters['products'][0]['id']); + $this->assertSame($quantity, $bodyParameters['products'][0]['quantity']); + } + + public function testStartWithAmount(): void + { + $transactionId = '123456'; + $amount = 200.00; + $orderCaptureRequest = $this->getMockBuilder(OrderCaptureRequest::class) + ->setConstructorArgs([$transactionId, $amount]) + ->onlyMethods(['start']) + ->getMock(); + + $mockPayOrder = $this->createMock(PayOrder::class); + + $orderCaptureRequest->method('start')->willReturn($mockPayOrder); + + $result = $orderCaptureRequest->start(); + + $this->assertInstanceOf(PayOrder::class, $result); + } + + public function testStartWithProduct(): void + { + $transactionId = '123456'; + $orderCaptureRequest = $this->getMockBuilder(OrderCaptureRequest::class) + ->setConstructorArgs([$transactionId]) + ->onlyMethods(['start']) + ->getMock(); + + $productId = 'prod-002'; + $quantity = 3; + $orderCaptureRequest->setProduct($productId, $quantity); + + $mockPayOrder = $this->createMock(PayOrder::class); + + $orderCaptureRequest->method('start')->willReturn($mockPayOrder); + + $result = $orderCaptureRequest->start(); + + $this->assertInstanceOf(PayOrder::class, $result); + } + +} \ No newline at end of file diff --git a/tests/ServiceGetConfigRequestTest.php b/tests/ServiceGetConfigRequestTest.php new file mode 100644 index 0000000..d69365b --- /dev/null +++ b/tests/ServiceGetConfigRequestTest.php @@ -0,0 +1,70 @@ +assertInstanceOf(ServiceGetConfigRequest::class, $serviceGetConfigRequest); + } + + /** + * @return void + */ + public function testGetPathParametersWithServiceId(): void + { + $serviceId = 'service123'; + $serviceGetConfigRequest = new ServiceGetConfigRequest($serviceId); + + $pathParameters = $serviceGetConfigRequest->getPathParameters(); + + $this->assertIsArray($pathParameters); + $this->assertArrayHasKey('serviceId', $pathParameters); + $this->assertSame($serviceId, $pathParameters['serviceId']); + } + + public function testGetPathParametersWithoutServiceId(): void + { + $serviceGetConfigRequest = new ServiceGetConfigRequest(); + + $pathParameters = $serviceGetConfigRequest->getPathParameters(); + + $this->assertIsArray($pathParameters); + $this->assertEmpty($pathParameters); + } + + public function testGetBodyParameters(): void + { + $serviceGetConfigRequest = new ServiceGetConfigRequest('service123'); + + $bodyParameters = $serviceGetConfigRequest->getBodyParameters(); + + $this->assertIsArray($bodyParameters); + $this->assertEmpty($bodyParameters); + } + + public function testStart(): void + { + $serviceId = 'service123'; + $serviceGetConfigRequest = $this->getMockBuilder(ServiceGetConfigRequest::class) + ->setConstructorArgs([$serviceId]) + ->onlyMethods(['start']) + ->getMock(); + + $mockResponse = $this->createMock(ServiceGetConfigResponse::class); + + $serviceGetConfigRequest->method('start')->willReturn($mockResponse); + + $result = $serviceGetConfigRequest->start(); + + $this->assertInstanceOf(ServiceGetConfigResponse::class, $result); + } + +} \ No newline at end of file diff --git a/tests/TerminalsBrowseRequestTest.php b/tests/TerminalsBrowseRequestTest.php index ad1f41b..56a49d5 100644 --- a/tests/TerminalsBrowseRequestTest.php +++ b/tests/TerminalsBrowseRequestTest.php @@ -35,7 +35,7 @@ public function testStartWrongConfig() try { $request->setConfig($config)->start(); } catch (PayException $e) { - $this->assertEquals('Wrong credentials', $e->getFriendlyMessage()); + $this->assertEquals('Something went wrong', $e->getFriendlyMessage()); } } } \ No newline at end of file From 1d84b3b8055f4fb66bb3ba7027d44e7620586448 Mon Sep 17 00:00:00 2001 From: woutse Date: Thu, 30 Jan 2025 12:11:34 +0100 Subject: [PATCH 05/18] Code polish --- src/Request/RequestData.php | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/Request/RequestData.php b/src/Request/RequestData.php index cd72147..f357fad 100644 --- a/src/Request/RequestData.php +++ b/src/Request/RequestData.php @@ -18,7 +18,7 @@ */ abstract class RequestData implements RequestDataInterface { - protected $application; + protected Application $application; protected string $mapperName = ''; protected string $uri = ''; protected string $methodType = 'GET'; @@ -48,10 +48,10 @@ public function setConfig(Config $config): self } /** - * @param $application + * @param Application $application * @return void */ - public function setApplication($application) + public function setApplication(Application $application): void { $this->application = $application; } @@ -113,14 +113,13 @@ public function start() } } - - /* - * For defining the arguments used in the requestpath + /** + * @return array */ abstract public function getPathParameters(): array; - /* - * For defining the arguments used in the body of the request + /** + * @return array */ abstract public function getBodyParameters(): array; @@ -147,4 +146,4 @@ public function getMethodName(): string { return $this->mapperName; } -} \ No newline at end of file +} From 9de819882a9ebe39cf54053d160267d210ced9f0 Mon Sep 17 00:00:00 2001 From: woutse Date: Thu, 30 Jan 2025 12:11:52 +0100 Subject: [PATCH 06/18] Updated min php version --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index ad7f6d3..60a934f 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "version": "0.2.0", "type": "library", "require": { - "php": "^8.2", + "php": "^8.1", "ext-curl": "*", "ext-json": "*", "psr/container": "^2 || ^1", From 6f55d5f8ae905ca1dd0b4e83fd5f600d7a3dff2d Mon Sep 17 00:00:00 2001 From: woutse Date: Thu, 30 Jan 2025 12:23:03 +0100 Subject: [PATCH 07/18] Moved tests --- .../Unit}/OrderAbortRequestTest.php | 24 +++++++++++++++---- .../Unit}/OrderApproveRequestTest.php | 7 +++--- .../Unit}/OrderCaptureRequestTest.php | 7 +++--- .../Unit}/OrderCreateRequestTest.php | 10 ++++---- .../Unit}/OrderStatusRequestTest.php | 10 ++++---- .../Unit}/ServiceGetConfigRequestTest.php | 5 ++-- .../Unit}/TerminalsBrowseRequestTest.php | 4 +++- 7 files changed, 44 insertions(+), 23 deletions(-) rename {tests => Tests/Unit}/OrderAbortRequestTest.php (86%) rename {tests => Tests/Unit}/OrderApproveRequestTest.php (97%) rename {tests => Tests/Unit}/OrderCaptureRequestTest.php (98%) rename {tests => Tests/Unit}/OrderCreateRequestTest.php (98%) rename {tests => Tests/Unit}/OrderStatusRequestTest.php (93%) rename {tests => Tests/Unit}/ServiceGetConfigRequestTest.php (98%) rename {tests => Tests/Unit}/TerminalsBrowseRequestTest.php (98%) diff --git a/tests/OrderAbortRequestTest.php b/Tests/Unit/OrderAbortRequestTest.php similarity index 86% rename from tests/OrderAbortRequestTest.php rename to Tests/Unit/OrderAbortRequestTest.php index 3c45fa4..d7a42be 100644 --- a/tests/OrderAbortRequestTest.php +++ b/Tests/Unit/OrderAbortRequestTest.php @@ -1,12 +1,16 @@ assertInstanceOf(OrderAbortRequest::class, $orderAbortRequest); } + /** + * @return void + */ public function testGetPathParameters(): void { $transactionId = '123456'; @@ -27,6 +34,9 @@ public function testGetPathParameters(): void $this->assertSame($transactionId, $pathParameters['transactionId']); } + /** + * @return void + */ public function testGetBodyParameters(): void { $transactionId = '123456'; @@ -38,6 +48,11 @@ public function testGetBodyParameters(): void $this->assertEmpty($bodyParameters); } + /** + * @return void + * @throws \PHPUnit\Framework\MockObject\Exception + * @throws \PayNL\Sdk\Exception\PayException + */ public function testStart(): void { $transactionId = '123456'; @@ -54,5 +69,4 @@ public function testStart(): void $this->assertInstanceOf(PayOrder::class, $result); } - -} \ No newline at end of file +} diff --git a/tests/OrderApproveRequestTest.php b/Tests/Unit/OrderApproveRequestTest.php similarity index 97% rename from tests/OrderApproveRequestTest.php rename to Tests/Unit/OrderApproveRequestTest.php index 0adb60a..510f496 100644 --- a/tests/OrderApproveRequestTest.php +++ b/Tests/Unit/OrderApproveRequestTest.php @@ -1,9 +1,10 @@ Date: Thu, 30 Jan 2025 14:02:15 +0100 Subject: [PATCH 08/18] Code polish --- Tests/Unit/OrderApproveRequestTest.php | 17 +++- Tests/Unit/OrderCaptureRequestTest.php | 25 +++++- Tests/Unit/OrderCreateRequestTest.php | 41 +++++++++ Tests/Unit/OrderStatusRequestTest.php | 16 +++- Tests/Unit/ServiceGetConfigRequestTest.php | 17 +++- Tests/Unit/TerminalsBrowseRequestTest.php | 11 ++- src/Config/Config.php | 100 ++++++++++----------- 7 files changed, 163 insertions(+), 64 deletions(-) diff --git a/Tests/Unit/OrderApproveRequestTest.php b/Tests/Unit/OrderApproveRequestTest.php index 510f496..367bd9c 100644 --- a/Tests/Unit/OrderApproveRequestTest.php +++ b/Tests/Unit/OrderApproveRequestTest.php @@ -8,6 +8,9 @@ class OrderApproveRequestTest extends TestCase { + /** + * @return void + */ public function testConstructor(): void { $transactionId = '123456'; @@ -16,6 +19,9 @@ public function testConstructor(): void $this->assertInstanceOf(OrderApproveRequest::class, $orderApproveRequest); } + /** + * @return void + */ public function testGetPathParameters(): void { $transactionId = '123456'; @@ -28,6 +34,9 @@ public function testGetPathParameters(): void $this->assertSame($transactionId, $pathParameters['transactionId']); } + /** + * @return void + */ public function testGetBodyParameters(): void { $transactionId = '123456'; @@ -39,6 +48,11 @@ public function testGetBodyParameters(): void $this->assertEmpty($bodyParameters); } + /** + * @return void + * @throws \PHPUnit\Framework\MockObject\Exception + * @throws \PayNL\Sdk\Exception\PayException + */ public function testStart(): void { $transactionId = '123456'; @@ -55,5 +69,4 @@ public function testStart(): void $this->assertInstanceOf(PayOrder::class, $result); } - -} \ No newline at end of file +} diff --git a/Tests/Unit/OrderCaptureRequestTest.php b/Tests/Unit/OrderCaptureRequestTest.php index 1d63207..eed0e68 100644 --- a/Tests/Unit/OrderCaptureRequestTest.php +++ b/Tests/Unit/OrderCaptureRequestTest.php @@ -8,6 +8,9 @@ class OrderCaptureRequestTest extends TestCase { + /** + * @return void + */ public function testConstructor(): void { $transactionId = '123456'; @@ -17,6 +20,9 @@ public function testConstructor(): void $this->assertInstanceOf(OrderCaptureRequest::class, $orderCaptureRequest); } + /** + * @return void + */ public function testGetPathParameters(): void { $transactionId = '123456'; @@ -29,6 +35,9 @@ public function testGetPathParameters(): void $this->assertSame($transactionId, $pathParameters['transactionId']); } + /** + * @return void + */ public function testGetBodyParametersWithAmount(): void { $transactionId = '123456'; @@ -42,6 +51,9 @@ public function testGetBodyParametersWithAmount(): void $this->assertSame((int)round($amount * 100), $bodyParameters['amount']); } + /** + * @return void + */ public function testSetProduct(): void { $transactionId = '123456'; @@ -61,6 +73,11 @@ public function testSetProduct(): void $this->assertSame($quantity, $bodyParameters['products'][0]['quantity']); } + /** + * @return void + * @throws \PHPUnit\Framework\MockObject\Exception + * @throws \PayNL\Sdk\Exception\PayException + */ public function testStartWithAmount(): void { $transactionId = '123456'; @@ -79,6 +96,11 @@ public function testStartWithAmount(): void $this->assertInstanceOf(PayOrder::class, $result); } + /** + * @return void + * @throws \PHPUnit\Framework\MockObject\Exception + * @throws \PayNL\Sdk\Exception\PayException + */ public function testStartWithProduct(): void { $transactionId = '123456'; @@ -99,5 +121,4 @@ public function testStartWithProduct(): void $this->assertInstanceOf(PayOrder::class, $result); } - -} \ No newline at end of file +} diff --git a/Tests/Unit/OrderCreateRequestTest.php b/Tests/Unit/OrderCreateRequestTest.php index c796767..3c0746f 100644 --- a/Tests/Unit/OrderCreateRequestTest.php +++ b/Tests/Unit/OrderCreateRequestTest.php @@ -12,6 +12,9 @@ class OrderCreateRequestTest extends TestCase { + /** + * @return void + */ public function testEnableFastCheckout(): void { $request = new OrderCreateRequest(); @@ -29,6 +32,9 @@ public function testEnableFastCheckout(): void ], $optimizeProperty->getValue($request)); } + /** + * @return void + */ public function testSetReturnUrl(): void { $request = new OrderCreateRequest(); @@ -41,6 +47,9 @@ public function testSetReturnUrl(): void $this->assertEquals('https://example.com/return', $returnUrlProperty->getValue($request)); } + /** + * @return void + */ public function testSetAmount(): void { $request = new OrderCreateRequest(); @@ -53,6 +62,10 @@ public function testSetAmount(): void $this->assertEquals(12345, $amountProperty->getValue($request)); } + /** + * @return void + * @throws \Exception + */ public function testSetReference(): void { $request = new OrderCreateRequest(); @@ -66,6 +79,10 @@ public function testSetReference(): void $this->assertEquals('Order123', $referenceProperty->getValue($request)); } + /** + * @return void + * @throws \Exception + */ public function testSetReferenceThrowsExceptionForInvalidReference(): void { $this->expectException(\Exception::class); @@ -75,6 +92,10 @@ public function testSetReferenceThrowsExceptionForInvalidReference(): void $request->setReference('Order#123'); } + /** + * @return void + * @throws \Exception + */ public function testSetNotification(): void { $request = new OrderCreateRequest(); @@ -91,6 +112,10 @@ public function testSetNotification(): void $this->assertEquals('test@example.com', $notificationRecipientProperty->getValue($request)); } + /** + * @return void + * @throws \Exception + */ public function testSetNotificationThrowsExceptionForInvalidEmail(): void { $this->expectException(\Exception::class); @@ -100,6 +125,10 @@ public function testSetNotificationThrowsExceptionForInvalidEmail(): void $request->setNotification('email', 'invalid-email'); } + /** + * @return void + * @throws \Exception + */ public function testSetNotificationThrowsExceptionForInvalidPushRecipient(): void { $this->expectException(\Exception::class); @@ -109,6 +138,10 @@ public function testSetNotificationThrowsExceptionForInvalidPushRecipient(): voi $request->setNotification('push', '1234'); } + /** + * @return void + * @throws \PHPUnit\Framework\MockObject\Exception + */ public function testSetCustomer(): void { $mockCustomer = $this->createMock(Customer::class); @@ -122,6 +155,10 @@ public function testSetCustomer(): void $this->assertSame($mockCustomer, $customerProperty->getValue($request)); } + /** + * @return void + * @throws \PHPUnit\Framework\MockObject\Exception + */ public function testSetOrder(): void { $mockOrder = $this->createMock(Order::class); @@ -135,6 +172,10 @@ public function testSetOrder(): void $this->assertSame($mockOrder, $orderProperty->getValue($request)); } + /** + * @return void + * @throws \PHPUnit\Framework\MockObject\Exception + */ public function testSetStats(): void { $mockStats = $this->createMock(Stats::class); diff --git a/Tests/Unit/OrderStatusRequestTest.php b/Tests/Unit/OrderStatusRequestTest.php index 2e35100..a46acaf 100644 --- a/Tests/Unit/OrderStatusRequestTest.php +++ b/Tests/Unit/OrderStatusRequestTest.php @@ -6,10 +6,11 @@ use PayNL\Sdk\Model\Request\OrderStatusRequest; use PHPUnit\Framework\TestCase; -; - class OrderStatusRequestTest extends TestCase { + /** + * @return void + */ public function testConstructorInitializesCorrectly(): void { $orderId = '12345'; @@ -17,6 +18,9 @@ public function testConstructorInitializesCorrectly(): void $this->assertEquals(['transactionId' => $orderId], $request->getPathParameters()); } + /** + * @return void + */ public function testGetPathParameters(): void { $orderId = '67890'; @@ -26,6 +30,9 @@ public function testGetPathParameters(): void $this->assertEquals($expected, $request->getPathParameters()); } + /** + * @return void + */ public function testGetBodyParametersReturnsEmptyArray(): void { $orderId = '67890'; @@ -34,6 +41,11 @@ public function testGetBodyParametersReturnsEmptyArray(): void $this->assertEquals([], $request->getBodyParameters()); } + /** + * @return void + * @throws \PHPUnit\Framework\MockObject\Exception + * @throws \PayNL\Sdk\Exception\PayException + */ public function testStartReturnsPayOrder(): void { $orderId = '12345'; diff --git a/Tests/Unit/ServiceGetConfigRequestTest.php b/Tests/Unit/ServiceGetConfigRequestTest.php index dfa9e38..bb9ebca 100644 --- a/Tests/Unit/ServiceGetConfigRequestTest.php +++ b/Tests/Unit/ServiceGetConfigRequestTest.php @@ -8,6 +8,9 @@ class ServiceGetConfigRequestTest extends TestCase { + /** + * @return void + */ public function testConstructor(): void { $serviceId = 'service123'; @@ -31,6 +34,9 @@ public function testGetPathParametersWithServiceId(): void $this->assertSame($serviceId, $pathParameters['serviceId']); } + /** + * @return void + */ public function testGetPathParametersWithoutServiceId(): void { $serviceGetConfigRequest = new ServiceGetConfigRequest(); @@ -41,6 +47,9 @@ public function testGetPathParametersWithoutServiceId(): void $this->assertEmpty($pathParameters); } + /** + * @return void + */ public function testGetBodyParameters(): void { $serviceGetConfigRequest = new ServiceGetConfigRequest('service123'); @@ -51,6 +60,11 @@ public function testGetBodyParameters(): void $this->assertEmpty($bodyParameters); } + /** + * @return void + * @throws \PHPUnit\Framework\MockObject\Exception + * @throws \PayNL\Sdk\Exception\PayException + */ public function testStart(): void { $serviceId = 'service123'; @@ -67,5 +81,4 @@ public function testStart(): void $this->assertInstanceOf(ServiceGetConfigResponse::class, $result); } - -} \ No newline at end of file +} diff --git a/Tests/Unit/TerminalsBrowseRequestTest.php b/Tests/Unit/TerminalsBrowseRequestTest.php index d03e12b..14b1004 100644 --- a/Tests/Unit/TerminalsBrowseRequestTest.php +++ b/Tests/Unit/TerminalsBrowseRequestTest.php @@ -10,6 +10,11 @@ class TerminalsBrowseRequestTest extends TestCase { + /** + * @return void + * @throws PayException + * @throws \PHPUnit\Framework\MockObject\Exception + */ public function testStartThrowsExceptionWithoutConfig() { $mockApplication = $this->createMock(Application::class); @@ -25,6 +30,10 @@ public function testStartThrowsExceptionWithoutConfig() $request->start(); } + /** + * @return void + * @throws \PHPUnit\Framework\MockObject\Exception + */ public function testStartWrongConfig() { $mockApplication = $this->createMock(Application::class); @@ -40,4 +49,4 @@ public function testStartWrongConfig() $this->assertEquals('Something went wrong', $e->getFriendlyMessage()); } } -} \ No newline at end of file +} diff --git a/src/Config/Config.php b/src/Config/Config.php index c2270ff..fef78fc 100644 --- a/src/Config/Config.php +++ b/src/Config/Config.php @@ -8,7 +8,6 @@ use Iterator; use ArrayAccess; - /** * Class Config * @@ -18,9 +17,9 @@ */ class Config implements Countable, Iterator, ArrayAccess { - const TGU1 = 'https://connect.pay.nl'; - const TGU2 = 'https://connect.payments.nl'; - const TGU3 = 'https://connect.achterelkebetaling.nl'; + protected const TGU1 = 'https://connect.pay.nl'; + protected const TGU2 = 'https://connect.payments.nl'; + protected const TGU3 = 'https://connect.achterelkebetaling.nl'; protected array $data = []; private static Config $configObject; @@ -58,29 +57,30 @@ public function __clone() } /** - * @param $key - * @param null $default + * @param mixed $key + * @param mixed $default + * @return mixed|null */ - public function get($key, $default = null) + public function get(mixed $key, mixed $default = null) { return $this->data[$key] ?? $default; } /** - * @param string|int $key + * @param string|integer $key + * @return mixed|null */ - public function __get($key) + public function __get($key) // phpcs:ignore { return $this->get($key); } /** - * @param string|int $key - * @param $value - * + * @param mixed $key + * @param mixed $value * @return void */ - public function set($key, $value): void + public function set(mixed $key, mixed $value): void { if (true === is_array($value)) { $value = new self($value); @@ -90,18 +90,17 @@ public function set($key, $value): void } /** - * @param string|int $key - * @param $value - * + * @param mixed $key + * @param mixed $value * @return void */ - public function __set($key, $value): void + public function __set($key, $value): void // phpcs:ignore { $this->set($key, $value); } /** - * @param string|int $key + * @param string|integer $key * * @return void */ @@ -113,7 +112,7 @@ public function remove($key): void } /** - * @param string|int $key + * @param string|integer $key * * @return void */ @@ -123,9 +122,9 @@ public function __unset($key): void } /** - * @param string|int $key + * @param string|integer $key * - * @return bool + * @return boolean */ public function has($key): bool { @@ -133,9 +132,9 @@ public function has($key): bool } /** - * @param string|int $key + * @param string|integer $key * - * @return bool + * @return boolean */ public function __isset($key): bool { @@ -161,7 +160,7 @@ public function toArray(): array } /** - * @inheritDoc + * @return mixed */ public function current(): mixed { @@ -180,9 +179,7 @@ public function next(): void } /** - * @inheritDoc - * - * @return + * @return mixed */ public function key(): mixed { @@ -191,8 +188,7 @@ public function key(): mixed /** * @inheritDoc - * - * @return bool + * @return boolean */ public function valid(): bool { @@ -210,47 +206,44 @@ public function rewind(): void } /** - * @inheritDoc - * - * @return bool + * @param mixed $offset + * @return boolean */ - public function offsetExists($offset): bool + public function offsetExists($offset): bool // phpcs:ignore { return $this->has($offset); } /** - * @inheritDoc - * - * @return + * @param mixed $offset + * @return mixed */ - public function offsetGet($offset): mixed + public function offsetGet(mixed $offset): mixed { return $this->get($offset); } /** - * @inheritDoc - * + * @param mixed $offset + * @param mixed $value * @return void */ - public function offsetSet($offset, $value): void + public function offsetSet($offset, $value): void // phpcs:ignore { $this->set($offset, $value); } /** - * @inheritDoc - * + * @param mixed $offset * @return void */ - public function offsetUnset($offset): void + public function offsetUnset($offset): void // phpcs:ignore { $this->remove($offset); } /** - * @inheritDoc + * @return integer */ public function count(): int { @@ -283,7 +276,7 @@ public function merge(Config $mergeConfig): self } /** - * @param bool $debug + * @param boolean $debug * @return $this */ public function setDebug(bool $debug): self @@ -293,7 +286,7 @@ public function setDebug(bool $debug): self } /** - * @return bool + * @return boolean */ public function getDebug(): bool { @@ -313,9 +306,8 @@ public function getFailoverUrl(): string /** * Set destination(core) url - * * @param string $url - * @return void + * @return $this */ public function setCore(string $url): self { @@ -356,12 +348,14 @@ public function setUsername(string $username): self } /** - * @return bool + * @return boolean */ public function isEmpty() { - if (empty($this->data['authentication']['password']) || - empty($this->data['authentication']['username'])) { + if ( + empty($this->data['authentication']['password']) || + empty($this->data['authentication']['username']) + ) { return true; } return false; @@ -405,8 +399,4 @@ public static function getConfig() } return self::$configObject; } - } - - - From 4a2f198e05b93e14834dd15229a7074490032cc5 Mon Sep 17 00:00:00 2001 From: Wouter Jonker Date: Fri, 31 Jan 2025 18:57:50 +0100 Subject: [PATCH 09/18] Update Config.php --- src/Config/Config.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Config/Config.php b/src/Config/Config.php index fef78fc..7b0ae1b 100644 --- a/src/Config/Config.php +++ b/src/Config/Config.php @@ -17,9 +17,9 @@ */ class Config implements Countable, Iterator, ArrayAccess { - protected const TGU1 = 'https://connect.pay.nl'; - protected const TGU2 = 'https://connect.payments.nl'; - protected const TGU3 = 'https://connect.achterelkebetaling.nl'; + public const TGU1 = 'https://connect.pay.nl'; + public const TGU2 = 'https://connect.payments.nl'; + public const TGU3 = 'https://connect.achterelkebetaling.nl'; protected array $data = []; private static Config $configObject; From 891dc43e7a06d78c352ff2046986ca8ed1fafee8 Mon Sep 17 00:00:00 2001 From: woutse Date: Fri, 31 Jan 2025 18:59:35 +0100 Subject: [PATCH 10/18] Updates for unit tests --- src/Config/Config.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Config/Config.php b/src/Config/Config.php index fef78fc..7b0ae1b 100644 --- a/src/Config/Config.php +++ b/src/Config/Config.php @@ -17,9 +17,9 @@ */ class Config implements Countable, Iterator, ArrayAccess { - protected const TGU1 = 'https://connect.pay.nl'; - protected const TGU2 = 'https://connect.payments.nl'; - protected const TGU3 = 'https://connect.achterelkebetaling.nl'; + public const TGU1 = 'https://connect.pay.nl'; + public const TGU2 = 'https://connect.payments.nl'; + public const TGU3 = 'https://connect.achterelkebetaling.nl'; protected array $data = []; private static Config $configObject; From ab1e3aa5ca715d312f128a0ecc0293f341a3c460 Mon Sep 17 00:00:00 2001 From: Wouter Jonker Date: Fri, 31 Jan 2025 19:52:13 +0100 Subject: [PATCH 11/18] Update Exchange.php --- src/Util/Exchange.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Util/Exchange.php b/src/Util/Exchange.php index cae6240..248e5d3 100644 --- a/src/Util/Exchange.php +++ b/src/Util/Exchange.php @@ -142,7 +142,7 @@ public function getPayLoad() } else { $rawBody = file_get_contents('php://input'); if (empty(trim($rawBody))) { - throw new Exception('Empty payload', 8002); + throw new Exception('Empty or incomplete payload', 8002); } $tguData = json_decode($rawBody, true, 512, 4194304); @@ -326,4 +326,4 @@ private function getRequestHeaders() return $this->headers; } -} \ No newline at end of file +} From f9e4030ad2fce4093f4bcca5b7f452ad9e64412a Mon Sep 17 00:00:00 2001 From: woutse Date: Sat, 1 Feb 2025 14:32:32 +0100 Subject: [PATCH 12/18] Updates for unit tests --- composer.json | 3 +- src/Config/Config.php | 18 ++++----- src/Model/Order.php | 10 +++++ src/Resources/functions/misc.php | 30 +++++++++++++++ src/Util/Exchange.php | 2 +- src/Util/Misc.php | 65 ++++++++++++++++++++++++++++++-- src/Util/Text.php | 32 ---------------- 7 files changed, 113 insertions(+), 47 deletions(-) create mode 100644 src/Resources/functions/misc.php diff --git a/composer.json b/composer.json index 60a934f..9e91e0b 100644 --- a/composer.json +++ b/composer.json @@ -36,7 +36,8 @@ }, "files": [ "./src/Resources/functions/text.php", - "./src/Resources/functions/vat.php" + "./src/Resources/functions/vat.php", + "./src/Resources/functions/misc.php" ] }, "autoload-dev": { diff --git a/src/Config/Config.php b/src/Config/Config.php index 7b0ae1b..a718991 100644 --- a/src/Config/Config.php +++ b/src/Config/Config.php @@ -70,7 +70,7 @@ public function get(mixed $key, mixed $default = null) * @param string|integer $key * @return mixed|null */ - public function __get($key) // phpcs:ignore + public function __get(string|int $key) { return $this->get($key); } @@ -94,7 +94,7 @@ public function set(mixed $key, mixed $value): void * @param mixed $value * @return void */ - public function __set($key, $value): void // phpcs:ignore + public function __set(mixed $key, mixed $value): void { $this->set($key, $value); } @@ -104,7 +104,7 @@ public function __set($key, $value): void // phpcs:ignore * * @return void */ - public function remove($key): void + public function remove(string|int $key): void { if (true === $this->has($key)) { unset($this->data[$key]); @@ -116,7 +116,7 @@ public function remove($key): void * * @return void */ - public function __unset($key): void + public function __unset(string|int $key): void { $this->remove($key); } @@ -126,7 +126,7 @@ public function __unset($key): void * * @return boolean */ - public function has($key): bool + public function has(string|int $key): bool { return isset($this->data[$key]); } @@ -136,7 +136,7 @@ public function has($key): bool * * @return boolean */ - public function __isset($key): bool + public function __isset(string|int $key): bool { return $this->has($key); } @@ -209,7 +209,7 @@ public function rewind(): void * @param mixed $offset * @return boolean */ - public function offsetExists($offset): bool // phpcs:ignore + public function offsetExists(mixed $offset): bool { return $this->has($offset); } @@ -228,7 +228,7 @@ public function offsetGet(mixed $offset): mixed * @param mixed $value * @return void */ - public function offsetSet($offset, $value): void // phpcs:ignore + public function offsetSet(mixed $offset, mixed $value): void { $this->set($offset, $value); } @@ -237,7 +237,7 @@ public function offsetSet($offset, $value): void // phpcs:ignore * @param mixed $offset * @return void */ - public function offsetUnset($offset): void // phpcs:ignore + public function offsetUnset(mixed $offset): void { $this->remove($offset); } diff --git a/src/Model/Order.php b/src/Model/Order.php index 8bfd5ef..f89e5d7 100644 --- a/src/Model/Order.php +++ b/src/Model/Order.php @@ -150,6 +150,16 @@ public function setDeliveryAddress(Address $deliveryAddress): self return $this; } + /** + * Alias for setDeliveryAddress + * @param Address $shippingAddress + * @return $this + */ + public function setShippingAddress(Address $shippingAddress): self + { + return $this->setDeliveryAddress($shippingAddress); + } + /** * @return Address */ diff --git a/src/Resources/functions/misc.php b/src/Resources/functions/misc.php new file mode 100644 index 0000000..eec9c09 --- /dev/null +++ b/src/Resources/functions/misc.php @@ -0,0 +1,30 @@ +splitAddress($address); + } +} + +if (false === function_exists('paynl_get_ip')) { + /** + * @param string $address + * + * @return array + */ + function paynl_get_ip(): array + { + return (new Misc())->getIp(); + } +} + diff --git a/src/Util/Exchange.php b/src/Util/Exchange.php index cae6240..33bb7b9 100644 --- a/src/Util/Exchange.php +++ b/src/Util/Exchange.php @@ -145,7 +145,7 @@ public function getPayLoad() throw new Exception('Empty payload', 8002); } - $tguData = json_decode($rawBody, true, 512, 4194304); + $tguData = json_decode($rawBody, true, 512, JSON_BIGINT_AS_STRING); $exchangeType = $tguData['type'] ?? null; if ($exchangeType != 'order') { diff --git a/src/Util/Misc.php b/src/Util/Misc.php index 677cef5..7691a42 100644 --- a/src/Util/Misc.php +++ b/src/Util/Misc.php @@ -20,14 +20,14 @@ class Misc /** * @param string $file * - * @throws InvalidArgumentException when given file can not be found or read + * @return string * @throws LogicException when the class name is not the same as the terminating class file name * (PSR-4 3.3 - https://www.php-fig.org/psr/psr-4/) * * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.CyclomaticComplexity) * - * @return string + * @throws InvalidArgumentException when given file can not be found or read */ public static function getClassNameByFile(string $file): string { @@ -73,9 +73,9 @@ public static function getClassNameByFile(string $file): string } if ($tokens[$counter][0] === T_CLASS) { - for ($nextCounter = $counter+1; $nextCounter < $tokenCount; $nextCounter++) { + for ($nextCounter = $counter + 1; $nextCounter < $tokenCount; $nextCounter++) { if ($tokens[$nextCounter] === '{') { - $class = $tokens[$counter+2][1]; + $class = $tokens[$counter + 2][1]; } } } @@ -107,4 +107,61 @@ public static function getClassNameByFQN(string $fqn): string $parts = explode($namespaceSeparator, $fqn); return array_pop($parts) ?? ''; } + + /** + * Get the IP of the user + * + * @return mixed + */ + public function getIp() + { + // Use $_SERVER or get the headers if we can + $headers = $_SERVER; + if (function_exists('apache_request_headers')) { + $headers = apache_request_headers(); + } + + // Get the forwarded IP if it exists + $the_ip = $_SERVER['REMOTE_ADDR']; + if (array_key_exists('X-Forwarded-For', $headers)) { + $the_ip = $headers['X-Forwarded-For']; + } elseif (array_key_exists('HTTP_X_FORWARDED_FOR', $headers)) { + $the_ip = $headers['HTTP_X_FORWARDED_FOR']; + } + $arrIp = explode(',', $the_ip); + + return filter_var(trim(trim(!empty($arrIp[0]) ? $arrIp[0] : ''), '[]'), FILTER_VALIDATE_IP); + } + + /** + * @param string $address + * + * @return array + */ + public function splitAddress(string $address): array + { + $street = $number = ''; + + $address = trim($address); + $addressParts = preg_split('/(\s+)(\d+)/', $address, 2, PREG_SPLIT_DELIM_CAPTURE); + + if (true === is_array($addressParts)) { + $street = trim(array_shift($addressParts) ?? ''); + $number = trim(implode('', $addressParts)); + } + + if (true === empty($street) || true === empty($number)) { + $addressParts = preg_split('/([A-z]{2,})/', $address, 2, PREG_SPLIT_DELIM_CAPTURE); + + if (true === is_array($addressParts)) { + $number = trim(array_shift($addressParts) ?? ''); + $street = trim(implode('', $addressParts)); + } + } + + $number = substr($number, 0, 45); + + return compact('street', 'number'); + } + } diff --git a/src/Util/Text.php b/src/Util/Text.php index ec8f836..d83c206 100644 --- a/src/Util/Text.php +++ b/src/Util/Text.php @@ -13,38 +13,6 @@ */ class Text { - - - /** - * @param string $address - * - * @return array - */ - public function splitAddress(string $address): array - { - $street = $number = ''; - - $address = trim($address); - $addressParts = preg_split('/(\s+)(\d+)/', $address, 2, PREG_SPLIT_DELIM_CAPTURE); - - if (true === is_array($addressParts)) { - $street = trim(array_shift($addressParts) ?? ''); - $number = trim(implode('', $addressParts)); - } - - if (true === empty($street) || true === empty($number)) { - $addressParts = preg_split('/([A-z]{2,})/', $address, 2, PREG_SPLIT_DELIM_CAPTURE); - - if (true === is_array($addressParts)) { - $number = trim(array_shift($addressParts) ?? ''); - $street = trim(implode('', $addressParts)); - } - } - - $number = substr($number, 0, 45); - - return compact('street', 'number'); - } /** * @param $errorMessage From 2aa691a76b39942c9f0ae0ed4f17e1f825b9a7c6 Mon Sep 17 00:00:00 2001 From: woutse Date: Sat, 1 Feb 2025 14:32:41 +0100 Subject: [PATCH 13/18] Updates for unit tests --- src/Resources/functions/text.php | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/Resources/functions/text.php b/src/Resources/functions/text.php index 9426642..baa3018 100644 --- a/src/Resources/functions/text.php +++ b/src/Resources/functions/text.php @@ -4,19 +4,6 @@ use PayNL\Sdk\Util\Text; -if (false === function_exists('paynl_split_address')) { - /** - * @param string $address - * - * @return array - */ - function paynl_split_address(string $address): array - { - return (new Text())->splitAddress($address); - } -} - - if (false === function_exists('dbg')) { /** * @param string $message From ff4f32d93b15eab5534590270a11fdcd67caecb1 Mon Sep 17 00:00:00 2001 From: woutse Date: Sat, 1 Feb 2025 15:26:44 +0100 Subject: [PATCH 14/18] Updates for unit tests --- src/Resources/functions/misc.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Resources/functions/misc.php b/src/Resources/functions/misc.php index eec9c09..abd1249 100644 --- a/src/Resources/functions/misc.php +++ b/src/Resources/functions/misc.php @@ -18,11 +18,9 @@ function paynl_split_address(string $address): array if (false === function_exists('paynl_get_ip')) { /** - * @param string $address - * - * @return array + * @return mixed */ - function paynl_get_ip(): array + function paynl_get_ip(): mixed { return (new Misc())->getIp(); } From 5e34057eb28e4fcd30f192d33d04a3540a9d20ae Mon Sep 17 00:00:00 2001 From: woutse Date: Mon, 3 Feb 2025 11:56:09 +0100 Subject: [PATCH 15/18] Code polish --- src/Model/Order.php | 2 +- src/Resources/functions/misc.php | 1 - src/Resources/functions/text.php | 2 +- src/Util/Misc.php | 1 - src/Util/Text.php | 7 +++---- 5 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/Model/Order.php b/src/Model/Order.php index f89e5d7..3476dba 100644 --- a/src/Model/Order.php +++ b/src/Model/Order.php @@ -4,7 +4,7 @@ namespace PayNL\Sdk\Model; -use JsonSerializable, DateTime; +use JsonSerializable; use PayNL\Sdk\Common\JsonSerializeTrait; /** diff --git a/src/Resources/functions/misc.php b/src/Resources/functions/misc.php index abd1249..eb273ab 100644 --- a/src/Resources/functions/misc.php +++ b/src/Resources/functions/misc.php @@ -25,4 +25,3 @@ function paynl_get_ip(): mixed return (new Misc())->getIp(); } } - diff --git a/src/Resources/functions/text.php b/src/Resources/functions/text.php index baa3018..e3f97ec 100644 --- a/src/Resources/functions/text.php +++ b/src/Resources/functions/text.php @@ -15,4 +15,4 @@ function dbg(string $message): void displayPayDebug($message); } } -} \ No newline at end of file +} diff --git a/src/Util/Misc.php b/src/Util/Misc.php index 7691a42..6756208 100644 --- a/src/Util/Misc.php +++ b/src/Util/Misc.php @@ -163,5 +163,4 @@ public function splitAddress(string $address): array return compact('street', 'number'); } - } diff --git a/src/Util/Text.php b/src/Util/Text.php index d83c206..acba9a6 100644 --- a/src/Util/Text.php +++ b/src/Util/Text.php @@ -1,6 +1,6 @@ 'Transaction not ready for refund.', From 7c82a3c03d2f959e3ca1e56862ccbbc5740eb134 Mon Sep 17 00:00:00 2001 From: woutse Date: Mon, 3 Feb 2025 12:08:13 +0100 Subject: [PATCH 16/18] Code polish --- src/Model/Method.php | 7 ++-- src/Model/Pay/PayLoad.php | 12 +++++- src/Model/Pay/PayStatus.php | 5 ++- src/Resources/functions/misc.php | 1 + src/Util/Exchange.php | 64 ++++++++++++++++++++++++++------ src/Util/ExchangeResponse.php | 36 ++++++++++++++++++ src/Util/Misc.php | 1 + 7 files changed, 108 insertions(+), 18 deletions(-) create mode 100644 src/Util/ExchangeResponse.php diff --git a/src/Model/Method.php b/src/Model/Method.php index 2c61031..9f13aaf 100644 --- a/src/Model/Method.php +++ b/src/Model/Method.php @@ -11,9 +11,10 @@ */ class Method implements ModelInterface { - const IDEAL = 10; - const PIN = 1927; - const PAYPAL = 138; + public const IDEAL = 10; + public const PIN = 1927; + public const PAYPAL = 138; + public const RETOURPIN = 2351; /** * @var int diff --git a/src/Model/Pay/PayLoad.php b/src/Model/Pay/PayLoad.php index 3cd394d..f8f55e1 100644 --- a/src/Model/Pay/PayLoad.php +++ b/src/Model/Pay/PayLoad.php @@ -64,7 +64,7 @@ public function getReference() { return $this->reference; } - + /** * @return array */ @@ -145,4 +145,12 @@ public function getPaymentProfile(): int return $this->paymentProfile; } -} \ No newline at end of file + /** + * @return array + */ + public function getCheckoutData(): array + { + return $this->checkoutData; + } + +} diff --git a/src/Model/Pay/PayStatus.php b/src/Model/Pay/PayStatus.php index ad0e91e..ace7001 100644 --- a/src/Model/Pay/PayStatus.php +++ b/src/Model/Pay/PayStatus.php @@ -28,6 +28,9 @@ class PayStatus const EVENT_PAID = 'new_ppt'; const EVENT_PENDING = 'pending'; + const EVENT_CHARGEBACK = 'chargeback'; + const EVENT_REFUND = 'retund'; + const EVENT_CAPTURE = 'capture'; /** * @param int $stateId @@ -69,4 +72,4 @@ public function get(int $stateId) } } -} \ No newline at end of file +} diff --git a/src/Resources/functions/misc.php b/src/Resources/functions/misc.php index eb273ab..abd1249 100644 --- a/src/Resources/functions/misc.php +++ b/src/Resources/functions/misc.php @@ -25,3 +25,4 @@ function paynl_get_ip(): mixed return (new Misc())->getIp(); } } + diff --git a/src/Util/Exchange.php b/src/Util/Exchange.php index 63d8545..e9b9715 100644 --- a/src/Util/Exchange.php +++ b/src/Util/Exchange.php @@ -7,6 +7,7 @@ use PayNL\Sdk\Config\Config as PayConfig; use PayNL\Sdk\Config\Config; use PayNL\Sdk\Model\Amount; +use PayNL\Sdk\Util\ExchangeResponse; use PayNL\Sdk\Model\Request\OrderStatusRequest; use PayNL\Sdk\Model\Pay\PayStatus; use PayNL\Sdk\Model\Pay\PayOrder; @@ -36,10 +37,38 @@ public function __construct(array $payload = null) /** * @return bool + * @throws PayException */ - public function eventStateChangeToPaid() + public function eventPaid($includeAuth = false) { - return $this->getAction() === PayStatus::EVENT_PAID; + return $this->getAction() === PayStatus::EVENT_PAID || ($includeAuth == true && $this->getAction() === PayStatus::AUTHORIZE); + } + + /** + * @return bool + * @throws PayException + */ + public function eventChargeback() + { + return substr($this->getAction(), 0, 10) === PayStatus::EVENT_CHARGEBACK; + } + + /** + * @return bool + * @throws PayException + */ + public function eventRefund() + { + return substr($this->getAction(), 0, 6) === PayStatus::EVENT_REFUND; + } + + /** + * @return bool + * @throws PayException + */ + public function eventCapture() + { + return $this->getAction() == PayStatus::EVENT_CAPTURE; } /** @@ -50,8 +79,10 @@ public function eventStateChangeToPaid() * @param bool $returnOutput If true, then this method returs the output string * @return false|string|void */ - public function setResponse(bool $result, string $message, $returnOutput = false) + public function setResponse(bool $result, string $message, bool $returnOutput = false) { + $message = ucfirst(strtolower($message)); + if ($this->isSignExchange() === true) { $response = json_encode(['result' => $result, 'description' => $message]); } else { @@ -66,41 +97,54 @@ public function setResponse(bool $result, string $message, $returnOutput = false } } + /** + * @param \PayNL\Sdk\Util\ExchangeResponse $e + * @param bool $returnOutput + * @return false|string|null + */ + public function setExchangeResponse(ExchangeResponse $e, bool $returnOutput = false) + { + return $this->setResponse($e->getResult(), $e->getMessage(), $returnOutput); + } + /** * @return string + * @throws PayException */ public function getAction() { try { $payload = $this->getPayload(); } catch (\Throwable $e) { - return false; + throw new PayException('Could not retrieve action: ' . $e->getMessage()); } return $payload->getAction(); } /** - * @return mixed|string + * @return string + * @throws PayException */ public function getReference() { try { $payload = $this->getPayload(); } catch (\Throwable $e) { - return false; + throw new PayException('Could not retrieve reference: ' . $e->getMessage()); } return $payload->getReference(); } /** * @return string + * @throws PayException */ public function getPayOrderId() { try { $payload = $this->getPayload(); } catch (\Throwable $e) { - return false; + throw new Exception('Could not retrieve payOrderId: ' . $e->getMessage()); } return $payload->getPayOrderId(); } @@ -146,11 +190,6 @@ public function getPayLoad() } $tguData = json_decode($rawBody, true, 512, JSON_BIGINT_AS_STRING); - - $exchangeType = $tguData['type'] ?? null; - if ($exchangeType != 'order') { - throw new Exception('Cant handle exchange type other then order', 8003); - } } if (empty($tguData['object'])) { @@ -236,6 +275,7 @@ public function process(PayConfig $config = null): PayOrder # Not a signing request... if ($payloadState === PayStatus::PENDING) { $payOrder = new PayOrder(); + $payOrder->setType($payload->getType()); $payOrder->setStatusCodeName(PayStatus::PENDING, 'PENDING'); } else { # Continue to check the order status manually diff --git a/src/Util/ExchangeResponse.php b/src/Util/ExchangeResponse.php new file mode 100644 index 0000000..8668b71 --- /dev/null +++ b/src/Util/ExchangeResponse.php @@ -0,0 +1,36 @@ +result = $result; + $this->message = $message; + } + + /** + * @return bool + */ + public function getResult(): bool + { + return $this->result; + + } + + /** + * @return string + */ + public function getMessage(): string + { + return $this->message; + } +} diff --git a/src/Util/Misc.php b/src/Util/Misc.php index 6756208..7691a42 100644 --- a/src/Util/Misc.php +++ b/src/Util/Misc.php @@ -163,4 +163,5 @@ public function splitAddress(string $address): array return compact('street', 'number'); } + } From 09edaae4b5068a292e15910348c0cdacd872e773 Mon Sep 17 00:00:00 2001 From: woutse Date: Mon, 3 Feb 2025 12:11:10 +0100 Subject: [PATCH 17/18] Code polish --- src/Util/Exchange.php | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/Util/Exchange.php b/src/Util/Exchange.php index e9b9715..9c54cc8 100644 --- a/src/Util/Exchange.php +++ b/src/Util/Exchange.php @@ -25,7 +25,7 @@ class Exchange { private PayLoad $payload; private ?array $custom_payload; - private $headers; + private string $headers; /** * @param array|null $payload @@ -36,25 +36,26 @@ public function __construct(array $payload = null) } /** - * @return bool + * @param boolean $includeAuth If yes, treat authorize as "paid" + * @return boolean * @throws PayException */ - public function eventPaid($includeAuth = false) + public function eventPaid(bool $includeAuth = false): bool { return $this->getAction() === PayStatus::EVENT_PAID || ($includeAuth == true && $this->getAction() === PayStatus::AUTHORIZE); } /** - * @return bool + * @return boolean * @throws PayException */ - public function eventChargeback() + public function eventChargeback(): bool { return substr($this->getAction(), 0, 10) === PayStatus::EVENT_CHARGEBACK; } /** - * @return bool + * @return boolean * @throws PayException */ public function eventRefund() @@ -63,7 +64,7 @@ public function eventRefund() } /** - * @return bool + * @return boolean * @throws PayException */ public function eventCapture() @@ -74,9 +75,9 @@ public function eventCapture() /** * Set your exchange response in the end of your exchange processing * - * @param bool $result + * @param boolean $result * @param string $message - * @param bool $returnOutput If true, then this method returs the output string + * @param boolean $returnOutput If true, then this method returs the output string * @return false|string|void */ public function setResponse(bool $result, string $message, bool $returnOutput = false) @@ -99,7 +100,7 @@ public function setResponse(bool $result, string $message, bool $returnOutput = /** * @param \PayNL\Sdk\Util\ExchangeResponse $e - * @param bool $returnOutput + * @param boolean $returnOutput * @return false|string|null */ public function setExchangeResponse(ExchangeResponse $e, bool $returnOutput = false) @@ -294,7 +295,6 @@ public function process(PayConfig $config = null): PayOrder } $payOrder = $request->setConfig($config)->start(); - } catch (PayException $e) { dbg($e->getMessage()); throw new Exception('API Retrieval error: ' . $e->getFriendlyMessage()); @@ -308,7 +308,7 @@ public function process(PayConfig $config = null): PayOrder /** * @param string $username Token code * @param string $password API Token - * @return bool Returns true if the signing is successful and authorised + * @return boolean Returns true if the signing is successful and authorised */ public function checkSignExchange(string $username = '', string $password = ''): bool { @@ -346,7 +346,7 @@ public function checkSignExchange(string $username = '', string $password = ''): } /** - * @return bool + * @return boolean */ public function isSignExchange(): bool { @@ -358,12 +358,11 @@ public function isSignExchange(): bool /** * @return array|false|string */ - private function getRequestHeaders() + private function getRequestHeaders(): bool|array|string { if (empty($this->headers)) { $this->headers = array_change_key_case(getallheaders()); } return $this->headers; } - } From cf8e1bac284b3571da268992069fe5820c7bfcff Mon Sep 17 00:00:00 2001 From: woutse Date: Mon, 3 Feb 2025 12:30:55 +0100 Subject: [PATCH 18/18] Code polish --- src/Model/Method.php | 29 ++++++++++++++----------- src/Model/Pay/PayLoad.php | 9 ++++---- src/Model/Pay/PayStatus.php | 37 ++++++++++++++++---------------- src/Resources/functions/misc.php | 1 - src/Resources/functions/text.php | 4 +--- src/Util/ExchangeResponse.php | 5 ++--- src/Util/Misc.php | 1 - 7 files changed, 42 insertions(+), 44 deletions(-) diff --git a/src/Model/Method.php b/src/Model/Method.php index 9f13aaf..9c305ed 100644 --- a/src/Model/Method.php +++ b/src/Model/Method.php @@ -62,7 +62,7 @@ class Method implements ModelInterface protected $maxAmount; /** - * @return int + * @return integer */ public function getId(): int { @@ -70,7 +70,7 @@ public function getId(): int } /** - * @param int $id + * @param integer $id * @return $this */ public function setId(int $id): self @@ -80,15 +80,15 @@ public function setId(int $id): self } /** - * @param $language + * @param string|null $language * @return string */ - public function getName($language = null): string + public function getName(string $language = null): string { if (!empty($language) && isset($this->translations['name'][$language])) { return $this->translations['name'][$language]; } - return (string)$this->name; + return $this->name; } /** @@ -173,16 +173,19 @@ public function setSettings(array $settings): self return $this; } + /** + * @return boolean + */ public function hasOptions(): bool { return !empty($this->options); } /** - * @param $language + * @param string|null $language * @return string */ - public function getDescription($language = null): string + public function getDescription(string $language = null): string { if (!empty($language)) { if (isset($this->translations['description'][$language])) { @@ -204,7 +207,7 @@ public function getDescription($language = null): string /** * @param string $description - * @return void + * @return $this */ public function setDescription(string $description): self { @@ -213,7 +216,7 @@ public function setDescription(string $description): self } /** - * @return int + * @return integer */ public function getMinAmount(): int { @@ -221,7 +224,8 @@ public function getMinAmount(): int } /** - * @param int $minAmount + * @param integer $minAmount + * @return $this */ public function setMinAmount(int $minAmount): self { @@ -230,7 +234,7 @@ public function setMinAmount(int $minAmount): self } /** - * @return int + * @return integer */ public function getMaxAmount(): int { @@ -238,7 +242,8 @@ public function getMaxAmount(): int } /** - * @param int $maxAmount + * @param integer $maxAmount + * @return $this */ public function setMaxAmount(int $maxAmount): self { diff --git a/src/Model/Pay/PayLoad.php b/src/Model/Pay/PayLoad.php index f8f55e1..5de2eaf 100644 --- a/src/Model/Pay/PayLoad.php +++ b/src/Model/Pay/PayLoad.php @@ -74,7 +74,7 @@ public function getFullPayLoad(): array } /** - * @return int + * @return integer */ public function getInternalStateId(): int { @@ -100,13 +100,13 @@ public function getPayOrderId(): string /** * @return string */ - public function nce(): string + public function nce(): string { return $this->reference; } /** - * @return int + * @return integer */ public function getAmount(): int { @@ -138,7 +138,7 @@ public function getAmountAuth(): float } /** - * @return int + * @return integer */ public function getPaymentProfile(): int { @@ -152,5 +152,4 @@ public function getCheckoutData(): array { return $this->checkoutData; } - } diff --git a/src/Model/Pay/PayStatus.php b/src/Model/Pay/PayStatus.php index ace7001..45b7eeb 100644 --- a/src/Model/Pay/PayStatus.php +++ b/src/Model/Pay/PayStatus.php @@ -14,31 +14,31 @@ */ class PayStatus { - const PENDING = 20; - const PAID = 100; - const AUTHORIZE = 95; - const CANCEL = -1; - const REFUND = -81; - const VERIFY = 85; - const PARTIAL_PAYMENT = 80; - const CHARGEBACK = -71; - const PARTIAL_REFUND = -82; - const PARTLY_CAPTURED = 97; - const CONFIRMED = 75; + public const PENDING = 20; + public const PAID = 100; + public const AUTHORIZE = 95; + public const CANCEL = -1; + public const REFUND = -81; + public const VERIFY = 85; + public const PARTIAL_PAYMENT = 80; + public const CHARGEBACK = -71; + public const PARTIAL_REFUND = -82; + public const PARTLY_CAPTURED = 97; + public const CONFIRMED = 75; - const EVENT_PAID = 'new_ppt'; - const EVENT_PENDING = 'pending'; - const EVENT_CHARGEBACK = 'chargeback'; - const EVENT_REFUND = 'retund'; - const EVENT_CAPTURE = 'capture'; + public const EVENT_PAID = 'new_ppt'; + public const EVENT_PENDING = 'pending'; + public const EVENT_CHARGEBACK = 'chargeback'; + public const EVENT_REFUND = 'retund'; + public const EVENT_CAPTURE = 'capture'; /** - * @param int $stateId + * @param integer $stateId * * Source: * https://developer.pay.nl/docs/transaction-statuses#processing-statusses * - * @return int|mixed + * @return integer|mixed * @throws Exception */ public function get(int $stateId) @@ -71,5 +71,4 @@ public function get(int $stateId) } } } - } diff --git a/src/Resources/functions/misc.php b/src/Resources/functions/misc.php index abd1249..eb273ab 100644 --- a/src/Resources/functions/misc.php +++ b/src/Resources/functions/misc.php @@ -25,4 +25,3 @@ function paynl_get_ip(): mixed return (new Misc())->getIp(); } } - diff --git a/src/Resources/functions/text.php b/src/Resources/functions/text.php index e3f97ec..3f3baab 100644 --- a/src/Resources/functions/text.php +++ b/src/Resources/functions/text.php @@ -2,12 +2,10 @@ declare(strict_types=1); -use PayNL\Sdk\Util\Text; - if (false === function_exists('dbg')) { /** * @param string $message - * @return string + * @return void */ function dbg(string $message): void { diff --git a/src/Util/ExchangeResponse.php b/src/Util/ExchangeResponse.php index 8668b71..d235b4f 100644 --- a/src/Util/ExchangeResponse.php +++ b/src/Util/ExchangeResponse.php @@ -8,7 +8,7 @@ class ExchangeResponse private string $message; /** - * @param bool $result + * @param boolean $result * @param string $message */ public function __construct(bool $result, string $message) @@ -18,12 +18,11 @@ public function __construct(bool $result, string $message) } /** - * @return bool + * @return boolean */ public function getResult(): bool { return $this->result; - } /** diff --git a/src/Util/Misc.php b/src/Util/Misc.php index 7691a42..6756208 100644 --- a/src/Util/Misc.php +++ b/src/Util/Misc.php @@ -163,5 +163,4 @@ public function splitAddress(string $address): array return compact('street', 'number'); } - }