Are you looking for test card numbers?

Would you like to contact support?

Classic-integration icon

Android 3D Secure 2 SDK

Support 3D Secure 2 authentication on your Android app.

This page is for our classic Direct API (/authorise) integration. If you are integrating using our Checkout APIs, refer to the Native 3D Secure 2 for Android on Checkout API documentation instead.
PSD2 compliance

If you are using 3D Secure for PSD2 SCA compliance, get more information from our comprehensive guide.

In a full 3D Secure 2 implementation, a payment can go through either a frictionless or a challenge authentication flow before it can be authorised.

Use our 3D Secure 2 Android SDK to get the device fingerprint and present the challenge to your shopper. From your server, you need to send a payment request, the encrypted device fingerprint, and the challenge result to Adyen.

How it works

Here's how a 3D Secure 2 challenge authentication flow works:

  1. 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.  
  2. Ge the 3D Secure 2 device fingerprint. If you receive an IdentifyShopper resultCode, you need to get the shopper's 3D Secure 2 device fingerprint. Initiate the mobile SDK, get the device fingerprint, and send the encrypted device fingerprint information to Adyen. If you get a response with an Authorised resultCode, this indicates that the 3D Secure 2 authentication was frictionless, and the payment authorisation was successfully completed.
  3. Present a challenge to the shopper. If you receive ChallengeShopper resultCode, this means that the issuer requires further shopper interaction. To handle a challenge flow, initiate the mobile SDK and then submit the challenge result to Adyen. 

In case the issuer does not support 3D Secure 2, we will initiate a 3D Secure 1 fallback by default, indicated by a RedirectShopper resultCode response. If you do not want to automatically fall back to 3D Secure 1, contact Support Team.

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

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

Before you begin

Adyen 3DS2 Android

Subscribe to our GitHub repository to get the latest updates and versions.

  1. If you haven't done so already, sign up for an Adyen test account. For more information, refer to Get started with Adyen.

  2. Get your API Key. Save a copy as you'll need it for API calls you make to the Adyen payments platform.

  3. Install one of our Libraries to connect with the Adyen APIs.

  4. Install the SDK either through:

    • jcenter: Add this line to your build.gradle file.

      implementation "com.adyen.threeds:adyen-3ds2:<latestSDKVersion>"
    • Our GitHub repository: Copy the SDK package adyen-3ds2.aar to the /libs folder in your module and add this line to your module build.gradle file.

      implementation "com.adyen.threeds:adyen-3ds2:<latestSDKVersion>@aar"

Step 1: Submit a payment request

Collect your shopper's card details then submit a payment request with a POST /authorise call. Include the threeDS2RequestData object to indicate that you are ready to accept 3D Secure 2 payments. 

  • deviceChannelapp
To increase the likelihood of achieving a frictionless flow and higher authorisation rates, we also recommend that you send additional parameters in this list.
curl \
-H "X-API-key: [Your API Key here]" \
-H "Content-Type: application/json" \
-d '{
      "holderName":"Card Holder",
# Set your X-API-KEY with the API key from the Customer Area.
adyen =
adyen.api_key = "YOUR X-API-KEY"

