Skip to content

Commit d6601e1

Browse files
authored
Merge pull request #858 from Adyen/develop-4
Release version 4.6.6
2 parents 5e43b22 + 063082a commit d6601e1

10 files changed

Lines changed: 97 additions & 33 deletions

File tree

.github/workflows/templates/docker-compose.playwright.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ version: '3'
22

33
services:
44
playwright:
5-
image: mcr.microsoft.com/playwright:v1.61.1-noble
5+
image: mcr.microsoft.com/playwright:v1.62.1-noble
66
networks:
77
- localnetwork
88
shm_size: 1gb

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
}
77
],
88
"description": "Official Shopware 6 Plugin to connect to Payment Service Provider Adyen",
9-
"version": "4.6.5",
9+
"version": "4.6.6",
1010
"type": "shopware-platform-plugin",
1111
"license": "MIT",
1212
"require": {

src/Controller/AdminController.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,8 @@ public function isCaptureAllowed(string $orderId): JsonResponse
276276
$isFullAmountAuthorised = $this->adyenPaymentService->isFullAmountAuthorized($orderTransaction);
277277
$isRequiredAmountCaptured = $this->captureService->isRequiredAmountCaptured($orderTransaction);
278278
$isPaymentMethodSupportsManualCapture = $this->captureService->isManualCapture(
279-
$orderTransaction->getPaymentMethod()->getHandlerIdentifier()
279+
$orderTransaction->getPaymentMethod()->getHandlerIdentifier(),
280+
$orderTransaction->getOrder()->getSalesChannelId()
280281
);
281282

282283
if ($isPaymentMethodSupportsManualCapture && $isFullAmountAuthorised && !$isRequiredAmountCaptured) {
@@ -312,7 +313,10 @@ public function isManualCaptureEnabled(string $orderId): JsonResponse
312313
$paymentMethodHandlerIdentifier = $orderTransaction->getPaymentMethod()->getHandlerIdentifier();
313314

314315
return new JsonResponse(
315-
$this->captureService->isManualCapture($paymentMethodHandlerIdentifier)
316+
$this->captureService->isManualCapture(
317+
$paymentMethodHandlerIdentifier,
318+
$orderTransaction->getOrder()->getSalesChannelId()
319+
)
316320
);
317321
} catch (Throwable $t) {
318322
return new JsonResponse(false);

src/Handlers/AbstractPaymentMethodHandler.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,8 @@ protected function getAdyenPaymentRequest(
520520
isOpenInvoice: static::$isOpenInvoice,
521521
shopperInteraction: static::class === OneClickPaymentMethodHandler::class
522522
? PaymentRequestService::SHOPPER_INTERACTION_CONTAUTH
523-
: PaymentRequestService::SHOPPER_INTERACTION_ECOMMERCE
523+
: PaymentRequestService::SHOPPER_INTERACTION_ECOMMERCE,
524+
paymentMethodHandler: static::class
524525
);
525526
} catch (PaymentException $exception) {
526527
$this->logger->error($exception->getMessage());

src/Handlers/PaymentResponseHandler.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,10 @@ public function handleShopwareApis(
248248
}
249249

250250
$stateTechnicalName = $stateMachineState->getTechnicalName();
251-
$requiresManualCapture = $this->captureService
252-
->isManualCapture($transaction->getOrderTransaction()->getPaymentMethod()->getHandlerIdentifier());
251+
$requiresManualCapture = $this->captureService->isManualCapture(
252+
$transaction->getOrderTransaction()->getPaymentMethod()->getHandlerIdentifier(),
253+
$salesChannelContext->getSalesChannelId()
254+
);
253255

254256
// Get already stored transaction custom fields
255257
$storedTransactionCustomFields = $transaction->getOrderTransaction()->getCustomFields() ?: [];

src/Resources/config/services.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@
124124
<service id="Adyen\Shopware\Service\PaymentRequest\PaymentRequestService">
125125
<argument type="service" id="Adyen\Shopware\Service\ClientService"/>
126126
<argument type="service" id="Adyen\Shopware\Service\ConfigurationService"/>
127+
<argument type="service" id="Adyen\Shopware\Service\CaptureService"/>
127128
<argument type="service" id="Adyen\Shopware\Util\Currency"/>
128129
<argument type="service" id="Adyen\Shopware\Util\CheckoutStateDataValidator"/>
129130
<argument type="service" id="Adyen\Shopware\Util\RatePayDeviceFingerprintParamsProvider"/>

src/ScheduledTask/Webhook/AuthorisationWebhookHandler.php

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,10 @@ private function handleSuccessfulNotification(
130130
$paymentMethodHandler = $orderTransaction->getPaymentMethod()->getHandlerIdentifier();
131131
}
132132

133-
$isManualCapture = $this->captureService->isManualCapture($paymentMethodHandler);
133+
$isManualCapture = $this->captureService->isManualCapture(
134+
$paymentMethodHandler,
135+
$orderTransaction->getOrder()->getSalesChannelId()
136+
);
134137
$currencyUtil = new Currency();
135138
$totalPrice = $orderTransaction->getAmount()->getTotalPrice();
136139
$isoCode = $orderTransaction->getOrder()->getCurrency()->getIsoCode();
@@ -141,9 +144,7 @@ private function handleSuccessfulNotification(
141144
$this->adyenPaymentService->insertAdyenPayment($notification, $orderTransaction, $isManualCapture);
142145
}
143146

144-
// check for partial payments
145-
$merchantOrderReference = isset(json_decode($notification->getAdditionalData())->merchantOrderReference);
146-
if ($merchantOrderReference) {
147+
if ($this->isPartialPayment($notification)) {
147148
return;
148149
}
149150

@@ -175,6 +176,26 @@ private function handleSuccessfulNotification(
175176
}
176177
}
177178

179+
/**
180+
* A payment is only part of an Adyen order if the merchant order reference differs from the
181+
* merchant reference of the payment.
182+
*
183+
* @param NotificationEntity $notification
184+
*
185+
* @return bool
186+
*/
187+
private function isPartialPayment(NotificationEntity $notification): bool
188+
{
189+
$additionalData = json_decode($notification->getAdditionalData() ?? '');
190+
$merchantOrderReference = $additionalData->merchantOrderReference ?? null;
191+
192+
if (is_null($merchantOrderReference)) {
193+
return false;
194+
}
195+
196+
return $merchantOrderReference !== $notification->getMerchantReference();
197+
}
198+
178199
/**
179200
* @param OrderTransactionEntity $orderTransactionEntity
180201
* @param Context $context

src/ScheduledTask/Webhook/OrderClosedWebhookHandler.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,10 @@ private function handleSuccessfulNotification(
110110
Context $context
111111
): void {
112112
$paymentMethodHandler = $orderTransactionEntity->getPaymentMethod()->getHandlerIdentifier();
113-
if ($this->captureService->isManualCapture($paymentMethodHandler)) {
113+
if ($this->captureService->isManualCapture(
114+
$paymentMethodHandler,
115+
$orderTransactionEntity->getOrder()->getSalesChannelId()
116+
)) {
114117
$this->logger->info(
115118
'Manual capture required. Setting payment to `authorised` state.',
116119
['notification' => $notificationEntity->getVars()]

src/Service/CaptureService.php

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ public function doOpenInvoiceCapture(string $orderNumber, $captureAmount, Contex
124124

125125
$paymentMethodHandler = $orderTransaction->getPaymentMethod()->getHandlerIdentifier();
126126

127-
if ($this->isManualCapture($paymentMethodHandler)) {
127+
if ($this->isManualCapture($paymentMethodHandler, $order->getSalesChannelId())) {
128128
$this->logger->info('Capture for order_number ' . $orderNumber . ' start.');
129129

130130
$customFields = $orderTransaction->getCustomFields();
@@ -209,22 +209,20 @@ public function getRescheduleNotificationTime(): \DateTime
209209

210210
/**
211211
* @param $handlerIdentifier
212+
* @param string|null $salesChannelId
212213
*
213214
* @return bool
214215
*/
215-
public function isManualCapture($handlerIdentifier): bool
216+
public function isManualCapture($handlerIdentifier, ?string $salesChannelId = null): bool
216217
{
217218
if ($handlerIdentifier::$isOpenInvoice) {
218-
if ($this->configurationService->isAutoCaptureActiveForOpenInvoices()) {
219-
// Open invoice payment methods can be auto capture if the merchant account is authorised.
220-
return false;
221-
} else {
222-
// Open invoice payment methods are manual capture by default.
223-
return true;
224-
}
225-
} else {
226-
return $this->configurationService->isManualCaptureActive() && $handlerIdentifier::$supportsManualCapture;
219+
// Open invoice payment methods are manual capture unless the merchant account is
220+
// authorised for auto capture.
221+
return !$this->configurationService->isAutoCaptureActiveForOpenInvoices($salesChannelId);
227222
}
223+
224+
return $handlerIdentifier::$supportsManualCapture &&
225+
(bool)$this->configurationService->isManualCaptureActive($salesChannelId);
228226
}
229227

230228
/**

src/Service/PaymentRequest/PaymentRequestService.php

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,11 @@
3636
use Adyen\Model\Checkout\Name;
3737
use Adyen\Model\Checkout\PaymentResponse;
3838
use Adyen\Service\Checkout\PaymentsApi;
39+
use Adyen\Shopware\Handlers\AbstractPaymentMethodHandler;
3940
use Adyen\Shopware\Models\PaymentRequest as IntegrationPaymentRequest;
4041
use Adyen\Shopware\PaymentMethods\RatepayDirectdebitPaymentMethod;
4142
use Adyen\Shopware\PaymentMethods\RatepayPaymentMethod;
43+
use Adyen\Shopware\Service\CaptureService;
4244
use Adyen\Shopware\Service\ClientService;
4345
use Adyen\Shopware\Service\ConfigurationService;
4446
use Adyen\Shopware\Service\Repository\SalesChannelRepository;
@@ -86,6 +88,7 @@ class PaymentRequestService
8688
/**
8789
* @param ClientService $clientService
8890
* @param ConfigurationService $configurationService
91+
* @param CaptureService $captureService
8992
* @param Currency $currency
9093
* @param CheckoutStateDataValidator $checkoutStateDataValidator
9194
* @param RatePayDeviceFingerprintParamsProvider $ratePayFingerprintParamsProvider
@@ -97,6 +100,7 @@ class PaymentRequestService
97100
public function __construct(
98101
private readonly ClientService $clientService,
99102
private readonly ConfigurationService $configurationService,
103+
private readonly CaptureService $captureService,
100104
private readonly Currency $currency,
101105
private readonly CheckoutStateDataValidator $checkoutStateDataValidator,
102106
private readonly RatePayDeviceFingerprintParamsProvider $ratePayFingerprintParamsProvider,
@@ -119,6 +123,7 @@ public function __construct(
119123
* @param array $adyenOrderData
120124
* @param bool $isOpenInvoice
121125
* @param string $shopperInteraction
126+
* @param string $paymentMethodHandler
122127
*
123128
* @return IntegrationPaymentRequest
124129
*/
@@ -131,7 +136,8 @@ public function buildPaymentRequestFromOrder(
131136
?int $partialAmount = null,
132137
array $adyenOrderData = [],
133138
bool $isOpenInvoice = false,
134-
string $shopperInteraction = self::SHOPPER_INTERACTION_ECOMMERCE
139+
string $shopperInteraction = self::SHOPPER_INTERACTION_ECOMMERCE,
140+
string $paymentMethodHandler = AbstractPaymentMethodHandler::class
135141
): IntegrationPaymentRequest {
136142
$paymentRequest = new IntegrationPaymentRequest($stateData);
137143

@@ -209,12 +215,15 @@ public function buildPaymentRequestFromOrder(
209215
$this->salesChannelRepository->getCurrentDomainUrl($salesChannelContext);
210216

211217
$paymentRequest->setOrigin($origin);
212-
$paymentRequest->setAdditionalData([
213-
'allow3DS2' => true,
214-
'manualCapture' => (bool)$this->configurationService->isManualCaptureActive(
218+
219+
$this->setAdditionalRequestData(
220+
$paymentRequest,
221+
$this->captureService->isManualCapture(
222+
$paymentMethodHandler,
215223
$salesChannelContext->getSalesChannel()->getId()
216224
),
217-
]);
225+
$isOpenInvoice
226+
);
218227
$paymentRequest->setChannel('Web');
219228

220229
// Set order data for multi-payment scenarios
@@ -290,12 +299,14 @@ public function buildPaymentRequestFromCart(
290299
}
291300

292301
$paymentRequest->setOrigin($this->salesChannelRepository->getCurrentDomainUrl($salesChannelContext));
293-
$paymentRequest->setAdditionalData([
294-
'allow3DS2' => true,
295-
'manualCapture' => (bool)$this->configurationService->isManualCaptureActive(
302+
303+
// Express checkout never uses an open invoice method, so the manual capture setting decides on its own.
304+
$this->setAdditionalRequestData(
305+
$paymentRequest,
306+
(bool)$this->configurationService->isManualCaptureActive(
296307
$salesChannelContext->getSalesChannel()->getId()
297-
),
298-
]);
308+
)
309+
);
299310
$paymentRequest->setChannel('Web');
300311
$paymentRequest->setShopperInteraction(self::SHOPPER_INTERACTION_ECOMMERCE);
301312

@@ -349,6 +360,29 @@ public function executePayment(
349360
}
350361
}
351362

363+
/**
364+
* @param IntegrationPaymentRequest $paymentRequest
365+
* @param bool $isManualCapture
366+
* @param bool $isOpenInvoice
367+
*
368+
* @return void
369+
*/
370+
protected function setAdditionalRequestData(
371+
IntegrationPaymentRequest $paymentRequest,
372+
bool $isManualCapture,
373+
bool $isOpenInvoice = false
374+
): void {
375+
$additionalData = ['allow3DS2' => true];
376+
377+
if ($isManualCapture) {
378+
$additionalData['manualCapture'] = true;
379+
} elseif ($isOpenInvoice) {
380+
$paymentRequest->setCaptureDelayHours(0);
381+
}
382+
383+
$paymentRequest->setAdditionalData($additionalData);
384+
}
385+
352386
/**
353387
* Set browser info on payment request
354388
*

0 commit comments

Comments
 (0)