Build your own UI

Integrate our Checkout SDK for Android with your own UI.


Our Checkout SDK for Android gives you the ability to take advantage of the SDK's payment flow, including the encrypted communication between the SDK and Adyen, but collect and present information using your own UI. There are additional functions that you need to implement to do this, which we explain below. To use the SDK, you'll also need to set up a server that can create a payment session and verify the result of payments.

To accept online payments with the Checkout SDK, you'll need to:

  1. Install the Android SDK.
  2. Initialize the SDK.
  3. Create a payment session from your server.
  4. Build your payment flow.
  5. Verify the payment result on your server.

Before accepting live payments, we also recommend that you test your integration.

Step 1: Install SDK

Import the SDK modules into your project:

  • Add the following to your build.gradle file.

    final checkoutVersion = "2.x.x"
    implementation "com.adyen.checkout:core:${checkoutVersion}"
    implementation "com.adyen.checkout:core-card:${checkoutVersion}" // Optional; Required for processing card payments.
    implementation "com.adyen.checkout:nfc:${checkoutVersion}" // Optional; Enables reading of card information with the device's NFC chip.
    implementation "com.adyen.checkout:util:${checkoutVersion}" // Optional; Collection of utility classes.

Step 2: Initialize SDK

  1. Call the startPayment method of the PaymentController class. A token will be returned in PaymentSetupParameters

    PaymentController.startPayment(/*Activity*/ this, new PaymentSetupParametersHandler() {
        @Override
        public void onRequestPaymentSession(@NonNull PaymentSetupParameters paymentSetupParameters) {
            // TODO: Forward to your own server and request the payment session from Adyen with the given PaymentSetupParameters.
        }
    
        @Override
        public void onError(@NonNull CheckoutException checkoutException) {
            // TODO: Handle error.
        }
    });
  2. Pass the token to your server to create a payment session.

  3. Handle the paymentSession value received by your server with PaymentController.

    String encodedPaymentSession = PAYMENTSESSION_VALUE_RECEIVED_BY_YOUR_SERVER;
    PaymentController.handlePaymentSessionResponse(/*Activity*/ this, encodedPaymentSession, new StartPaymentParametersHandler() {
        @Override
        public void onPaymentInitialized(@NonNull StartPaymentParameters startPaymentParameters) {
            PaymentReference paymentReference = startPaymentParamters.getPaymentReference();
            // TODO: Use the PaymentReference to retrieve a PaymentHandler (see the Create Payment Flow section).
        }
    
        @Override
        public void onError(@NonNull CheckoutException checkoutException) {
            // TODO: Handle error.
        }
    });

Step 3: Create payment session

A payment session is used to securely transmit payment data between the shopper and the Adyen payments platform. Create one from your server by making a POST request to the /paymentSession endpoint.

You can also use our demo server until you have implemented your own:
https://checkoutshopper-test.adyen.com/checkoutshopper/demoserver/

  1. In the request, specify: 
    • merchantAccount: Your merchant account name.
    • channelAndroid.
    • returnUrl: The URI of your app.
    • amount.
    • reference: Your unique reference for this payment.
    • countryCode: The country code of the shopper.
    • token: The token generated by the SDK.

    curl -H "Content-Type: application/json" -H "X-API-Key: YourAPIkey" -X POST -d '{ 
           "merchantAccount": "YourMerchantAccount",
           "channel": "Android",
           "returnUrl": "my-shopping-app://"
           "amount": { 
              "currency": "EUR", 
              "value": "17408"
           }, 
           "reference": "Your order number",
           "countryCode": "NL",
           "shopperLocale": "nl_NL",
           "token": "TOKEN_GENERATED_BY_SDK",
        }' https://checkout-test.adyen.com/v40/paymentSession

    Execute this code from your server, not your app. This helps to prevent tampering with transaction data.

  2. Use the paymentSession you receive in the response to initialize the SDK.

Step 4: Build payment flow