response = adyen.authorise({
  "amount" => {
    "currency" => "EUR",
    "value" => 1500
  "merchantAccount" => "YOUR_MERCHANT_ACCOUNT",
  "reference" => "YOUR_ORDER_NUMBER",
  "threeDS2RequestData" => {
    "deviceChannel" => "app"
  "card" => {
    "cvc" => "737",
    "expiryMonth" => "10",
    "expiryYear" => "2020",
    "holderName" => "Card Holder",
    "number" => "4917610000000000"
// Set your X-API-KEY with the API key from the Customer Area.
Config config = new Config();
config.setApiKey("Your X-API-KEY"));
Client client = new Client(config);

Checkout checkout = new Checkout(client);
AuthoriseRequest authoriseRequest = new AuthoriseRequest();
Amount amount = new Amount();
authoriseRequest.setThreeDS2RequestData(new HashMap<String, String>());
authoriseRequest.putThreeDS2RequestData("deviceChannel", "app");
authoriseRequest.setCard(new HashMap<String, String>());
authoriseRequest.putCardItem("cvc", "737");
authoriseRequest.putCardItem("expiryMonth", "10");
authoriseRequest.putCardItem("expiryYear", "2020");
authoriseRequest.putCardItem("holderName", "Card Holder");
authoriseRequest.putCardItem("number", "4917610000000000");
authoriseResponse response = checkout.authorise(authoriseRequest);
// Set your X-API-KEY with the API key from the Customer Area.
$client = new \Adyen\Client();
$client->setXApiKey("YOUR X-API-KEY");
$service = new \Adyen\Service\Authorise($client);

$params = array(
  "amount" => array(
    "currency" => "EUR",
    "value" => 1500
  "reference" => "YOUR_ORDER_NUMBER",
  "threeDS2RequestData" => array(
    "deviceChannel" => "app"
  "card" => array(
    "cvc" => "737",
    "expiryMonth" => "10",
    "expiryYear" => "2020",
    "holderName" => "Card Holder",
    "number" => "4917610000000000"
  "merchantAccount" => "YOUR_MERCHANT_ACCOUNT"
$result = $service->authorise($params);
#Set your X-API-KEY with the API key from the Customer Area.
ady = Adyen.Adyen()
client = ady.client
client.xapikey = "YOUR X-API-KEY"

request = {}
request['amount'] = {
  "value": 1500,
  "currency": "EUR"
request['threeDS2RequestData] = {
  "deviceChannel" = "app"
request['reference'] = "YOUR_ORDER_NUMBER"
request['card'] = {
  "cvc": "737",
  "expiryMonth": "10",
  "expiryYear": "2020",
  "holderName": "Card Holder",
  "number": "4917610000000000"
request['merchantAccount'] = "YOUR_MERCHANT_ACCOUNT"
result = self.ady.checkout.authorise(request)
// Set your X-API-KEY with the API key from the Customer Area.
var client = new Client ("YOUR-X-API-KEY", Environment.Test);
var checkout = new Checkout(client);

var amount = new Model.Checkout.Amount("EUR", 1500);
var details = new Model.Checkout.DefaultCardDetails{
  Cvc = "737",
  ExpiryMonth = "10",
  ExpiryYear = "2020",
  HolderName= "Card Holder",
  Number = "4917610000000000"
var threeds2requestdata = new Model.Checkout.threeDS2RequestData{
  deviceChannel = "app"
var authoriseRequest = new Model.Checkout.AuthoriseRequest
  Reference = "YOUR_ORDER_NUMBER",
  Amount = amount,
  MerchantAccount = "YOUR_MERCHANT_ACCOUNT",
  Card = details,
  ThreeDS2RequestData = threeds2requestdata

var paymentResponse = checkout.Authorise(authoriseRequest); 

You'll receive a response containing:

  • resultCodeIdentifyShopper. This means that you need to perform the Identify the shopper flow.
  • The following parameters which you'll need to create a transaction in the 3D Secure 2 SDK.
    • additionalData.threeds2.threeDS2DirectoryServerInformation.directoryServerId
    • additionalData.threeds2.threeDS2DirectoryServerInformation.publicKey
      Alternatively, you can choose to prefetch the device fingerprinting keys.
In case the issuer does not support 3D Secure 2, we will initiate a 3D Secure 1 fallback by default, indicated by a RedirectShopper resultCode. See 3D Secure fallback for more information.
Payment response
    "additionalData": {
        "threeds2.threeDSServerTransID": "055fadfb-9fe4-4e70-99f0-9b8935bf1eb2",
        "threeds2.threeDS2DirectoryServerInformation.algorithm": "RSA",
        "threeds2.threeDS2Token": "BQABAQC2LEWucYNwQRzhH9c1/hup5ZZa9HUehFbwdC86PAfhpGJ/+...",
        "threeds2.threeDS2DirectoryServerInformation.directoryServerId": "A000000003",
        "threeds2.threeDS2DirectoryServerInformation.publicKey": "eyJrdHkiOiJSU0EiLCJlIjoiQVFBQiIsIm4iOiI4VFBxZkFQ==..."
    "pspReference": "8835495304426403",
    "resultCode": "IdentifyShopper"

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

Step 2: Get the 3D Secure 2 device fingerprint

If your server receives an IdentifyShopper resultCode, start the 3D Secure 2 device fingerprinting process.

  1. Create an instance of ConfigParameters using the parameters from the /authorise response or from your prefetched cached keys.

    ConfigParameters configParameters = AdyenConfigParameters.from(
            {hint:The directoryServerId from the authorise response}directoryServerId{/hint},
            {hint:The publicKey from the authorise response}directoryServerPublicKey{/hint}

    For a complete description of all SDK classes, see our Javadoc page.

  2. Use ThreeDS2Service.INSTANCE to create a transaction.

    ThreeDS2Service.INSTANCE.initialize(/*Activity*/ this, configParameters, null, null);
    Transaction mTransaction = ThreeDS2Service.INSTANCE.createTransaction(null, null);

    Keep a reference to your Transaction instance until the transaction is complete.

  3. Use the AuthenticationRequestParameters to get the device fingerprint information.

    AuthenticationRequestParameters authenticationRequestParameters = mTransaction.getAuthenticationRequestParameters();

    You'll get the following information:

    • transaction.authenticationRequestParameters.deviceData
    • transaction.authenticationRequestParameters.SDKTransactionID
    • transaction.authenticationRequestParameters.SDKAppID
    • transaction.authenticationRequestParameters.SDKReferenceNumber
    • transaction.authenticationRequestParameters.SDKEphemeralPublicKey
    • transaction.authenticationRequestParameters.MessageVersion

  4. Make a POST /authorise3ds2 call to send the encrypted device fingerprint information to Adyen:

    • sdkEncData: Device data
    • sdkTransID: SDK Transaction ID
    • sdkAppID: SDK App ID
    • sdkReferenceNumber: SDK Reference Number
    • sdkEphemPubKey: SDK Ephemeral Public Key
      To increase the likelihood of achieving a frictionless flow and higher authorisation rates, we also recommend that you send additional parameters in this list.
    Send device fingerprint to Adyen
      curl \
       -H "X-API-key: [Your API Key here]" \
       -H "Content-Type: application/json" \
       -d '{
          "merchantAccount": "YOUR_MERCHANT_ACCOUNT",
          "threeDS2RequestData": {
            "deviceChannel": "app",
            "sdkAppID": "9063b12c-fcde-43c7-b28e-8d0af5520e8a",
            "sdkEncData": "<device-fingerprint>",
            "sdkEphemPubKey": {
                "crv": "P-256",
                "kty": "EC",
                "x": "LYImJkRzS92vogM6AUPCBhJ20VagSe8IL0Q9SdisUSo",
                "y": "Rav4sKHnLUIUHVdyR4dyV7G2_EeAnuCn_6621ZhqZYU"
            "sdkReferenceNumber": "3DS_LOA_SDK_ADBV_739485_94783",
            "sdkTransID": "b60c9879-ac77-4918-a317-7b01c4317053/8Q==.."

    You'll receive a response containing a resultCode that can be:

    • Authorised – Indicates that the 3D Secure 2 authentication was frictionless, and the payment authorisation 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. This means that you'll have to perform the challenge flow.

    In case of a ChallengeShopper result code, you'll also get the following parameters from the response. You'll need these parameters to start the challenge flow in the 3D Secure 2 SDK:

    • threeds2.threeDS2ResponseData.threeDSServerTransID
    • threeds2.threeDS2ResponseData.acsTransID
    • threeds2.threeDS2ResponseData.acsReferenceNumber
    • threeds2.threeDS2ResponseData.acsSignedContent
    • threeds2.threeDS2Token

    Here's an example of a challenge flow response:

    Response showing ChallengeShopper
        "additionalData": {
            "threeds2.threeDS2ResponseData.acsSignedContent": "eyJhbGciOiJQUzI1NiIsIngPVEFOQmdrcWhraUc5dtw4I-RBJ8_OUt8yIZEsoc...",
            "threeds2.threeDS2ResponseData.transStatus": "C",
            "threeds2.threeDS2ResponseData.acsChallengeMandated": "Y",
            "threeds2.threeDS2ResponseData.acsURL": "",
            "threeds2.threeDS2ResponseData.threeDSServerTransID": "930h2k09-1986-4hl2-800a-c8d7783918bf",
            "threeds2.threeDS2ResponseData.authenticationType": "01",
            "threeds2.threeDS2ResponseData.messageVersion": "2.1.0",
            "threeds2.threeDS2Token": "BQABAQC2LEWucYNwQRzhH9c1/hup5ZZa9HUehFbwdC86PAfhpGJ/+...",
            "threeds2.threeDS2ResponseData.acsTransID": "45e79886-e60c-4c6d-a962-7aa43d59b150",
            "threeds2.threeDS2ResponseData.acsReferenceNumber": "ADYEN-ACS-SIMULATOR"
        "pspReference": "8825495326513370",
        "resultCode": "ChallengeShopper"

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

Step 3: 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.

  1. Create an instance of ChallengeParameters and pass the values from the /authorise3ds2 response.

    Map<String, String> additionalData = ...; // Retrieved from Adyen.
    ChallengeParameters challengeParameters = new ChallengeParameters();
  2. Present the challenge.

    mTransaction.doChallenge(/*Activity*/ this, challengeParameters, new ChallengeStatusReceiver() {
                    public void completed(CompletionEvent completionEvent) {
                        String transactionStatus = completionEvent.getTransactionStatus();
                        // Submit the transactionStatus to /authorise3ds2.
                    public void cancelled() {
                        // Cancelled by the user or the App.
                    public void timedout() {
                        // The user didn't submit the challenge within the given time, 5 minutes in this case.
                    public void protocolError(ProtocolErrorEvent protocolErrorEvent) {
                        // An error occurred.
                    public void runtimeError(RuntimeErrorEvent runtimeErrorEvent) {
                        // An error occurred.
                }, 5);
  3. When the challenge flow has been completed, get the transactionStatus from the completionEvent and pass this to your server.

  4. Make a POST /authorise3ds2 request from your server, specifying the transStatus generated by the SDK, and the threeds2.threeDS2Token.

    Send challenge result
     curl \
      -H "X-API-key: [Your API Key here]" \
      -H "Content-Type: application/json" \
      -d '{
         "merchantAccount": "YOUR_MERCHANT_ACCOUNT",
         "threeDS2Result": {
            "transStatus": "Y"
        "threeDS2Token": "BQABAQC2LEWucYNwQRzhH9c1/hup5ZZa9HUehFbwdC86PAfhpGJ/+..."

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

        "additionalData": {
            "liabilityShift": "true",
            "authCode": "44402",
            "avsResult": "4 AVS not supported for this card type",
            "threeDOffered": "true",
            "refusalReasonRaw": "AUTHORISED",
            "authorisationMid": "1000",
            "acquirerAccountCode": "TestPmmAcquirerAccount",
            "cvcResult": "1 Matches",
            "avsResultRaw": "4",
            "threeDAuthenticated": "true",
            "cvcResultRaw": "M",
            "acquirerCode": "TestPmmAcquirer",
            "acquirerReference": "7CASOGMCCB4"
        "pspReference": "8825495331860022",
        "resultCode": "Authorised",
        "authCode": "44402"

Optional: Prefetch device fingerprinting keys

This functionality requires additional configuration on Adyen's end. To enable it, contact our Support Team.

You can opt to retrieve and cache 3D Secure device fingerprint keys for specific BIN ranges or card brands. When you cache the keys, you reduce the number of calls for each transaction as you can already start with performing 3D Secure 2 device fingerprinting.

To use cached keys for your authentication flow, you will need to:

  1. Retrieve device fingerprinting keys once for each card brand or BIN and save the keys to your cache.
  2. Use the cached keys to perform 3D Secure 2 device fingerprinting and submit the result in a payment request.
  3. Present a challenge if required by the issuer.

Make sure to update your cache regularly to get the latest keys and to avoid getting your transactions refused.

Retrieve device fingerprinting keys

  1. Send a POST /get3dsAvailability request, providing your merchantAccount along with a cardNumber from a BIN range you want to cache, or a list of card brand names.

    Request with card number
    curl \
      -H "X-API-key: [Your API Key here]" \
      -H "Content-Type: application/json" \
      -d '{
    Response for card number
      "binDetails": {
        "issuerCountry": "PL"
      "dsPublicKeys": [
          "brand": "visa",
          "directoryServerId": "F013371337",
          "publicKey": "eyJrdHkiOiJSU0==.."
      "threeDS1Supported": true,
      "threeDS2CardRangeDetails": [
          "brandCode": "visa",
          "endRange": "491761000000",
          "startRange": "491761000000",
          "threeDS2Version": "2.1.0",
          "threeDSMethodURL": ""
      "threeDS2supported": true
    Request with card brand
    curl \
      -H "X-API-key: [Your API Key here]" \
      -H "Content-Type: application/json" \
      -d '{
          "brands" : ["visa","mc"]
    Response for card brands
  2. Save the values of the following parameters for the specific BIN range or brand:
    • dsPublicKeys.directoryServerId
    • dsPublicKeys.publicKey

Next, use the cached keys to create a transaction in the 3D Secure 2 SDK to get the device fingerprint.

UI customizations

Customize the SDK theme

The SDK 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>

Using UiCustomization class

If you require further UI customizations, the SDK 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 ThreeDS2Service.INSTANCE.

For example, to change the toolbar's title text and text color:

ToolbarCustomization toolbarCustomization = new ToolbarCustomization();
toolbarCustomization.setHeaderText("Secure Checkout");

UiCustomization uiCustomization = new UiCustomization();

ThreeDS2Service.INSTANCE.initialize(getContext(), configParameters, null, uiCustomization);

Check out the UiCustomization class reference documentation for a complete list of customizable properties.

You can also customize the following UI elements used in the challenge flow:

Customizable elements Customizable properties
  • Font size
  • Text
  • Font color
  • Font size
Info items
  • Heading and info text
  • Heading and info font color
  • Heading and info font size
  • Expanded state indicator color
  • Highlighted background color
Input fields
  • Font size
Input fields header
  • Font size
Navigation bar
  • Text
  • Font color
  • Font size
  • Status bar background color
Continue/Verify button
  • Font size
Cancel button
  • Font size
  • Highlighted background color
Resend button
  • Font size
  • Highlighted background color

Testing 3D Secure 2

Before going live, use the following card numbers and credentials to test your integration.

We recommend testing each Card Type.

To test how your integration handles different 3D Secure 2 authentication scenarios, use our test card numbers.
All our test cards use the following expiry dates and security codes:

Expiry Date CVC/CVV CID
10/2020 737 7373
03/2030 737 7373

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

  • For mobile, use password: 1234
  • For web, use password: password
Card Type Card Number
American Express 3714 4963 5398 431
Cartes Bancaires 4035 5014 2814 6300
Diners 3056 9309 0259 04
Discover 6011 1111 1111 1117
Maestro 1 5000 5500 0000 0029
Mastercard 5454 5454 5454 5454
UnionPay 6212 3456 7890 1232
Visa 4917 6100 0000 0000

1 This card doesn't require a CVC.
When you make a payment request with these cards, you'll receive the following result codes depending on your integration:

  • RedirectShopper: You'll receive this result code if you are using the Redirect authentication.
  • IdentifyShopper: You'll receive this result code if you are using the Native authentication.
  • ChallengeShopper: You might get this result code after you submit the 3D Secure 2 device fingerprinting result in a Native authentication, indicating a challenge flow.

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
Visa 4212 3456 7891 0006

To test the frictionless flow, specify in your payment request:

  • amount.value: 12002

App-based integration

To test different authentication scenarios for app-based integration, use the following test cards:

Card number Authentication scenario
5201 2855 6567 2311 Basic text authentication
5201 2874 9905 2008 Basic single select
5201 2815 9233 1633 Basic multi select
5201 2888 2269 6974 Basic out-of-band (OOB) authentication
5201 2895 0084 3268 HTML OOB authentication
5201 2861 5377 1465 App single select then text authentication

Other scenarios

Card number Scenario
4199 3500 0000 0002 The card is not enrolled for 3D Secure transactions,
5201 2829 9900 5515 There was a technical error.

See also