Airwallex logo

Payment with 3D secure

3D Secure helps to protect you and your eCommerce business against potentially non legitimate buyers. In order to decide when or not use 3D Secure Airwallex leverages its own Risk module (that you can configure accordingly). Airwallex's Risk module provides you the ability to trigger 3DS only when it is required, leverage the specific section in this guide to configure it and use the below flow.

There are two versions of 3D Secure that are being run in parallel by Issuers, 3D Secure 1 and 3D Secure 2 (with its incremental variations). Our implementation abstracts you from this complexity and will automatically drive you through the right flow.

Effectively the 3DS 1 implementation will always request the Challenge flow, the 3D Secure 2 implementation will request either the Frictionless flow or the Challenge flow.

3D Secure 2 is an enhanced version of 3D Secure, it provides a significantly better user experience and helps increasing conversion by reducing the redirection likelihood to the issuer and when that occurs provides technical measures to make it smoother.

Both flows, Frictionless and Challenge are required to complete a successful implementation.

Frictionless flow

The Frictionless flow of 3D Secure 2 allows you to avoid an explicit authentication by the buyer in exchange of providing enough additional data to the issuer so that they can complete the authentication silently.

  1. Just like a regular payment, a Payment Intent needs to be created using POST/api/v1/pa/payment_intents/create.

Request

curl -X POST \
  https://pci-api.airwallex.com/api/v1/pa/payment_intents/create \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer your_bearer_token' \
  -d '{
    "request_id": "ad11e38a-7234-11ea-aa94-7fd44ffd1b89",
    "amount": 5001,
    "currency": "AUD",
    "merchant_order_id":"{{$guid}}"}'

Response

{
    "id": "int_gECH4yeBzr50vOYFtzNyIsSW9e8",
    "request_id": "95527c7f-88d9-44c2-ba01-15886323c102",
    "amount": 5001,
    "currency": "AUD",
    "merchant_order_id": "d45fe031-ac74-4347-b2db-00cb3528adca",
    "status": "REQUIRES_PAYMENT_METHOD",
    "captured_amount": 0,
    "created_at": "2020-06-21T05:23:25+0000",
    "updated_at": "2020-06-21T05:23:25+0000",
    "available_payment_method_types": [
        "card",
        "wechatpay"
    ],
    "client_secret": "your_client_secret"
}
  1. Use POST/api/v1/pa/payment_intents/{id}/confirm in a similar way and confirm the payment providing the payment method details. Do not forget to provide the return_url that is required to provide the response upon the completion of the flow.

The response of this /confirm is specific to a 3DS flow. Be aware of the status AUTHENTICATION_REDIRECTED at which point you need to gather more information. The next_action field guides you to the next step within the 3D secure flow you need to undertake.

You will start with WAITING_DEVICE_DATA_COLLECTION that indicates more data needs to be collected from the buyer's device to aim for a frictionless flow. If you receive WAITING_USER_INFO_INPUT indicates that the data provided is not enough and a challenge flow is required (see next section for this).

curl -X POST \
  https://pci-api.airwallex.com/api/v1/pa/payment_intents/int_kaAB2ImTzoHeHG8TAzNtdr17x7C/confirm \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer your_bearer_token' \
  -d '{
  "request_id": "ad11e38a-7234-11ea-aa94-7fd44ffd1b89",
  "payment_method": {
        "type": "card",
        "card": {
          "number": "4000000000001091",
          "expiry_month": "01",
          "expiry_year": "2023",  
          "cvc": "123",
          "name": "Adam"
        }
    },
   "payment_method_options": {
        "card": {
            "three_ds": {
                "return_url": "http://awx-dev-37.awx.im:10012/feedback"
            }
        }
    },
}'

Response:

