Checkout icon

3D Secure 2 API integration

Support 3D Secure 2 authentication for web and in-app transactions with your online payments integration.

This page describes 3D Secure 2 integration steps for version 46 or earlier of the /payments endpoint. If you are using a later version, refer Native 3D Secure 2 authentication.

How it works

If you are using 3D Secure for PSD2 compliance, read our comprehensive PSD2 SCA guide.

A payment qualified for 3D Secure 2 can go through either a frictionless or a challenge authentication flow before it is authorised. To simplify your implementation, use our web, Android, or iOS 3D Secure 2 Component in addition to your existing API integration.

Components are our pre-built modules that you can use to perform specific functions such as 3D Secure 2 authentication. To implement, submit API requests from your backend and then use our 3D Secure 2 Component to:

  • Handle the device fingerprinting and challenge flows, including the data exchange between your front end or client and the issuer's Access Control Server (ACS).
  • Return the device fingerprinting and the challenge flow result.

If you do not want to use the 3D Secure 2 Component and want to build the web-based implementation on your own, see Build your own 3D Secure 2 implementation. You can also choose to prefetch 3D Secure 2 device fingerprinting keys to reduce the number of calls for each transaction.

For an app-based implementation, we recommend that you use our 3D Secure 2 Android or iOS Component. Both our Android and iOS 3D Secure 2 Component implementations are approved and certified by EMVCo. If you want to build your own 3D Secure 2 mobile implementation, you will need to get an EMVCo certification.

3D Secure 2 is supported from v41 and later of /payments and /payments/details endpoints.

If you only want to perform a 3D Secure 2 authentication and then authorise the payment later, see the Authentication-only integration page.

Here's a diagram for a 3D Secure 2 full implementation with the 3D Secure 2 Component:

  • Submit a payment request with the required 3D Secure 2 objects to start the authentication process. Build your implementation depending on the resultCode returned in the response.
  • Get the 3D Secure 2 device fingerprint. If you receive an IdentifyShopper resultCode, you need to get the shopper's 3D Secure 2 device fingerprint. Initialize the 3D Secure 2 Component for device fingerprinting and submit the result to Adyen. If after submitting the result you get a response with an Authorised resultCode, this indicates that the transaction was authenticated in a frictionless flow, and the payment was successfully completed.
  • Present a challenge to the shopper. If you receive ChallengeShopper resultCode, this means that the issuer requires further shopper interaction and is initiating a challenge flow. In a web-based integration, this result code can be returned after you submit a payment request or after you submit the device fingerprint result to Adyen, depending on the logic on the issuer's side. To handle a challenge flow, initialize the 3D Secure 2 Component for the challenge flow and submit the result to Adyen.

Based on issuer performance, Adyen's Authentication Engine might also route payments to the 3D Secure 2 redirect flow. This is indicated by a RedirectShopper resultCode response. For more information, refer to Payments routed to 3D Secure 1.

For a complete list of resultCode values and the actions that you need to take, see Result codes.

Before you begin

Before you begin to integrate, make sure you have followed the Get started with Adyen guide to:

  • Get an overview of the steps needed to accept live payments.
  • Create your test account.

After you have created your test account:

  1. Get your API Key. Save a copy as you'll need it for API calls you make to the Adyen payments platform.
  2. Read and understand the Components integration guide. You should already know how to collect shopper information, either with the Card component or with your own payment form implementation.
  3. Install the 3D Secure Component depending on your current integration:
    • If you are using Adyen iOS and Adyen Android version 3.0.0 and later: Use the 3D Secure 2 Action Components for iOS or Android.
    • If you are using Adyen iOS and Adyen Android version 2.x.x and earlier: Use the 3D Secure 2 Components described on this page.

Install 3D Secure 2 Component for Adyen iOS version 2.6.0 to 2.8.4

Import the iOS 3D Secure 2 Component to your project using either CocoaPods or Carthage:

CocoaPods

  1. Add pod 'Adyen' to your Podfile.
  2. Run pod install.

Carthage

  1. Add github "adyen/adyen-ios" to your Cartfile.
  2. Run carthage update.
  3. Link the framework with your target as described in Carthage Readme.

Install 3D Secure 2 Component for Adyen Android version 2.4.0 to 2.4.5

 Import the Android 3D Secure 2 Component by adding this line to your build.gradle file.

implementation "com.adyen.checkout:threeds:<latest-version>"

