# 3DS Android SDK Use our 3D Secure (3DS) Android SDK to seamlessly handle the end-to-end [3DS](https://www.checkout.com/docs/payments/authenticate-payments/3d-secure.md) authentication flow. With a single method call, the SDK handles: - collecting required device data - communicating with the customer's bank - presenting 3DS challenges when required When used alongside our [non-hosted sessions](https://www.checkout.com/docs/payments/authenticate-payments/3d-secure/standalone-sessions/non-hosted-sessions.md) authentication solution, the 3DS SDK allows you to authenticate within the payment authorization flow. Alternatively, you can use the authentication result to complete the payment manually at a later time. Additionally, the SDK is fully EMVCo and PCI-compliant, ensuring interoperability with card issuers and secure handling of your customers' data. > **Information** > > The SDK only collects data which your app already has permission to collect – the customer will never be prompted to grant new permissions. The device data collected is encrypted throughout the authentication process but is never stored, and the SDK does not retain any personal information about the customer. --- ## 3DS flows 3DS allows you and your payment provider to share additional data with the customer's bank. For example, the customer's device ID and payment history. This data allows the bank to assess the risk of the transaction more accurately, and determine which flow the customer will be required to go through: - frictionless flow - challenge flow ### Frictionless flow If the customer's bank is satisfied with the data and trusts that the cardholder making the payment is genuine, the transaction will be authenticated without interrupting the customer. The customer is only shown a brief _Processing_ UI, with their card scheme's branding. ![A frictionless 3DS mobile experience – no additional customer action is required](https://www.checkout.com/docs/large-media-assets/iOS_frictionless.gif) ### Challenge flow If the bank requires additional evidence to authenticate the cardholder, they will prompt the customer to verify their identity. To do this, the bank may use any of the following methods: - one-time password – the customer is sent a single-use password or code via text or email, which they must enter - single-select or multi-select – the customer is asked a multiple-choice question, with one or more selections allowed - out-of-band – the customer is asked to confirm the transaction through another channel, typically their banking app - HTML – the bank explicitly defines the view that should be presented to the customer via HTML, which can be that of any of the previous methods, or a custom approach ![A challenge 3DS mobile experience – the customer must confirm their identity to proceed](https://www.checkout.com/docs/large-media-assets/iOS_OOB.gif) > **Information** > > To provide a consistent experience across different devices and schemes, there are standard templates and rules that the 3DS challenge screens adhere to. However, there is some leeway around styling. Our SDK gives you control over the display of the native challenges in your app, while ensuring that the rules are followed. --- ## Integrate the 3DS SDK 1. Add the SDK as a project dependency. 1. Initialize the SDK. 1. Configure authentication parameters. 1. Handle authentication results. 1. Handle Android App Links. 1. Customize the 3DS Challenge UI. --- ## Before you start Make sure you have a [test account](https://www.checkout.com/get-test-account) with Checkout.com. To use the SDK, you'll also need to have onboarded with our [non-hosted sessions](https://www.checkout.com/docs/payments/authenticate-payments/3d-secure/standalone-sessions/non-hosted-sessions.md) authentication solution. You'll also need the following: - a [public key](https://www.checkout.com/docs/developer-resources/api/manage-api-keys/api-keys.md#Public_API_keys), to initialize the SDK and authenticate your payment request - a [secret key](https://www.checkout.com/docs/developer-resources/api/manage-api-keys/api-keys.md#Secret_API_keys) or [OAuth 2.0 client credentials](https://www.checkout.com/docs/developer-resources/api/manage-api-keys/oauth-2-0-client-credentials.md), to use as an authentication mechanism --- ## Add the SDK as a project dependency The [3DS SDK for Android](https://github.com/checkout/checkout-3ds-sdk-android) is available for download as a package on GitHub and in Maven Central. > **Information** > > You can subscribe to the GitHub repository to be notified about updates to the SDK. ### Minimum requirements The minimum requirements to use the Android SDK are: - Kotlin 1.8.10 or higher - JDK 17 or higher - Gradle 8.0.2 or higher - Android Gradle Plugin 8.0 - Android API level 21 (Android 5.0) or higher as a build target > **Information** > > The SDK makes use of Java 8+ language features. To run on Android level 25 (Android 7) or lower, you must enable [desugaring](https://developer.android.com/studio/write/java8-support#library-desugaring). ### Add the SDK dependency Declare the 3DS SDK as an application or library dependency in your `build.gradle` file, using Maven Repository or GitHub Packages. **Maven repository** ```kotlin // Option 1: add the following to your project’s top-level Gradle file allprojects { repositories { mavenCentral() } } // Option 2: add the following to your project’s Gradle settings file dependencyResolutionManagement { repositories { mavenCentral() } } // Add the following to your application or library's Gradle file dependencies { implementation("com.checkout:checkout-sdk-3ds-android:") } ``` **GitHub Packages** ```kotlin // Option 1: add the following to your project’s top-level Gradle file allprojects { repositories { maven { url = uri("https://maven.pkg.github.com/checkout/checkout-3ds-sdk-android") credentials { username = "Add your GitHub Username" password = "Add your GitHub Token" } } } } // Option 2: add the following to your project’s Gradle setting file dependencyResolutionManagement { repositories { maven { url = uri("https://maven.pkg.github.com/checkout/checkout-3ds-sdk-android") credentials { username = "Add your GitHub Username" password = "Add your GitHub Token" } } } } // Add the following to your application or library's Gradle file. dependencies { implementation("com.checkout:checkout-sdk-3ds-android:") } ``` --- ## Initialize the SDK Initialize the SDK and set the: - environment – for example, `production` or `sandbox` - locale - 3DS challenge UI configuration **Kotlin** ```kotlin // Option 1: initialize with default configuration val checkout3DS = Checkout3DSService(context) // Option 2: initialize with custom configuration val checkout3DS = Checkout3DSService( context, Environment.PRODUCTION, Locale.UK, uiCustomization, Uri.parse("https://sampleAppName.com/3ds_authentication") ) ``` **Java** ```java // Option 1: initialize with default configuration Checkout3DSService checkout3DS = new Checkout3DSService(context); // Option 2: initialize with custom configuration Checkout3DSService checkout3DS = new Checkout3DSService( context, Environment.PRODUCTION.INSTANCE, Locale.UK, uiCustomisation, Uri.parse("sampleAppScheme://sampleAppName/3ds_authentication") ); ``` ### Checkout3DSService The SDK's `Checkout3DSService` class provides the core functionality to perform payment authentication via the `authenticate()` method. You only need to initialize the class once for the lifetime of the application. You must specify an app `context` when you initialize the SDK. All other configuration options are optional. **View Checkout3DSService reference** When you initialize, you can specify any of the following configuration options: | Parameter | Type | Description | | --- | --- | --- | | `environment` | `Environment` | The environment the SDK will connect to. For example, `PRODUCTION` or `SANDBOX`.