{
    "id": "int_1EVVaB6iziXFU3PQ5zsy0GPe3Bi",
    "request_id": "adcd0c55-da83-411e-a480-36f82790fc12",
    "amount": 5001,
    "currency": "AUD",
    "status": "REQUIRES_CUSTOMER_ACTION",
    "captured_amount": 0,
    "latest_payment_attempt": {
        "id": "att_cPderyjSzsuXJg8myzsy0GPe3Bi",
        "amount": 5001,
        "payment_method": {
            "id": "mtd_uPe7watMKtXh46cNrSnnPlYif6r",
            "type": "card",
            "card": {
                "expiry_month": "01",
                "expiry_year": "2023",
                "name": "Adam",
                "bin": "400000",
                "last4": "1091",
                "brand": "visa",
                "issuer_country_code": "US",
                "card_type": "credit",
                "fingerprint": "LFGVWnCHaXBCYnbWa5g30aVKKJ4="
            },
            "status": "CREATED",
            "created_at": "2020-06-21T10:03:04+0000",
            "updated_at": "2020-06-21T10:03:04+0000"
        },
        "status": "AUTHENTICATION_REDIRECTED",
        "captured_amount": 0,
        "refunded_amount": 0,
        "created_at": "2020-06-21T10:03:04+0000",
        "updated_at": "2020-06-21T10:03:05+0000",
        "authentication_data": {
            "ds_data": {},
            "fraud_data": {
                "action": "VERIFY",
                "score": "-1"
            },
            "avs_result": "U",
            "cvc_result": "U"
        }
    },
    "created_at": "2020-06-21T10:02:50+0000",
    "updated_at": "2020-06-21T10:03:05+0000",
    "next_action": {
        "type": "redirect",
        "method": "POST",
        "url": "https://centinelapistag.cardinalcommerce.com/V1/Cruise/Collect",
        "data": {
            "jwt": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI2NDZlNjU1Zi1iZGI0LTRhNzgtOGQ5ZS01NDk0MTFkNThjMzUiLCJpYXQiOjE1OTI3MzM3ODUsImlzcyI6IjVlNDQzYmU4YWZhODBkMmQ5OGY2MjBiOCIsIk9yZ1VuaXRJZCI6IjVlNDI2ZDRmOTBkNzQxMjdlNDJmYzczZSIsIlJldHVyblVybCI6Imh0dHA6Ly9hd3gtZGV2LTM3LmF3eC5pbToxMDAxMi9mZWVkYmFjayIsIk9iamVjdGlmeVBheWxvYWQiOmZhbHNlfQ.zRiPFBdMElo0Myt_QEYw-06R4aWH7Y8QxWrrJHEdkr4",
            "stage": "WAITING_DEVICE_DATA_COLLECTION"
        }
    }
}
  1. This step is aimed to collect the Device Data the Issuer needs to offer you a frictionless authentication. Leverage the information in the next_action group, post these data from the shopper's web browser so the issuer can collect the shopper’s device data to identify its legitimacy. You don't need to visually alter your checkout at this step, it is just collecting device data.

The 3D Secure 2 flow will provide a response in the return_url you earlier provided. The encrypted content you have received contains the device details that the issuer requires.

<html>
<body>
<form id="collectionForm" name="devicedata" method="POST" action="https://centinelapistag.cardinalcommerce.com/V1/Cruise/Collect">
    <input type="hidden" name="Bin" value="400000" />
    <input type="hidden" name="JWT" value="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI2NDZlNjU1Zi1iZGI0LTRhNzgtOGQ5ZS01NDk0MTFkNThjMzUiLCJpYXQiOjE1OTI3MzM3ODUsImlzcyI6IjVlNDQzYmU4YWZhODBkMmQ5OGY2MjBiOCIsIk9yZ1VuaXRJZCI6IjVlNDI2ZDRmOTBkNzQxMjdlNDJmYzczZSIsIlJldHVyblVybCI6Imh0dHA6Ly9hd3gtZGV2LTM3LmF3eC5pbToxMDAxMi9mZWVkYmFjayIsIk9iamVjdGlmeVBheWxvYWQiOmZhbHNlfQ.zRiPFBdMElo0Myt_QEYw-06R4aWH7Y8QxWrrJHEdkr4" />
    <input type="submit" name="continue" value="Continue" />
