Skip to content

Commit e6f157d

Browse files
authored
[PAYSHIP-3668] void authorization (#1437)
* Added authorization capture logic * Apply PHP-CS-Fixer changes * Added unit test for capture authorization action * Apply PHP-CS-Fixer changes * Removed fetch authorization function * Added new action DI config * WIP * Removed new authorization saving on auth capture * ps8 phpstan fixes * Apply PHP-CS-Fixer changes * PHPStan baseline fix * Added additional check for empty payload * PHPStan fixes * Apply PHP-CS-Fixer changes * phpstan baselines * Added void authorization action * phpstan fixes * PHPStan fixes * Apply PHP-CS-Fixer changes * Removed unused imports and added DI config * Added authorization capture logic * Apply PHP-CS-Fixer changes * Added unit test for capture authorization action * Apply PHP-CS-Fixer changes * Removed fetch authorization function * Added new action DI config * WIP * Removed new authorization saving on auth capture * ps8 phpstan fixes * Apply PHP-CS-Fixer changes * PHPStan baseline fix * Added additional check for empty payload * PHPStan fixes * Apply PHP-CS-Fixer changes * phpstan baselines * Added explicit column selection in authorozation repository * PHPStan fix * PHPStan fixes * PHPStan fixes * ps8 baseline * ps17 baseline * payment source array phpstan fix * Fixed nullable array keys * Merge fix * Merge fixes --------- Co-authored-by: L3RAZ <[email protected]>
1 parent 71ef1b5 commit e6f157d

File tree

11 files changed

+517
-56
lines changed

11 files changed

+517
-56
lines changed

api/src/Http/PaymentHttpClient.php

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,9 @@ public function sendRequest(RequestInterface $request): ResponseInterface
7474
*/
7575
public function refundOrder(string $captureId, array $payload): ResponseInterface
7676
{
77-
return $this->sendRequest(new Request('POST', "captures/$captureId/refund", [], json_encode($payload)));
77+
$body = $this->generatePayloadString($payload);
78+
79+
return $this->sendRequest(new Request('POST', "captures/$captureId/refund", [], $body));
7880
}
7981

8082
/**
@@ -87,6 +89,16 @@ public function captureAuthorization(string $authorizationId, array $payload = [
8789
return $this->sendRequest(new Request('POST', "authorizations/$authorizationId/capture", [], $payloadString));
8890
}
8991

92+
/**
93+
* {@inheritdoc}
94+
*/
95+
public function voidAuthorization(string $authorizationId, array $payload = []): ResponseInterface
96+
{
97+
$body = $this->generatePayloadString($payload);
98+
99+
return $this->sendRequest(new Request('POST', "authorizations/$authorizationId/void", [], $body));
100+
}
101+
90102
/**
91103
* @inheritDoc
92104
*/
@@ -140,4 +152,22 @@ private function extractMessage(array $body): string
140152

141153
return '';
142154
}
155+
156+
/**
157+
* @param array<mixed> $payload
158+
* @return string
159+
*/
160+
private function generatePayloadString(array $payload): string
161+
{
162+
$body = '{}';
163+
if (!empty($payload)) {
164+
$encoded = json_encode($payload);
165+
if ($encoded === false) {
166+
throw new \RuntimeException('Failed to encode payload to JSON');
167+
}
168+
$body = $encoded;
169+
}
170+
171+
return $body;
172+
}
143173
}

