3D Secure (3DS) Payment Flow

This guide explains how to integrate the 3D Secure (3DS) redirect-based authentication flow using Ecart Pay. The goal is to authenticate the cardholder (when required) and then process the payment, returning the user to your application via a controlled redirect.

Test Cards (3D Secure)

Use the following test cards to validate the 3D Secure (3DS) flow in your sandbox environment. These cards simulate different 3DS outcomes (frictionless and step-up), including successful and unsuccessful authentication scenarios.

Note: These cards are for testing purposes only and must not be used in production.

Test Card List

Card NumberBrandExp. MonthExp. Year3DS EnabledExpected Payment StatusScenario Description
4000 0000 0000 2701Visa012050paidSuccessful frictionless authentication
4000 0000 0000 2925Visa122050paidUnsuccessful frictionless authentication
4000 0000 0000 2503Visa112050paidSuccessful step-up authentication
4000 0000 0000 2370Visa112050paidUnsuccessful step-up authentication

Overview

The 3DS flow in Ecart Pay works like this:

  1. Create a payment order
  2. Obtain a card token (permanent or single-use)
  3. Create the 3DS enrollment
  4. Redirect the user to Ecart Pay for authentication
  5. Ecart Pay runs 3DS and attempts payment processing
  6. Ecart Pay redirects the user back to your redirect_url
  7. Confirm the final result by querying the order status

Flow Summary

  1. Create a payment order.
  2. Obtain a card token (permanent or single-use).
  3. Create a 3DS enrollment using POST /api/three-d-secure.
  4. Redirect the user to the url returned in the response.
  5. Ecart Pay runs the 3DS authentication and processes the payment.
  6. Ecart Pay redirects the user back to your redirect_url including result parameters.
  7. Query the order status using GET /api/orders/:id.
  8. Review 3DS indicators and activity logs in the order activity attribute.

Prerequisites

Before starting the 3DS flow, you must have:

1) Payment Order (order_id)

A payment order must be created first, since the order ID is required to create the 3DS record.

2) Card Token (token)

You must also provide a card token, which can be either:

  • Permanent token
  • Single-use token

1. Create a 3D Secure Enrollment

Once you have your order_id and token, start the 3DS process by creating a 3D Secure record.

Endpoint

POST /api/three-d-secure

Important: redirect_url

Make sure you send a redirect_url, since Ecart Pay will redirect the user back to that URL once the 3DS flow is completed.

  • For web apps, use a standard HTTPS URL.
  • For mobile apps, this can be a deeplink.

Required Request Body Fields

You must send:

  • order_id (string) — the payment order ID
  • token (string) — the card token (permanent or single-use)
  • redirect_url (string) — the URL where the user should be returned after the 3DS flow
{
  "order_id": "69581fcb2bdfc3343fb983c9",
  "token": "6954201a0deca359dec01434",
  "redirect_url": "https://example.com/three-d-secure/process-payment"
}

2. Redirect the User to the Enrollment URL

The enrollment response includes a url attribute.

✅ Your integration must redirect the user to that URL to start the 3DS authentication flow.

{
  "account_id": "5fab3b20b40b0a613e1b6f15",
  "order_id": "69581fcb2bdfc3343fb983c9",
  "status": "created",
  "action": "enrollment",
  "url": "https://checkoutdev.ecartpay.com/three-d-secure?id=695d34b6d8740550a67373fb",
  "reference_id": "cba34245-3939-4302-8bbc-ea782f9f5f7c",
  "auth_info": {
    "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "device_data_collection_url": "https://centinelapistag.cardinalcommerce.com/V1/Cruise/Collect",
    "token": "AxizbwSToC4ALZA3aKlGACcBT36oZRDoAu7QyaSZejF6eAuAgAAATgns"
  },
  "redirect_url": "https://example.com/three-d-secure/process-payment",
  "id": "695d34b6d8740550a67373fb"
}

What to do with the response

Store these values for traceability and troubleshooting:

  • id (3DS id)
  • reference_id
  • order_id

Then redirect the user to:

  • url

3. Authentication and Payment Processing (Handled by Ecart Pay)

After the user is redirected:

  • Ecart Pay runs the 3DS authentication flow
  • Ecart Pay attempts payment processing
  • Regardless of success or failure, Ecart Pay redirects the user back to your redirect_url

✅ You do not need to take any action during this phase besides waiting for the final redirect.


4. Final Redirect Back to Your redirect_url

Once the flow ends, Ecart Pay redirects the user back to your redirect_url and includes query parameters.

Returned Parameters

  • order_id — the order ID
  • threeds_status — the 3DS flow result status
  • error (optional) — included when authentication or payment fails

Important: Even if threeds_status indicates success, you must always validate the payment by checking the order status.


5. Confirm the Payment Status (Required)

In your redirect handler endpoint (your redirect_url), you must query the order status to confirm whether the payment was actually completed.

Endpoint

GET /api/orders/:id

Expected Result

  • If status is paid → ✅ payment successful
  • If the status is anything else → ❌ payment not completed or failed

✅ This is the source of truth for your UI and business logic.


6. 3DS Activity and Indicators

To review 3DS indicators, authentication details, and the payment attempt history, check the activity attribute in the order response.

✅ The activity field contains the relevant 3DS information and the transaction timeline.


Implementation Recommendations

  • Always use the order status as the source of truth. Do not assume success based only on threeds_status.
  • In your redirect_url handler, always query the order and display the final result to the user.
  • Store reference_id and/or the returned 3DS id for internal traceability and correlation across logs.
  • Treat your redirect_url as a public endpoint: validate parameters, log events, and avoid exposing sensitive logic on the client side.

Notes

  • The final redirect may occur even when authentication fails or the bank declines the payment.
  • The only way to confirm that funds were captured is by querying the order and verifying it is in paid status.
  • If the user closes the browser before returning, you can still query the order status from your backend.