</form>
</body>
</html>
{
    "Response": [
        "eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiI1ZTQ0M2JlOGFmYTgwZDJkOThmNjIwYjgiLCJpYXQiOjE1OTI3MzQwODQsImV4cCI6MTU5Mjc0MTI4NCwianRpIjoiMGM4YmUwMDAtMTc0MC00ZDY1LWE5NTktOGYwMTVlMmMxMzJlIiwiUGF5bG9hZCI6IntcIkFjdGlvbkNvZGVcIjpcIlNVQ0NFU1NcIixcIlNlc3Npb25JZFwiOlwiMF9mOTA5YTMyYy1kYzhmLTQyNzItOGE2MC0yYmJkY2Q3OWQ4ZWJcIixcIkVycm9yTnVtYmVyXCI6MCxcIkVycm9yRGVzY3JpcHRpb25cIjpcIlN1Y2Nlc3NcIn0ifQ.DKgzpXuMisD06Sk38P5QF9o5FxzspjQRGzmHqtxnEb8"
    ]
}
  1. Submit the device information to the Issuer through POST/api/v1/pa/payment_intents/{id}/confirm_continue in the field device_data_collection_res.

Be aware of the status, if you receive an AUTHORIZED message your transaction is completed at this stage. You also receive additional information related to the 3D Secure process. If you still receive AUTHENTICATION_REDIRECTED check next_action, at this point you are required to continue through the challenge flow.

curl -X POST \
https://pci-api.airwallex.com/api/v1/pa/payment_intents/int_kaAB2ImTzoHeHG8TAzNtdr17x7C/confirm_continue \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer your_bearer_token' \
  -d '{
  "request_id": "xd11e38a-7234-11ea-aa94-7fd44ffd1b89",
  "type": "3ds_check_enrollment",
  "three_ds": {
             "device_data_collection_res":"eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiI1ZTQ0M2JlOGFmYTgwZDJkOThmNjIwYjgiLCJpYXQiOjE1OTI3MzQwODQsImV4cCI6MTU5Mjc0MTI4NCwianRpIjoiMGM4YmUwMDAtMTc0MC00ZDY1LWE5NTktOGYwMTVlMmMxMzJlIiwiUGF5bG9hZCI6IntcIkFjdGlvbkNvZGVcIjpcIlNVQ0NFU1NcIixcIlNlc3Npb25JZFwiOlwiMF9mOTA5YTMyYy1kYzhmLTQyNzItOGE2MC0yYmJkY2Q3OWQ4ZWJcIixcIkVycm9yTnVtYmVyXCI6MCxcIkVycm9yRGVzY3JpcHRpb25cIjpcIlN1Y2Nlc3NcIn0ifQ.DKgzpXuMisD06Sk38P5QF9o5FxzspjQRGzmHqtxnEb8"
    }
}'
{
    "id": "int_4Bwrudwszdgel4ymgzDopLJMa5M",
    "request_id": "d7f12f11-2731-4764-97db-8c5968c745ed",
    "amount": 5001,
    "currency": "AUD",
    "status": "SUCCEEDED",
    "captured_amount": 0,
    "latest_payment_attempt": {
        "id": "att_pYS5tRSLzjWQbAY4ozDopLJMa5M",
        "amount": 5001,
        "payment_method": {
            "id": "mtd_q72K0Yh7hPwLgT0IBXFWKFjffBS",
            "type": "card",
            "card": {
                "expiry_month": "01",
                "expiry_year": "2023",
                "name": "Adam",
                "bin": "400000",
                "last4": "1000",
                "brand": "visa",
                "issuer_country_code": "US",
                "card_type": "credit",
                "fingerprint": "1qHqTWoQWN4QQKWCA78XivjoN4g=",
                "cvc_check": "unknown",
                "avs_check": "unknown"
            },
            "status": "VERIFIED",
            "created_at": "2020-06-21T13:56:18+0000",
            "updated_at": "2020-06-21T13:56:18+0000"
        },
        "status": "AUTHORIZED",
        "provider_original_response_code": "00",
        "captured_amount": 0,
        "refunded_amount": 0,
        "created_at": "2020-06-21T13:56:18+0000",
        "updated_at": "2020-06-21T13:59:50+0000",
        "authentication_data": {
            "ds_data": {
                "version": "2.1.0",
                "liability_shift_indicator": "Y",
                "eci": "05",
                "cavv": "Y2FyZGluYWxjb21tZXJjZWF1dGg=",
                "xid": "Y2FyZGluYWxjb21tZXJjZWF1dGg=",
                "enrolled": "Y",
                "pa_res_status": "Y",
                "challenge_cancellation_reason": "",
                "frictionless": "Y"
            },
            "fraud_data": {
                "action": "VERIFY",
                "score": "-1"
            },
            "avs_result": "U",
            "cvc_result": "U"
        }
    },
    "created_at": "2020-06-21T13:54:41+0000",
    "updated_at": "2020-06-21T13:59:50+0000"
}

