Updated 5 min read By Namso Gen
3D Secure Testing: How 3DS2 Works and Test Cards That Trigger Each Flow

3D Secure Testing: How 3DS2 Works and Test Cards That Trigger Each Flow

3D Secure (3DS) is the authentication layer that shifts fraud liability from merchants to issuers. It is also the part of checkout testing that breaks most often, because it involves redirects, iframes, mobile SDKs and asynchronous outcomes. This guide covers what to test, which test cards trigger which flow, and the bugs that consistently slip through.

From 3DS1 to 3DS2 in one paragraph

3DS1 was the original browser-redirect flow: the customer left your page, authenticated on the issuer's page, and was redirected back with a result. Visa, Mastercard and American Express retired 3DS1 (3-D Secure 1.0.2) in October 2022, and the last regional extensions ended in 2023, so test plans today only need EMV 3DS (3DS2). 3DS2 sends the issuer far more device and transaction data, so it can approve frictionlessly (no user interaction) or issue a challenge. It has two channels: a browser flow, which collects device data through a hidden 3DS Method iframe and shows the challenge in an iframe (or a provider-hosted redirect), and an app flow that uses the 3DS SDK in native mobile apps.

The three outcomes you must handle

Every 3DS transaction ends in one of three ways, and all three need explicit UI states:

  1. Frictionless success β€” authentication succeeds without user interaction. The most common 3DS2 result.
  2. Challenge β€” the customer is asked to authenticate (OTP, app approval). Handle both success and failure/cancel.
  3. Not enrolled / unsupported β€” the card or issuer does not take part. Either no authentication runs at all, or the network answers on the issuer's behalf with an attempt. Depending on your gateway configuration you proceed or fail the transaction.

Under the hood every result is a transStatus value: Y (authenticated), A (attempted; usually still shifts liability to the issuer), N (not authenticated), R (rejected; do not authorize), U (unavailable, a technical failure with no liability shift). C and D mean a challenge or decoupled authentication is still in progress.

The failure paths are where checkouts break: a cancelled challenge is not the same as a decline, and users who close the modal must be able to try again without rebuilding the whole cart.

Interactive

3D Secure outcome simulator

Pick an outcome to see which steps run and what your checkout has to do.

  1. Create the payment and persist the order
  2. Authentication request with device data
  3. Issuer decision
  4. Customer challenge (OTP or app)
  5. Authorization

What your checkout should do

Stripe test cards for 3DS flows

Stripe documents dedicated test numbers for authentication behaviour:

Card number What it triggers
4000 0025 0000 3155 Requires authentication for on-session payments, and off-session until the card is saved with a SetupIntent
4000 0027 6000 3184 Requires authentication on every payment, however the card was set up
4000 0000 0000 3055 Supports 3DS but does not require it
4000 0000 0000 3220 3DS required; it must be completed for the payment to succeed
4000 0084 0000 1629 3DS required, then the payment is declined (card_declined) after authentication

These are designed for sandbox use only. For other providers, Adyen documents 4917 6100 0000 0000 (Visa enrolled in 3DS2; expiry 03/2030, CVC 737) for challenge flows, and 4111 1111 1111 1111 among its general Visa test cards. Always re-check the current provider docs β€” test card behaviour changes without notice.

A fuller list lives in our test card numbers reference.

Sandbox setup checklist

  • Enable 3DS in the gateway dashboard, not just in the API call. Many gateways have a per-account toggle that silently disables authentication in test mode.
  • Use the 3DS2 SDK in native apps, and test the browser flow (iframe and any redirect your provider uses) separately.
  • Whitelist return URLs for every environment, including local dev tunnels.
  • Test on real mobile devices, not only desktop narrow viewports. In-app browsers (Instagram, TikTok, banking apps) behave differently from Safari and Chrome.
  • Keep the challenge window responsive. A challenge rendered inside a fixed-height iframe is a classic conversion killer.

Bugs that slip through

  • Losing the cart on redirect. Persist the order before starting authentication, not after.
  • Not handling the user pressing back. Browsers restore the page from bfcache; your JS must re-query the payment state instead of assuming a fresh load.
  • Double submission. Users click "Pay" twice while the challenge is open. Use idempotency keys on the authorization request.
  • Assuming success after challenge. The authentication result is a separate signal; the authorization can still decline afterwards.
  • Async webhooks ignored. Some 3DS2 flows complete asynchronously. If you only listen to the redirect, you will miss results.
  • Wrong amount or currency. The authentication covers the amount and currency you sent; if the cart changes, authenticate again (on Stripe, changing a PaymentIntent's amount means confirming it again).

How to test without real cards

You do not need a real card to exercise 3DS. Provider test cards plus generated data cover the full matrix:

  1. Use provider cards for authenticated success, failure and frictionless flows.
  2. Use our card generator to produce large volumes of structurally valid numbers for load, fuzzing and UI tests.
  3. Use the advanced generator when you need every combination of a specific pattern.
  4. Validate any test number with the Luhn validator.

Summary

3DS testing is mostly about covering the unhappy paths: cancelled challenges, failed authentication, asynchronous results and mobile browsers. Provider test cards trigger each flow deliberately, and a generated dataset fills the gaps. Treat authentication as a separate state machine from authorization and you will avoid the majority of production incidents.

Related articles