diff --git a/CHANGELOG.md b/CHANGELOG.md index 83ab875..117d2e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Changelog All notable changes to this project will be documented in this file. +## [2.0.8] +### Fixed +- Payment status was shown as Failed even though the order was placed successfully. +- Add a new configuration option to enable or disable Known IP Protection for callbacks. ## [2.0.7] ### Fixed diff --git a/Docs/Configuration/shopware_setup_altapay_credentials.png b/Docs/Configuration/shopware_setup_altapay_credentials.png index 4730faf..d6211ee 100644 Binary files a/Docs/Configuration/shopware_setup_altapay_credentials.png and b/Docs/Configuration/shopware_setup_altapay_credentials.png differ diff --git a/composer.json b/composer.json index bf83c4e..1adda35 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "description": "AltaPay plugin for Shopware 6", "type": "shopware-platform-plugin", "license": "MIT", - "version": "2.0.7", + "version": "2.0.8", "authors": [ { "name": "AltaPay A/S", diff --git a/src/Controller/CallbackController.php b/src/Controller/CallbackController.php index d9efca8..eaf7f31 100644 --- a/src/Controller/CallbackController.php +++ b/src/Controller/CallbackController.php @@ -165,8 +165,12 @@ public function getError(Request $request): Response )] public function notification(Request $request, SalesChannelContext $salesChannelContext) { - if (!IpUtils::checkIp($request->getClientIp(), PaymentService::ALTAPAY_IP_ADDRESS_SET)) { - return new Response('Invalid request', 400); + $enableKnownIpProtection = $this->systemConfigService->getBool( + 'WexoAltaPay.config.enableKnownIpProtection', + $salesChannelContext->getSalesChannelId() + ); + if ($enableKnownIpProtection && !IpUtils::checkIp($request->getClientIp(), PaymentService::ALTAPAY_IP_ADDRESS_SET)) { + return new Response('Invalid callback request', 400); } try { $result = new SimpleXMLElement($request->get('xml')); diff --git a/src/Resources/config/config.xml b/src/Resources/config/config.xml index 533da7a..01064a6 100644 --- a/src/Resources/config/config.xml +++ b/src/Resources/config/config.xml @@ -54,6 +54,18 @@ false + + Known IP Protection + + enableKnownIpProtection + + true + + Restricts callbacks to known gateway IP addresses. + Disable this option if the store is using a firewall or proxy service (such as Cloudflare). + + + Checkout Settings diff --git a/src/Service/PaymentService.php b/src/Service/PaymentService.php index ff389ec..c465129 100644 --- a/src/Service/PaymentService.php +++ b/src/Service/PaymentService.php @@ -56,7 +56,8 @@ class PaymentService extends AbstractPaymentHandler public const ALTAPAY_TRANSACTION_ID_CUSTOM_FIELD = "wexoAltaPayTransactionId"; public const ALTAPAY_TRANSACTION_PAYMENT_SCHEME_NAME_CUSTOM_FIELD = "wexoAltapayTransactionPaymentSchemeName"; public const ALTAPAY_TRANSACTION_PAYMENT_NATURE_CUSTOM_FIELD = "wexoAltapayTransactionPaymentNature"; - public const ALTAPAY_IP_ADDRESS_SET = ["185.206.120.0/24", "2a10:a200::/29"]; + public const ALTAPAY_IP_ADDRESS_SET = ["185.206.120.0/24", "2a10:a200::/29", '185.203.232.129', '185.203.233.129']; //NOSONAR + public const ALTAPAY_ORDER_STATUS = "altaPayOrderStatus"; public function __construct( protected readonly SystemConfigService $systemConfigService, @@ -268,6 +269,12 @@ public function transactionCallback( case "Open": break; case "Success": + $customFields = $order->getCustomFields() ?? []; + $orderStatus = $customFields[self::ALTAPAY_ORDER_STATUS] ?? null; + + if ($orderStatus === 'processed') { + break; + } // Delete cart when either customer or AltaPay reaches this page. $cartToken = $order->getCustomFieldsValue(field: WexoAltaPay::ALTAPAY_CART_TOKEN); if (!empty($cartToken)) { @@ -280,41 +287,47 @@ public function transactionCallback( $stateMachineState = $transaction->getStateMachineState(); // Handle case when state machine state is null - force status update if (!$stateMachineState) { - // Force the transaction to open state first, then process - $this->orderTransactionStateHandler->reopen( - $transaction->getId(), - $salesChannelContext->getContext() - ); - - // Now process to in_progress - $this->orderTransactionStateHandler->process( - $transaction->getId(), - $salesChannelContext->getContext() - ); - - // Handle payment status - if ($result->Body->Transactions->Transaction->CapturedAmount > 0) { - $this->orderTransactionStateHandler->paid( + try { + // Force the transaction to open state first, then process + $this->orderTransactionStateHandler->reopen( $transaction->getId(), $salesChannelContext->getContext() ); - if ($updateOrderStateAfterPayment) { - // Update order state to "in progress" - $this->updateOrderStateToInProgress($order, $salesChannelContext->getContext()); - } - } elseif ($result->Body->Transactions->Transaction->ReservedAmount > 0) { - $this->orderTransactionStateHandler->authorize( + // Now process to in_progress + $this->orderTransactionStateHandler->process( $transaction->getId(), $salesChannelContext->getContext() ); - if ($updateOrderStateAfterPayment) { - // Update order state to "in progress" - $this->updateOrderStateToInProgress($order, $salesChannelContext->getContext()); + // Handle payment status + if ($result->Body->Transactions->Transaction->CapturedAmount > 0) { + $this->orderTransactionStateHandler->paid( + $transaction->getId(), + $salesChannelContext->getContext() + ); + + if ($updateOrderStateAfterPayment) { + // Update order state to "in progress" + $this->updateOrderStateToInProgress($order, $salesChannelContext->getContext()); + } + } elseif ($result->Body->Transactions->Transaction->ReservedAmount > 0) { + $this->orderTransactionStateHandler->authorize( + $transaction->getId(), + $salesChannelContext->getContext() + ); + + if ($updateOrderStateAfterPayment) { + // Update order state to "in progress" + $this->updateOrderStateToInProgress($order, $salesChannelContext->getContext()); + } } + $order->changeCustomFields([ + self::ALTAPAY_ORDER_STATUS => 'processed' + ]); + } catch (\Exception $e) { + $this->logger->error("order transaction state error:". $e->getMessage()); } - break; } diff --git a/src/WexoAltaPay.php b/src/WexoAltaPay.php index c90e13d..51615b6 100644 --- a/src/WexoAltaPay.php +++ b/src/WexoAltaPay.php @@ -21,7 +21,7 @@ class WexoAltaPay extends Plugin public const ALTAPAY_FIELD_SET_NAME = "wexoAltaPay"; public const ALTAPAY_PAYMENT_METHOD_FIELD_SET_NAME = "wexoAltaPayPaymentMethod"; public const ALTAPAY_CART_TOKEN = "wexoAltaPayCartToken"; - public const ALTAPAY_PLUGIN_VERSION = '2.0.7'; + public const ALTAPAY_PLUGIN_VERSION = '2.0.8'; public const ALTAPAY_PLUGIN_NAME = 'WexoAltaPay'; public function update(UpdateContext $updateContext): void diff --git a/wiki.md b/wiki.md index c30e7d0..e5f11e9 100644 --- a/wiki.md +++ b/wiki.md @@ -63,9 +63,11 @@ be provided by AltaPay. 3. Enable the **Change the order status to In-Progress after a successful payment** setting if you want to update the order status to **In Progress** automatically after a successful payment. -3. Select the payment form logo to be displayed in the header of the payment form. +4. Enable **Known IP Protection** option to restrict callbacks to known gateway IP addresses. Disable this option if the store is using a firewall or proxy service (such as Cloudflare). -4. From the Checkout Form Style dropdown, choose the preferred checkout form style. +5. Select the payment form logo to be displayed in the header of the payment form. + +6. From the Checkout Form Style dropdown, choose the preferred checkout form style. `Legacy`