Challenge flow

The challenge flow is a follow-up of the frictionless flow required by the issuer when either the information provided is not enough or the issuer aims to step up given his own risk policy.

In this case, the response you will receive is as below. The response of confirm (or confirm_continue) has the status AUTHENTICATION_REDIRECTED, the next_action field guides you to the next step within the 3D secure flow you need to undertake and WAITING_USER_INFO_INPUT indicates that the data provided is not enough and a challenge flow must be started.

{
    "id": "int_1EVVaB6iziXFU3PQ5zsy0GPe3Bi",
    "request_id": "757f0ed0-40b0-4aa3-a290-70ced5bd4b1a",
    "amount": 5001,
    "currency": "AUD",
    "status": "REQUIRES_CUSTOMER_ACTION",
    "captured_amount": 0,
    "latest_payment_attempt": {
        "id": "att_cPderyjSzsuXJg8myzsy0GPe3Bi",
        "amount": 5001,
        "payment_method": {
            "id": "mtd_uPe7watMKtXh46cNrSnnPlYif6r",
            "type": "card",
            "card": {
                "expiry_month": "01",
                "expiry_year": "2023",
                "name": "Adam",
                "bin": "400000",
                "last4": "1091",
                "brand": "visa",
                "issuer_country_code": "US",
                "card_type": "credit",
                "fingerprint": "LFGVWnCHaXBCYnbWa5g30aVKKJ4="
            },
            "status": "CREATED",
            "created_at": "2020-06-21T10:03:04+0000",
            "updated_at": "2020-06-21T10:03:04+0000"
        },
        "status": "AUTHENTICATION_REDIRECTED",
        "captured_amount": 0,
        "refunded_amount": 0,
        "created_at": "2020-06-21T10:03:04+0000",
        "updated_at": "2020-06-21T10:09:28+0000",
        "authentication_data": {
            "ds_data": {
                "version": "2.1.0",
                "liability_shift_indicator": "N",
                "eci": "",
                "cavv": "null",
                "xid": "",
                "enrolled": "Y",
                "pa_res_status": "",
                "challenge_cancellation_reason": "",
                "frictionless": "N"
            },
            "fraud_data": {
                "action": "VERIFY",
                "score": "-1"
            },
            "avs_result": "U",
            "cvc_result": "U"
        }
    },
    "created_at": "2020-06-21T10:02:50+0000",
    "updated_at": "2020-06-21T10:03:05+0000",
    "next_action": {
        "type": "redirect",
        "method": "POST",
        "url": "https://centinelapistag.cardinalcommerce.com/V2/Cruise/StepUp",
        "data": {
            "jwt": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4YjgxMDk3Ni1hY2VlLTRiYTctOTE1Mi0xMzk1NTUwMWQwYmEiLCJpYXQiOjE1OTI3MzQxNjgsImlzcyI6IjVlNDQzYmU4YWZhODBkMmQ5OGY2MjBiOCIsIk9yZ1VuaXRJZCI6IjVlNDI2ZDRmOTBkNzQxMjdlNDJmYzczZSIsIlJldHVyblVybCI6Imh0dHA6Ly9hd3gtZGV2LTM3LmF3eC5pbToxMDAxMi9mZWVkYmFjayIsIlJlZmVyZW5jZUlkIjoiMF9mOTA5YTMyYy1kYzhmLTQyNzItOGE2MC0yYmJkY2Q3OWQ4ZWIiLCJQYXlsb2FkIjp7IlBheWxvYWQiOiJleUp0WlhOellXZGxWSGx3WlNJNklrTlNaWEVpTENKdFpYTnpZV2RsVm1WeWMybHZiaUk2SWpJdU1TNHdJaXdpZEdoeVpXVkVVMU5sY25abGNsUnlZVzV6U1VRaU9pSmxOVGt6TkdFeE9DMDRPV0U1TFRSak1EUXRZamN4WWkwMU1ERTRZMkUyTURnM1ptSWlMQ0poWTNOVWNtRnVjMGxFSWpvaVpURTFZemRtT0dNdE1qYzBOaTAwTkdVMUxUZ3pOelF0WldVeE56Tm1PRGN5TkRNeUlpd2lZMmhoYkd4bGJtZGxWMmx1Wkc5M1UybDZaU0k2SWpBeUluMCIsIkFDU1VybCI6Imh0dHBzOi8vMG1lcmNoYW50YWNzc3RhZy5jYXJkaW5hbGNvbW1lcmNlLmNvbS9NZXJjaGFudEFDU1dlYi9jcmVxLmpzcCIsIlRyYW5zYWN0aW9uSWQiOiJoaUlHSkFPZEhhbHd3YzMxUmpEMCJ9fQ.PD0ksGL7eizMjkmIE3NZuPyNIo3bYdMjaSe0kot1Z6o",
            "acs": "https://0merchantacsstag.cardinalcommerce.com/MerchantACSWeb/creq.jsp",
            "xid": "hiIGJAOdHalwwc31RjD0",
            "req": "eyJtZXNzYWdlVHlwZSI6IkNSZXEiLCJtZXNzYWdlVmVyc2lvbiI6IjIuMS4wIiwidGhyZWVEU1NlcnZlclRyYW5zSUQiOiJlNTkzNGExOC04OWE5LTRjMDQtYjcxYi01MDE4Y2E2MDg3ZmIiLCJhY3NUcmFuc0lEIjoiZTE1YzdmOGMtMjc0Ni00NGU1LTgzNzQtZWUxNzNmODcyNDMyIiwiY2hhbGxlbmdlV2luZG93U2l6ZSI6IjAyIn0",
            "stage": "WAITING_USER_INFO_INPUT"
        }
    }
}
  1. Render an iframe to lodge the authentication page provided by the issuing bank. Choose the display that better suits your checkout, in here the buyer will complete the challenge the issuer has decided to show. The return_url will be used to provide you the response of the process.
