fix(checkout): defer the guest logout while PUI payment instructions are pending - #827
Max Stegmeyer (mstegmeyer) wants to merge 1 commit into
Conversation
The PUI finish page is the only one that is not self-contained: when the instructions are not back from Ratepay yet it renders a polling widget that needs two further authenticated requests. The automatic guest logout runs between loading and rendering that page, so the polling died in a destroyed session and the customer ended up on the order edit page with a payment declined error on a payment that had actually been captured. The suppression that was shipped for this cancelled the logout for every PUI order, which honours the finish page but silently voids the merchant setting forever. Suppress it only while the polling widget is actually rendered, so the logout happens on the reload that shows the instructions. A voided PayPal order also reported "not ready" instead of failing, so a genuinely declined payment polled indefinitely. It now throws a dedicated terminal exception.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f86b1f2f42
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "Codex (@codex) review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "Codex (@codex) address that feedback".
| } catch (MissingPaymentInstructionsException $e) { | ||
| // paid, but PayPal sent no instructions, so render the page without them |
There was a problem hiding this comment.
Reload the finish page when polling finds missing instructions
When the initial finish-page request sees a pending order but a later polling request sees COMPLETED without instructions, MissingPaymentInstructionsException is returned by the polling endpoint as HTTP 404. The existing polling client treats every status other than 417 as a payment failure and redirects to errorUrl, so this new catch is never reached and a successfully completed payment is presented as declined. The polling response must distinguish this terminal successful-without-instructions case and reload the finish page instead.
Useful? React with 👍 / 👎.
| } catch (MissingPaymentInstructionsException $e) { | ||
| // paid, but PayPal sent no instructions, so render the page without them |
There was a problem hiding this comment.
Mark completed payments paid before accepting missing details
When PayPal reports COMPLETED without instructions, this catch now treats the result as a terminal, successfully renderable finish page, but PUIInstructionsFetchService throws MissingPaymentInstructionsException before calling the transaction state's paid() transition. The transaction therefore remains authorized/in-progress despite the completed payment, and the scheduled fetch task continues selecting it while its message handler does not catch this exception, producing repeated failures and preventing downstream paid-order processing. Finalize the transaction state before handling missing instructions as a nonfatal display condition.
Useful? React with 👍 / 👎.
1. Why is this change necessary?
The Pay Upon Invoice finish page is the only checkout finish page that is not self-contained: when Ratepay has not returned the bank details yet, it renders a polling widget that needs further authenticated requests. The automatic guest logout runs between loading and rendering that page, so the polling ran into a destroyed session and the customer landed on the order edit page with a "payment declined" error — on a payment that had in fact been captured.
The fix shipped for this in 10.1.1 cancelled the logout for every PUI order. That unblocks the page, but it silently voids the merchant's setting forever.
2. What does this change do, exactly?
It defers the logout rather than cancelling it: the suppression now applies only while the polling widget is actually rendered, so the logout runs as configured on the reload that shows the instructions.
Whether polling is pending is no longer inferred from "no instructions present", because a third case exists between the two: a completed payment that came back without any instructions. That one used to throw straight through the page loader, and now renders the page with a notice instead.
Separately, a voided PayPal order reported "not ready" instead of failing, so a genuinely declined payment kept polling indefinitely. It now raises a terminal exception, which the storefront's existing error path already handles.
3. Describe each step to reproduce the issue or behaviour.
Enable "log out guest customers after order" under Settings → Cart, then order as a guest with Pay Upon Invoice and let the payment instructions arrive late enough for the finish page to show the polling spinner.
4. Please link to the relevant issues (if any).
closes shopware/shopware#7962
5. Checklist