3D Secure

Step by Step Integration

Table of ContentsAnchorIcon

3DS Client side flowAnchorIcon

Generate a client tokenAnchorIcon

Important

The SSL certificates for Braintree Mobile (iOS and Android) SDKs are set to expire on March 30, 2026. This will impact existing versions of the SDK in published versions of your app. To reduce the impact, upgrade the iOS SDK to version 6.17.0+Android SDK to version 4.45.0+ or version 5.0.0+ for the new SSL certifications.

If you do not decommission your app versions that include the older SDK versions or force upgrade your app with the updated certificates by the expiration date, 100% of your customer traffic will fail.

Before you can initialize a ThreeDSecureClient, you will need to set up the SDK and initialize a BraintreeClient with a ClientTokenProvider.

Additionally, add the following Maven repository and (non-sensitive) credentials to your app-level gradle.

  1. Groovy
repositories {
    maven {
        url "https://cardinalcommerceprod.jfrog.io/artifactory/android"
        credentials {
            username = 'braintree_team_sdk'
            password = 'cmVmdGtuOjAxOjIwMzgzMzI5Nzg6Q3U0eUx5Zzl5TDFnZXpQMXpESndSN2tBWHhJ'
        }
    }
}

If you would like to use a merchant account ID other than your default, specify the merchant_account_id when generating the client token. The merchant account ID used to create the client token must match the merchant account ID used to create the subsequent transaction or verification.

Verify a card using 3DSAnchorIcon

Create a requestAnchorIcon

To use 3DS, you will need to create a ThreeDSecureRequest object with relevant customer and transaction data in order to minimize the need for issuing banks to present authentication challenges to customers.

The ThreeDSecureRequest object must contain the following fields:

  • amount
  • nonce

The object should contain as many of the following fields as possible. The full list of fields is described in the SDK documentation.

  1. Java
  2. Kotlin
ThreeDSecurePostalAddress address = new ThreeDSecurePostalAddress();
address.setGivenName("Jill"); // ASCII-printable characters required, else will throw a validation error
address.setSurname("Doe"); // ASCII-printable characters required, else will throw a validation error
address.setPhoneNumber("5551234567");
address.setStreetAddress("555 Smith St");
address.setExtendedAddress("#2");
address.setLocality("Chicago");
address.setRegion("IL");  // ISO-3166-2 code
address.setPostalCode("12345");
address.setCountryCodeAlpha2("US");

// For best results, provide as many additional elements as possible.
ThreeDSecureAdditionalInformation additionalInformation = new ThreeDSecureAdditionalInformation();
additionalInformation.setShippingAddress(address);

ThreeDSecureRequest threeDSecureRequest = new ThreeDSecureRequest();
threeDSecureRequest.setAmount("10.00");
threeDSecureRequest.setEmail("test@email.com");
threeDSecureRequest.setBillingAddress(address);
threeDSecureRequest.setVersionRequested(ThreeDSecureRequest.VERSION_2);
threeDSecureRequest.setAdditionalInformation(additionalInformation);

Drop-in UIAnchorIcon

Important

3DS support requires Drop-in version 4.3.0 or higher.

Note

If you are using the Drop-In UI to tokenize cards, you have CVV rules enabled and you run 3D Secure verifications, the default setting to vault cards on your client will result in a processor error. Instead, you should disable vaulting via the Drop-In UI and vault the card on your server. You can do so by setting vaultCardDefaultValue to false when initializing the Drop-In UI and include the vault_on_success=true parameter when creating a transaction using transaction:sale or a GraphQL mutation from your server.

First, make sure to include our Drop-in in your project. Next, declare a URL scheme in your AndroidManifest. This allows your app to switch to a browser to complete the 3D Secure verification workflow and return.

The ThreeDSecureRequest object must contain the following fields:

  • amount
  • versionRequested (set as ThreeDSecureRequest.VERSION_2)
  1. Java
  2. Kotlin
ThreeDSecureRequest threeDSecureRequest = new ThreeDSecureRequest();
threeDSecureRequest.setAmount("10.00");
threeDSecureRequest.setVersionRequested(ThreeDSecureRequest.VERSION_2);

//Pass other 3DS parameters here

Then, add the ThreeDSecureRequest object to your DropInRequest.

  1. Java
  2. Kotlin
DropInRequest dropInRequest = new DropInRequest();
dropInRequest.setThreeDSecureRequest(threeDSecureRequest);

Custom UIAnchorIcon

To make sure your app can complete a 3D Secure verification, declare a URL scheme in your AndroidManifest. This will allow Android to return to your app from a browser-based verification flow.

Add the following to your app-level build.gradle file:

  1. Kotlin
  2. Groovy
dependencies {
    implementation("com.braintreepayments.api:three-d-secure:4.49.1")
}

The ThreeDSecureRequest object must contain the following fields:

  • amount
  • nonce
  • versionRequested (set as ThreeDSecureRequest.VERSION_2)
  1. Java
  2. Kotlin
// Card nonce that we wish to upgrade to a 3DS nonce.
CardNonce cardNonce = (CardNonce) paymentMethodNonce;

ThreeDSecureRequest threeDSecureRequest = new ThreeDSecureRequest();
threeDSecureRequest.setAmount("10.00");
threeDSecureRequest.setNonce(cardNonce.getString());
threeDSecureRequest.setVersionRequested(ThreeDSecureRequest.VERSION_2);

//Pass other 3DS parameters here
Note

To verify vaulted cards, you would need to first generate the nonce on the server and then pass it in the ThreeDSecureRequest.