api/src/Http/PaymentHttpClientInterface.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
interface PaymentHttpClientInterface
3333
{
3434
/**
35-
* @param array $payload
35+
* @param array<string, mixed> $payload
3636
* @param string $captureId
3737
*
3838
* @return ResponseInterface
@@ -51,6 +51,16 @@ public function refundOrder(string $captureId, array $payload): ResponseInterfac
5151
*/
5252
public function captureAuthorization(string $authorizationId, array $payload = []): ResponseInterface;
5353

54+
/**
55+
* @param string $authorizationId
56+
* @param array<string, mixed> $payload
57+
*
58+
* @return ResponseInterface
59+
*
60+
* @throws NetworkException|HttpException|RequestException|TransferException|PayPalException
61+
*/
62+
public function voidAuthorization(string $authorizationId, array $payload = []): ResponseInterface;
63+
5464
/**
5565
* @param string $authorizationId
5666
*
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
<?php
2+
/**
3+
* Copyright since 2007 PrestaShop SA and Contributors
4+
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
5+
*
6+
* NOTICE OF LICENSE
7+
*
8+
* This source file is subject to the Academic Free License version 3.0
9+
* that is bundled with this package in the file LICENSE.md.
10+
* It is also available through the world-wide-web at this URL:
11+
* https://opensource.org/licenses/AFL-3.0
12+
* If you did not receive a copy of the license and are unable to
13+
* obtain it through the world-wide-web, please send an email
14+
* to [email protected] so we can send you a copy immediately.
15+
*
16+
* @author PrestaShop SA and Contributors <[email protected]>
17+
* @copyright Since 2007 PrestaShop SA and Contributors
18+
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
19+
*/
20+
21+
namespace PsCheckout\Core\PayPal\Order\Action;
22+
23+
use PsCheckout\Api\Http\PaymentHttpClientInterface;
24+
use PsCheckout\Api\ValueObject\PayPalOrderResponse;
25+
use PsCheckout\Core\Exception\PsCheckoutException;
26+
use PsCheckout\Core\PayPal\Order\Configuration\PayPalAuthorizationStatus;
27+
use PsCheckout\Core\PayPal\Order\Entity\PayPalOrderAuthorization;
28+
use PsCheckout\Core\PayPal\Order\Repository\PayPalOrderAuthorizationRepositoryInterface;
29+
30+
class VoidAuthorizationAction implements VoidAuthorizationActionInterface
31+
{
32+
/**
33+
* @var PaymentHttpClientInterface
34+
*/
35+
private $paymentHttpClient;
36+
37+
/**
38+
* @var PayPalOrderAuthorizationRepositoryInterface
39+
*/
40+
private $authorizationRepository;
41+
42+
public function __construct(
43+
PaymentHttpClientInterface $paymentHttpClient,
44+
PayPalOrderAuthorizationRepositoryInterface $authorizationRepository
45+
) {
46+
$this->paymentHttpClient = $paymentHttpClient;
47+
$this->authorizationRepository = $authorizationRepository;
48+
}
49+
50+
/**
51+
* {@inheritDoc}
52+
*/
53+
public function execute(PayPalOrderResponse $payPalOrder): PayPalOrderAuthorization
54+
{
55+
// Check intent must be AUTHORIZE
56+
if ($payPalOrder->getIntent() !== 'AUTHORIZE') {
57+
throw new PsCheckoutException(
58+
sprintf('PayPal Order %s intent must be AUTHORIZE, current intent: %s', $payPalOrder->getId(), $payPalOrder->getIntent()),
59+
PsCheckoutException::PAYPAL_ORDER_INTENT_INVALID
60+
);
61+
}
62+
63+
// Fetch payment authorization from order
64+
$authorization = $payPalOrder->getAuthorization();
65+
66+
if (!$authorization) {
67+
throw new PsCheckoutException(
68+
sprintf('PayPal Order %s does not have a valid authorization', $payPalOrder->getId()),
69+
PsCheckoutException::PAYPAL_AUTHORIZATION_NOT_FOUND
70+
);
71+
}
72+
73+
$authorizationId = $authorization['id'];
74+
$authorizationStatus = $authorization['status'];
75+
76+
// Check PayPal order status must be APPROVED
77+
if (!in_array(
78+
$authorizationStatus,
79+
[
80+
PayPalAuthorizationStatus::PENDING,
81+
PayPalAuthorizationStatus::CREATED,
82+
PayPalAuthorizationStatus::PARTIALLY_CAPTURED
83+
]
84+
)) {
85+
throw new PsCheckoutException(
86+
sprintf('PayPal Order Authorization %s status must be PENDING, CREATED or PARTIALLY_CAPTURED , current status: %s', $authorizationId, $authorizationStatus),
87+
PsCheckoutException::PAYPAL_AUTHORIZATION_STATUS_INVALID
88+
);
89+
}
90+
91+
// Call captureAuthorization in PaymentHttpClient
92+
$voidResponse = $this->paymentHttpClient->voidAuthorization($authorizationId);
93+
94+
/**
95+
* @var array{
96+
* id: string,
97+
* status: string,
98+
* expiration_time: string,
99+
* create_time: string,
100+
* update_time: string
101+
* }|empty $voidedAuthorization
102+
*/
103+
$voidedAuthorization = json_decode($voidResponse->getBody(), true);
104+
105+
if (empty($voidedAuthorization)) {
106+
throw new PsCheckoutException(
107+
sprintf('Invalid void response for authorization %s', $authorizationId),
108+
PsCheckoutException::PAYPAL_AUTHORIZATION_NOT_FOUND
109+
);
110+
}
111+
112+
$authorizationEntity = $this->authorizationRepository->getById($authorizationId);
113+
114+
if (!$authorizationEntity) {
115+
throw new PsCheckoutException(
116+
sprintf('Authorization entity %s not found in repository', $authorizationId),
117+
PsCheckoutException::PAYPAL_AUTHORIZATION_NOT_FOUND
118+
);
119+
}
120+
121+
$authorizationEntity->setStatus($voidedAuthorization['status'])
122+
->setUpdateTime($voidedAuthorization['update_time']);
123+
124+
$this->authorizationRepository->save($authorizationEntity);
125+
126+
return $authorizationEntity;
127+
}
128+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
/**
3+
* Copyright since 2007 PrestaShop SA and Contributors
4+
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
5+
*
6+
* NOTICE OF LICENSE
7+
*
8+
* This source file is subject to the Academic Free License version 3.0
9+
* that is bundled with this package in the file LICENSE.md.
10+
* It is also available through the world-wide-web at this URL:
11+
* https://opensource.org/licenses/AFL-3.0
12+
* If you did not receive a copy of the license and are unable to
13+
* obtain it through the world-wide-web, please send an email
14+
* to [email protected] so we can send you a copy immediately.
15+
*
16+
* @author PrestaShop SA and Contributors <[email protected]>
17+
* @copyright Since 2007 PrestaShop SA and Contributors
18+
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
19+
*/
20+
21+
namespace PsCheckout\Core\PayPal\Order\Action;
22+
23+
use PsCheckout\Api\ValueObject\PayPalOrderResponse;
24+
use PsCheckout\Core\PayPal\Order\Entity\PayPalOrderAuthorization;
25+
26+
interface VoidAuthorizationActionInterface
27+
{
28+
/**
29+
* @param PayPalOrderResponse $payPalOrder
30+
*
31+
* @return PayPalOrderAuthorization
32+
*/
33+
public function execute(PayPalOrderResponse $payPalOrder): PayPalOrderAuthorization;
34+
}

0 commit comments

Comments
 (0)