If no value is specified, `PRODUCTION` is used by default. | | `locale` | `Locale` | The customer's locale and preferred language.

If no value is specified, the device locale is used by default. | | `uiCustomization` | `UICustomization` | The UI customization options for the 3DS challenge presented to the customer. | | `context` | `Context` | The app context.

You must specify an app `context` during initialization, as Android requires this in order to access app resources. | | `appUrl` | `URL` | The application URL, up to 211 characters, used to open your app and bring it to the foreground.

If the card issuer supports this feature, the authenticating app automatically uses this `appUrl` to redirect the user to your application after an out-of-band (OOB) authentication.

This field must be an [Android App Link](https://developer.android.com/training/app-links). Your app must later [handle the Android App Link](#Handle_Android_App_Links). | ### Check for security warnings You can use the `getWarnings()` method to check for any security warnings when you initialize the SDK, or at any time after initialization. **View getWarnings reference** The method returns the following values: | Value | Type | Description | | --- | --- | --- | | `id` | `string` | An identifier for the warning.

Security warnings IDs are prefixed with `SW`, while initialization warning IDs are prefixed with `CW`. | | `message` | `string` | A description of the warning. | | `severity` | `string` | The severity of the warning, as a value of either `LOW`, `MEDIUM`, or `HIGH`. | ### Warning IDs The following table outlines the possible `id` values returned by the `getWarnings()` method: | Warning ID | Severity | Description | | --- | --- | --- | | `SW01` | `high` | The app is running on a jailbroken device | | `SW02` | `high` | The SDK has been tempered with | | `SW03` | `high` | The app is running within an emulator | | `SW04` | `medium` | A debugger is attached to the app | | `SW05` | `high` | The app is running on an unsupported OS version | | `CW01` | `low` | The `appUrl` provided exceeds the 211-character limit and has been ignored | | `CW03` | `low` | The `appUrl` provided is not in a recognized Universal App Link format and has been ignored | --- ## Configure authentication parameters Before you can begin authentication using the SDK, your back end must first call the [Request a session](https://api-reference.checkout.com/tag/Standalone/#operation/createSession) endpoint to authenticate the cardholder. In your application code, create an instance of `AuthenticationParameters` and populate it with the values returned in the Session API response. **Kotlin** ```kotlin val authenticationParameters = AuthenticationParameters( sessionId = "sessionId", sessionSecret = "sessionSecret", scheme = "scheme" ) ``` **Java** ```java AuthenticationParameters authenticationParameters = new AuthenticationParameters( "sessionId", "sessionSecret", "scheme"); ``` **View authenticationParameters reference** | Parameter | Type | Description | | --- | --- | --- | | `sessionID` | `string` | The unique ID of the authentication session. | | `sessionSecret` | `string` | The session secret. | | `scheme` | `string` | The customer's card scheme, as a value of either `Visa`, `Mastercard`, `Jcb`, `Amex`, or `Diners`.

The value provided determines which card scheme logo will be displayed to the customer. | With the authentication information, the SDK will take care of: - gathering the necessary device data - sharing the information with the customer's bank - if necessary, presenting a native challenge screen to the customer The type of challenge presented to the customer depends on the configuration of the customer’s bank. --- ## Handle authentication results When the authentication process is completed after you call the `authenticate()` method, the SDK will return the authentication results: - If authentication was successful, the SDK returns an `AuthenticationCompleted` object. You can complete the payment with the [Payments API](https://api-reference.checkout.com/tag/Payments/#operation/requestAPaymentOrPayout) or with an alternative payments service provider. - If authentication was unsuccessful, the SDK returns the reason for the failure as a [3DS SDK error code](https://www.checkout.com/docs/developer-resources/codes/3ds-sdk-error-codes.md) within `AuthenticationError`. You must handle the error before proceeding. > **Note** > > In rare circumstances, there may be inconsistencies between the SDK output and the authentication status. This can be due to timing differences between the SDK, back end, Access Control Server (ACS), and card scheme during the flow. > > To ensure that you receive the accurate authentication status (session status), we recommend that you implement one of the following at the end of every authentication flow: > > - Perform a [GET session](https://api-reference.checkout.com/tag/Standalone/#operation/getSession) request, referencing the session status > - Use the [Authentication approved](https://www.checkout.com/docs/developer-resources/event-notifications/event-types/authentication_approved.md), [Authentication expired](https://www.checkout.com/docs/developer-resources/event-notifications/event-types/authentication_expired.md), or [Authentication failed](https://www.checkout.com/docs/developer-resources/event-notifications/event-types/authentication_failed.md) webhooks to understand the true session status of the flow **Kotlin** ```kotlin checkout3DS.authenticate(authenticationParameters, context) { result: AuthenticationResult -> when (result.resultType) { ResultType.Completed -> { // Handle authentication result - continue with the payment based on transaction status val authenticationCompleted: AuthenticationCompleted = (authResult as AuthenticationCompleted) val sdkTransactionId = authenticationCompleted.sdkTransactionId val transactionStatus = authenticationCompleted.transactionStatus } ResultTypeError -> { // Handle error (result as AuthenticationError) // Handle error based on error type category val errorType: AuthenticationErrorType = (result as AuthenticationError).errorType // Handle error based on fine grained error code or simply log the error val errorCode: String = (result as AuthenticationError).errorCode } } } ``` **Java** ```java checkout3DS.authenticate(authenticationParameters, result -> { switch (result.getEventType()) { case Completed: AuthenticationCompleted authenticationCompleted = (AuthenticationCompleted) result; String sdkTransactionId = authenticationCompleted.getSdkTransactionId(); String transactionStatus = authenticationCompleted.getTransactionStatus(); // Handle authentication result and continue with payment based on transaction status break; case Error: // Handle error AuthenticationError authenticationError = (AuthenticationError) result; // Handle error based on error type category AuthenticationErrorType errorType = authenticationError.getErrorType(); // Handle error based on error code String errorCode = authenticationError.getErrorCode(); break; } }); ``` **View authenticate reference** | Parameter | Type | Description | | --- | --- | --- | | `authenticationParameters` | `AuthenticationParameters` | The object containing the authentication parameters. | | `callback` | `AuthenticationCallback` | The listener to invoke with the result of the authentication process. | **View AuthenticationResult reference** | Parameter | Type | Description | | --- | --- | --- | | `resultType` | `ResultType` | Returns the outcome of the authentication.

If the value returned is `Completed`, you can proceed with the payment.

If the value returned is `Error`, you must handle the error that occurred during authentication. | **View AuthenticationCompleted reference** | Parameter | Type | Description | | --- | --- | --- | | `resultType` | `ResultType` | Returns the outcome of the authentication.

In an `AuthenticationCompleted` object, this value will always be `Completed`. | | `sdkTransactionID` | `string` | The SDK transaction ID that was received by the 3DS SDK in the final Challenge Response | | `transactionStatus` | `string` | The transaction status that was received in the Challenge Response | **View AuthenticationError reference** | Parameter | Type | Description | | --- | --- | --- | | `resultType` | `ResultType` | Returns the outcome of the authentication.

In an `AuthenticationError` object, this value will always be `Error`. | | `errorType` | `AuthenticationErrorType` | The type of error that occurred during authentication | | `errorCode` | `string` | The transaction status that was received in the Challenge Response | **View AuthenticationErrorType reference** | Enum value | Description | Retry available | | --- | --- | --- | | `AuthenticationProcessError` | Authentication did not complete due to the SDK's business rules. | ✗ | | `ConnectivityError` | Communication between the SDK and the remote server could not be established. Retry the authentication. | ✓ | | `ThreeDS2ProtocolError` | The SDK encountered an error specified in the 3DS2 protocol. | ✗ | | `InternalError` | The SDK encountered an error related to the implementation of the SDK. | ✗ | The value of `transactionStatus` returned in the `AuthenticationResult` object determines whether you can proceed with [requesting a payment authorization](https://api-reference.checkout.com/tag/Payments/#operation/requestAPaymentOrPayout): | Value | Description | Proceed to payment authorization | | --- | --- | --- | | `A` | Attempt at processing performed | ✓ | | `I` | Informational only | ✓ | | `N` | Not authenticated or account not verified | ✗ | | `R` | Authentication or account verification rejected | ✗ | | `U` | Authentication or account verification could not be performed | ✗ | | `Y` | Authentication verification successful | ✓ | > **Information** > > You can view a [transaction's status](https://www.checkout.com/docs/business-operations/use-the-dashboard/payment-activity/track-3ds-events.md#Transaction_status) from the _Payments_ > _Processing_ > _All Payments_ section of the [Dashboard](https://dashboard.checkout.com). --- ## Handle Android App Links 1. Add the following code to your `AndroidManifest.xml` file: ```xml ``` - Replace the `{yourapp.com}` value from in the `android:host` field with your web domain name. Do not change any other configuration. - Optionally, you can specify another value for `android:pathPrefix` to generate a unique App Link. 2. Verify the App Link. See Android Developers – [Verify Android App Links](https://developer.android.com/training/app-links/verify-android-applinks). --- ## Customize the 3DS Challenge UI With the default SDK implementation, the 3DS challenge screens presented to your customers are displayed with a clean, minimalist UI. The SDK also provides built-in display and accessibility features: - support for different screen sizes and orientations - dynamic text sizing - support for screen-reading technologies, including VoiceOver on iOS and TalkBack on Android - support for 37 languages If you want to customize the screen to match your app's visual design, you can use the SDK's customization options to change the following properties: - fonts and font colors - navigation bar and footer background colors - action button background colors, opacity, shadows, and corner shapes ![Examples of customized 3DS challenge user interfaces](https://www.checkout.com/docs/NAS/3DS SDK/3ds-sdk-custom-challenge-ui-android.png) To customize the UI, create a new `UICustomization` instance and include it as an argument when you [initialize](#Initialize_the_SDK) `Checkout3DSService`. The following example demonstrates the customization options available: **Kotlin** ### Simplified customization ```kotlin uiCustomization { all { textColor = R.color.styleGreenColor textFont = R.font.raleway tint = R.color.styleGreenColor } } ``` ### Full customization ```kotlin uiCustomization { navigationBar { backgroundColor = R.color.customStyle1Color1 panelElevation = R.dimen.navigationBarElevation1 heading { textColor = R.color.customStyle1Color6 text = R.string.navigationBarHeadingText1 textFont = R.font.raleway } button { textColor = R.color.customStyle1Color2 text = R.string.navigationBarButtonText1 textFont = R.font.raleway } } informationHeader { textColor = R.color.customStyle1Color1 textFont = R.font.raleway } informationText { textColor = R.color.customStyle1Color1 textFont = R.font.raleway } entryLabel { textColor = R.color.customStyle1Color1 textFont = R.font.raleway } whitelistLabel { thumbColor = R.color.customStyle1Color2 textColor = R.color.customStyle1Color5 textFont = R.font.raleway } actionButton { label { textColor = R.color.customStyle1Color6 textFont = R.font.raleway } background { backgroundColor = R.color.customStyle1Color1 cornerRadius = R.dimen.buttonCornerRadius1 bgElevation = R.dimen.buttonElevation1 } } alternativeButton { label { textColor = R.color.customStyle1Color3 textFont = R.font.raleway } background { backgroundColor = R.color.customStyle1Color4 borderColor = R.color.customStyle1Color3 borderWidth = R.dimen.buttonBorderWidth1 cornerRadius = R.dimen.buttonCornerRadius1 bgElevation = R.dimen.buttonElevation1 } } entryBox { input { textColor = R.color.customStyle1Color1 textFont = R.font.raleway } background { backgroundColor = R.color.customStyle1Color6 borderColor = R.color.customStyle1Color2 borderWidth = R.dimen.buttonBorderWidth1 cornerRadius = R.dimen.buttonCornerRadius1 bgElevation = R.dimen.buttonElevation1 } } entrySelector { selectorColor = R.color.customStyle1Color2 label { textColor = R.color.customStyle1Color1 textFont = R.font.raleway } } footer { expandIndicatorColor = R.color.customStyle1Color2 label { textColor = R.color.customStyle1Color5 textFont = R.font.raleway } text { textColor = R.color.customStyle1Color5 textFont = R.font.raleway } } } ``` **Java** ```java UICustomization uiCustomization = new UICustomization(); uiCustomization.navigationBar(navigationBarCustom -> { navigationBarCustom.setBackgroundColor(R.color.colorAccent); navigationBarCustom.setPanelElevation(R.dimen.buy_button_min_width); return Unit.INSTANCE; }); uiCustomization.informationHeader(navigationBarCustom -> { navigationBarCustom.setTextColor(R.color.colorAccent); return Unit.INSTANCE; }); // Add customization options as required ``` --- ## Security In accordance with PCI and EMVCo standards, the 3DS SDK incorporates several security approaches. This maintains the integrity of the SDK and ensures your customers' data is secure. ### SDK integrity protection The 3DS SDK is an encrypted binary. This provides increased protection from a number of threats including tampering and reverse engineering. Additionally, the SDK checks: - if the app was installed from a trusted app store and sends this information to the card issuer - the environment on which it's running and sends warnings to your app and the card issuer if it detects any threat indicators For example, the following scenarios would be classed as a threat indicator: - the device has unauthorized modifications (also referred to as a jailbroken device), which could enable unrestricted access to critical files - the SDK is running on an emulator - the SDK source code has been tampered with or its functionality has been modified - a debugging application is attached > **Information** > > After you initialize the SDK, check the [security warnings](#Check_for_security_warnings) for any potential threat indicators before you proceed with a transaction. ### Sensitive data protection To keep your customers' data secure and protect the 3DS process, the SDK takes the following precautions with sensitive data: - only collects sensitive data where it is essential for the authentication process and uses it solely for this purpose - does not disclose sensitive data to channels outside of the 3D Secure process - does not hardcode sensitive data into the SDK except where necessary and permitted - deletes all sensitive data elements once the 3DS transaction is complete For additional protection, the SDK also: - secures the UI to prevent access from outside the SDK - employs run-time data protection techniques to prevent access by unauthorized services - intercepts and handles any external URL requests contained within 3D Secure HTML – during the 3DS process, the SDK prevents the injection and execution of any JavaScript code by 3D Secure HTML, or any other process outside the 3DS SDK - securely stores any reference data required for the SDK's operation to prevent unauthorized modifications - uses EMVCo-approved cryptographic algorithms and methods in all cryptography handled by the 3DS SDK, and employs cryptographically strong random number generation - uses third-party services to help maintain security ### Communication security The 3DS SDK communicates with various systems managed by the multiple parties involved in the 3D Secure process. Each of these communication channels is secure and all data exchanged is encrypted. Communication with the Checkout.com 3DS Server is secured using the latest versions of Transport Layer Security (TLS). The device data passed to the Checkout.com 3DS Server and forwarded to the card scheme’s Directory Server (DS) is transferred in an encrypted format. Communication with the card issuer’s Access Control Server (ACS) is done over a secure channel that is encrypted end-to-end. The 3DS SDK also uses Certificate Transparency to ensure end-to-end security and to prevent a man-in-the-middle attack. For this purpose, it checks that all certificates were issued by a trusted Certificate Authority. Due to the use of Certificate Transparency, the 3DS SDK may not be able to establish a secure connection on devices that are connected to certain SSL Proxy Servers. In these scenarios, the 3DS SDK will return a connectivity error, which you can communicate to your customer. We recommend that your customer switches to a mobile data connection where available. We regularly update our 3DS SDK and review our security guidance. --- ## Compatibility with third-parties As with our core [Standalone](https://www.checkout.com/docs/payments/authenticate-payments/3d-secure/standalone-sessions.md) authentication product, you can use the 3DS SDK to authenticate a payment and continue to payment authorization with a different payment services provider. --- ## Related topics **[3DS SDK error codes](https://www.checkout.com/docs/developer-resources/codes/3ds-sdk-error-codes.md)** View the error codes returned by the 3DS SDKs for Android and iOS. **[Mobile SDKs lifecycle policy](https://www.checkout.com/docs/developer-resources/sdks/mobile-sdks-lifecycle-policy.md)** Learn how we version, support, and deprecate our mobile SDKs, and how long you have to adopt each new release.