Integration steps

  1. Collect the shopper's card payment details with your existing Cards integration - whether through Drop-in, Card Component, or your own UI for the API-only integration.
  2. Proceed to submit a payment request
  3. Use the resultCode from the response to determine your next action. For example, to complete a 3D Secure 2 authentication flow, you might need to get the 3D Secure 2 device fingerprint, or present a challenge to the shopper, or both. Choose the integration steps for web, Android, or iOS.
  4. Submit the 3D Secure device fingerprinting result and in case of a challenge flow, submit the challenge result.

To test your integration, see Testing 3D Secure 2.

Step 1: Submit a payment request

Submit a payment request with a POST  /payments call containing the shopper's card details. Include the following parameters to indicate that you are ready to accept 3D Secure 2 authenticated payments:

Parameter name Required Description
paymentMethod -white_check_mark- Object that contains the shopper's card details. Include the cardholder's name.
If you are fully PCI compliant you can pass raw card data instead.
channel -white_check_mark- Specify platform that you are using. Use Web, iOS, or Android.
authenticationData.threeDSRequestData.nativeThreeDS -white_check_mark- Set to preferred. Indicates that your payment page can handle 3D Secure 2 transactions natively.
browserInfo -white_check_mark- Object that contains information about the shopper's browser.
  • Full object required is for channel web.
  • For mobile integrations (channel iOS and Android), the userAgent and acceptHeader fields are required to indicate that your integration can handle 3D Secure 2 redirect authentication. If your mobile integration is unable to generate this information, you can send the same data as in the code samples below.
    returnUrl -white_check_mark- In case of a 3D Secure 1 flow, this is the URL where the shopper will be redirected back to after completing 3D Secure 1 authentication. This URL can have a maximum of 1024 characters. See Return URL formats for each channel.
    origin Required for channel Web. The URL of the page where you are loading the 3D Secure 2 Component from. The origin should not include subdirectories and a trailing slash. You can also get this by opening the browser console and calling window.location.origin.
    shopperIP The shopper's IP address.
    billingAddress The cardholder's billing address.
    shopperEmail The cardholder's email address.

    Return URL formats

    • For Web, the URL should include the protocol: http:// or https://. For example, https://your-company.com/checkout/.
    • For iOS, use the custom URL for your app. For example, my-app://. For more information on setting custom URL schemes, refer to the Apple Developer documentation.
    • For Android, if you are using the Android SDK, get the URL from CheckoutSetupParameters.getReturnUrl(). Otherwise, use a custom URL handled by an Activity on your app. You can configure it with an intent filter. For example, configure my-app://your.package.name, and then add that to your manifest.xml file.

      <activity
      android:name=".YourActivity">
      <intent-filter>
        <action android:name="android.intent.action.VIEW"/>
      
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="android.intent.category.BROWSABLE"/>
      
        <data
          android:host="${applicationId}"
          android:scheme="my-app"/>
      </intent-filter>
      </activity>

    We recommend that you provide all available information to increase the likelihood of achieving a frictionless flow and a higher authorisation rate. In addition to the regular parameters you provide to Adyen, send additional parameters in this list.

    Request

    Response

    You'll receive a response containing:

    • resultCodeIdentifyShopper or ChallengeShopper. Perform the corresponding 3D Secure device fingerprinting or present a challenge flows. If the transaction is exempted from 3D Secure 2, you might get an Authorised resultCode
    • threeds2.fingerprintToken or threeds2.challengeToken: Use this to initiate the 3D Secure 2 Component. If you want to know the contents of the encoded string, see payload structure.
    • paymentData: Use this for your next POST  /payments/details request.

    For other possible resultCode values and the actions that you need to take, see Result codes

    Step 2: Get the 3D Secure 2 device fingerprint

    If your server receives an IdentifyShopper resultCode, perform the 3D Secure 2 device fingerprinting. Follow the 3D Secure device fingerprinting procedure for webiOS, or Android.

    Collect the 3D Secure 2 device fingerprint with the Web Component

    If you are using v49 of our APIs with Adyen JS version 3.1.0 and later, use createFromAction to load the 3D Secure 2 Component instead.

    1. Make sure that you have already added the Components JavaScript file and the required configuration on your payments page.

    2. Create a DOM element.

      <div id="threeDS2"></div>
    3. Initiate the 3D Secure 2 Component with the threeds2.fingerprintToken you received from the  /payments response, assign a function to handle the onComplete and onError events, and mount the 3D Secure 2 Component.

      const threeDS2IdentifyShopper = checkout
              .create('threeDS2DeviceFingerprint', {
                  fingerprintToken: resultObject.authentication['threeds2.fingerprintToken'],
                  onComplete: function() {}, // Called whenever a result is available, regardless if the outcome is successful or not.
                  onError: function() {} // Gets triggered on error.
              })
              .mount('#threeDS2');
    4. When the onComplete event is triggered, get the result and proceed to submit the 3D Secure 2 device fingerprinting result.

      If the 3D Secure 2 device fingerprinting failed, both onComplete and onError will be called.

    Collect the 3D Secure 2 device fingerprint from an iOS app

    If you are using v49 of our APIs with Adyen iOS version 3.0.0 and later, use the 3D Secure 2 Action Component instead.

    1. Create a Card3DS2Authenticator instance. 

      let authenticator = Card3DS2Authenticator()
    2. Create a fingerprint with the threeds2.fingerprintToken you received from the   /payments response. 

      authenticator.createFingerprint(usingToken: fingerprintToken) { result in
           switch result {
           case let .success(fingerprint):
                // Submit fingerprint
           case let .failure(error):
                // Handle error
           }
      }
    3. If the success event is triggered, proceed to submit the 3D Secure 2 device fingerprinting result with the value passed in success. Otherwise, handle the failure event. The failure event will be triggered in case of a timeout, user cancellation, or system failures such as a certificate validation error or an invalid response from the issuer. 

    Collect the 3D Secure 2 device fingerprint from an Android app

    If you are using v49 of our APIs with Adyen Android version 3.0.0 and later, use the 3D Secure 2 Action Component instead.

    1. Create a Card3DS2Authenticator instance and pass the current context.

      mCard3DS2Authenticator = new Card3DS2Authenticator(/* Activity */ this);
    2. Create a fingerprint with the threeds2.fingerprintToken you received from the /payments response.

      mCard3DS2Authenticator.createFingerprint(fingerprintToken, new Card3DS2Authenticator.FingerprintListener() {
      @Override
      public void onSuccess(@NonNull String fingerprint) {
          // Submit fingerprint
      }
      
      @Override
      public void onFailure(@NonNull ThreeDS2Exception e) {
          mCard3DS2Authenticator.release();
          // Handle error
      }
      });
    3. If the onSuccess event is triggered, proceed to submit the 3D Secure 2 device fingerprinting result. Otherwise, handle the onFailure event. The onFailure event will be triggered in case of a timeout, user cancellation, or system failures such as a certificate validation error or an invalid response from the issuer.

    Step 3: Submit the 3D Secure 2 device fingerprinting result

    Make a POST   /payments/details request from your server with the details object and the paymentData as parameters.

    • threeds2.fingerprint: Pass the fingerprintResult from the onComplete event handler for web, success from iOS, or onSuccess for Android event handler. 
    • paymentData: Pass the paymentData from the initial payment response.
    Request
    {
      "details": {
        "threeds2.fingerprint": "eyJ0aHJlZURTQ29tcEluZCI6ICJZIn0="
      },
      "paymentData": "YOUR_PAYMENT_DATA..."
    }
    Response

    You'll receive a response containing any of the following resultCode:

    • Authorised – This indicates that the transaction was authenticated in a frictionless flow, and the payment was successfully completed. This state serves as an indicator to proceed with the delivery of goods and services. 
    • ChallengeShopper – The issuer has requested further shopper interaction and is initiating a challenge flow. You will also get the threeds2.challengeToken and the paymentData which you will need in the challenge flow. If you want to know the contents of the encoded threeds2.challengeToken string, see payload structure.

    For other possible resultCode values and the actions that you need to take, see Result codes.

    {
      "resultCode": "ChallengeShopper",
      "authentication": {
        "threeds2.challengeToken": "eyJ0aH..."
      },
      "details": [
        {
          "key": "threeds2.challengeResult",
          "type": "text"
        }
      ],
      "paymentData": "Ab02b4c0!..."
    }

    Step 4: Present a challenge

    If your server receives a ChallengeShopper resultCode, this means that the issuer would like to perform additional checks in order to verify that the shopper is indeed the cardholder. Follow the challenge flow procedure for webAndroid, or iOS.

    Present a challenge with the Web Component

    If you are using v49 of our APIs with Adyen JS version 3.1.0 and later, use createFromAction to load the 3D Secure 2 Component instead.

    1. Make sure that you have already added the Components JavaScript file and the required configuration on your payments page.

    2. Create a DOM element, or reuse the existing one if you are proceeding from the device fingerprinting flow.

      <div id="threeDS2"></div>
    3. Initiate the 3D Secure 2 Component with the threeds2.challengeToken you received from  /payments response or from  /payments/details if you are proceeding from the device fingerprinting flow. Assign a function to handle the onComplete and onError events, set the challenge window size, and then mount the 3D Secure 2 Component.

       const threeDS2Challenge = checkout
              .create('threeDS2Challenge', {
                  challengeToken: resultObject.authentication['threeds2.challengeToken'],
                  onComplete: function() {}, // Called whenever a result is available, regardless if the outcome is successful or not.
                  onError: function() {}, // Gets triggered on error.
                  challengeWindowSize: '05' // Defaults to '02'
              })
              .mount('#threeDS2');

      Set the challengeWindowSize to any of the following identifiers:

      identifier size
      01 250px x 400px
      02 390px x 400px
      03 500px x 600px
      04 600px x 400px
      05 100% x 100%
    4. When the onComplete event is triggered, always get the result and proceed to submit the challenge result.

      If the challenge flow failed, both onComplete and onError will be called.

    Present a challenge in an iOS app

    If you are using v49 of our APIs with Adyen iOS version 3.0.0 and later, use the 3D Secure 2 Action Component instead.

    1. Use the same Card3DS2Authenticator instance from the 3D Secure device fingerprinting flow. Pass the threeds2.challengeToken you received from  /payments/details to the presentChallenge() function. 

      authenticator.presentChallenge(usingToken: challengeToken) { result in
           switch result {
           case let .success(challengeResult):
                let payload = challengeResult.payload
                // Submit challenge result payload
           case let .failure(error):
                // Handle error
           }
      }
    2. If the success event is triggered, proceed to submit the challenge result with the payload value passed in the challengeResult of the success event. Otherwise, handle the failure event. The failure event will be triggered in case of a timeout, user cancellation, or system failures such as a certificate validation error or an invalid response from the issuer. 

    Present a challenge in an Android app

    If you are using v49 of our APIs with Adyen Android version 3.0.0 and later, use the 3D Secure 2 Action Component instead.

    1. Pass the threeds2.challengeToken you received from the  /payments/details to the Card3DS2Authenticator

      mCard3DS2Authenticator.presentChallenge(challengeToken, new Card3DS2Authenticator.SimpleChallengeListener() {
      @Override
      public void onSuccess(@NonNull ChallengeResult challengeResult) {
          mCard3DS2Authenticator.release();
          String payload = challengeResult.getPayload();
          // Pass the challenge result payload
      }
      
      @Override
      public void onFailure(@NonNull ThreeDS2Exception e) {
          mCard3DS2Authenticator.release();
          // Handle error
      }
      });
    2. If the onSuccess event is triggered, proceed to submit the challenge result with the payload value passed in the challengeResult of the onSuccess event. Otherwise, handle the onFailure event. The onFailure event will be triggered in case of a timeout, user cancellation, or system failures such as a certificate validation error or an invalid response from the issuer.

    Step 5: Submit the challenge result

    Make a POST   /payments/details request from your server and include details and the paymentData as parameters.

    • threeds2.challengeResult: Pass the result from the challengeResult from the onComplete event handler for web, onSuccess for Android, or the payload value in the challengeResult of the success iOS event handler. 
    • paymentData: This is the paymentData from the latest API response, either from the  /payments or from the  /payments/details response if you are proceeding from the device fingerprinting flow.

    Request

    {
      "details": {
        "threeds2.challengeResult": "eyJ0cmFuc1N0YXR1cyI6IlkifQ=="
      },
      "paymentData": "YOUR_PAYMENT_DATA"
    }

    Response

    You'll receive Authorised as the resultCode if the payment was successful.

    {
        "pspReference": "V4HZ4RBFJGXXGN82",
        "resultCode": "Authorised"
    }

    UI customizations for apps

    Customizing iOS UI

    The 3D Secure 2 Component for Adyen iOS version 2.x.x inherits your app's theme to ensure the UI of the challenge flow fits your app's look and feel. If you require further UI customizations, the Component provides some customization options through the ADYAppearanceConfiguration class.

    To customize your UI, create an instance of ADYAppearanceConfiguration, configure the desired properties, and pass it during initialization of the Card3DS2Authenticator.

    let appearanceConfiguration = ADYAppearanceConfiguration()
    // Customize properties of appearanceConfiguration.
    
    let authenticator = Card3DS2Authenticator(appearanceConfiguration: appearanceConfiguration)

    For a complete list of customizable properties, see the ADYAppearanceConfiguration class reference documentation.

    Customizing Android UI

    Customize the SDK theme

    The 3D Secure 2 Component for Adyen Android version 2.x.x inherits your app's theme to ensure the UI of the challenge flow fits your app's look and feel. You can override the default SDK theme to inherit from one of AppCompat's theme variants. To do this, add the following XML snippet to your styles.xml file.

    <style name="ThreeDS2Theme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize the SDK theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    Using UiCustomization class

    If you require further UI customizations, the 3D Secure 2 Component for Adyen Android version 2.x.x provides some customization options through the UiCustomization class.

    To use the UiCustomization class, create an instance of UiCustomization, configure the desired properties, and pass it during initialization of the Card3DS2Authenticator.

    mCard3DS2Authenticator = new Card3DS2Authenticator(/* Activity */ this, uiCustomization);

    For a complete list of customizable properties, see the UiCustomization class reference documentation.

    Testing 3D Secure 2

    To test how your integration handles different 3D Secure 2 authentication scenarios, you need to use a card number for the specific flow.

    When prompted for 3D Secure 2 text challenges, use the following credentials to authenticate:

    • For native mobile integrations, use password: 1234
    • For web and mobile browser integrations, use password: password

    Depending on the authentication option, you can receive the following result codes:

    • RedirectShopper: you receive this result code if you are using the Redirect authentication flow.
    • IdentifyShopper: you receive this result code if you are using the Native authentication flow.
    • ChallengeShopper: you receive this result code after you submit the 3D Secure 2 device fingerprinting result in a Native authentication, unless you specify a frictionless flow.

    Depending on your integration, use the following test cards to simulate different authentication flows.

    Card Type Card Number Expiry Date Security Code (CVC/CVV/CID)
    American Express 3714 4963 5398 431 03/2030 7373
    Bancontact / Maestro 6703 4444 4444 4449 03/2030
    Bancontact / Visa 4871 0499 9999 9910 03/2030 737
    Cartes Bancaires / Visa Debit 4035 5014 2814 6300 03/2030 737
    Cartes Bancaires 4360 0000 0100 0005 03/2030 737
    China UnionPay (Credit) 6250 9470 0000 0014 03/2030 123
    China UnionPay (Debit) 6250 9460 0000 0016 03/2030 123
    Diners 3056 9309 0259 04 03/2030 737
    Discover 6011 1111 1111 1117 03/2030 737
    Maestro 5000 5500 0000 0029 03/2030 n/a
    Mastercard 5454 5454 5454 5454 03/2030 737
    Mastercard Credit 2222 4000 1000 0008 03/2030 737
    Visa 4917 6100 0000 0000 03/2030 737
    Visa Classic 4166 6766 6766 6746 03/2030 737

    Challenge without fingerprint

    To test the web-based flow where the device fingerprinting step is skipped (because the issuer's ACS has not configured a threeDSMethodURL), and you get a ChallengeShopper resultCode immediately after submitting the payment request, use the following card:

    Card Type Card Number Expiry Date Security Code (CVC/CVV/CID)
    Visa 4212 3456 7891 0006 03/2030 737

    Fingerprint without challenge

    To test the frictionless flow, in which you perform a fingerprint but no challenge, use the following test card number:

    Card number Expiry Date Security Code (CVC/CVV/CID) Authentication scenario
    5201 2815 0512 9736 03/2030 737 Fingerprint but no challenge

    Native authentication

    To test authentication scenarios for native mobile (app-based) integrations, use the following test cards:

    Card number Expiry Date Security Code (CVC/CVV/CID) Authentication scenario
    5201 2855 6567 2311 03/2030 737 Basic text authentication
    5201 2874 9905 2008 03/2030 737 Basic single select
    5201 2815 9233 1633 03/2030 737 Basic multi select
    5201 2888 2269 6974 03/2030 737 Basic out-of-band (OOB) authentication
    5201 2895 0084 3268 03/2030 737 HTML out-of-band (OOB) authentication
    5201 2861 5377 1465 03/2030 737 App single select then text authentication
    4917 6100 0000 0042 03/2030 737 Advanced: ACS sends an empty Challenge Response (CRes)
    4917 6100 0000 0067 03/2030 737 Advanced: Invalid content in the acsSignedContent field in Authentication Response (ARes)
    4917 6100 0000 0059 03/2030 737 Advanced: Challenge Response (CRes) timeout

    Technical error

    To test simulate an error due to a timeout during the 3D Secure 2 authentication on the issuer side, use the following test card:

    Card number Expiry Date Security Code (CVC/CVV/CID) Scenario
    5201 2829 9900 5515 03/2030 737 Depending on your configuration, the transaction might still proceed to a successful authorization.

    See also