You can submit a ThreeDSecureRequest object by calling ThreeDSecureClient#performVerification. If a card is enrolled in a 3D Secure program (e.g. Verified by Visa), the sdk will present a 3D Secure authentication challenge using card data linked to a payment method nonce.

  1. Java
  2. Kotlin
BraintreeClient braintreeClient = new BraintreeClient(this, new ExampleClientTokenProvider());
  ThreeDSecureClient threeDSecureClient = new ThreeDSecureClient(this, braintreeClient);

  threeDSecureClient.performVerification(activity, threeDSecureRequest, (threeDSecureLookupResult, lookupError) -> {
    // optional: inspect the lookup result and prepare UI if a challenge is required
    threeDSecureClient.continuePerformVerification(activity, threeDSecureRequest, threeDSecureLookupResult);
  });

Implement a ThreeDSecureListener to receive results from the 3D Secure flow. Once the user completes the 3D Secure process, send the nonce to your server and create a transaction.

  1. Java
  2. Kotlin
public class MyActivity extends AppCompatActivity implements ThreeDSecureListener {

  @Override
  public void onThreeDSecureSuccess(@NonNull ThreeDSecureResult threeDSecureResult) {
    // send this nonce to your server
    String nonce = threeDSecureResult.getTokenizedCard().getString();  
  }

  @Override
  public void onThreeDSecureFailure(@NonNull Exception error) {
    if (error instanceof UserCanceledException) {
      // user canceled
    } else {
      // handle error
    }
  }
}

If you are using using an Activity and your Activity's launch mode is singleTop, singleTask, or singleInstance you will also need to override onNewIntent:

  1. Java
  2. Kotlin
public class MyActivity extends AppCompatActivity {

  @Override
  protected void onNewIntent(Intent newIntent) {
    super.onNewIntent(newIntent);

    setIntent(newIntent);
  }
}

A validation error from Braintree will be returned if a field does not follow Cardinal's documentation.

3DS Server side flowAnchorIcon

An alternative way of performing 3DS is to make the 3DS call from the server instead of from the client machine.

To meet the device data collection requirements for 3DS, merchants must either make a prerequisite prepareLookup call in the client SDK or pass in the browser fields directly as input parameters.

Prepare the 3DS lookupAnchorIcon

The prepareLookup call will return the data needed to perform a 3D Secure lookup call. This call is triggered from the client's device. The payload returned by this call should be passed on to the server so a 3DS lookup can be done from there.

  1. Java
ThreeDSecureRequest threeDSecureRequest = new ThreeDSecureRequest()
  .amount("10")
  .email("test@email.com")
  .billingAddress(address)
  .additionalInformation(additionalInfo)
  .nonce(paymentMethodNonce)
  .versionRequested(ThreeDSecureRequest.VERSION_2);
  .accountType(ThreeDSecureRequest.CREDIT);

BraintreeClient braintreeClient = new BraintreeClient(this, new ExampleClientTokenProvider());
ThreeDSecureClient threeDSecureClient = new ThreeDSecureClient(this, braintreeClient);
threeDSecureClient.prepareLookup(context, threeDSecureRequest,
  (threeDSecureLookupResult, lookupError) -> {
    // Send payload to the server to do server side lookup
  }
)

Make the 3DS lookup callAnchorIcon

Use the GraphQL mutation performThreeDSecureLookup to attempt to perform 3D Secure Authentication on credit card payment method. This may consume the payment method and return a new single-use payment method.

Including device data is mandatory. This can be done either by passing along the dfReferenceId or browserInformation.

  1. Mutation
mutation PerformThreeDSecureLookup($input: PerformThreeDSecureLookupInput!) {
    performThreeDSecureLookup(input: $input) {
      clientMutationId
      threeDSecureLookupData {
        authenticationId
      }
      paymentMethod {
        id
        details {
          ... on CreditCardDetails {
            bin
            threeDSecure {
              authentication {
                cavv
                eciFlag
                liabilityShifted
                liabilityShiftPossible
              }
            }
          }
        }
      }
    }
  }
  1. Variables
{
    input: {
      paymentMethodId: single_use_payment_method_id,
      amount: "10.00",
      transactionInformation: {
        browserInformation: 
          {
            javaEnabled: false,
            acceptHeader: "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
            language: "en-GB",
            colorDepth: 24,
            screenHeight: 720,
            screenWidth: 1280,
            timeZone: "0",
            userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safar  i/537.36",
            javascriptEnabled: true,
          }
        ipAddress: "82.34.105.112",
        deviceChannel: "BROWSER",
      },
    }
  }

Trigger 3DS challengeAnchorIcon

This call will launch the iframe challenge using a 3D Secure lookup response from a server side lookup. This call is only necessary if a challenge is required.

  1. Java
ThreeDSecureRequest threeDSecureRequest = new ThreeDSecureRequest()
  .amount("10")
  .email("test@email.com")
  .billingAddress(address)

BraintreeClient braintreeClient = new BraintreeClient(this, new ExampleClientTokenProvider());
ThreeDSecureClient threeDSecureClient = new ThreeDSecureClient(this, braintreeClient);
threeDSecureClient.initializeChallengeWithLookupResponse(
  activity, request, lookupResponse, new ThreeDSecureResultCallback() {
  
  @Override
  public void onResult(@Nullable ThreeDSecureResult threeDSecureResult,
                       @Nullable Exception error) {
    if (threeDSecureResult != null) {
      listener.onThreeDSecureSuccess(threeDSecureResult);
    } else if (error != null) {
      listener.onThreeDSecureFailure(error);
    }
  }
});

See also


Next Page: Applying 3DS to Transactions and Verifications

If you accept cookies, we’ll use them to improve and customize your experience and enable our partners to show you personalized PayPal ads when you visit other sites. Manage cookies and learn more