Process 3DS Payments (Redirect)
This guide walks through authenticating a card payment with 3D Secure using the redirect transport: Credova creates the 3DS session server-side, and any challenge is presented by navigating the cardholder to a hosted page. When the challenge finishes, the cardholder is returned to a callback route you host. For a conceptual overview and the comparison with the iframe transport, see 3D Secure.
The redirect transport requires no JavaScript SDK on your checkout page, which makes it a good fit for native mobile webviews and server-rendered checkouts.
Before you start
Secret Key- Authenticates requests from your server. Never send it to the browser.
Prerequisites
This guide assumes you have:
- A saved card. Save one with Save Cards from your web app or your servers to get a
card_…payment method. - 3DS enabled on your account. 3DS is off by default — contact support to enable it.
- Two callback routes you control — a success URL and a failure URL — that Basis Theory will return the cardholder to after the challenge.
https://merchant.example.com/3ds/success/pi_2YKewBonG4tgk12MheY3PiHDy.Process a 3DS Payment
Complete these in order.
Confirm the Payment Intent
From your backend, call Confirm Payment Intent with the three_d_secure block set to the redirect transport and your callback URLs. The session is created server-side, so no session_id is supplied here.
curl 'https://api.publicsquare.com/payment-intents/pi_2YKewBonG4tgk12MheY3PiHDy/confirm' \
-X 'POST' \
-H 'X-API-KEY: <SECRET_API_KEY>' \
-H 'IDEMPOTENCY-KEY: 09ec2c87-7fb8-44ca-bb18-5c71a76974da' \
-H 'Content-Type: application/json' \
-d '{
"three_d_secure": {
"transport": "redirect",
"success_url": "https://merchant.example.com/3ds/success/pi_2YKewBonG4tgk12MheY3PiHDy",
"failure_url": "https://merchant.example.com/3ds/failure/pi_2YKewBonG4tgk12MheY3PiHDy"
}
}'
The response is a PaymentIntent. There are two outcomes:
Frictionless — authentication succeeded with no challenge. The intent is succeeded and you are done.
{
"id": "pi_2YKewBonG4tgk12MheY3PiHDy",
"status": "succeeded",
"payment_id": "pmt_2YKewBonG4tgk12MheY3PiHDy",
...
}
Challenge required — the intent is requires_action and next_action.three_d_secure carries a redirect_url.
{
"id": "pi_2YKewBonG4tgk12MheY3PiHDy",
"status": "requires_action",
"next_action": {
"type": "three_d_secure",
"three_d_secure": {
"session_id": "<SESSION_ID>",
"transport": "redirect",
"redirect_url": "https://app.basistheory.com/3ds/..."
}
},
...
}
Redirect the Cardholder
When the intent is requires_action, navigate the browser to next_action.three_d_secure.redirect_url. The hosted page handles the challenge and then returns the cardholder to your success_url or failure_url.
window.location.href = nextAction.redirect_url;
Handle the Callback and Complete
When the cardholder lands on your callback route, read the session id (from your stored state or the path) and call Complete Payment Intent 3DS Challenge from your backend. Credova retrieves the authentication result and submits the payment to the processor.
curl 'https://api.publicsquare.com/payment-intents/pi_2YKewBonG4tgk12MheY3PiHDy/three_d_secure/complete' \
-X 'POST' \
-H 'X-API-KEY: <SECRET_API_KEY>' \
-H 'IDEMPOTENCY-KEY: 09ec2c87-7fb8-44ca-bb18-5c71a76974da' \
-H 'Content-Type: application/json' \
-d '{
"three_d_secure": {
"session_id": "<SESSION_ID>"
}
}'
If you did not save the session_id from the confirm response, get it from next_action.three_d_secure.session_id on the intent. Use Get Payment Intent by ID. Do this before you call complete.
The response is the final PaymentIntent, succeeded when authentication and authorization both pass, or failed with a last_payment_error otherwise.
{
"id": "pi_2YKewBonG4tgk12MheY3PiHDy",
"status": "succeeded",
"payment_id": "pmt_2YKewBonG4tgk12MheY3PiHDy",
...
}
Testing
Use the 3D Secure test cards to exercise frictionless, challenge, and failure scenarios in the test environment.
Conclusion
You have authenticated a card payment with 3DS via redirect. Next:
- Process 3DS Payments (Iframe) — the in-page challenge alternative
- Authorize and Capture Payments
- Issue a Refund