Skip to content

Conversation

@dkoo
Copy link
Contributor

@dkoo dkoo commented Nov 17, 2025

All Submissions:

Changes proposed in this Pull Request:

Recover from expired checkout sessions

Attempts to load a new modal checkout session if the current checkout session becomes expired or invalid. This should help users to pick up where they left off if their checkout session hits a dead end. Requires Automattic/newspack-plugin#4310 to prevent the checkout session from attempting to reload the session within the modal checkout iframe, which will result in invalid nonce values and an expired session.

Handle inline checkout errors

#2247 added a "processing payment..." overlay when attempting to complete a transaction via modal checkout. This includes error handling for if the request fails on the server and returns an error to the AJAX request, but it doesn't handle inline errors thrown by and shown inline by the payment gateway form, which happens in an iframe element and prevents the checkout AJAX request from proceeding.

In this scenario, the checkout form will trigger a checkout_place_order jQuery event, but will not trigger any other event to indicate that the iframe's form validation failed, so we need to manually check the form's checkout processing state and infer an error state if it stops processing before we receive the checkout_place_order_success event.

Closes NPPM-2394.

How to test the changes in this Pull Request:

When testing, make sure your Woo and Newspack settings allow for anonymous checkouts without registering or logging in first.

Recover from expired checkout sessions

  1. On trunk, start a modal checkout as an anonymous reader.
  2. On the second screen of the modal, attempt to complete checkout with a card number which will be declined (see Stripe test card numbers). Observe that the modal checkout goes back to the first screen, and that after this you're unable to proceed past this screen or complete checkout.
  3. Check out this branch and fix(modal-checkout): prevent session reload after new customer account newspack-plugin#4310.
  4. In a new anonymous browser session, repeat steps 1-2:
  5. After checking out with the declined card number, the checkout shows the proper error message:
Screenshot 2025-11-17 at 2 54 05 PM
  1. After resubmitting this form, confirm that you briefly see an error message stating "We ran into a problem processing this request. Trying again..." before the modal checkout reloads itself back to the second screen with the same transaction details already loaded.
  2. After the checkout modal reloads, confirm that you can successfully complete the transaction with a valid card number.

Handle inline checkout errors

  1. On trunk, start a modal checkout as an anonymous reader.
  2. On the second screen of the modal, attempt to complete checkout without filling in any payment details. Observe that the modal hangs in the "processing payment..." overlay state and never resolves (you can also use dev tools to hide the overlay and see that there are inline form errors hidden underneath it).
  3. Check out this branch, repeat in a new anonymous browser session, and confirm that after a brief moment, the overlay disappears and allows you to see and correct the inline form errors.

Other information:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your changes, as applicable?
  • Have you successfully ran tests with your changes locally?

@dkoo dkoo self-assigned this Nov 17, 2025
@dkoo dkoo changed the title fix: handle inline checkout form validation errors fix: handle checkout form inline errors and expired sessions Nov 17, 2025
@dkoo dkoo marked this pull request as ready for review November 17, 2025 21:59
@dkoo dkoo requested a review from a team as a code owner November 17, 2025 21:59
@dkoo dkoo requested a review from Copilot November 17, 2025 21:59
Copilot finished reviewing on behalf of dkoo November 17, 2025 22:03
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR improves the modal checkout error handling by addressing two key issues: recovering from expired checkout sessions and handling inline checkout form errors. The changes enable the checkout modal to automatically reload when it encounters critical errors like expired sessions, and properly detect when payment gateway form validation fails inline within the iframe.

Key changes:

  • Added new onCheckoutPlaceOrderProcessing and onCheckoutPlaceOrderCriticalError event handlers to detect and handle different error states
  • Implemented automatic checkout session refresh when critical errors are detected
  • Added error detection logic to identify when checkout form processing stops unexpectedly due to inline validation errors

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
src/modal-checkout/utils.js Renamed event handler from onCheckoutPlaceOrderSuccess to onCheckoutPlaceOrderProcessing for better semantic accuracy, and added new onCheckoutPlaceOrderCriticalError handler
src/modal-checkout/modal.js Added checkout form tracking and refresh functionality to reload checkout session when critical errors occur
src/modal-checkout/index.js Implemented error detection logic to identify inline validation failures and differentiate critical errors from regular checkout errors
includes/class-modal-checkout.php Added new critical error message label and processing payment message timing to support inline error detection

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