<html>
<body>
<form id="stepUpForm" name="stepup" method="POST"  action="https://centinelapistag.cardinalcommerce.com/V2/Cruise/StepUp">
    <input type="hidden" name="JWT" value="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4YjgxMDk3Ni1hY2VlLTRiYTctOTE1Mi0xMzk1NTUwMWQwYmEiLCJpYXQiOjE1OTI3MzQxNjgsImlzcyI6IjVlNDQzYmU4YWZhODBkMmQ5OGY2MjBiOCIsIk9yZ1VuaXRJZCI6IjVlNDI2ZDRmOTBkNzQxMjdlNDJmYzczZSIsIlJldHVyblVybCI6Imh0dHA6Ly9hd3gtZGV2LTM3LmF3eC5pbToxMDAxMi9mZWVkYmFjayIsIlJlZmVyZW5jZUlkIjoiMF9mOTA5YTMyYy1kYzhmLTQyNzItOGE2MC0yYmJkY2Q3OWQ4ZWIiLCJQYXlsb2FkIjp7IlBheWxvYWQiOiJleUp0WlhOellXZGxWSGx3WlNJNklrTlNaWEVpTENKdFpYTnpZV2RsVm1WeWMybHZiaUk2SWpJdU1TNHdJaXdpZEdoeVpXVkVVMU5sY25abGNsUnlZVzV6U1VRaU9pSmxOVGt6TkdFeE9DMDRPV0U1TFRSak1EUXRZamN4WWkwMU1ERTRZMkUyTURnM1ptSWlMQ0poWTNOVWNtRnVjMGxFSWpvaVpURTFZemRtT0dNdE1qYzBOaTAwTkdVMUxUZ3pOelF0WldVeE56Tm1PRGN5TkRNeUlpd2lZMmhoYkd4bGJtZGxWMmx1Wkc5M1UybDZaU0k2SWpBeUluMCIsIkFDU1VybCI6Imh0dHBzOi8vMG1lcmNoYW50YWNzc3RhZy5jYXJkaW5hbGNvbW1lcmNlLmNvbS9NZXJjaGFudEFDU1dlYi9jcmVxLmpzcCIsIlRyYW5zYWN0aW9uSWQiOiJoaUlHSkFPZEhhbHd3YzMxUmpEMCJ9fQ.PD0ksGL7eizMjkmIE3NZuPyNIo3bYdMjaSe0kot1Z6o" />
    <input type="hidden" name="MD" value="custom field" />
    <input type="submit" name="continue" value="Continue" />
