Skip to content

3D Secure mobile SDKs

Last updated: 9th August 2022

Our 3D Secure (3DS) mobile SDKs allow you to provide a native 3DS2 experience in your Android and iOS apps, with visual styling that you can control.

They work with our non-hosted authentication solution, so you can authenticate within the payment authorization flow, or perform only authentication and complete the payment later.

Once you've initiated the authentication, the SDK handles the tasks of collecting device data, exchanging information with the customer's bank, and, if necessary, presenting a challenge to the customer. You can then use the authentication result to authorize the payment.

Your customers' data

Our SDKs collect only data which your app has permission to collect, and it is encrypted throughout authentication. The customer will never be prompted to grant new permissions. We don't store any of the device data collected during authentication, and our SDKs do not retain any personal information about the user.

Our 3D Secure SDK supports 3DS2 (version 2.1.0 and, if your configuration supports it, 2.2.0). It also supports 3DS1 in cases where 3DS2 is not available. However, this feature must be enabled for your account. The SDK handles the version complexity for you, and passes a simple authentication result back to your app, regardless of the 3D Secure version used.


The 3DS2 customer experience

3DS2 allows you and your payment provider to share more data (like the customer's device ID and payment history) with the customer's bank so they can better assess the risk of the transaction and select the appropriate response: either the "frictionless flow" or "challenge flow".


Frictionless flow

If the customer's bank is satisfied with the data and trusts that it is the cardholder making the payment, the transaction will be authenticated without interrupting the customer. All the customer will see of the 3DS process is a short "processing" overlay, with branding from their card scheme.

ios frictionless

Challenge flow

If, however, the bank decides it needs further proof, they will prompt the customer to verify their identity. This can take one of the following forms:

  • One-time password. The customer's bank sends a single use password or code to the customer, usually as a text message or email, and asks them to enter it.

  • Single-select or multi-select. The bank asks the customer a multiple choice question, with either a single or multiple selections allowed.

  • Out-of-band. The customer is asked to confirm the transaction through another channel, typically their banking app. (See example below.)

  • HTML. The customer's bank defines the exact view to be presented to the customer, using HTML formatting. The challenge may take one of the above forms, or the bank may devise their own approach.

ios oob

Customize the challenge UI

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 SDKs give you control over the display of the native challenges in your app, while ensuring that the rules are followed.


How it works

To use one of our 3DS mobile SDKs, first integrate the library into your project. Then, configure your iOS or Android app to:

  1. Initialize the SDK with your preferred user interface options.
  2. Configure the parameters for an authentication.
  3. Request authentication and handle the result to continue your payment flow.

Implementation examples

Below are some code examples for each platform.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    // 1. Init with defaults
    let checkout3DS = Checkout3DSService()
    // 2. Init with explicit arguments
    let checkout3DS = Checkout3DSService(
    environment: .production,
    locale: Locale(identifier: "en_GB"),
    uiCustomization: uiCustomization,
    appURL: URL(string: "myapp://my-app-url")!
    )
    let authenticationParameters = AuthenticationParameters(
    sessionID: sessionID,
    sessionSecret: sessionSecret,
    scheme: scheme)
    checkout3DS.authenticate(authenticationParameters: authenticationParameters) { error in
    if let error = error {
    // Handle error.
    } else {
    // Continue with payment.
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    // 1. Init with defaults
    CKOCheckout3DSService *checkout3DS2 = [[CKOCheckout3DSService alloc] init];
    // 2. Init with explicit arguments
    CKOCheckout3DSService *checkout3DS2 = [[CKOCheckout3DSService alloc] initWithEnvironment:CKOEnvironmentProduction
    locale:[NSLocale localeWithLocaleIdentifier:@"en_GB"]
    uiCustomization:uiCustomization
    appURL:[NSURL URLWithString:@"myapp://my-app-url"]];
    CKOAuthenticationParameters *authenticationParameters = [[CKOAuthenticationParameters alloc] initWithSessionID:sessionID
    sessionSecret:sessionSecret
    scheme:scheme];
    [checkout3DS2 authenticateWithAuthenticationParameters:authenticationParameters
    completionHandler:^(NSError * _Nullable error) {
    if (error) {
    // Handle error.
    } else {
    // Continue with payment.
    }
    }];

    Integrate the 3D Secure SDK into your app

    To gain access to the 3D Secure mobile SDKs, contact your Customer Success Manager or Integrations engineer, or email us at support@checkout.com.

    Then, on iOS, install the library in your app project using CocoaPods. For Android, add the library to your app as a Gradle dependency.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      // Add the following to your project’s top-level build.gradle.kts file.
      allprojects {
      repositories {
      maven {
      url = uri("https://maven.pkg.github.com/checkout/checkout-3ds-sdk-android")
      credentials {
      username = ""
      password = ""
      }
      }
      }
      }
      // Add the following to the module level build.gradle.kts file.
      dependencies {
      implementation("com.checkout:checkout-sdk-3ds-android:")
      }

      Add the 3D Secure SDK to your app's payment flow

      Step 1: Initialize the SDK

      Initialize the SDK, setting the environment (production or sandbox), the locale, and your preferred challenge user interface options.

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        // 1a. Initialize with default arguments
        let checkout3DS = Checkout3DSService()
        // 1b. Alternatively, initialize with explicit arguments
        let checkout3DS = Checkout3DSService(
        environment: .production,
        locale: Locale(identifier: "en_GB"),
        uiCustomization: uiCustomization,
        appURL: URL(string: "https://my-app-url.com")!
        )

        Checkout3DSService

        This is the main class of the SDK that performs payment authentication with the authenticate method. It only needs to be initialized once for the lifetime of the application, and is initialized with the following parameters.

          Field nameField typeDescription

          environment

          optional

          Environment

          The environment the SDK will connect to (PRODUCTION or SANDBOX).

          Default: PRODUCTION

          locale

          optional

          Locale

          The customer's locale and preferred language.

          Default: the device locale

          uiCustomization

          optional

          uiCustomization

          The customizations for the challenge user interface.

          appUrl

          optional

          URL

          The application URL used to open and move your application to the foreground.

          This field is optional, but we recommend including it to ensure a smoother out-of-band challenge experience for your user. This way, the user is automatically redirected back to your app after their banking app has authorized the transaction. This feature is available if the user’s card issuer also supports it.

          If your app uses a deep link scheme, make sure that the appURL field value links to the current 3D Secure transaction or app page.

          The appUrl field value can have up to 211 characters. If it exceeds 211 characters, it is ignored and the SDK returns an initialization warning.

          Check for security warnings

          Optionally, you can use the getWarnings method to check for any security warnings when initializing the SDK, or any time afterwards. It will return the following information:

          Field nameDescription

          id

          string
          required

          An identifier of the warning. Security warnings are in the format SWxx, and initialization warnings use the format CWxx.

          message

          string
          required

          The warning description

          severity

          string
          required

          The severity of the warning. It can be either low, medium, or high.

          Step 2: Configure the authentication parameters

          After your backend has requested an authentication session with our Sessions API, you will receive a response.

          Use the authenticate method to start the authentication, passing the values you received in the Sessions API response into authenticationParameters.

          The SDK will then gather the device data, share the information with the customer's bank, and, if necessary, present a challenge to the customer.

            1
            2
            3
            4
            let authenticationParameters = AuthenticationParameters(
            sessionID: sessionID,
            sessionSecret: sessionSecret,
            scheme: scheme)

              authenticate method parameters

              Parameter nameParameter typeDescription

              authenticationParameters

              required

              AuthenticationParameters

              The authentication parameters, including sessionId, sessionSecret, and scheme.

              completionHandler

              required

              (AuthenticationError?) → Void

              Closure that is called with the error that occurred during authentication, or nil if the authentication is successful.

              authenticationParameters properties

              Parameter nameDescription

              sessionID

              string
              required

              The unique ID of the authentication session. You will have received this in the response to the create session call to our Sessions API.

              sessionSecret

              string
              required

              The session secret. You will have received this in the response to the create session call to our Sessions API.

              scheme

              string
              required

              The name of the customer's card scheme: Visa, Mastercard, Jcb, Amex, or Diners. Used to display the scheme's logo on the progress user interface.

              Step 3: Request authentication and handle the result

              Once the authentication is completed, the SDK returns a result.

              • On Android, the result is either Successful, Failed, or Error.
              • On iOS, the SDK returns an optional AuthenticationError. If the attempt was unsuccessful, this indicates the failure reason, otherwise this value is nil.

              If successful, you can use our Payments API to complete the payment, or use another payment services provider to do so.

                1
                2
                3
                4
                5
                6
                7
                checkout3DS.authenticate(authenticationParameters: authenticationParameters) { error in
                if let error = error {
                // Handle error.
                } else {
                // Continue with payment.
                }
                }

                  AuthenticationError

                  This enumeration contains all the possible errors that might occur during authentication. Each error has a readable name and an associated error code.

                  Swift uses AuthenticationError, but Objective-C uses NSError.

                  Customize the challenge user interface

                  We’ve built a simple, clean default style for the native challenge user interfaces, so you can quickly get going without defining your own style. But if you want to tailor the challenge screens in your app, our SDKs let you control:

                  • Fonts and font colors.
                  • The background color of the navigation bar and footer.
                  • The background color, opacity, shadows, and corner radiuses of the action buttons.

                  Our SDKs also handle different screen sizes and orientations, and allow you to address different user needs with dynamic text sizing, TalkBack and VoiceOver assistance, and support for 37 languages (though the body of the challenge screens is always presented in the language provided by the customer's bank).

                  To apply your own style, simply include a UI Customization object when you initialize the SDK. We've included some code examples below to show you how you might build the object.

                    1
                    2
                    3
                    4
                    5
                    6
                    7
                    8
                    9
                    10
                    11
                    12
                    13
                    14
                    15
                    16
                    17
                    18
                    19
                    20
                    21
                    22
                    23
                    24
                    25
                    26
                    27
                    28
                    29
                    30
                    31
                    32
                    33
                    34
                    35
                    36
                    37
                    38
                    39
                    40
                    41
                    42
                    43
                    44
                    45
                    46
                    47
                    48
                    49
                    50
                    51
                    52
                    final class Customization1: UICustomization {
                    let toolbarCustomization: ToolbarCustomization = DefaultToolbarCustomization(
                    backgroundColor: .blue,
                    headerTitle: "3DS Check",
                    buttonTitle: "Cancel",
                    font: UIFont(name: "Optima-Bold", size: 20)!,
                    textColor: .black)
                    let labelCustomization: LabelCustomization = DefaultLabelCustomization(
                    headingTextColor: .purple,
                    headingFont: UIFont(name: "Optima-Bold", size: 16)!,
                    font: UIFont(name: "Optima-Regular", size: 16)!,
                    textColor: .orange)
                    let buttonCustomizations: ButtonCustomizations = DefaultButtonCustomizations(
                    verifyButtonCustomization: DefaultButtonCustomization(
                    backgroundColor: .red,
                    cornerRadius: 24,
                    cornerCurve: .circular,
                    font: UIFont(name: "Optima-Regular", size: 14)!,
                    textColor: .white,
                    borderWidth: 0,
                    borderColor: UIColor.clear.cgColor),
                    continueFlowButtonCustomization: DefaultButtonCustomization(
                    backgroundColor: UIColor.blue,
                    cornerRadius: 24,
                    cornerCurve: .circular,
                    font: UIFont(name: "Optima", size: 14)!,
                    textColor: .white,
                    borderWidth: 0,
                    borderColor: UIColor.clear.cgColor))
                    let whitelistCustomization: WhitelistCustomization = DefaultWhitelistCustomization(
                    font: UIFont(name: "Optima-Regular", size: 16)!,
                    textColor: .black,
                    switchTintColor: .green)
                    let footerCustomization: FooterCustomization = DefaultFooterCustomization(
                    backgroundColor: .clear,
                    font: UIFont(name: "Optima-Bold", size: 16)!,
                    textColor: .black,
                    labelFont: UIFont(name: "Optima-Regular", size: 16)!,
                    labelTextColor: .blue,
                    expandIndicatorColor: .green)
                    let entrySelectionCustomization: EntrySelectionCustomization = DefaultEntrySelectionCustomization(
                    borderWidth: 1,
                    borderColor: UIColor.blue.cgColor,
                    cornerRadius: 4,
                    cornerCurve: .continuous,
                    font: .systemFont(ofSize: 16),
                    textColor: .black,
                    borderStyle: .line,
                    backgroundColor: .white,
                    unselectedColor: .white,
                    selectedColor: .blue)
                    }