diff --git a/Tests/Unit/OrderAbortRequestTest.php b/Tests/Unit/OrderAbortRequestTest.php new file mode 100644 index 0000000..d7a42be --- /dev/null +++ b/Tests/Unit/OrderAbortRequestTest.php @@ -0,0 +1,72 @@ +assertInstanceOf(OrderAbortRequest::class, $orderAbortRequest); + } + + /** + * @return void + */ + 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']); + } + + /** + * @return void + */ + public function testGetBodyParameters(): void + { + $transactionId = '123456'; + $orderAbortRequest = new OrderAbortRequest($transactionId); + + $bodyParameters = $orderAbortRequest->getBodyParameters(); + + $this->assertIsArray($bodyParameters); + $this->assertEmpty($bodyParameters); + } + + /** + * @return void + * @throws \PHPUnit\Framework\MockObject\Exception + * @throws \PayNL\Sdk\Exception\PayException + */ + 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); + } +} diff --git a/Tests/Unit/OrderApproveRequestTest.php b/Tests/Unit/OrderApproveRequestTest.php new file mode 100644 index 0000000..367bd9c --- /dev/null +++ b/Tests/Unit/OrderApproveRequestTest.php @@ -0,0 +1,72 @@ +assertInstanceOf(OrderApproveRequest::class, $orderApproveRequest); + } + + /** + * @return void + */ + 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']); + } + + /** + * @return void + */ + public function testGetBodyParameters(): void + { + $transactionId = '123456'; + $orderApproveRequest = new OrderApproveRequest($transactionId); + + $bodyParameters = $orderApproveRequest->getBodyParameters(); + + $this->assertIsArray($bodyParameters); + $this->assertEmpty($bodyParameters); + } + + /** + * @return void + * @throws \PHPUnit\Framework\MockObject\Exception + * @throws \PayNL\Sdk\Exception\PayException + */ + 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); + } +} diff --git a/Tests/Unit/OrderCaptureRequestTest.php b/Tests/Unit/OrderCaptureRequestTest.php new file mode 100644 index 0000000..eed0e68 --- /dev/null +++ b/Tests/Unit/OrderCaptureRequestTest.php @@ -0,0 +1,124 @@ +assertInstanceOf(OrderCaptureRequest::class, $orderCaptureRequest); + } + + /** + * @return void + */ + 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']); + } + + /** + * @return void + */ + 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']); + } + + /** + * @return void + */ + 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']); + } + + /** + * @return void + * @throws \PHPUnit\Framework\MockObject\Exception + * @throws \PayNL\Sdk\Exception\PayException + */ + 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); + } + + /** + * @return void + * @throws \PHPUnit\Framework\MockObject\Exception + * @throws \PayNL\Sdk\Exception\PayException + */ + 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); + } +} diff --git a/Tests/Unit/OrderCreateRequestTest.php b/Tests/Unit/OrderCreateRequestTest.php new file mode 100644 index 0000000..3c0746f --- /dev/null +++ b/Tests/Unit/OrderCreateRequestTest.php @@ -0,0 +1,191 @@ +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)); + } + + /** + * @return void + */ + 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)); + } + + /** + * @return void + */ + 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)); + } + + /** + * @return void + * @throws \Exception + */ + 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)); + } + + /** + * @return void + * @throws \Exception + */ + 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'); + } + + /** + * @return void + * @throws \Exception + */ + 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)); + } + + /** + * @return void + * @throws \Exception + */ + 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'); + } + + /** + * @return void + * @throws \Exception + */ + public function testSetNotificationThrowsExceptionForInvalidPushRecipient(): void + { + $this->expectException(\Exception::class); + $this->expectExceptionMessage('Recepient expected to be AD-####-#### code'); + + $request = new OrderCreateRequest(); + $request->setNotification('push', '1234'); + } + + /** + * @return void + * @throws \PHPUnit\Framework\MockObject\Exception + */ + 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)); + } + + /** + * @return void + * @throws \PHPUnit\Framework\MockObject\Exception + */ + 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)); + } + + /** + * @return void + * @throws \PHPUnit\Framework\MockObject\Exception + */ + 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/Unit/OrderStatusRequestTest.php b/Tests/Unit/OrderStatusRequestTest.php new file mode 100644 index 0000000..a46acaf --- /dev/null +++ b/Tests/Unit/OrderStatusRequestTest.php @@ -0,0 +1,66 @@ +assertEquals(['transactionId' => $orderId], $request->getPathParameters()); + } + + /** + * @return void + */ + public function testGetPathParameters(): void + { + $orderId = '67890'; + $request = new OrderStatusRequest($orderId); + + $expected = ['transactionId' => $orderId]; + $this->assertEquals($expected, $request->getPathParameters()); + } + + /** + * @return void + */ + public function testGetBodyParametersReturnsEmptyArray(): void + { + $orderId = '67890'; + $request = new OrderStatusRequest($orderId); + + $this->assertEquals([], $request->getBodyParameters()); + } + + /** + * @return void + * @throws \PHPUnit\Framework\MockObject\Exception + * @throws \PayNL\Sdk\Exception\PayException + */ + 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); + } +} diff --git a/Tests/Unit/ServiceGetConfigRequestTest.php b/Tests/Unit/ServiceGetConfigRequestTest.php new file mode 100644 index 0000000..bb9ebca --- /dev/null +++ b/Tests/Unit/ServiceGetConfigRequestTest.php @@ -0,0 +1,84 @@ +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']); + } + + /** + * @return void + */ + public function testGetPathParametersWithoutServiceId(): void + { + $serviceGetConfigRequest = new ServiceGetConfigRequest(); + + $pathParameters = $serviceGetConfigRequest->getPathParameters(); + + $this->assertIsArray($pathParameters); + $this->assertEmpty($pathParameters); + } + + /** + * @return void + */ + public function testGetBodyParameters(): void + { + $serviceGetConfigRequest = new ServiceGetConfigRequest('service123'); + + $bodyParameters = $serviceGetConfigRequest->getBodyParameters(); + + $this->assertIsArray($bodyParameters); + $this->assertEmpty($bodyParameters); + } + + /** + * @return void + * @throws \PHPUnit\Framework\MockObject\Exception + * @throws \PayNL\Sdk\Exception\PayException + */ + 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); + } +} diff --git a/Tests/Unit/TerminalsBrowseRequestTest.php b/Tests/Unit/TerminalsBrowseRequestTest.php new file mode 100644 index 0000000..14b1004 --- /dev/null +++ b/Tests/Unit/TerminalsBrowseRequestTest.php @@ -0,0 +1,52 @@ +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(); + } + + /** + * @return void + * @throws \PHPUnit\Framework\MockObject\Exception + */ + 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('Something went wrong', $e->getFriendlyMessage()); + } + } +} diff --git a/composer.json b/composer.json index 6f94f63..9e91e0b 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", @@ -22,7 +22,7 @@ "plugins" ], "require-dev": { - "ext-simplexml": "*", + "ext-simplexml": "*", "phpmd/phpmd": "^2", "phpstan/phpstan": "^2", "phpunit/phpunit": "^11", @@ -36,9 +36,15 @@ }, "files": [ "./src/Resources/functions/text.php", - "./src/Resources/functions/vat.php" + "./src/Resources/functions/vat.php", + "./src/Resources/functions/misc.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..a718991 100644 --- a/src/Config/Config.php +++ b/src/Config/Config.php @@ -8,779 +8,395 @@ use Iterator; use ArrayAccess; -if (PHP_VERSION_ID >= 80000) { +/** + * Class Config + * + * @package PayNL\Sdk + * + * @SuppressWarnings(PHPMD.TooManyPublicMethods) + */ +class Config implements Countable, Iterator, ArrayAccess +{ + 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; + /** - * Class Config - * - * @package PayNL\Sdk + * Config constructor. * - * @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; - } - - /** - * @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 - { + * @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); - } - - /** - * @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 void + */ + public function __clone() + { + $data = []; - /** - * @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; + foreach ($this->data as $key => $value) { + if ($value instanceof self) { + $value = clone $value; } - - return $array; + $data[$key] = $value; } - /** - * @inheritDoc - */ - public function current(): mixed - { - return current($this->data); - } + $this->data = $data; + } + /** + * @param mixed $key + * @param mixed $default + * @return mixed|null + */ + public function get(mixed $key, mixed $default = null) + { + return $this->data[$key] ?? $default; + } - /** - * @inheritDoc - * - * @return void - */ - public function next(): void - { - next($this->data); - } + /** + * @param string|integer $key + * @return mixed|null + */ + public function __get(string|int $key) + { + return $this->get($key); + } - /** - * @inheritDoc - * - * @return - */ - public function key(): mixed - { - return key($this->data); + /** + * @param mixed $key + * @param mixed $value + * @return void + */ + public function set(mixed $key, mixed $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 mixed $key + * @param mixed $value + * @return void + */ + public function __set(mixed $key, mixed $value): void + { + $this->set($key, $value); + } - /** - * @inheritDoc - * - * @return bool - */ - public function offsetExists($offset): bool - { - return $this->has($offset); + /** + * @param string|integer $key + * + * @return void + */ + public function remove(string|int $key): void + { + if (true === $this->has($key)) { + unset($this->data[$key]); } + } - /** - * @inheritDoc - * - * @return - */ - public function offsetGet($offset): mixed - { - return $this->get($offset); - } + /** + * @param string|integer $key + * + * @return void + */ + public function __unset(string|int $key): void + { + $this->remove($key); + } - /** - * @inheritDoc - * - * @return void - */ - public function offsetSet($offset, $value): void - { - $this->set($offset, $value); - } + /** + * @param string|integer $key + * + * @return boolean + */ + public function has(string|int $key): bool + { + return isset($this->data[$key]); + } - /** - * @inheritDoc - * - * @return void - */ - public function offsetUnset($offset): void - { - $this->remove($offset); - } + /** + * @param string|integer $key + * + * @return boolean + */ + public function __isset(string|int $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; - } + /** + * @return mixed + */ + 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; - } + /** + * @return mixed + */ + public function key(): mixed + { + return key($this->data); + } - /** - * @return string - */ - public function getCore(): string - { - return $this->data['api']['url'] ?? ''; - } + /** + * @inheritDoc + * @return boolean + */ + 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'] ?? ''; - } + /** + * @param mixed $offset + * @return boolean + */ + public function offsetExists(mixed $offset): bool + { + return $this->has($offset); + } - /** - * @param string $password - * @return $this - */ - public function setPassword(string $password): self - { - $this->data['authentication']['password'] = $password; - return $this; - } + /** + * @param mixed $offset + * @return mixed + */ + public function offsetGet(mixed $offset): mixed + { + return $this->get($offset); + } - /** - * @return string - */ - public function getPassword() - { - return $this->data['authentication']['password'] ?? ''; - } + /** + * @param mixed $offset + * @param mixed $value + * @return void + */ + public function offsetSet(mixed $offset, mixed $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; - } + /** + * @param mixed $offset + * @return void + */ + public function offsetUnset(mixed $offset): void + { + $this->remove($offset); + } + /** + * @return integer + */ + 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); - } - - /** - * @inheritDoc - */ - public function count(): int - { - return count($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); - } - return $this; - } + /** + * @param boolean $debug + * @return $this + */ + public function setDebug(bool $debug): self + { + $this->data['debug'] = $debug; + return $this; + } - /** - * @param bool $debug - * @return $this - */ - public function setDebug(bool $debug): self - { - $this->data['debug'] = $debug; - return $this; - } + /** + * @return boolean + */ + public function getDebug(): bool + { + return $this->data['debug'] == 1; + } - /** - * @return bool - */ - public function getDebug(): bool - { - return $this->data['debug'] == 1; + /** + * @return string + */ + public function getFailoverUrl(): string + { + if (!empty($this->data['failoverUrl'])) { + return trim($this->data['failoverUrl']); } + return ''; + } - /** - * @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 $this + */ + public function setCore(string $url): self + { + if (!empty($url)) { + $this->data['api']['url'] = $url; } + 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; - } + /** + * Set version of API URL + * + * @param integer $version + * @return $this + */ + public function setVersion(int $version): self + { + $this->data['api']['version'] = $version; + 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 string + */ + public function getCore(): string + { + return $this->data['api']['url'] ?? ''; + } - /** - * @return string - */ - public function getCore(): string - { - return $this->data['api']['url'] ?? ''; - } + /** + * @param string $username + * @return $this + */ + public function setUsername(string $username): self + { + $this->data['authentication']['username'] = $username; + return $this; + } - /** - * @param string $username - * @return $this - */ - public function setUsername(string $username): self - { - $this->data['authentication']['username'] = $username; - return $this; + /** + * @return boolean + */ + public function isEmpty() + { + if ( + empty($this->data['authentication']['password']) || + empty($this->data['authentication']['username']) + ) { + return true; } + return false; + } - /** - * @return string - */ - public function getUsername() - { - return $this->data['authentication']['username'] ?? ''; - } + /** + * @return string + */ + public function getUsername() + { + return $this->data['authentication']['username'] ?? ''; + } - /** - * @param string $password - * @return $this - */ - public function setPassword(string $password): self - { - $this->data['authentication']['password'] = $password; - return $this; - } + /** + * @param string $password + * @return $this + */ + public function setPassword(string $password): self + { + $this->data['authentication']['password'] = $password; + return $this; + } - /** - * @return string - */ - public function getPassword() - { - return $this->data['authentication']['password'] ?? ''; - } + /** + * @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; + /** + * 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/Model/Method.php b/src/Model/Method.php index 2c61031..9c305ed 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 @@ -61,7 +62,7 @@ class Method implements ModelInterface protected $maxAmount; /** - * @return int + * @return integer */ public function getId(): int { @@ -69,7 +70,7 @@ public function getId(): int } /** - * @param int $id + * @param integer $id * @return $this */ public function setId(int $id): self @@ -79,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; } /** @@ -172,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])) { @@ -203,7 +207,7 @@ public function getDescription($language = null): string /** * @param string $description - * @return void + * @return $this */ public function setDescription(string $description): self { @@ -212,7 +216,7 @@ public function setDescription(string $description): self } /** - * @return int + * @return integer */ public function getMinAmount(): int { @@ -220,7 +224,8 @@ public function getMinAmount(): int } /** - * @param int $minAmount + * @param integer $minAmount + * @return $this */ public function setMinAmount(int $minAmount): self { @@ -229,7 +234,7 @@ public function setMinAmount(int $minAmount): self } /** - * @return int + * @return integer */ public function getMaxAmount(): int { @@ -237,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/Order.php b/src/Model/Order.php index 8bfd5ef..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; /** @@ -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/Model/Pay/PayLoad.php b/src/Model/Pay/PayLoad.php index 3cd394d..5de2eaf 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 */ @@ -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,11 +138,18 @@ public function getAmountAuth(): float } /** - * @return int + * @return integer */ 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..45b7eeb 100644 --- a/src/Model/Pay/PayStatus.php +++ b/src/Model/Pay/PayStatus.php @@ -14,28 +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'; + 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) @@ -68,5 +71,4 @@ public function get(int $stateId) } } } - -} \ No newline at end of file +} diff --git a/src/Request/RequestData.php b/src/Request/RequestData.php index 83a5220..f357fad 100644 --- a/src/Request/RequestData.php +++ b/src/Request/RequestData.php @@ -18,6 +18,7 @@ */ abstract class RequestData implements RequestDataInterface { + protected Application $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 $application + * @return void + */ + public function setApplication(Application $application): void + { + $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())); @@ -95,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; @@ -129,4 +146,4 @@ public function getMethodName(): string { return $this->mapperName; } -} \ No newline at end of file +} diff --git a/src/Resources/functions/misc.php b/src/Resources/functions/misc.php new file mode 100644 index 0000000..eb273ab --- /dev/null +++ b/src/Resources/functions/misc.php @@ -0,0 +1,27 @@ +splitAddress($address); + } +} + +if (false === function_exists('paynl_get_ip')) { + /** + * @return mixed + */ + function paynl_get_ip(): mixed + { + return (new Misc())->getIp(); + } +} diff --git a/src/Resources/functions/text.php b/src/Resources/functions/text.php index 9426642..3f3baab 100644 --- a/src/Resources/functions/text.php +++ b/src/Resources/functions/text.php @@ -2,25 +2,10 @@ declare(strict_types=1); -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 - * @return string + * @return void */ function dbg(string $message): void { @@ -28,4 +13,4 @@ function dbg(string $message): void displayPayDebug($message); } } -} \ No newline at end of file +} diff --git a/src/Util/Exchange.php b/src/Util/Exchange.php index cae6240..9c54cc8 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; @@ -24,7 +25,7 @@ class Exchange { private PayLoad $payload; private ?array $custom_payload; - private $headers; + private string $headers; /** * @param array|null $payload @@ -35,23 +36,54 @@ public function __construct(array $payload = null) } /** - * @return bool + * @param boolean $includeAuth If yes, treat authorize as "paid" + * @return boolean + * @throws PayException */ - public function eventStateChangeToPaid() + public function eventPaid(bool $includeAuth = false): bool { - return $this->getAction() === PayStatus::EVENT_PAID; + return $this->getAction() === PayStatus::EVENT_PAID || ($includeAuth == true && $this->getAction() === PayStatus::AUTHORIZE); + } + + /** + * @return boolean + * @throws PayException + */ + public function eventChargeback(): bool + { + return substr($this->getAction(), 0, 10) === PayStatus::EVENT_CHARGEBACK; + } + + /** + * @return boolean + * @throws PayException + */ + public function eventRefund() + { + return substr($this->getAction(), 0, 6) === PayStatus::EVENT_REFUND; + } + + /** + * @return boolean + * @throws PayException + */ + public function eventCapture() + { + return $this->getAction() == PayStatus::EVENT_CAPTURE; } /** * 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, $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 +98,54 @@ public function setResponse(bool $result, string $message, $returnOutput = false } } + /** + * @param \PayNL\Sdk\Util\ExchangeResponse $e + * @param boolean $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(); } @@ -142,15 +187,10 @@ 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); - - $exchangeType = $tguData['type'] ?? null; - if ($exchangeType != 'order') { - throw new Exception('Cant handle exchange type other then order', 8003); - } + $tguData = json_decode($rawBody, true, 512, JSON_BIGINT_AS_STRING); } if (empty($tguData['object'])) { @@ -236,6 +276,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 @@ -254,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()); @@ -268,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 { @@ -306,7 +346,7 @@ public function checkSignExchange(string $username = '', string $password = ''): } /** - * @return bool + * @return boolean */ public function isSignExchange(): bool { @@ -318,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; } - -} \ No newline at end of file +} diff --git a/src/Util/ExchangeResponse.php b/src/Util/ExchangeResponse.php new file mode 100644 index 0000000..d235b4f --- /dev/null +++ b/src/Util/ExchangeResponse.php @@ -0,0 +1,35 @@ +result = $result; + $this->message = $message; + } + + /** + * @return boolean + */ + 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 677cef5..6756208 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,60 @@ 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..acba9a6 100644 --- a/src/Util/Text.php +++ b/src/Util/Text.php @@ -1,6 +1,6 @@ 'Transaction not ready for refund.',