three_ds_required, next_action, and final settlement.
What 3DS changes in your flow
3DS adds one asynchronous customer-authentication step between card submission and the final payment result. That means:- your frontend may need to pause for a bank challenge or issuer approval flow
- your backend still creates the transaction normally
- your order must stay pending until the final webhook or reconciliation confirms success or failure
Recommended operating model
State handling rules
| State | Meaning | What your system should do |
|---|---|---|
pending | the card flow started but is not final | keep checkout open and wait |
three_ds_required | issuer authentication is still required | let Payment Element continue the challenge |
authorized | issuer approved, but your internal fulfillment rule may still wait for a later state | keep pending unless your business explicitly ships on authorization |
captured | final merchant-safe success | fulfill the order |
refused | the issuer or acquirer rejected the charge | show retry or another payment method |
canceled | the attempt was canceled during the flow | close the attempt and let the customer retry |
three_ds_required as a successful payment.
Frontend pattern
When possible, letelements.submit() orchestrate 3DS automatically.
What the browser should do
- show a submitting or authenticating state while
elements.submit()is running - prevent double-submits during the challenge flow
- treat the immediate response as provisional unless the final state is already terminal
- return the shopper to a pending screen if the challenge completes but settlement is still asynchronous
Backend pattern
Your backend should stay simple: create the transaction, return the Pagou response, and let webhook processing own final fulfillment.Webhook ownership of final state
Your webhook consumer should be the source of truth for fulfillment.Failure modes to plan for
- The customer closes the challenge window: keep the order pending, then reconcile or wait for webhook outcome.
- The browser times out after the challenge: query
GET /v2/transactions/{id}before telling the customer to retry. - The issuer declines after 3DS: surface a recoverable card-failure message and keep inventory reserved only if your business requires it.
- The webhook arrives before the browser flow fully finishes: trust the backend state machine, not the browser session.
Production checklist
- Use one stable
external_refper order attempt. - Store the Pagou transaction ID returned by your backend.
- Disable duplicate submit while the challenge is in progress.
- Fulfill only on a final state such as
capturedorpaid. - Reconcile uncertain outcomes through
GET /v2/transactions/{id}.

