Skip to content

Commit 321da64

Browse files
FC#0132520 - add config options to change capture trigger, disable automatic refunds (#81)
1 parent 043751e commit 321da64

5 files changed

Lines changed: 123 additions & 12 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## Version 9.0.0 - WIP
4+
5+
* FC#0132520 - add config options to change capture trigger, disable automatic refunds
6+
37
## Version 8.0.0 - Released on 2025-09-18
48

59
* RATESWSX-332: add Shopware 6.7.x.x compatibility

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "ratepay/shopware6-module",
33
"description": "Ratepay payment methods for Shopware 6",
4-
"version": "8.0.0",
4+
"version": "9.0.0",
55
"license": "MIT",
66
"authors": [
77
{

src/Components/StateMachine/Subscriber/TransitionSubscriber.php

Lines changed: 86 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Exception;
1515
use Psr\Log\LoggerInterface;
1616
use Ratepay\RpayPayments\Components\RatepayApi\Dto\OrderOperationData;
17+
use Ratepay\RpayPayments\Components\RatepayApi\Service\Request\AbstractModifyRequest;
1718
use Ratepay\RpayPayments\Components\RatepayApi\Service\Request\PaymentCancelService;
1819
use Ratepay\RpayPayments\Components\RatepayApi\Service\Request\PaymentDeliverService;
1920
use Ratepay\RpayPayments\Components\RatepayApi\Service\Request\PaymentReturnService;
@@ -25,6 +26,9 @@
2526
use Shopware\Core\Checkout\Order\Aggregate\OrderDelivery\OrderDeliveryDefinition;
2627
use Shopware\Core\Checkout\Order\Aggregate\OrderDelivery\OrderDeliveryEntity;
2728
use Shopware\Core\Checkout\Order\Aggregate\OrderDelivery\OrderDeliveryStates;
29+
use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionDefinition;
30+
use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionEntity;
31+
use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStates;
2832
use Shopware\Core\Checkout\Order\OrderEntity;
2933
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
3034
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
@@ -38,6 +42,7 @@ class TransitionSubscriber implements EventSubscriberInterface
3842

3943
public function __construct(
4044
private readonly EntityRepository $orderDeliveryRepository,
45+
private readonly EntityRepository $orderTransactionRepository,
4146
private readonly EntityRepository $orderRepository,
4247
private readonly PluginConfigService $configService,
4348
private readonly PaymentDeliverService $paymentDeliverService,
@@ -56,7 +61,60 @@ public static function getSubscribedEvents(): array
5661

5762
public function onTransition(StateMachineTransitionEvent $event): void
5863
{
59-
if ($event->getEntityName() !== OrderDeliveryDefinition::ENTITY_NAME || !$this->configService->isAutoOperationBasedOnDeliveryStatusEnabled()) {
64+
if ($event->getEntityName() === OrderTransactionDefinition::ENTITY_NAME) {
65+
$this->onTransactionStatusTransition($event);
66+
} else if ($event->getEntityName() === OrderDeliveryDefinition::ENTITY_NAME) {
67+
$this->onDeliveryStatusTransition($event);
68+
}
69+
}
70+
71+
protected function onTransactionStatusTransition(StateMachineTransitionEvent $event): void
72+
{
73+
if ($this->configService->getCaptureTrigger() !== 'pay') {
74+
return;
75+
}
76+
77+
/** @var ArrayStruct|null $struct */
78+
$struct = $event->getContext()->getExtension('ratepay');
79+
if ($struct?->get(self::PREVENT_BIDIRECTIONALITY) === true) {
80+
return;
81+
}
82+
83+
/** @var OrderTransactionEntity $orderTransaction */
84+
$orderTransaction = $this->orderTransactionRepository->search(new Criteria([$event->getEntityId()]), $event->getContext())->first();
85+
/** @var OrderEntity $order */
86+
$order = $this->orderRepository->search(CriteriaHelper::getCriteriaForOrder($orderTransaction->getOrderId()), $event->getContext())->first();
87+
88+
if (!MethodHelper::isRatepayOrder($order)) {
89+
return;
90+
}
91+
92+
$ratepayData = $order->getExtension(OrderExtension::EXTENSION_NAME);
93+
94+
if (!$ratepayData instanceof RatepayOrderDataEntity) {
95+
$this->logger->warning('Error during bidirectionality: No Ratepay Data was found.', [
96+
'order' => $order->getId(),
97+
'orderNumber' => $order->getOrderNumber(),
98+
]);
99+
return;
100+
}
101+
102+
switch ($event->getToPlace()->getTechnicalName()) {
103+
case OrderTransactionStates::STATE_PAID:
104+
$operation = OrderOperationData::OPERATION_DELIVER;
105+
$service = $this->paymentDeliverService;
106+
break;
107+
default:
108+
// do nothing
109+
return;
110+
}
111+
112+
$this->performOperation($event, $order, $operation, $service, $ratepayData);
113+
}
114+
115+
protected function onDeliveryStatusTransition(StateMachineTransitionEvent $event): void
116+
{
117+
if (!$this->configService->isAutoOperationBasedOnDeliveryStatusEnabled()) {
60118
return;
61119
}
62120

@@ -79,30 +137,47 @@ public function onTransition(StateMachineTransitionEvent $event): void
79137

80138
if (!$ratepayData instanceof RatepayOrderDataEntity) {
81139
$this->logger->warning('Error during bidirectionality: No Ratepay Data was found.', [
82-
'order' => $order->getId(),
140+
'order' => $order->getId(),
83141
'orderNumber' => $order->getOrderNumber(),
84142
]);
85143
return;
86144
}
87145

88146
switch ($event->getToPlace()->getTechnicalName()) {
89147
case OrderDeliveryStates::STATE_SHIPPED:
148+
if ($this->configService->getCaptureTrigger() !== 'deliver') {
149+
// do nothing
150+
return;
151+
}
90152
$operation = OrderOperationData::OPERATION_DELIVER;
91-
$service = $this->paymentDeliverService;
153+
$service = $this->paymentDeliverService;
92154
break;
93155
case OrderDeliveryStates::STATE_CANCELLED:
156+
if (!$this->configService->isTransactionRefundsOnDeliveryStatusChange()) {
157+
// do nothing
158+
return;
159+
}
94160
$operation = OrderOperationData::OPERATION_CANCEL;
95-
$service = $this->paymentCancelService;
161+
$service = $this->paymentCancelService;
96162
break;
97163
case OrderDeliveryStates::STATE_RETURNED:
164+
if (!$this->configService->isTransactionRefundsOnDeliveryStatusChange()) {
165+
// do nothing
166+
return;
167+
}
98168
$operation = OrderOperationData::OPERATION_RETURN;
99-
$service = $this->paymentReturnService;
169+
$service = $this->paymentReturnService;
100170
break;
101171
default:
102172
// do nothing
103173
return;
104174
}
175+
$this->performOperation($event, $order, $operation, $service, $ratepayData);
176+
177+
}
105178

179+
protected function performOperation(StateMachineTransitionEvent $event, OrderEntity $order, string $operation, AbstractModifyRequest $service, RatepayOrderDataEntity $ratepayData): void
180+
{
106181
// we need this to prevent endless recursion if update-delivery-status is enabled.
107182
// this should never happen, because shopware can not change the status to the actual status again and so this subscriber should never called again.
108183
$event->getContext()->addExtension('ratepay', new ArrayStruct([
@@ -114,17 +189,17 @@ public function onTransition(StateMachineTransitionEvent $event): void
114189
$response = $service->doRequest($orderOperationData);
115190
if (!$response->getResponse()->isSuccessful()) {
116191
$this->logger->error('Error during bidirectionality. (Exception: ' . $response->getResponse()->getReasonMessage() . ')', [
117-
'order' => $order->getId(),
118-
'transactionId' => $ratepayData->getTransactionId(),
119-
'orderNumber' => $order->getOrderNumber(),
192+
'order' => $order->getId(),
193+
'transactionId' => $ratepayData->getTransactionId(),
194+
'orderNumber' => $order->getOrderNumber(),
120195
'itemsToProcess' => $orderOperationData->getItems(),
121196
]);
122197
}
123198
} catch (Exception $exception) {
124199
$this->logger->critical('Exception during bidirectionality. (Exception: ' . $exception->getMessage() . ')', [
125-
'order' => $order->getId(),
126-
'transactionId' => $ratepayData->getTransactionId(),
127-
'orderNumber' => $order->getOrderNumber(),
200+
'order' => $order->getId(),
201+
'transactionId' => $ratepayData->getTransactionId(),
202+
'orderNumber' => $order->getOrderNumber(),
128203
'itemsToProcess' => $orderOperationData->getItems(),
129204
]);
130205
}

src/Core/PluginConfigService.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,20 @@ public function isUpdateDeliveryStatusOnOrderItemOperation(): bool
106106
return (bool) ($config['updateDeliveryStatus'] ?? false);
107107
}
108108

109+
public function getCaptureTrigger(): string
110+
{
111+
$config = $this->getPluginConfiguration();
112+
113+
return $config['captureTrigger'] ?? 'deliver';
114+
}
115+
116+
public function isTransactionRefundsOnDeliveryStatusChange(): bool
117+
{
118+
$config = $this->getPluginConfiguration();
119+
120+
return (bool) ($config['automaticTransactionRefunds'] ?? true);
121+
}
122+
109123
protected function getContext(): Context
110124
{
111125
return Context::createDefaultContext();

src/Resources/config/config.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,24 @@
194194
<label lang="de-DE">Automatische Versandmeldung von virtuellen Produkten deaktivieren</label>
195195
</input-field>
196196

197+
<input-field type="single-select">
198+
<name>captureTrigger</name>
199+
<options>
200+
<option><id>deliver</id><name>On delivery status "Shipped"</name><name lang="de-DE">Bei Lieferungstatus "Versandt"</name></option>
201+
<option><id>pay</id><name>On payment status "Paid"</name><name lang="de-DE">Bei Zahlungsstatus "Bezahlt"</name></option>
202+
</options>
203+
<defaultValue>deliver</defaultValue>
204+
<label>Capture trigger</label>
205+
<label lang="de-DE">Auslöser Zahlungseinzug</label>
206+
</input-field>
207+
208+
<input-field type="bool">
209+
<name>automaticTransactionRefunds</name>
210+
<label>Refund transactions automatically when order delivery status changes to "Cancelled" or "Returned".</label>
211+
<label lang="de-DE">Transaktionen automatisch erstatten, wenn sich der Lieferstatus auf "Abgebrochen" oder "Retour" ändert.</label>
212+
<defaultValue>true</defaultValue>
213+
</input-field>
214+
197215
<input-field type="textarea">
198216
<name>featureFlags</name>
199217
<label>Feature Flags</label>

0 commit comments

Comments
 (0)