Skip to content

Fix capture action retry payment after abandoning checkout - #335

Open
TheMilek wants to merge 13 commits into
Sylius:3.4from
TheMilek:fix-capture-action-retry-payment-after-abandoning-checkout
Open

Fix capture action retry payment after abandoning checkout#335
TheMilek wants to merge 13 commits into
Sylius:3.4from
TheMilek:fix-capture-action-retry-payment-after-abandoning-checkout

Conversation

@TheMilek

@TheMilek TheMilek commented Mar 27, 2026

Copy link
Copy Markdown
Member

fixes #329

How it is fixed

StatusAction maps open to markNew(). open means nothing happened and the session is still payable, which is what new means in Sylius. processing is now reached from pending, where the customer has committed on the PSP side. No core change needed, both gates are satisfied by the payment telling the truth.

ConvertMolliePaymentAction carries the tracked ids into its result. Not a separate decision, the price of the one above: Payum\Core\Action\CapturePaymentAction re-runs Convert on every capture while the status is new and replaces Payment::details with the result, so without carrying payment_mollie_id over, CaptureAction cannot recognise the session it created and builds a competing one each round trip.

CaptureAction delegates to ExistingMollieSessionResolver, which answers with one of three decisions, in order:

  • leave it to the status flow, when the resource is not open, or when the request arrived on the same Payum token that is the resource's redirectUrl. Mollie redirects back to the token that created the session after every attempt, abandoned ones included, so that equality identifies a return rather than a new intent. This is the cut that closes the loop.
  • resume, when the method on the resource matches the requested one. The method reaches Payment::details only through a form submission, so equality means nothing new was chosen. We PATCH redirectUrl to the current token and redirect to the existing checkoutUrl. The PATCH is needed because CaptureController::doAction() invalidates the token once execute() returns normally, so without it the customer would come back to a dead token after paying.
  • replace, when a different method was chosen. The old session is locked to the old method, so it is cancelled where Mollie allows it and exactly one new session is created.

One Mollie payment per order, plus one per deliberate method change.

The orphan log moves to error level so it survives realistic gateway settings, and says that money was collected and needs review.

Once an order is placed, only surcharge neutral methods are offered. PaymentSurchargeProcessor bails on !$order->canBeProcessed(), which is state === STATE_CART, so after checkout the total can no longer follow the method: switching from a 5.00 fee to a 4.00 one left the order charging 5.00. MolliePaymentsMethodResolver now offers only methods whose surcharge equals the one already on the order. The selected method's surcharge is by construction the one that produced the adjustment, so the list never comes back empty, and nothing changes during checkout.

To compare surcharges without reimplementing them, the fee calculators gained PaymentSurchargeAmountCalculatorInterface, reporting an amount instead of applying it, and calculate() delegates to it so the two cannot drift apart.

@TheMilek
TheMilek force-pushed the fix-capture-action-retry-payment-after-abandoning-checkout branch 3 times, most recently from 5fb2883 to 5bc05ce Compare April 21, 2026 11:54
Comment thread src/Payum/Action/NotifyAction.php Outdated
}
}
if (isset($details['payment_mollie_id']) || isset($details['order_mollie_id'])) {
$handled = $this->handleExistingMolliePayment($request, $details);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

allows to choose different payment method

@TheMilek
TheMilek force-pushed the fix-capture-action-retry-payment-after-abandoning-checkout branch 2 times, most recently from c9808de to 5bbb584 Compare April 22, 2026 13:02
@marekrzytki
marekrzytki force-pushed the fix-capture-action-retry-payment-after-abandoning-checkout branch from 5bbb584 to a5c256f Compare August 11, 2026 07:56
@TheMilek
TheMilek marked this pull request as ready for review August 11, 2026 11:39
@TheMilek
TheMilek force-pushed the fix-capture-action-retry-payment-after-abandoning-checkout branch from ad6ed99 to 8900d9e Compare August 17, 2026 11:58
@TheMilek
TheMilek force-pushed the fix-capture-action-retry-payment-after-abandoning-checkout branch from 8900d9e to ef04697 Compare August 17, 2026 12:43
Comment thread src/Payum/Action/CaptureAction.php
Comment thread src/Payum/Action/CaptureAction.php Outdated
Comment thread src/Resolver/MolliePaymentsMethodResolver.php Outdated
Comment thread src/Api/Controller/SelectMollieMethodAction.php Outdated
Comment thread UPGRADE-3.4.md
Comment thread src/Payum/Action/ConvertMolliePaymentAction.php
Comment thread src/Resolver/MolliePaymentsMethodResolver.php Outdated
Comment thread src/Resolver/MolliePaymentsMethodResolver.php Outdated
@TheMilek
TheMilek changed the base branch from 3.3 to 3.4 August 17, 2026 13:59
@TheMilek
TheMilek force-pushed the fix-capture-action-retry-payment-after-abandoning-checkout branch from 5585085 to bd6574a Compare August 18, 2026 06:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CaptureAction early return breaks payment retry after abandoned checkout

4 participants