Prerequisites
- Embedded Checkout: An Embedded Checkout integration with Apple Pay or Google Pay enabled. See the payment methods guide.
- React SDK: The code samples use
@crossmint/client-sdk-react-uiwithCrossmintCheckoutProvider. See React Hooks.
Option 1: Enable the Built-In Error Banner
The checkout component includes an error banner that displays the decline reason. On the Apple Pay and Google Pay screens this banner is hidden by default. Enable it with one appearance rule —appearance.rules.GlobalMessage.display: "visible":
The built-in banner dismisses automatically after 8 seconds. If your page constrains the checkout iframe’s height,
the banner can render outside the visible area. For full control over placement and persistence, use Option 2.
Option 2: Render Your Own Error Message
The checkout reports every order change to your page. After a decline, the updated order containspayment.failureReason. Read it with the useCrossmintCheckout hook and render the message anywhere on your page:
failureReason whenever it appears, and clear your error UI when the buyer starts a new attempt.
Tell a Cancellation Apart from a Decline
The sheet closing is ambiguous on its own: it happens both when the buyer cancels and when the card is declined. Use the order state to distinguish the two:
A cancellation never produces a
failureReason, and a decline always does. Gate your error UI strictly on failureReason — never on the sheet closing.
The failureReason Object
Common
code values include insufficient_funds, expired_card, incorrect_cvc, incorrect_number, do_not_honor, card_not_supported, authentication_required, issuer_unavailable, duplicate_transaction, and generic. Codes that do not map to a specific reason collapse to generic.
Most declines return the order to the awaiting-payment state, so the buyer can retry — ideally with a different card or payment method, as the message suggests where relevant. Some declines are terminal and leave the order in a failed state; in those cases the order does not return to awaiting-payment and a retry on the same order is not possible. Gate any “retry” affordance on the order returning to awaiting-payment rather than assuming every decline is retryable, and never retry a declined payment automatically on the buyer’s behalf.
Common Gotchas
The error message renders but the buyer never sees it
The error message renders but the buyer never sees it
The checkout iframe’s height is managed dynamically by the SDK. If your page wraps the iframe in a
fixed-height container with internal scrolling, content near the bottom — including the built-in error banner —
can land below the fold. Let the SDK manage the iframe height, or render your own error message outside the
iframe (Option 2).
The decline arrives after the sheet is already closed
The decline arrives after the sheet is already closed
This is expected, particularly with Google Pay, where authorization completes before the charge is attempted.
Keep observing order updates after the sheet closes instead of checking once.

