From c9c4d3d5a7cc6e3be93f66afb2be8af8ea99d8d4 Mon Sep 17 00:00:00 2001 From: Lukasz Falda Date: Mon, 6 Nov 2023 10:23:01 +0100 Subject: [PATCH] Pay method on Payment --- .php-cs-fixer.php | 1 + core/Action/Request/Capture.php | 23 ++++++++ src/Action/CaptureAction.php | 13 ++-- src/Action/StatusAction.php | 4 +- src/Action/SyncPaymentAction.php | 4 +- src/Enum/ModelFields.php | 2 + src/Enum/PayMethodType.php | 1 + src/Model/Model.php | 2 + .../Response/OrderCreated/StatusCode.php | 2 + .../Response/OrderCreatedResponse.php | 4 +- .../Integration/Action/CaptureActionTest.php | 59 ++++++++++++++++++- .../Action/data/expectedOrderRequest.json | 37 ++++++++++++ .../expectedOrderRequestWithPayMethod.json | 44 ++++++++++++++ 13 files changed, 183 insertions(+), 13 deletions(-) create mode 100644 core/Action/Request/Capture.php create mode 100644 tests/Integration/Action/data/expectedOrderRequest.json create mode 100644 tests/Integration/Action/data/expectedOrderRequestWithPayMethod.json diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php index c51474e..c07384c 100644 --- a/.php-cs-fixer.php +++ b/.php-cs-fixer.php @@ -36,5 +36,6 @@ ], 'sort_algorithm' => 'alpha', ], + 'nullable_type_declaration_for_default_null_value' => true, ] ); diff --git a/core/Action/Request/Capture.php b/core/Action/Request/Capture.php new file mode 100644 index 0000000..a2b14b4 --- /dev/null +++ b/core/Action/Request/Capture.php @@ -0,0 +1,23 @@ +setModel($payment); + $this->setModel($payment->getDetails()); + } +} diff --git a/src/Action/CaptureAction.php b/src/Action/CaptureAction.php index b9478a7..b1f3133 100644 --- a/src/Action/CaptureAction.php +++ b/src/Action/CaptureAction.php @@ -58,7 +58,7 @@ public function execute($request): void } $configKey = PaymentHelper::getConfigKey($model, $firstModel); - $orderRequest = $this->prepareOrderRequest($token, $model); + $orderRequest = $this->prepareOrderRequest($request, $token, $model); if (RecurringEnum::Standard === $model->recurring()) { $this->setRecurringStandardPayment($orderRequest, $model, $configKey); } @@ -69,7 +69,7 @@ public function execute($request): void $this->updatePayment($model, $orderCreatedResponse, $firstModel, $token); $request->setModel($model); - throw new HttpRedirect($orderCreatedResponse->redirectUri ?? $token->getTargetUrl()); + throw new HttpRedirect($orderCreatedResponse->redirectUri ?? $token->getAfterUrl()); } if (StatusCode::WarningContinue3ds === $orderCreatedResponse->status->statusCode) { @@ -125,8 +125,13 @@ private function updatePayment( /** Payment will be auto-updated on @see \Payum\Core\Extension\StorageExtension::onPostExecute */ } - private function prepareOrderRequest(TokenInterface $token, Model $model): OrderRequest + private function prepareOrderRequest(Capture $request, TokenInterface $token, Model $model): OrderRequest { + $payMethod = $model->payMethod(); + if ($request instanceof \Answear\Payum\Action\Request\Capture && null !== $request->payMethod) { + $payMethod = $request->payMethod; + } + return new OrderRequest( $model->description(), $model->currencyCode(), @@ -144,7 +149,7 @@ private function prepareOrderRequest(TokenInterface $token, Model $model): Order $model->extOrderId(), $token->getAfterUrl(), $model->buyer(), - $model->payMethod(), + $payMethod, $model->additionalDescription(), $model->visibleDescription(), $model->statementDescription() diff --git a/src/Action/StatusAction.php b/src/Action/StatusAction.php index 06d40c8..9aac5c0 100644 --- a/src/Action/StatusAction.php +++ b/src/Action/StatusAction.php @@ -46,7 +46,7 @@ public function execute($request): void public function supports($request): bool { return - $request instanceof GetStatusInterface && - $request->getModel() instanceof \ArrayAccess; + $request instanceof GetStatusInterface + && $request->getModel() instanceof \ArrayAccess; } } diff --git a/src/Action/SyncPaymentAction.php b/src/Action/SyncPaymentAction.php index c4871a4..22df40f 100644 --- a/src/Action/SyncPaymentAction.php +++ b/src/Action/SyncPaymentAction.php @@ -40,8 +40,8 @@ public function execute($request): void public function supports($request): bool { return - $request instanceof SyncPayment && - $request->getModel() instanceof PaymentInterface; + $request instanceof SyncPayment + && $request->getModel() instanceof PaymentInterface; } protected function updatePayment(PaymentInterface $payment, Model $model): void diff --git a/src/Enum/ModelFields.php b/src/Enum/ModelFields.php index 401512a..279c1f5 100644 --- a/src/Enum/ModelFields.php +++ b/src/Enum/ModelFields.php @@ -25,6 +25,8 @@ enum ModelFields public const PAY_METHOD = 'payMethod'; public const PAY_METHOD_TYPE = 'type'; public const PAY_METHOD_VALUE = 'value'; + public const PAY_METHOD_AUTHORIZATION_CODE = 'authorizationCode'; + public const PAY_METHOD_SPECIFIC_DATA = 'specificData'; public const PRODUCT_LISTING_DATE = 'listingDate'; public const PRODUCT_VIRTUAL = 'virtual'; public const PRODUCT_QUANTITY = 'quantity'; diff --git a/src/Enum/PayMethodType.php b/src/Enum/PayMethodType.php index dc8c9a0..8267abb 100644 --- a/src/Enum/PayMethodType.php +++ b/src/Enum/PayMethodType.php @@ -10,4 +10,5 @@ enum PayMethodType: string case CardToken = 'CARD_TOKEN'; case Installments = 'INSTALLMENTS'; case PaymentWall = 'PAYMENT_WALL'; + case BlikAuthorizationCode = 'BLIK_AUTHORIZATION_CODE'; } diff --git a/src/Model/Model.php b/src/Model/Model.php index 42e9033..702fd90 100644 --- a/src/Model/Model.php +++ b/src/Model/Model.php @@ -104,6 +104,8 @@ public function payMethod(): ?PayMethod return new PayMethod( $type instanceof PayMethodType ? $type : PayMethodType::tryFrom($type), $this[ModelFields::PAY_METHODS][ModelFields::PAY_METHOD][ModelFields::PAY_METHOD_VALUE], + $this[ModelFields::PAY_METHODS][ModelFields::PAY_METHOD][ModelFields::PAY_METHOD_AUTHORIZATION_CODE] ?? null, + $this[ModelFields::PAY_METHODS][ModelFields::PAY_METHOD][ModelFields::PAY_METHOD_SPECIFIC_DATA] ?? null, ); } diff --git a/src/ValueObject/Response/OrderCreated/StatusCode.php b/src/ValueObject/Response/OrderCreated/StatusCode.php index 09ecec3..50efa79 100644 --- a/src/ValueObject/Response/OrderCreated/StatusCode.php +++ b/src/ValueObject/Response/OrderCreated/StatusCode.php @@ -11,8 +11,10 @@ enum StatusCode: string case WarningContinue3ds = 'WARNING_CONTINUE_3DS'; case WarningContinueCVV = 'WARNING_CONTINUE_CVV'; case Error_syntax = 'ERROR_SYNTAX'; + case ErrorAuthorizationCode = 'ERROR_AUTHORIZATION_CODE'; case ErrorValueInvalid = 'ERROR_VALUE_INVALID'; case ErrorValueMissing = 'ERROR_VALUE_MISSING'; + case ErrorToken = 'ERROR_TOKEN'; case ErrorOrderNotUnique = 'ERROR_ORDER_NOT_UNIQUE'; case ErrorInternal = 'ERROR_INTERNAL'; case BusinessError = 'BUSINESS_ERROR'; diff --git a/src/ValueObject/Response/OrderCreatedResponse.php b/src/ValueObject/Response/OrderCreatedResponse.php index 0c0ea0b..e861e74 100644 --- a/src/ValueObject/Response/OrderCreatedResponse.php +++ b/src/ValueObject/Response/OrderCreatedResponse.php @@ -10,7 +10,7 @@ class OrderCreatedResponse { public function __construct( public readonly OrderCreatedStatus $status, - public readonly string $redirectUri, + public readonly ?string $redirectUri, public readonly string $orderId, public readonly ?string $extOrderId = null, public readonly ?array $payMethods = null, @@ -21,7 +21,7 @@ public static function fromResponse(array $response): self { return new self( OrderCreatedStatus::fromResponse($response['status']), - $response['redirectUri'], + $response['redirectUri'] ?? null, $response['orderId'], $response['extOrderId'] ?? null, $response['payMethods'] ?? null diff --git a/tests/Integration/Action/CaptureActionTest.php b/tests/Integration/Action/CaptureActionTest.php index 5766dbc..6a14e09 100644 --- a/tests/Integration/Action/CaptureActionTest.php +++ b/tests/Integration/Action/CaptureActionTest.php @@ -5,11 +5,14 @@ namespace Answear\Payum\PayU\Tests\Integration\Action; use Answear\Payum\PayU\Action\CaptureAction; +use Answear\Payum\PayU\Enum\PayMethodType; use Answear\Payum\PayU\Exception\PayUException; use Answear\Payum\PayU\Model\Model; use Answear\Payum\PayU\Request\OrderRequestService; use Answear\Payum\PayU\Request\PayMethodsRequestService; use Answear\Payum\PayU\Tests\Util\FileTestUtil; +use Answear\Payum\PayU\ValueObject\Request\Order\PayMethod; +use Answear\Payum\PayU\ValueObject\Request\OrderRequest; use Answear\Payum\PayU\ValueObject\Response\OrderCreated\OrderCreatedStatus; use Answear\Payum\PayU\ValueObject\Response\OrderCreated\StatusCode; use Answear\Payum\PayU\ValueObject\Response\OrderCreatedResponse; @@ -33,7 +36,9 @@ class CaptureActionTest extends TestCase */ public function captureTest(): void { - $captureAction = $this->getCaptureAction(); + $captureAction = $this->getCaptureAction( + expectedCreateRequest: FileTestUtil::decodeJsonFromFile(__DIR__ . '/data/expectedOrderRequest.json') + ); $captureToken = new Token(); $capture = new Capture($captureToken); @@ -51,6 +56,38 @@ public function captureTest(): void self::assertTrue($redirected); } + /** + * @test + */ + public function captureWithPayMethodTest(): void + { + $captureAction = $this->getCaptureAction( + expectedCreateRequest: FileTestUtil::decodeJsonFromFile(__DIR__ . '/data/expectedOrderRequestWithPayMethod.json') + ); + + $payment = new \Answear\Payum\PayU\Tests\Payment(); + $payment->setDetails(FileTestUtil::decodeJsonFromFile(__DIR__ . '/data/details.json')); + + $payMethod = new PayMethod( + PayMethodType::Pbl, + 'some value', + 'some authorisation code' + ); + + $captureToken = new Token(); + $capture = new \Answear\Payum\Action\Request\Capture($captureToken, $payment, $payMethod); + + $redirected = false; + try { + $captureAction->execute($capture); + } catch (HttpRedirect $httpRedirect) { + $redirected = true; + self::assertSame('http://redirect-after-create-payment.url', $httpRedirect->getUrl()); + } + + self::assertTrue($redirected); + } + /** * @test */ @@ -155,8 +192,11 @@ public function captureWithOrderIdFailsTest(): void $captureAction->execute($capture); } - private function getCaptureAction(?OrderCreatedResponse $response = null, ?array $details = null): CaptureAction - { + private function getCaptureAction( + ?OrderCreatedResponse $response = null, + ?array $details = null, + ?array $expectedCreateRequest = null + ): CaptureAction { $response = $response ?? new OrderCreatedResponse( new OrderCreatedStatus( StatusCode::Success, @@ -169,6 +209,19 @@ private function getCaptureAction(?OrderCreatedResponse $response = null, ?array $orderRequestService = $this->createMock(OrderRequestService::class); $orderRequestService->method('create') + ->with( + $this->callback( + static function (OrderRequest $createRequest) use ($expectedCreateRequest) { + + if ($expectedCreateRequest) { + $jsonE = json_encode($createRequest->toArray('posId')); + self::assertSame($createRequest->toArray('posId'), $expectedCreateRequest); + } + + return true; + } + ) + ) ->willReturn($response); $captureAction = new CaptureAction( diff --git a/tests/Integration/Action/data/expectedOrderRequest.json b/tests/Integration/Action/data/expectedOrderRequest.json new file mode 100644 index 0000000..795f442 --- /dev/null +++ b/tests/Integration/Action/data/expectedOrderRequest.json @@ -0,0 +1,37 @@ +{ + "extOrderId": "221214-0026UJ-CZ", + "notifyUrl": "http:\/\/notify.url", + "customerIp": "10.0.13.152", + "merchantPosId": "posId", + "validityTime": 259200, + "description": "Platnost za objedn\u00e1vku \u010d.: 221214-0026UJ-CZ", + "additionalDescription": null, + "visibleDescription": null, + "statementDescription": null, + "currencyCode": "CZK", + "totalAmount": 95500, + "continueUrl": null, + "buyer": { + "email": "test@email-fake.domain", + "firstName": "Testy", + "lastName": "Mjzykdwmh", + "phone": "+420733999019", + "customerId": null, + "extCustomerId": null, + "nin": null, + "language": "cs", + "delivery": null + }, + "products": [ + { + "name": "Platnost za objedn\u00e1vku \u010d.: 221214-0026UJ-CZ", + "unitPrice": 95500, + "quantity": 1, + "virtual": null, + "listingDate": null + } + ], + "payMethods": null, + "cardOnFile": null, + "recurring": null +} diff --git a/tests/Integration/Action/data/expectedOrderRequestWithPayMethod.json b/tests/Integration/Action/data/expectedOrderRequestWithPayMethod.json new file mode 100644 index 0000000..2f84f9e --- /dev/null +++ b/tests/Integration/Action/data/expectedOrderRequestWithPayMethod.json @@ -0,0 +1,44 @@ +{ + "extOrderId": "221214-0026UJ-CZ", + "notifyUrl": "http:\/\/notify.url", + "customerIp": "10.0.13.152", + "merchantPosId": "posId", + "validityTime": 259200, + "description": "Platnost za objedn\u00e1vku \u010d.: 221214-0026UJ-CZ", + "additionalDescription": null, + "visibleDescription": null, + "statementDescription": null, + "currencyCode": "CZK", + "totalAmount": 95500, + "continueUrl": null, + "buyer": { + "email": "test@email-fake.domain", + "firstName": "Testy", + "lastName": "Mjzykdwmh", + "phone": "+420733999019", + "customerId": null, + "extCustomerId": null, + "nin": null, + "language": "cs", + "delivery": null + }, + "products": [ + { + "name": "Platnost za objedn\u00e1vku \u010d.: 221214-0026UJ-CZ", + "unitPrice": 95500, + "quantity": 1, + "virtual": null, + "listingDate": null + } + ], + "payMethods": { + "payMethod": { + "type": "PBL", + "value": "some value", + "authorizationCode": "some authorisation code", + "specificData": null + } + }, + "cardOnFile": null, + "recurring": null +}