Checkout icon

Advanced flow integration guide

Accept payments using the Advanced flow.

Web
iOS
Android
React Native
Flutter
Use our pre-built UI for accepting payments
Use our customizable UI components
Use Adyen APIs and your own UI
/user/pages/filters/sessions-flow-integration/android/components/visual/android-components.svg

Android Components

Render individual payment methods anywhere in your app.

Supported payment methods

Cards, buy now pay later, wallets, and many more.

See all supported payment methods

Features

  • Low development time to integrate each payment method component
  • UI styling customization for each payment method
  • Flexibility to add payment method components with configuration for each
  • 3D Secure 2 support using the 3D Secure 2 Component

Start integrating with Android Components

Choose your version
5.0.0

Requirements

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:

How it works

For a Components integration, you must implement the following parts:

  • Your payment server: sends the API requests to get available payment methods, make a payment, and send additional payment details.
  • Your client app: shows the the Component UI where the shopper makes the payment. The Component uses the data from the API responses to handle the payment flow and additional actions on your client app.
  • Your webhook server: receives webhooks that include the outcome of each payment.
  • The parts of your integration work together to complete the payment flow:

    1. From your server, submit a request to get a list of payment methods available to the shopper.
    2. Configure and launch the Component to collect the shopper's details.
    3. From your server, make a payment request with data that you receive from the Component.
    4. Handle additional client-side actions, if required.
    5. From your server, send additional payment details that you receive from the Component, if required.
    6. Get the payment outcome to inform the shopper and update your order management system.

    If you are integrating these parts separately, you can start at the corresponding part of this integration guide:

    Install an API library

    Payment server

    We provide server-side API libraries for several programming languages, available through common package managers, like Gradle and npm, for easier installation and version management. Our API libraries will save you development time, because they:

    • Use an API version that is up to date.
    • Have generated models to help you construct requests.
    • Send the request to Adyen using their built-in HTTP client, so you do not have to create your own.
    Try our example integration

    Requirements

    • Java 11 or later.

    Installation

    You can use Maven, adding this dependency to your project's POM.

    Add the API library
    Expand view
    Copy link to code block
    Copy code
    Copy code
    <dependency>
    <groupId>com.adyen</groupId>
    <artifactId>adyen-java-api-library</artifactId>
    <version>LATEST_VERSION</version>
    </dependency>

    You can find the latest version on GitHub. Alternatively, you can download the release on GitHub.

    Setting up the client

    Create a singleton resource that you use for the API requests to Adyen:

    Set up your client
    Expand view
    Copy link to code block
    Copy code
    Copy code
    // Import the required classes.
    package com.adyen.service;
    import com.adyen.Client;
    import com.adyen.service.checkout.PaymentsApi;
    import com.adyen.model.checkout.Amount;
    import com.adyen.enums.Environment;
    import com.adyen.service.exception.ApiException;
    import java.io.IOException;
    public class Snippet {
    public Snippet() throws IOException, ApiException {
    // Set up the client and service.
    Client client = new Client("ADYEN_API_KEY", Environment.TEST);
    }
    }

    Get available payment methods

    Payment server

    When the shopper is ready to pay, get a list of the available payment methods based on their country, device, and the payment amount.

    From your server, make a POST /paymentMethods request, including:

    We recommend that you include all the optional parameters to get the most accurate list of available payment methods.

    Parameter name Required Description
    merchantAccount -white_check_mark- Your merchant account name.
    amount The currency and value of the payment, in minor units.
    channel Use Android. Adyen returns only the payment methods available for Android.
    countryCode The shopper's country/region. Adyen returns only the payment methods available in this country.
    Format: the two-letter ISO-3166-1 alpha-2 country code. Exception: QZ (Kosovo).
    shopperLocale By default, the shopperlocale is set to en-US. To change the language, set this to the shopper's language and country code. You also need to set the same ShopperLocale within your Checkout configuration.

    For example, to get available payment methods for a shopper in the Netherlands, for a payment of 10 EUR:

    Expand view
    Copy link to code block
    Copy code
    Copy code
    curl https://checkout-test.adyen.com/checkout/v70/paymentMethods \
    -H 'x-api-key: ADYEN_API_KEY' \
    -H 'content-type: application/json' \
    -d '{
    "merchantAccount": "ADYEN_MERCHANT_ACCOUNT",
    "countryCode": "NL",
    "amount": {
    "currency": "EUR",
    "value": 1000
    },
    "channel": "Android",
    "shopperLocale": "nl-NL"
    }'

    The response includes the list of available paymentMethods:

    /paymentMethods response
    Expand view
    Copy link to code block
    Copy code
    Copy code
    {
    "paymentMethods":[
    {
    "details":[...],
    "name":"Cards",
    "type":"scheme"
    ...
    },
    {
    "details":[...],
    "name":"SEPA Direct Debit",
    "type":"sepadirectdebit"
    },
    ...
    ]
    }

    You must pass the response to your client app to launch and show Components.

    Set up Components

    Client app

    1: Import the library

    The default implementation is with Jetpack Compose, but you can import the library without Jetpack Compose instead.

    Import the compatibility module in your build.gradle file. For example, to import the Card Component:

    Import the module with Compose
    Expand view
    Copy link to code block
    Copy code
    Copy code
    implementation "com.adyen.checkout:card:YOUR_VERSION"
    implementation "com.adyen.checkout:components-compose:YOUR_VERSION"

    2. Configure components

    1. Create a configuration object, setting the following properties:
    Property Required Description
    shopperLocale -white_check_mark- The shopper's locale. To use the device's default locale, replace this with your context.
    environment -white_check_mark- Use Environment.TEST for testing. When going live, use one of our live environments.
    clientKey -white_check_mark- Your client key.
    1. Include other optional configurations for the Component and call the build function.

      For example:

      Create the configuration object
      Expand view
      Copy link to code block
      Copy code
      Copy code
      // Create a configuration object. For example, for the card Component.
      val cardConfiguration = cardConfiguration.Builder(
      shopperLocale, // Use your context instead to use the device's default locale.
      environment,
      clientKey
      )
      // Set additional configuration.
      .setHolderNameRequired(true) // Optional property to show the cardholder name input field.
      .setSubmitButtonVisible(false) // Optional property to hide the Pay button.
      .build()

    2: Create the configuration object

    1. Set the following properties in the configuration object:

      Property Required Description
      amount If you want to show the amount on the Pay button. The currency and value of the payment amount shown on the Pay button.
      shopperLocale -white_check_mark- The shopper's locale. To use the device's default locale, replace this with your context.
      environment -white_check_mark- Use Environment.TEST for testing. When going live, use one of our live environments.
      clientKey -white_check_mark- Your client key.
    2. Call the build function.

    For example, to configure the card Component:

    Configure the card Component
    Expand view
    Copy link to code block
    Copy code
    Copy code
    // Create the amount object.
    val amount = Amount(
    currency = "EUR",
    value = 1000,
    )
    // Create a configuration object.
    val cardConfiguration = CardConfiguration.Builder(
    shopperLocale, // Use your context instead to use the device's default locale.
    environment,
    clientKey
    )
    // Set the amount in the configuration object.
    .setAmount(amount) // Optional to show the amount on the Pay button.
    .setHolderNameRequired(true) // Optional configuration property to show the cardholder name input field.
    .build()
    1. Implement methods in ComponentCallback to pass data between your client app and your server.

      Method Description
      onSubmit Make a /payments request.
      onAdditionalDetails Make a /payments/details request.
      onError Handle an error if the Component encounters one.

    For example, for the card Component:

    Implement methods for the card Component
    Expand view
    Copy link to code block
    Copy code
    Copy code
    // Handler to make a /payments request.
    override fun onSubmit(state: CardComponentState) {
    val paymentComponentJson = PaymentComponentData.SERIALIZER.serialize(state.data)
    // Your server makes /payments request, including paymentComponentJson.
    // This is used in Step 4: Make a payment.
    // If additional action is required, handle the action.
    val action = Action.SERIALIZER.deserialize(actionJSONObject)
    cardComponent.handleAction(action, activity)
    }
    // Handler to make a /payments/details request to send additional payment details.
    override fun onAdditionalDetails(actionComponentData: ActionComponentData) {
    val actionComponentJson = ActionComponentData.SERIALIZER.serialize(actionComponentData)
    // Your server makes a /payments/details request, including actionComponentJson.
    // This is used in Step 5: Submit additional payment details.
    }
    // The Component encounters an error.
    override fun onError(componentError: ComponentError) {
    // Handle the error.
    }

    4: Launch and show the Component

    1. Implement the SessionComponentCallback class to handle additional actions and receive the result of the session.

      Add handlers
      Expand view
      Copy link to code block
      Copy code
      Copy code
      override fun onFinished(result: SessionPaymentResult) {
      // The payment finishes with a result.
      }
      override fun onAction(action: Action) {
      // An additional action needs to be handled. Forward the action to the Component.
      cardComponent.handleAction(action, activity)
      }
      override fun onError(componentError: ComponentError) {
      // The Component encounters an error.
      }
    2. Create the Component and attach it to a view. For example:

      Create the Component
      Expand view
      Copy link to code block
      Copy code
      Copy code
      import com.adyen.checkout.components.compose.get
      // Get the payment method.
      val paymentMethod = checkoutSession.getPaymentMethod(PaymentMethodTypes.SCHEME)
      @Composable
      private fun ComposableCardComponent() {
      // Keep a reference to this Component in case you need to access it later.
      val cardComponent = CardComponent.PROVIDER.get(
      checkoutSession = checkoutSession,
      paymentMethod = paymentMethod,
      configuration = configuration,
      componentCallback = callback,
      // This key is required to ensure a new Component gets created for each different screen or payment session.
      // Generate a new value for this key every time you need to reset the Component.
      key = "YOUR_UNIQUE_KEY_FOR_THIS_COMPONENT",
      )
      // This is your composable, a wrapper around our xml view.
      AdyenComponent(
      component = cardComponent,
      modifier = YOUR_MODIFIER,
      )
      }

    Your app shows the Component, and the Component handles the whole payment flow.

    Make a payment

    Payment server

    When the shopper enters their payment details and selects the Pay button, the onSubmit method in your ComponentCallback class is called, passing the paymentComponentJson object.

    1. Pass the paymentComponentJson object to your server.

    2. From your server, make a POST /payments request, including:

      Parameter name Required Description
      merchantAccount -white_check_mark- Your merchant account name.
      amount -white_check_mark- The currency and value of the payment, in minor units.
      reference -white_check_mark- Your unique reference for this payment.
      paymentMethod -white_check_mark- The paymentComponentData.paymentMethod from your client app.
      returnUrl -white_check_mark- In case of a redirection, this is the URL to where your shopper is redirected after they complete the payment. Maximum length: 1024 characters. Get this URL from the RedirectComponent.getReturnUrl(context).
      applicationInfo If you are building an Adyen solution for multiple merchants, include some basic identifying information, so that we can offer you better support.

      For the following cases, you must include additional parameters in your request:

    3. For example, to make a payment request for EUR 10:

      Expand view
      Copy link to code block
      Copy code
      Copy code
      curl https://checkout-test.adyen.com/checkout/v70/payments \
      -H 'x-api-key: ADYEN_API_KEY' \
      -H 'content-type: application/json' \
      -d '{
      "amount":{
      "currency":"EUR",
      "value":1000
      },
      "reference":"YOUR_ORDER_NUMBER",
      "paymentMethod":STATE_DATApaymentMethod field of an object passed from your client app,
      "returnUrl":"adyencheckout://your.package.name",
      "merchantAccount":"ADYEN_MERCHANT_ACCOUNT"
      }'
    4. Your next steps depend on if the /payments response contains an action object:

      Description Next steps
      No action object No additional steps are needed to complete the payment. 1. Pass the resultCode from your server to your client app.
      2. Get the payment outcome.
      With action object The shopper needs to do additional actions to complete the payment. 1. Pass the action object from your server to your client app.
      2. Call handleAction from your Component, passing the action object and your activity.
      3. Send additional payment details.

      The following example shows a /payments response with action.type: threeDS2 that you need to handle:

      /payments response
      Expand view
      Copy link to code block
      Copy code
      Copy code
      {
      "resultCode" : "IdentifyShopper",
      "action" : {
      "token" : "eyJkaXJl...",
      "paymentMethodType" : "scheme",
      "paymentData" : "Ab02b4c0...",
      "type" : "threeDS2",
      "authorisationToken" : "BQABAQ...",
      "subtype" : "fingerprint"
      }
      }

    Error handling

    If the /payments request fails, show the error to the shopper in your client UI.

    Handle the additional action

    Client app

    Some payment methods require you to handle an additional action in your client app. For example, you must handle the action to authenticate a payment with 3D Secure 2 or to redirect the shopper to another app.

    Implement your server logic to handle all of the following action types, so that you can add payment methods that require additional actions.

    You can receive different action types in the /payments response:

    action.type Description Action handling
    voucher The Component shows the voucher that the shopper uses to complete the payment. Handle the action without a redirect.
    qrCode The Component shows the QR code that the shopper uses to complete the payment. Handle the action without a redirect.
    await The Component shows the waiting screen while the shopper completes the payment. Handle the action without a redirect.
    sdk The Component presents the specific payment method's UI as an overlay. Handle the action without a redirect.
    threeDS2 The payment qualifies for 3D Secure 2, and goes through either frictionless or challenge flow. Handle the action without a redirect.
    redirect The Component redirects the shopper to another website or app to complete the payment. Handle the redirect.

    Handle the additional action without a redirect

    To handle an action.type without a redirect:

    1. Pass the complete action object from your server to the Component.
    2. The Component calls the onAdditionalDetails method in your ComponentCallback class.
    3. From onAdditionalDetails, get the actionComponentJson object.
    4. Pass the actionComponentJson object from your client app to your server.
    5. Send additional payment details.

    Handle the redirect

    To handle action.type: redirect:

    1. Add an IntentFilter to your Activity that handles redirects.

      Add handling for redirects
      Expand view
      Copy link to code block
      Copy code
      Copy code
      <activity
      android:name="YOUR_ACTIVITY"
      android:exported="true">
      <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="YOUR_APPLICATION_ID" android:scheme="adyencheckout"/>
      </intent-filter>
      </activity>

      The android:host value is your package name at build time. This must match the returnUrl from the /payments request.
      To get your returnUrl from the Component, you can use the RedirectComponent.getReturnUrl(context) function.

    2. Pass the complete action object from your server to the Component.

    3. The Component redirects the shopper to another website or app.

    4. The shopper gets redirected back to your client app.

    5. From your Activity, get the result of the redirect.

    6. Pass the Intent to the the Component. Depending on your activity's launch mode, you get the intent in either onCreate or onNewIntent.

      Handle the intent
      Expand view
      Copy link to code block
      Copy code
      Copy code
      private fun handleIntent(intent: Intent?) {
      if (intent.data?.toString().orEmpty().startsWith(RedirectComponent.REDIRECT_RESULT_SCHEME)) {
      cardComponent?.handleIntent(intent)
      }
      }
    7. The Component notifies you through the ComponentCallback.onAdditionalDetails method with the actionComponentData object from intent.data.

    8. Pass the actionComponentData object from your client app to your server.

    9. Send additional payment details.

    Send additional payment details

    Payment server

    If you handled an additional action, you must send additional payment details (actionComponentJson) to Adyen.

    1. From your server, make a POST /payments/details request, including actionComponentJson object:

      Expand view
      Copy link to code block
      Copy code
      Copy code
      curl https://checkout-test.adyen.com/checkout/v70/payments/details \
      -H 'x-api-key: ADYEN_API_KEY' \
      -H 'content-type: application/json' \
      -d 'STATE_DATAobject passed from your client app'
    2. Pass the /payments/details response from your server to your client app.

    Get the payment outcome

    After the Component finishes the payment flow, you can show the shopper the current payment status. Adyen sends a webhook with the outcome of the payment.

    Inform the shopper

    Client app

    Use the resultCode to show the shopper the current payment status. This synchronous response doesn't give you the final outcome of the payment. You get the final payment status in a webhook that you use to update your order management system.

    Update your order management system

    Webhook server

    You get the outcome of each payment asynchronously, in an AUTHORISATION webhook. Use the merchantReference from the webhook to match it to your order reference.
    For a successful payment, the event contains success: true.

    Example webhook for a successful payment
    Expand view
    Copy link to code block
    Copy code
    Copy code
    {
    "live": "false",
    "notificationItems":[
    {
    "NotificationRequestItem":{
    "eventCode":"AUTHORISATION",
    "merchantAccountCode":"YOUR_MERCHANT_ACCOUNT",
    "reason":"033899:1111:03/2030",
    "amount":{
    "currency":"EUR",
    "value":2500
    },
    "operations":["CANCEL","CAPTURE","REFUND"],
    "success":"true",
    "paymentMethod":"mc",
    "additionalData":{
    "expiryDate":"03/2030",
    "authCode":"033899",
    "cardBin":"411111",
    "cardSummary":"1111"
    },
    "merchantReference":"YOUR_REFERENCE",
    "pspReference":"NC6HT9CRT65ZGN82",
    "eventDate":"2021-09-13T14:10:22+02:00"
    }
    }
    ]
    }

    For an unsuccessful payment, you get success: false, and the reason field has details about why the payment was unsuccessful.

    Example webhook for an unsuccessful payment
    Expand view
    Copy link to code block
    Copy code
    Copy code
    {
    "live": "false",
    "notificationItems":[
    {
    "NotificationRequestItem":{
    "eventCode":"AUTHORISATION",
    "merchantAccountCode":"YOUR_MERCHANT_ACCOUNT",
    "reason":"validation 101 Invalid card number",
    "amount":{
    "currency":"EUR",
    "value":2500
    },
    "success":"false",
    "paymentMethod":"unknowncard",
    "additionalData":{
    "expiryDate":"03/2030",
    "cardBin":"411111",
    "cardSummary":"1112"
    },
    "merchantReference":"YOUR_REFERENCE",
    "pspReference":"KHQC5N7G84BLNK43",
    "eventDate":"2021-09-13T14:14:05+02:00"
    }
    }
    ]
    }

    Test and go live

    Before going live, use our list of test cards and other payment methods to test your integration. Use the Adyen Android test cards app to access, copy, and autofill card details from within your Android device. We recommend testing each payment method that you intend to offer to your shoppers.

    You can check the status of a test payment in your Customer Area, under TransactionsPayments.

    To debug or troubleshoot test payments, you can also use API logs in your test environment.

    When you are ready to go live, you need to:

    1. Apply for a live account. Review the process to start accepting payments on Get started with Adyen.
    2. Assess your PCI DSS compliance by submitting the Self-Assessment Questionnaire-A.
    3. Configure your live account
    4. Submit a request to add payment methods in your live Customer Area .
    5. Switch from test to our live endpoints.
    6. Load from one of our live environments and set the environment to match your live endpoints:

      Endpoint region Value
      Europe (EU) live EUROPE
      United States (US) live UNITED_STATES
      Australia (AU) live AUSTRALIA
      Asia Pacific & Southeast (APSE) live APSE
      India (IN) live INDIA