You'll need to create your app's payment flow by building a UI that responds to the SDK's observers and handlers. 

  1. Use the PaymentHandler you retrieved earlier from the PaymentReference.

    PaymentReference is Parcelable, so you can pass it along to another Activity.

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        PaymentReference paymentReference = getIntent().getParcelableExtra(EXTRA_PAYMENT_REFERENCE);
        mPaymentHandler = paymentReference.getPaymentHandler(/*Activity*/ this);
  2. Attach the observers and handlers below in the scope of the current Activity. These will be removed automatically when the Activity is destroyed.

Show progress indicator

  1. Attach an observer to the NetworkingStateObservable. When the networking state changes, this will receive a callback with the latest networkingState.
  2. When isExecutingRequests is true, present a progress indicator to the shopper in your UI.

        ...
        mPaymentHandler.getNetworkingStateObservable().observe(/*Activity*/ this, new Observer<NetworkingState>() {
            @Override
            public void onChanged(@NonNull NetworkingState networkingState) {
                if (networkingState.isExecutingRequests() == true){
                    // Display progress screen
                else {
                    // Remove progress screen
                }
            }
        });

Present available payment methods

To present a list of available payment methods to the shopper:

  1. Attach an observer to the PaymentSessionObservable. This will be lifecycle aware, and receive callbacks with the latest paymentSession

  2. From the paymentSession, retrieve a list of available payment methods . These are represented in two indexed arrays:
    • oneClickPaymentMethodsOne-click enabled payment methods, that the shopper has used previously.

    • paymentMethods: All other payment methods.

          ...
          PaymentHandler mPaymentHandler = startPaymentParameters.getPaymentReference().getPaymentHandler(MainActivity.this);
          mPaymentHandler.getPaymentSessionObservable().observe(MainActivity.this, new com.adyen.checkout.core.Observer<PaymentSession>() {
              @Override
              public void onChanged(@NonNull PaymentSession paymentSession) {
                  List<PaymentMethod> oneClickPaymentMethods = paymentSession.getOneClickPaymentMethods();
                  List<PaymentMethod> paymentMethods = paymentSession.getPaymentMethods();
                  // TODO: Optionally group and show in UI.
              }
          });
          ...
  3. Present a list of available payment methods in your UI.

    You should also refresh the list of payment methods in your UI whenever the paymentSession is updated.

  4. When the shopper has chosen a payment method, present a form in your UI, and collect the required payment details from the shopper. Use the type to determine which payment method input screen to present, and show input fields based on the required inputDetails

    For example, if the shopper selected the payment method at index 5:

        ...
        PaymentMethod paymentMethod = paymentMethods.get(5);
        String type = paymentMethod.getType();
        List<InputDetail> inputDetails = paymentMethod.getInputDetails();
        // TODO: Present UI based on type and inputDetails.
        ...

Submit payment

Use the shopper's chosen payment method and the payment details that you collected from the shopper to submit the payment:

  1. In a paymentMethodDetails object, provide the required payment details.
  2. Pass these, together with the paymentMethod the shopper selected, to the SDK by calling initiatePayment. In the example below we show how you'd do this for an issuer-based payment method such as iDEAL, where:

    1. The InputDetail at index 0 has IssuerDetails.KEY_ISSUER as key.

    2. The Item at index 5 is the shopper's selected issuer.

        //InputDetail at index 0 has key IssuerDetails.KEY_ISSUER
        InputDetail issuersInputDetail = paymentMethod.getInputDetails().get(0);
        // Item at index 5 was selected by shopper
        Item issuerItem = issuersInputDetail.getItems().get(5);
        IssuerDetails issuerDetails = new IssuerDetails.Builder(issuerItem.getId()).build();
        mPaymentHandler.initiatePayment(paymentMethod, issuerDetails);

Optional: Collect SMS verification

For some payment methods, such as China UnionPay, you'll need to collect SMS verification codes. When required, the onAdditionalDetailsRequired is called.

  • Use the parameters in additionalDetails to present an input field in your UI to collect the SMS verification code from the shopper.

        ...
        mPaymentHandler.setAdditionalDetailsHandler(/*Activity*/ this, new AdditionalDetailsHandler() {
            @Override
            public void onAdditionalDetailsRequired(@NonNull AdditionalDetails additionalDetails) {
                // TODO: Handle AdditionalDetails.
            }
        });
        ...

Handle redirects

For many local payment methods, such as iDEAL and Sofort, and card payments with 3D Secure verification, you'll need to redirect the shopper to a webpage or app to verify the payment. Once verified, they will be returned to your app. The onRedirectRequired method is called when a redirect is required.

  1. Redirect the shopper to the URI specified in redirectDetails.

        ...
        mPaymentHandler.setRedirectHandler(/*Activity*/ this, new RedirectHandler() {
            @Override
            public void onRedirectRequired(@NonNull RedirectDetails redirectDetails) {
                Uri redirectUri = redirectDetails.getUri();
                Intent redirectIntent = new Intent(Intent.ACTION_VIEW, redirectUri);
                startActivityForResult(redirectIntent, REQUEST_CODE_REDIRECT);
            }
        });
        ...
  2. Once the shopper has completed verification, they'll be redirected to the URI you passed when you created the payment session. Then call handleRedirectResult to dispatch the data from the Intent to the PaymentHandler.

    You should declare an IntentFilter for the Activity that handles the redirect to this URI in your AndroidManifest.

        ...
        @Override
        protected void onNewIntent(Intent intent) {
            super.onNewIntent(intent);
    
            Uri data = intent.getData();
    
            if (data != null) {
                mPaymentHandler.handleRedirectResult(data);
            }
        }
        ...

Handle payment result

  1. Attach an observer to the PaymentResultObservable. This will receive a callback with the PaymentResult when the payment has been processed.

        ...
        mPaymentHandler.getPaymentResultObservable().observe(/*Activity*/ this, new Observer<PaymentResult>() {
            @Override
            public void onChanged(@NonNull PaymentResult paymentResult) {
                // TODO: Handle PaymentResult.
            }
        });
        ...
  2. Present the received payment result to the shopper in your calling Activity. For a list of possible payment results and what they mean, refer to Result codes.

  3. You'll also receive a payload. Send this to your server to verify the result of the payment. 

Handle errors

  1. Set a handler with setErrorHandler. This will receive a callback with a CheckoutException when an error unrelated to the payment result occurred.

  2. Use the parameters contained in CheckoutException to determine the cause of the error:
        ...
        mPaymentHandler.setErrorHandler(/*Activity*/ this, new ErrorHandler() {
            @Override
            public void onError(@NonNull CheckoutException error) {
                // TODO: Handle CheckoutException.
            }
        });
        ...
  3. Present an error message to the shopper in your UI.

Step 5: Verify payment result

Once the payment has been completed, verify its result from your server with a  /payments/result request. Include the  payload that was  generated by the SDK.
curl \
-H "Content-Type: application/json" \
-H "X-API-Key: YourAPIkey" \
-X POST \
-d '{ "payload": "2he28Ddhwj242he28Ddhwj..." }' \
https://checkout-test.adyen.com/v40/payments/result

If the payment was successful you'll receive an Authorised resultCode and a pspReference, which is our unique identifier for the transaction. If you've set up notifications, you'll also receive a successful AUTHORISATION notification.

If you received a different resultCode, check our result codes documentation for what action you should take.

Testing your integration

Before going live, use our list of  test cards and other payment methods to test your integration. 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.

When you've completed testing, there are some additional steps you'll need to complete before you can accept live payments from shoppers. Refer to Getting started with Adyen for more information.

Next steps

Set up notifications

Receive confirmation when a payment is authorised or fails.

link

Add payment methods

Learn about payment methods and how to integrate them.

link

Payment modifications

Find out how to cancel, refund, or capture a payment using our API.

link