Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ECP-9639] Refactor API clients, validator and handlers #2910

Draft
wants to merge 44 commits into
base: develop-10
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
752f83b
[ECP-9593] Implement an abstract handler for order status history
Mar 5, 2025
e505f01
[ECP-9593] Revert changes related to CAPTURE response handler
Mar 10, 2025
7b8d213
[ECP-9593] Implement comment builder for webhooks
Mar 10, 2025
848d53e
[ECP-9593] Refactor the renamed method
Mar 10, 2025
37dcfde
[ECP-9593] Improve order cancellation message and add optional reason
Mar 10, 2025
a078565
[ECP-9593] Add comment builder for webhooks
Mar 10, 2025
04d8501
[ECP-9593] Improve object handling on capture webhook handling proces…
Mar 10, 2025
e58a17c
[ECP-9593] Remove CheckoutPaymentCommentHistoryHandler class
Mar 10, 2025
b6543fb
[ECP-9639] Refactor CheckoutResponseValidator
Mar 11, 2025
93b252a
[ECP-9639] Add argument type declaration
Mar 11, 2025
c19260a
[ECP-9639] Use SubjectReader for response collection
Mar 11, 2025
13a9b32
[ECP-9639] Implement abstract response validator for modification req…
Mar 11, 2025
c793c2b
[ECP-9639] Move abstract class parameters to di.xml
Mar 11, 2025
3946811
[ECP-9639] Refactor Pay by Link request validator
Mar 11, 2025
26e32f9
[ECP-9639] Refactor InstallmentValidator class
Mar 11, 2025
0e36438
[ECP-9639] Remove hasOnlyGiftCards temporary handler
Mar 11, 2025
f681b9c
[ECP-9639] Refactor CheckoutPaymentsDetailsHandler
Mar 11, 2025
6128eb6
Merge remote-tracking branch 'origin/develop-10' into ECP-9593
Mar 11, 2025
7c9da9a
Merge remote-tracking branch 'origin/ECP-9593' into ECP-9639
Mar 11, 2025
e76ea26
[ECP-9639] Refactor PaymentLinks handlers and validators
Mar 11, 2025
ab390a2
[ECP-9639] Refactor DonateResponseValidator
Mar 11, 2025
93ffab8
[ECP-9639] Update payment method vaults response handler and remove r…
Mar 11, 2025
987c4f5
[ECP-9639] Remove redundant response handler
Mar 11, 2025
3c216a2
[ECP-9639] Rename the class only used by capture command pool
Mar 11, 2025
bd4f6a3
[ECP-9639] Move argument validator to the constructor
Mar 11, 2025
801a9cb
[ECP-9639] Refactor refunds response handler
Mar 11, 2025
e4e0f2f
[ECP-9639] Refactor cancels response handler
Mar 11, 2025
ae6762b
[ECP-9639] Rename the class
Mar 11, 2025
d48ab29
[ECP-9639] Refactor captures response handler
Mar 11, 2025
cc1dd9a
[ECP-9639] Update lastTransId logic
Mar 11, 2025
d464908
[ECP-9639] Add required field validator to modifications response val…
Mar 11, 2025
f797659
[ECP-9639] Formatting
Mar 11, 2025
ae34409
[ECP-9639] Merge VaultDetailsHandler into CheckoutPaymentsResponseHan…
Mar 11, 2025
2112a35
[ECP-9639] Refactor state data handler
Mar 11, 2025
08b6188
[ECP-9639] Use abstract order status history handler for captures
Mar 11, 2025
2dfae66
[ECP-9639] Update valid status constants
Mar 11, 2025
abe09cb
[ECP-9639] Remove hasOnlyGiftCards flag on payments chain
Mar 11, 2025
c4e1a55
[ECP-9639] Remove abstract keyword from the classes to use DI
Mar 11, 2025
61cf61a
[ECP-9639] Remove the comment
Mar 11, 2025
aa67447
[ECP-9639] Fix the class name
Mar 11, 2025
9e03866
[ECP-9639] Fix the response type
Mar 11, 2025
7e72072
[ECP-9639] Refactor Cancel command chain
Mar 12, 2025
f81059b
[ECP-9639] Introduce a constant for the string
Mar 12, 2025
97edd2a
[ECP-9639] Refactor capture command chain
Mar 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 8 additions & 19 deletions Gateway/Http/Client/TransactionCancel.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* Adyen Payment module (https://www.adyen.com/)
*
* Copyright (c) 2023 Adyen N.V. (https://www.adyen.com/)
* Copyright (c) 2025 Adyen N.V. (https://www.adyen.com/)
* See LICENSE.txt for license details.
*
* Author: Adyen <[email protected]>
Expand All @@ -22,27 +22,14 @@

class TransactionCancel implements ClientInterface
{
/**
* @var Data
*/
private Data $adyenHelper;

/**
* @var Idempotency
*/
private Idempotency $idempotencyHelper;

/**
* @param Data $adyenHelper
* @param Idempotency $idempotencyHelper
*/
public function __construct(
Data $adyenHelper,
Idempotency $idempotencyHelper
) {
$this->adyenHelper = $adyenHelper;
$this->idempotencyHelper = $idempotencyHelper;
}
private readonly Data $adyenHelper,
private readonly Idempotency $idempotencyHelper
) { }

/**
* @param TransferInterface $transferObject
Expand All @@ -58,7 +45,7 @@ public function placeRequest(TransferInterface $transferObject): array

$client = $this->adyenHelper->initializeAdyenClientWithClientConfig($clientConfig);
$service = $this->adyenHelper->initializeModificationsApi($client);
$responseData = [];
$responseCollection = [];

foreach ($requests as $request) {
$idempotencyKey = $this->idempotencyHelper->generateIdempotencyKey(
Expand All @@ -83,8 +70,10 @@ public function placeRequest(TransferInterface $transferObject): array
$responseData['error'] = $e->getMessage();
$this->adyenHelper->logAdyenException($e);
}

$responseCollection[] = $responseData;
}

return $responseData;
return $responseCollection;
}
}
149 changes: 43 additions & 106 deletions Gateway/Http/Client/TransactionCapture.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* Adyen Payment module (https://www.adyen.com/)
*
* Copyright (c) 2023 Adyen N.V. (https://www.adyen.com/)
* Copyright (c) 2025 Adyen N.V. (https://www.adyen.com/)
* See LICENSE.txt for license details.
*
* Author: Adyen <[email protected]>
Expand All @@ -14,53 +14,30 @@
use Adyen\AdyenException;
use Adyen\Client;
use Adyen\Model\Checkout\PaymentCaptureRequest;
use Adyen\Payment\Api\Data\OrderPaymentInterface;
use Adyen\Payment\Gateway\Validator\AbstractModificationsResponseValidator;
use Adyen\Payment\Helper\Data;
use Adyen\Payment\Helper\Idempotency;
use Adyen\Payment\Helper\Requests;
use Adyen\Payment\Logger\AdyenLogger;
use Adyen\Service\Checkout\ModificationsApi;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Payment\Gateway\Http\ClientInterface;
use Magento\Payment\Gateway\Http\TransferInterface;

class TransactionCapture implements ClientInterface
{
const MULTIPLE_AUTHORIZATIONS = 'multiple_authorizations';
const FORMATTED_CAPTURE_AMOUNT = 'formatted_capture_amount';
const CAPTURE_AMOUNT = 'capture_amount';
const CAPTURE_AMOUNT = 'amount';
const CAPTURE_VALUE = 'value';
const ORIGINAL_REFERENCE = 'paymentPspReference';
const CAPTURE_RECEIVED = 'received';

/**
* @var Data
*/
private Data $adyenHelper;

/**
* @var AdyenLogger
*/
private AdyenLogger $adyenLogger;

/**
* @var Idempotency
*/
private Idempotency $idempotencyHelper;

/**
* @param Data $adyenHelper
* @param AdyenLogger $adyenLogger
* @param Idempotency $idempotencyHelper
*/
public function __construct(
Data $adyenHelper,
AdyenLogger $adyenLogger,
Idempotency $idempotencyHelper
) {
$this->adyenHelper = $adyenHelper;
$this->adyenLogger = $adyenLogger;
$this->idempotencyHelper = $idempotencyHelper;
}
private readonly Data $adyenHelper,
private readonly AdyenLogger $adyenLogger,
private readonly Idempotency $idempotencyHelper
) { }

/**
* @param TransferInterface $transferObject
Expand All @@ -70,109 +47,61 @@ public function __construct(
*/
public function placeRequest(TransferInterface $transferObject): array
{
$request = $transferObject->getBody();
$requestCollection = $transferObject->getBody();
$headers = $transferObject->getHeaders();
$clientConfig = $transferObject->getClientConfig();

$client = $this->adyenHelper->initializeAdyenClientWithClientConfig($clientConfig);
$service = $this->adyenHelper->initializeModificationsApi($client);

$requestOptions['headers'] = $headers;
$request['applicationInfo'] = $this->adyenHelper->buildApplicationInfo($client);

if (array_key_exists(self::MULTIPLE_AUTHORIZATIONS, $request)) {
return $this->placeMultipleCaptureRequests($service, $request, $requestOptions);
}

$idempotencyKeyExtraData = $request['idempotencyExtraData'];
unset($request['idempotencyExtraData']);

$idempotencyKey = $this->idempotencyHelper->generateIdempotencyKey(
$request,
$idempotencyKeyExtraData ?? null
);
$requestOptions['idempotencyKey'] = $idempotencyKey;

$this->adyenHelper->logRequest($request, Client::API_CHECKOUT_VERSION, '/captures');
$paymentCaptureRequest = new PaymentCaptureRequest($request);
$responseData = [];

try {
$response = $service->captureAuthorisedPayment(
$request['paymentPspReference'],
$paymentCaptureRequest,
$requestOptions
);
$responseCollection = [];

$responseData = $response->toArray();
$responseData = $this->copyParamsToResponse($responseData, $request);
$this->adyenHelper->logResponse($responseData);
} catch (AdyenException $e) {
$this->adyenHelper->logAdyenException($e);
$responseData['error'] = $e->getMessage();
}

return $responseData;
}

/**
* @param ModificationsApi $service
* @param array $requestContainer
* @param array $requestOptions
* @return array
*/
private function placeMultipleCaptureRequests(
ModificationsApi $service,
array $requestContainer,
array $requestOptions
): array {
$response = [];
$applicationInfo = $requestContainer['applicationInfo'];

foreach ($requestContainer[self::MULTIPLE_AUTHORIZATIONS] as $request) {
foreach ($requestCollection as $request) {
$idempotencyKeyExtraData = $request['idempotencyExtraData'];
unset($request['idempotencyExtraData']);
$idempotencyKey = $this->idempotencyHelper->generateIdempotencyKey(
$request,
$idempotencyKeyExtraData ?? null
);

$request['applicationInfo'] = $this->adyenHelper->buildApplicationInfo($client);
$requestOptions['headers'] = $headers;
$requestOptions['idempotencyKey'] = $idempotencyKey;

$paymentPspReference = $request['paymentPspReference'];
unset($request['paymentPspReference']);

try {
// Copy merchant account from parent array to every request array
$request[Requests::MERCHANT_ACCOUNT] = $requestContainer[Requests::MERCHANT_ACCOUNT];
$request['applicationInfo'] = $applicationInfo;
$paymentCaptureRequest = new PaymentCaptureRequest($request);
$singleResponseObj = $service->captureAuthorisedPayment(
$request['paymentPspReference'],
$this->adyenHelper->logRequest($request, Client::API_CHECKOUT_VERSION, '/captures');

$response = $service->captureAuthorisedPayment(
$paymentPspReference,
$paymentCaptureRequest,
$requestOptions
);

$singleResponse = $singleResponseObj->toArray();
$singleResponse[self::FORMATTED_CAPTURE_AMOUNT] = $request['amount']['currency'] . ' ' .
$this->adyenHelper->originalAmount(
$request['amount']['value'],
$request['amount']['currency']
);
$singleResponse = $this->copyParamsToResponse($singleResponse, $request);
$response[self::MULTIPLE_AUTHORIZATIONS][] = $singleResponse;
} catch (AdyenException $e) {
$pspReference = $request[OrderPaymentInterface::PSPREFRENCE] ?? 'pspReference not set';
$responseData = $response->toArray();
$this->adyenHelper->logResponse($responseData);

$responseCollection[] = $this->copyParamsToResponse($responseData, $request);
} catch (AdyenException $e) {
$message = sprintf(
'Exception occurred when attempting to capture multiple authorizations.
Authorization with pspReference %s: %s',
$pspReference,
"An error occurred during the capture attempt%s. %s",
!empty($paymentPspReference) ?
' of authorisation with pspreference ' . $paymentPspReference :
'',
$e->getMessage()
);

$responseData['error'] = $message;

$this->adyenLogger->error($message);
$response[self::MULTIPLE_AUTHORIZATIONS]['error'] = $message;
$responseCollection[] = $responseData;
}
}

return $response;
return $responseCollection;
}

/**
Expand All @@ -182,8 +111,16 @@ private function placeMultipleCaptureRequests(
*/
private function copyParamsToResponse(array $response, array $request): array
{
$response[self::CAPTURE_AMOUNT] = $request['amount']['value'];
$response[self::ORIGINAL_REFERENCE] = $request[self::ORIGINAL_REFERENCE];
$originalAmount = $this->adyenHelper->originalAmount(
$request['amount']['value'],
$request['amount']['currency']
);

$response[AbstractModificationsResponseValidator::FORMATTED_MODIFICATIONS_AMOUNT] = sprintf(
"%s %s",
$request['amount']['currency'],
$originalAmount
);

return $response;
}
Expand Down
2 changes: 0 additions & 2 deletions Gateway/Http/Client/TransactionPayment.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ public function placeRequest(TransferInterface $transferObject): array
$client = $this->adyenHelper->initializeAdyenClientWithClientConfig($clientConfig);
$service = $this->adyenHelper->initializePaymentsApi($client);
$responseCollection = [];
$responseCollection['hasOnlyGiftCards'] = false;

try {
list($requestData, $giftcardResponseCollection) = $this->processGiftcards($requestData, $service);
Expand All @@ -130,7 +129,6 @@ public function placeRequest(TransferInterface $transferObject): array
$responseCollection = array_merge($responseCollection, $giftcardResponseCollection);

if ($this->remainingOrderAmount === 0) {
$responseCollection['hasOnlyGiftCards'] = true;
return $responseCollection;
}
}
Expand Down
1 change: 1 addition & 0 deletions Gateway/Http/Client/TransactionRefundInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ interface TransactionRefundInterface extends ClientInterface
const REFUND_AMOUNT = 'refund_amount';
const REFUND_CURRENCY = 'refund_currency';
const ORIGINAL_REFERENCE = 'original_reference';
const PSPREFERENCE = 'pspReference';
}
27 changes: 8 additions & 19 deletions Gateway/Request/CancelDataBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* Adyen Payment module (https://www.adyen.com/)
*
* Copyright (c) 2015 Adyen BV (https://www.adyen.com/)
* Copyright (c) 2025 Adyen N.V. (https://www.adyen.com/)
* See LICENSE.txt for license details.
*
* Author: Adyen <[email protected]>
Expand All @@ -16,31 +16,20 @@
use Magento\Payment\Gateway\Request\BuilderInterface;
use Adyen\Payment\Model\ResourceModel\Order\Payment;
use Adyen\Payment\Helper\Data;
use Adyen\Payment\Helper\Config;

/**
* Class CustomerDataBuilder
*/
class CancelDataBuilder implements BuilderInterface
{
/** @var Payment $adyenPaymentResourceModel */
private $adyenPaymentResourceModel;

/** @var Config $configHelper */
private $configHelper;

/** @var Data $adyenHelper */
private $adyenHelper;

/**
* @param Payment $adyenPaymentResourceModel
* @param Data $adyenHelper
*/
public function __construct(
Payment $adyenPaymentResourceModel,
Data $adyenHelper,
Config $configHelper
){
$this->adyenPaymentResourceModel = $adyenPaymentResourceModel;
$this->adyenHelper = $adyenHelper;
$this->configHelper = $configHelper;
}
private readonly Payment $adyenPaymentResourceModel,
private readonly Data $adyenHelper
){ }

/**
* Create cancel_or_refund request
Expand Down
Loading
Loading