/**
* Run a callback when the checkout place order succeeds.
* Run a callback when the checkout place order processing.
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

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

The description is grammatically incomplete. It should read "Run a callback when the checkout place order is processing." (add "is").

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@laurelfulford laurelfulford left a comment

Choose a reason for hiding this comment

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

Hey @dkoo! I ran into some weirdness (description and video below) - just let me know if you can't recreate, and I can try on a JN site!

Recover from expired checkout sessions

This issue is technically fixed (you get the new error message and if you enter a working test credit card the second time it lets you complete the transaction), but it doesn't act like you described:

After entering a credit card that won't work, I either get this (briefly showing the second screen and error before being getting booted to the first screen), or only get the first screen again and no visible error.

Screen.Recording.2025-11-19.at.1.19.08.PM.mov

On trunk, this issue also doesn't present the same for me (so maybe there's something there): instead of kicking me back to the first screen, I get the same infinite loading I get when trying to submit empty credit card information.

Handle inline checkout errors

This works as described!

@laurelfulford
Copy link
Contributor

laurelfulford commented Nov 19, 2025

Hey @dkoo! I retested these PRs on a fresh JN site and was able to narrow this down a bit more:

The issue I found only happens when trying to purchase a giftable subscription:

  • It happens whether or not you check the "This purchase is a gift" checkbox.
  • If you do check the "This purchase is a gift" checkbox, when it kicks you back to the first screen it is no longer checked. The giftee's email is still saved, though, and appears when you re-check it.

If I test it with a non-giftable subscription, I don't think it's quite 1:1 what what you described, but it's a lot closer!

  • When I enter a failing credit card number, I briefly see the error before the second screen is reloaded.
  • I don't see the "We ran into a problem processing this request. Trying again..." message at all, but I'm unclear what's triggering that (entering a working credit card number works fine).

This video shows what I get (it also shows that I don't know how to format postal codes!):

Screen.Recording.2025-11-19.at.2.04.22.PM.mov

@laurelfulford laurelfulford self-requested a review November 20, 2025 23:49
Copy link
Contributor

@laurelfulford laurelfulford left a comment

Choose a reason for hiding this comment

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

Thanks @dkoo!

The behaviour for gitftable products is looking a lot better!

For both giftable and non-giftable products, the error message no longer explains what the issue was - was this deliberate?

Image Image

I think the styles also need to be fixed, but that could be a separate PR. We have CSS in the new My Account styles that should fix it here -- I think we just need to make that more general so it applies anytime these classes are inside of a .newspack-ui container, not just the My Account ones.

@dkoo
Copy link
Contributor Author

dkoo commented Nov 21, 2025

I think the styles also need to be fixed, but that could be a separate PR. We have CSS in the new My Account styles that should fix it here -- I think we just need to make that more general so it applies anytime these classes are inside of a .newspack-ui container, not just the My Account ones.

Good point, I almost didn't notice that it had the wrong styles. e44f4e3 in the other PR should fix this by applying newspack-ui notice styles to all Woo notices that are nested inside a .newspack-ui wrapper.

Screenshot 2025-11-21 at 10 10 50 AM

As for the generic "We ran into an error processing this request...", that message should only be shown when the checkout session becomes invalidated due to a payment processing error that happens in the same session where a new customer account is created, as the creation and authentication of the customer account will invalidate the checkout session which started as an anonymous session. Because this isn't the only scenario when the checkout session could become invalidated, the error message has to be fairly generic.

You should still see the "Your card was declined" error the first time you try to complete checkout with an invalid card number, then when you try to complete the checkout again, that should trigger the checkout modal refresh and the generic error message.

@dkoo dkoo requested a review from laurelfulford November 21, 2025 17:18
Copy link
Contributor

@laurelfulford laurelfulford left a comment

Choose a reason for hiding this comment

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

Thanks for tweaks, @dkoo! 🎉

I ran through the checkout with a bad card:

  • Without login required with a giftable sub
  • Without login required with an ungiftable sub
  • Without login required with regular product

In all cases:

  • I got the credit card declined message
  • When I tried with a good card in the same window, I got the generic error message
  • When I restarted the transaction (closed the modal and reopened it), it let me run it successfully with a good card

I also tested the same products with login required, just in case - in all cases I just got the credit card declined message, then was able to get through fine with a good card in the same modal (as expected since there isn't the account weirdness when you're logged in!).

The error messages are also looking good! :shipit:

@dkoo dkoo merged commit 9beb64e into trunk Nov 21, 2025
8 checks passed
@dkoo dkoo deleted the fix/anon-transaction-failures branch November 21, 2025 20:30
@github-actions
Copy link

Hey @dkoo, good job getting this PR merged! 🎉

Now, the needs-changelog label has been added to it.

Please check if this PR needs to be included in the "Upcoming Changes" and "Release Notes" doc. If it doesn't, simply remove the label.

If it does, please add an entry to our shared document, with screenshots and testing instructions if applicable, then remove the label.

Thank you! ❤️

matticbot pushed a commit that referenced this pull request Nov 27, 2025
# [4.19.0-alpha.1](v4.18.0...v4.19.0-alpha.1) (2025-11-27)

### Bug Fixes

* add a max-width to the Content Carousel block ([#2253](#2253)) ([b791a3a](b791a3a))
* handle checkout form inline errors and expired sessions ([#2255](#2255)) ([9beb64e](9beb64e))
* linting issues ([#2254](#2254)) ([776514b](776514b))
* **modal-checkout:** require change payment class ([#2257](#2257)) ([4d606ef](4d606ef))

### Features

* **donate-block:** default frequency for tiered layout ([#2248](#2248)) ([df0e2f9](df0e2f9))
@matticbot
Copy link
Contributor

🎉 This PR is included in version 4.19.0-alpha.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants