Skip to content

Commit 669f53e

Browse files
update: implement browser back button handling to control order cancellation behavior
1 parent b20bece commit 669f53e

File tree

16 files changed

+205
-21
lines changed

16 files changed

+205
-21
lines changed

Controller/Redirect/Process.php

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,22 @@ protected function handleFailed($statusCode)
512512
$this->removeCoupon();
513513
$this->removeAmastyGiftcardOnFailed();
514514

515+
// Detect browser back button scenario
516+
$isBrowserBack = ($statusCode === $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_CANCELLED_BY_USER'));
517+
518+
// Check configuration for browser back behavior
519+
$store = $this->order->getStore();
520+
$shouldCancelOnBrowserBack = (bool) $this->accountConfig->getCancelOnBrowserBack($store);
521+
522+
$this->logger->addDebug(sprintf(
523+
'%s - Handle Failed Check | Order: %s | statusCode: %s | isBrowserBack: %s | shouldCancelOnBrowserBack: %s',
524+
__METHOD__,
525+
$this->order->getIncrementId(),
526+
$statusCode,
527+
var_export($isBrowserBack, true),
528+
var_export($shouldCancelOnBrowserBack, true)
529+
));
530+
515531
if (!$this->getSkipHandleFailedRecreate()) {
516532
if (!$this->quoteRecreate->recreate($this->quote, $this->response)) {
517533
$this->logger->addError('Could not recreate the quote.');
@@ -530,7 +546,7 @@ protected function handleFailed($statusCode)
530546
$this->helper->getStatusCode('BUCKAROO_MAGENTO2_ORDER_FAILED') => 'Unfortunately an error occurred while processing your payment. Please try again. If this error persists, please choose a different payment method.',
531547
$this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_FAILED') => 'Unfortunately an error occurred while processing your payment. Please try again. If this error persists, please choose a different payment method.',
532548
$this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_REJECTED') => 'Unfortunately an error occurred while processing your payment. Please try again. If this error persists, please choose a different payment method.',
533-
$this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_CANCELLED_BY_USER') => 'According to our system, you have canceled the payment. If this is not the case, please contact us.',
549+
$this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_CANCELLED_BY_USER') => 'Payment cancelled. You can try again using the same or a different payment method.',
534550
];
535551

536552
$this->addErrorMessage(__($statusCodeAddErrorMessage[$statusCode] ?? 'An error occurred while processing your payment.'));
@@ -540,12 +556,45 @@ protected function handleFailed($statusCode)
540556
return $this->redirectFailure();
541557
}
542558

543-
// Cancel the order and log an error if it fails
544-
if (!$this->cancelOrder($statusCode, $statusCodeAddErrorMessage[$statusCode])) {
545-
$this->logger->addError('Could not cancel the order.');
559+
// For browser back button, check configuration
560+
if ($isBrowserBack && !$shouldCancelOnBrowserBack) {
561+
$this->logger->addDebug(sprintf(
562+
'%s - Browser Back Button Detected - Order left in pending state (config: cancel_on_browser_back = disabled). Quote recreated for retry. Order: %s',
563+
__METHOD__,
564+
$this->order->getIncrementId()
565+
));
566+
567+
// Add a status history comment to track this
568+
$this->order->addCommentToStatusHistory(
569+
__('Customer returned using browser back button. Order left pending for push notification.'),
570+
false,
571+
false
572+
);
573+
$this->order->save();
574+
575+
} else {
576+
// For actual failures OR if config says to cancel on browser back, cancel the order as before
577+
if ($isBrowserBack) {
578+
$this->logger->addDebug(sprintf(
579+
'%s - Browser Back Button Detected - Order will be canceled (config: cancel_on_browser_back = enabled). Order: %s',
580+
__METHOD__,
581+
$this->order->getIncrementId()
582+
));
583+
}
584+
585+
if (!$this->cancelOrder($statusCode, $statusCodeAddErrorMessage[$statusCode])) {
586+
$this->logger->addError('Could not cancel the order.');
587+
}
546588
}
547589

548-
$this->logger->addDebug(__METHOD__ . '|8|');
590+
$this->logger->addDebug(sprintf(
591+
'%s - Redirect Failure | Order: %s | isBrowserBack: %s | shouldCancelOnBrowserBack: %s',
592+
__METHOD__,
593+
$this->order->getIncrementId(),
594+
var_export($isBrowserBack, true),
595+
var_export($shouldCancelOnBrowserBack, true)
596+
));
597+
549598
return $this->redirectFailure();
550599
}
551600

Model/ConfigProvider/Account.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
* @method mixed getSuccessRedirect()
4040
* @method mixed getFailureRedirect()
4141
* @method mixed getCancelOnFailed()
42+
* @method mixed getCancelOnBrowserBack()
4243
* @method mixed getDigitalSignature()
4344
* @method mixed getDebugTypes()
4445
* @method mixed getDebugEmail()
@@ -68,6 +69,7 @@ class Account extends AbstractConfigProvider
6869
public const XPATH_ACCOUNT_FAILURE_REDIRECT = 'buckaroo_magento2/account/failure_redirect';
6970
public const XPATH_ACCOUNT_FAILURE_REDIRECT_TO_CHECKOUT = 'buckaroo_magento2/account/failure_redirect_to_checkout';
7071
public const XPATH_ACCOUNT_CANCEL_ON_FAILED = 'buckaroo_magento2/account/cancel_on_failed';
72+
public const XPATH_ACCOUNT_CANCEL_ON_BROWSER_BACK = 'buckaroo_magento2/account/cancel_on_browser_back';
7173
public const XPATH_ACCOUNT_DIGITAL_SIGNATURE = 'buckaroo_magento2/account/digital_signature';
7274
public const XPATH_ACCOUNT_DEBUG_TYPES = 'buckaroo_magento2/account/debug_types';
7375
public const XPATH_ACCOUNT_DEBUG_EMAIL = 'buckaroo_magento2/account/debug_email';
@@ -129,6 +131,7 @@ public function getConfig($store = null)
129131
'failure_redirect' => $this->getFailureRedirect($store),
130132
'failure_redirect_to_checkout' => $this->getFailureRedirectToCheckout($store),
131133
'cancel_on_failed' => $this->getCancelOnFailed($store),
134+
'cancel_on_browser_back' => $this->getCancelOnBrowserBack($store),
132135
'digital_signature' => $this->getDigitalSignature($store),
133136
'debug_types' => $this->getDebugTypes($store),
134137
'debug_email' => $this->getDebugEmail($store),

Model/Method/AbstractMethod.php

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -834,9 +834,10 @@ public function order(InfoInterface $payment, $amount)
834834

835835
if (!(isset($response[0]->RequiredAction->Type) && $response[0]->RequiredAction->Type === 'Redirect')) {
836836
$this->setPaymentInTransit($payment, false);
837-
$this->helper->setRestoreQuoteLastOrder($order->getId());
838837
}
839838

839+
$this->helper->setRestoreQuoteLastOrder($order->getId());
840+
840841
$this->eventManager->dispatch('buckaroo_order_after', ['order' => $order]);
841842

842843
$this->afterOrder($payment, $response);
@@ -2856,16 +2857,36 @@ private function cancelPreviousPendingOrder(InfoInterface $payment)
28562857
$order = $orderRepository->get((int)$orderId);
28572858

28582859
if ($order->getState() === Order::STATE_NEW) {
2859-
$orderManagement = $this->objectManager->get(OrderManagementInterface::class);
2860-
$orderManagement->cancel($order->getEntityId());
2861-
$order->addCommentToStatusHistory(
2862-
__('Canceled on browser back button')
2863-
)
2864-
->setIsCustomerNotified(false)
2865-
->setEntityName('invoice')
2866-
->save();
2867-
}
2860+
$this->logger2->addDebug(sprintf(
2861+
'[%s] Canceling previous pending order: %s (browser back scenario)',
2862+
__METHOD__,
2863+
$order->getIncrementId()
2864+
));
28682865

2866+
try {
2867+
$order->cancel()->save();
2868+
2869+
$order->addCommentToStatusHistory(
2870+
__('Canceled on browser back button - customer placed a new order.')
2871+
)
2872+
->setIsCustomerNotified(false)
2873+
->save();
2874+
2875+
$this->logger2->addDebug(sprintf(
2876+
'[%s] Successfully canceled order: %s and restored stock',
2877+
__METHOD__,
2878+
$order->getIncrementId()
2879+
));
2880+
} catch (\Exception $e) {
2881+
$this->logger2->addError(sprintf(
2882+
'[%s] Failed to cancel order: %s - Error: %s',
2883+
__METHOD__,
2884+
$order->getIncrementId(),
2885+
$e->getMessage()
2886+
));
2887+
throw $e;
2888+
}
2889+
}
28692890

28702891
} catch (\Throwable $th) {
28712892
$this->logger2->addError(__METHOD__." ".(string)$th);

Model/Push.php

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,17 @@ private function receivePushCheckDuplicates($receivedStatusCode = null, $trxId =
708708
$trxId = $this->postData['brq_transactions'];
709709
}
710710
$payment = $this->order->getPayment();
711+
712+
// Check if order was canceled and payment succeeds - reactivate it
713+
if (
714+
$this->order->getState() === Order::STATE_CANCELED
715+
&& $receivedStatusCode === $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS')
716+
&& (!isset($this->postData['brq_relatedtransaction_partialpayment'])
717+
|| $this->postData['brq_relatedtransaction_partialpayment'] == null)
718+
) {
719+
$this->reactivateCanceledOrder();
720+
}
721+
711722
$ignoredPaymentMethods = [
712723
Giftcards::PAYMENT_METHOD_CODE,
713724
Transfer::PAYMENT_METHOD_CODE,
@@ -757,6 +768,54 @@ private function receivePushCheckDuplicates($receivedStatusCode = null, $trxId =
757768
return false;
758769
}
759770

771+
/**
772+
* Reactivate canceled order when payment succeeds
773+
* Handles scenario where customer clicked back button but payment was completed
774+
*
775+
* @return bool
776+
* @throws \Exception
777+
*/
778+
private function reactivateCanceledOrder(): bool
779+
{
780+
$payment = $this->order->getPayment();
781+
782+
// Check if order was already reactivated to prevent duplicate reactivation
783+
$alreadyReactivated = $payment->getAdditionalInformation('buckaroo_order_reactivated');
784+
785+
if ($alreadyReactivated) {
786+
$this->logging->addDebug(sprintf(
787+
'%s - Order already reactivated in this session, skipping duplicate reactivation. Order: %s',
788+
__METHOD__,
789+
$this->order->getIncrementId()
790+
));
791+
return false;
792+
}
793+
794+
$this->logging->addDebug(sprintf(
795+
'%s - Resetting from CANCELED to STATE_NEW/PENDING | Order: %s',
796+
__METHOD__,
797+
$this->order->getIncrementId()
798+
));
799+
800+
$this->order->setState(Order::STATE_NEW);
801+
$this->order->setStatus('pending');
802+
803+
// Reset canceled quantities
804+
foreach ($this->order->getAllItems() as $item) {
805+
$item->setQtyCanceled(0);
806+
}
807+
808+
// Mark order as reactivated to prevent duplicate reactivation
809+
$payment->setAdditionalInformation('buckaroo_order_reactivated', true);
810+
$payment->save();
811+
812+
// Save the order immediately to persist the state change
813+
$this->order->save();
814+
815+
$this->forceInvoice = true;
816+
return true;
817+
}
818+
760819
/**
761820
* Get and store the postdata parameters
762821
*/

Observer/RestoreQuote.php

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,20 @@ public function execute(Observer $observer)
9797
}
9898

9999
$this->rollbackPartialPayment($lastRealOrder->getIncrementId());
100-
$this->setOrderToCancel($previousOrderId);
100+
101+
$isPaymentInTransit = $payment->getAdditionalInformation(AbstractMethod::BUCKAROO_PAYMENT_IN_TRANSIT) === true;
102+
103+
if ($isPaymentInTransit) {
104+
$this->helper->addDebug(__METHOD__ . '|45|Payment in transit - storing order ID for cancellation on next order placement');
105+
106+
$restoredQuote = $this->checkoutSession->getQuote();
107+
if ($restoredQuote && $restoredQuote->getPayment()) {
108+
$restoredQuote->getPayment()->setAdditionalInformation('buckaroo_cancel_order_id', $previousOrderId);
109+
$restoredQuote->getPayment()->save();
110+
}
111+
} else {
112+
$this->setOrderToCancel($previousOrderId);
113+
}
101114
}
102115
}
103116