</form>
</body>
</html>

The response of submitting the page is like below.

{
    "TransactionId": [
        "hiIGJAOdHalwwc31RjD0"
    ],
    "Response": [
        ""
    ],
    "MD": [
        "custom field"
    ]
}
  1. Submit the transaction ID to the Issuer through POST/api/v1/pa/payment_intents/{id}/confirm_continue. This completes the authentication and authorization process. If the status of your payment attempt is AUTHORIZED, you have completed the payment and can release your goods safely.
curl -X POST \
  https://pci-api.airwallex.com/api/v1/pa/payment_intents/int_kaAB2ImTzoHeHG8TAzNtdr17x7C/confirm_continue \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer your_bearer_token' \
  -d '{
  "request_id": "xee1e38a-7234-11ea-aa94-7fd44ffd1b89",
  "type": "3ds_validate",
  "three_ds": {
                "ds_transaction_id":"hiIGJAOdHalwwc31RjD0"
    }
}'
{
    "id": "int_1EVVaB6iziXFU3PQ5zsy0GPe3Bi",
    "request_id": "f2fe13ae-275f-436c-9fd7-8c232bdde7ac",
    "amount": 5001,
    "currency": "AUD",
    "status": "SUCCEEDED",
    "captured_amount": 0,
    "latest_payment_attempt": {
        "id": "att_cPderyjSzsuXJg8myzsy0GPe3Bi",
        "amount": 5001,
        "payment_method": {
            "id": "mtd_uPe7watMKtXh46cNrSnnPlYif6r",
            "type": "card",
            "card": {
                "expiry_month": "01",
                "expiry_year": "2023",
                "name": "Adam",
                "bin": "400000",
                "last4": "1091",
                "brand": "visa",
                "issuer_country_code": "US",
                "card_type": "credit",
                "fingerprint": "LFGVWnCHaXBCYnbWa5g30aVKKJ4=",
                "cvc_check": "unknown",
                "avs_check": "unknown"
            },
            "status": "VERIFIED",
            "created_at": "2020-06-21T10:03:04+0000",
            "updated_at": "2020-06-21T10:03:04+0000"
        },
        "status": "AUTHORIZED",
        "provider_original_response_code": "00",
        "captured_amount": 0,
        "refunded_amount": 0,
        "created_at": "2020-06-21T10:03:04+0000",
        "updated_at": "2020-06-21T10:13:55+0000",
        "authentication_data": {
            "ds_data": {
                "version": "2.1.0",
                "liability_shift_indicator": "Y",
                "eci": "05",
                "cavv": "MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=",
                "xid": "MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=",
                "enrolled": "",
                "pa_res_status": "Y",
                "challenge_cancellation_reason": "Success",
                "frictionless": "N"
            },
            "fraud_data": {
                "action": "VERIFY",
                "score": "-1"
            },
            "avs_result": "U",
            "cvc_result": "U"
        }
    },
    "created_at": "2020-06-21T10:02:50+0000",
    "updated_at": "2020-06-21T10:13:55+0000"
}