Production-safe flow
- Disable duplicate submits in the browser.
- Call
elements.submit(...)once per checkout attempt. - Let your backend create the transaction.
- Let
elements.submit(...)complete card authentication when the payment requires it. - Resume the transaction if the buyer is interrupted mid-payment.
- Fulfill only from webhook or reconciliation state.
Frontend submit pattern
elements.submit(...) drives the whole attempt. It creates an Element session if needed, asks the
hosted card field to tokenize, calls your createTransaction callback with the token payload, then
completes any card authentication the payment requires before resolving.
Authentication needs no extra input from your checkout form. It uses the buyer and products your
backend already sends when it creates the transaction. See
3D Secure.
Resume an interrupted payment
If the buyer reloads or navigates away mid-payment, resume the same transaction instead of starting a new attempt:Token payload
YourcreateTransaction callback receives non-sensitive card metadata with the token:
tokenData.token to your backend to create the transaction. Use brand, last4, exp_month, and exp_year only for provisional checkout UI or your own backend bookkeeping; final payment state still comes from the transaction response, webhook, or reconciliation.
Backend request example
Backend response example
next_action is opaque — elements.submit(...) reads
it and completes card authentication for you.
Common error
Invalid state handling
Keep the submit button disabled until the card field reports a valid state:elements.submit(...) returns { "status": "error" }, do not call your backend again with a missing or stale token. Show the returned error, let the buyer correct the card details, then run a new checkout attempt.