@@ -155,11 +168,6 @@ private function processShippingAddress($quote)
155168
*/
156169
private function shouldRestoreQuote($lastRealOrder, $payment)
157170
{
158-
if ($payment->getAdditionalInformation(AbstractMethod::BUCKAROO_PAYMENT_IN_TRANSIT) === true) {
159-
$this->helper->addDebug(__METHOD__ . '|Payment in transit, not restoring quote to prevent duplicate orders');
160-
return false;
161-
}
162-
163171
return (
164172
($this->helper->getRestoreQuoteLastOrder() &&
165173
($lastRealOrder->getData('state') === 'new') &&

etc/adminhtml/system/account.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,13 @@
209209
<config_path>buckaroo_magento2/account/cancel_on_failed</config_path>
210210
</field>
211211

212+
<field id="cancel_on_browser_back" translate="label comment" type="select" sortOrder="115" showInDefault="1" showInWebsite="1" showInStore="1">
213+
<label>Cancel Order on Browser Back Button</label>
214+
<comment><![CDATA[Determines behavior when customer clicks browser back button after reaching payment page:<br/><strong>No (Recommended)</strong>: Order remains pending. If payment completes, order is reactivated automatically.<br/><strong>Yes</strong>: Order is canceled immediately (old behavior). Customer must start over.]]></comment>
215+
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
216+
<config_path>buckaroo_magento2/account/cancel_on_browser_back</config_path>
217+
</field>
218+
212219
<field id="debug_types" translate="label comment" type="multiselect" sortOrder="120" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1">
213220
<label>Debugging</label>
214221
<comment><![CDATA[Decide what to debug. Log files will be created within the var/log/Buckaroo/ directory.]]></comment>

etc/config.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,7 @@
553553
<failure_redirect>checkout/cart</failure_redirect>
554554
<failure_redirect_to_checkout>0</failure_redirect_to_checkout>
555555
<cancel_on_failed>1</cancel_on_failed>
556+
<cancel_on_browser_back>0</cancel_on_browser_back>
556557
<order_status_new>pending</order_status_new>
557558
<order_status_pending>pending_payment</order_status_pending>
558559
<order_status_success>processing</order_status_success>

i18n/de_AT.csv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,3 +507,7 @@
507507
"An error occurred, please try another payment method or try again later."."Ein Fehler ist aufgetreten. Bitte versuchen Sie eine andere Zahlungsmethode oder versuchen Sie es später erneut."
508508
"Payment processing failed. Please try again.","Zahlungsverarbeitung fehlgeschlagen. Bitte versuchen Sie es erneut."
509509
"Payment token is missing. Please try again.","Zahlungstoken fehlt. Bitte versuchen Sie es erneut."
510+
"Cancel Order on Browser Back Button","Cancel Order on Browser Back Button"
511+
"Payment cancelled. You can try again using the same or a different payment method.","Payment cancelled. You can try again using the same or a different payment method."
512+
"Customer returned using browser back button. Order left pending for push notification.","Customer returned using browser back button. Order left pending for push notification."
513+
"Order reactivated: Payment completed after cancellation (Push notification received). Transaction ID: ""%1""","Order reactivated: Payment completed after cancellation (Push notification received). Transaction ID: ""%1"""

i18n/de_CH.csv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,3 +507,7 @@
507507
"An error occurred, please try another payment method or try again later."."Ein Fehler ist aufgetreten. Bitte versuchen Sie eine andere Zahlungsmethode oder versuchen Sie es später erneut."
508508
"Payment processing failed. Please try again.","Zahlungsverarbeitung fehlgeschlagen. Bitte versuchen Sie es erneut."
509509
"Payment token is missing. Please try again.","Zahlungstoken fehlt. Bitte versuchen Sie es erneut."
510+
"Cancel Order on Browser Back Button","Cancel Order on Browser Back Button"
511+
"Payment cancelled. You can try again using the same or a different payment method.","Payment cancelled. You can try again using the same or a different payment method."
512+
"Customer returned using browser back button. Order left pending for push notification.","Customer returned using browser back button. Order left pending for push notification."
513+
"Order reactivated: Payment completed after cancellation (Push notification received). Transaction ID: ""%1""","Order reactivated: Payment completed after cancellation (Push notification received). Transaction ID: ""%1"""

i18n/de_DE.csv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,3 +507,7 @@
507507
"An error occurred, please try another payment method or try again later."."Ein Fehler ist aufgetreten. Bitte versuchen Sie eine andere Zahlungsmethode oder versuchen Sie es später erneut."
508508
"Payment processing failed. Please try again.","Zahlungsverarbeitung fehlgeschlagen. Bitte versuchen Sie es erneut."
509509
"Payment token is missing. Please try again.","Zahlungstoken fehlt. Bitte versuchen Sie es erneut."
510+
"Cancel Order on Browser Back Button","Cancel Order on Browser Back Button"
511+
"Payment cancelled. You can try again using the same or a different payment method.","Payment cancelled. You can try again using the same or a different payment method."
512+
"Customer returned using browser back button. Order left pending for push notification.","Customer returned using browser back button. Order left pending for push notification."
513+
"Order reactivated: Payment completed after cancellation (Push notification received). Transaction ID: ""%1""","Order reactivated: Payment completed after cancellation (Push notification received). Transaction ID: ""%1"""

0 commit comments

Comments
 (0)