Search

Are you looking for test card numbers?

Would you like to contact support?

Online-payment icon

Web Drop-in integration guide

Accept popular payment methods with a single front-end implementation.

See sample code

  Explore Web Drop-in on GitHub.

Drop-in is our all-in-one UI solution you can use on your checkout page to accept payments for popular payment methods using a single front-end implementation. To see a complete list of all payment methods supported by our Drop-in solution, see Drop-in payment methods.

If you are new to integrating with Adyen, see our Online payments page for an overview of integration options and available features.

Drop-in is supported from v49 of the /paymentMethods, /payments, and /payments/details endpoints.

How Drop-in works

The following flow applies for each payment method supported in Drop-in:

On this page we talk about both server-side and client-side integration steps:

  1. From your server, submit a request to get a list of payment methods available to the shopper.
  2. Create an instance of Drop-in on your payments form.
  3. From your server, submit a payment request with the data returned by Drop-in.
  4. Determine from the response if you need to perform additional actions on your front end.
  5. From your server, submit additional payment details with the data returned by Drop-in.
  6. Present the payment result to the shopper.

When you have completed the integration, proceed to test your integration.

Before you begin

Before you start integrating with our online payments API, make sure that you have performed the following steps:

  1. Sign up for an Adyen test account
  2. Get your API Key. Save a copy as you need it for API calls you make to the Adyen payments platform.
  3. Install one of our Libraries to connect with the Adyen APIs.
  4. Use the latest version of our APIs.
  5. Get your origin key. To find out how to generate one, see How to get an Origin Key.
  6. If you're building for multiple merchants, provide some basic information so that we can offer you better support.

For more information on these steps, refer to Get started with Adyen.

Step 1: Get available payment methods

  1. Make a POST /paymentMethods request, providing:

    • merchantAccount: Your merchant account name. 
    • countryCode: The shopper's country.
    • amount: The currency and value of the payment. 
    • channel: The platform of the shopper's device. Use Web.

    We use the countryCodeamount, and channel to tailor the list of payment methods to your shopper.

    curl https://checkout-test.adyen.com/v50/paymentMethods \
    -H "x-API-key: YOUR_X-API-KEY" \
    -H "content-type: application/json" \
    -d '{
      "merchantAccount": "YOUR_MERCHANT_ACCOUNT",
      "countryCode": "NL",
      "amount": {
        "currency": "EUR",
        "value": 1000
      },
      "channel": "Web"
    }'
    # Set your X-API-KEY with the API key from the Customer Area.
    adyen = Adyen::Client.new
    adyen.env = :test
    adyen.api_key = "YOUR_X-API-KEY"
    
    response = adyen.checkout.payment_methods({
      :merchantAccount => 'YOUR_MERCHANT_ACCOUNT',
      :countryCode => 'NL',
      :amount => {
        :currency => 'EUR',
        :value => 1000
      },
      :channel => 'Web'
    })
    # Pass the response to your front end
    // Set your X-API-KEY with the API key from the Customer Area.
    Client client = new Client(xApiKey,Environment.TEST);
    
    Checkout checkout = new Checkout(client);
    PaymentMethodsRequest paymentMethodsRequest = new PaymentMethodsRequest();
    paymentMethodsRequest.setMerchantAccount("YOUR_MERCHANT_ACCOUNT");
    paymentMethodsRequest.setCountryCode("NL");
    Amount amount = new Amount();
    amount.setCurrency("EUR");
    amount.setValue(1000L);
    paymentMethodsRequest.setAmount(amount);
    paymentMethodsRequest.setChannel(PaymentMethodsRequest.ChannelEnum.WEB);
    PaymentMethodsResponse response = checkout.paymentMethods(paymentMethodsRequest);
    // Set your X-API-KEY with the API key from the Customer Area.
    $client = new \Adyen\Client();
    $client->setXApiKey("YOUR_X-API-KEY");
    $service = new \Adyen\Service\Checkout($client);
    
    $params = array(
      "merchantAccount" => "YOUR_MERCHANT_ACCOUNT",
      "countryCode" => "NL",
      "amount" => array(
        "currency" => "EUR",
        "value" => 1000
      ),
      "channel" => "Web"
    );
    
    $result = $service->paymentMethods($params);
    // Pass the response to your front end
    # Set your X-API-KEY with the API key from the Customer Area.
    adyen = Adyen.Adyen()
    adyen.client.xapikey = 'YOUR_X-API-KEY'
    
    request = {
      'merchantAccount': 'YOUR_MERCHANT_ACCOUNT',
      'countryCode': 'NL',
      'amount': {
        'value': 1000,
        'currency': 'EUR'
      },
      'channel': 'Web'
    }
    
    response = adyen.checkout.payment_methods(request)
    # Pass the response to your front end
    // Set your X-API-KEY with the API key from the Customer Area.
    var client = new Client ("YOUR-X-API-KEY", Environment.Test);
    var checkout = new Checkout(client);
    var amount = new Model.Checkout.Amount("EUR", 1000);
    var paymentMethodsRequest = new Model.Checkout.PaymentMethodsRequest(MerchantAccount: "YOUR_MERCHANT_ACCOUNT")
    {
       CountryCode = "NL",
       Amount = amount,
       Channel = "Web"
    };
    const config = new Config();
    // Set your X-API-KEY with the API key from the Customer Area.
    config.apiKey = '[API_KEY]';
    config.merchantAccount = '[MERCHANT_ACCOUNT]';
    const client = new Client({ config });
    client.setEnvironment("TEST");
    const checkout = new CheckoutAPI(client);
    const paymentsResponse = checkout.paymentMethods({
        amount: {
            currency: "EUR",
            value: 1000,
        },
        countryCode: "NL",
        channel: "Web",
        merchantAccount: config.merchantAccount
    }).then(res => res);

    A list of available paymentMethods is returned in the response, including any required fields. If you want to know more about the properties returned in the response, see the response parameters in our API Explorer.

    {
     "paymentMethods":[
      {
        "details":[...],
        "name":"Credit Card",
        "type":"scheme"
        ...
      },
      {
        "details":[...],
        "name":"SEPA Direct Debit",
        "type":"sepadirectdebit"
      },
      ...
      ]
    }
  2. Pass the response to your front end. You'll use this in the next step to show which payment methods are available for the shopper.

Step 2: Add Drop-in to your payments form

  1. Include the following script in the <body> above any other JavaScript in your checkout page: 

    <script src="https://checkoutshopper-live.adyen.com/checkoutshopper/sdk/3.3.0/adyen.js"></script>
  2. Use the following CSS file:

    <link rel="stylesheet" href="https://checkoutshopper-live.adyen.com/checkoutshopper/sdk/3.3.0/adyen.css"/>

    You can add your own styling by overriding the rules in this CSS file.

  3. Create a DOM element on your checkout page, placing it where you want to render Drop-in.

    <div id="dropin"></div>
  4. Create an instance of AdyenCheckout. Add the following code on your checkout page, specifying:

    • locale: The shopper's locale. This is used to set the language rendered in the Components. For a list of supported locales, see Localization.
    • environment: Use test. When you're ready to accept live payments, change the value to one of our live environments.  
    • originKey: The Origin Key of your website. To find out how to generate one, see How to get an Origin Key.
    • paymentMethodsResponse: The available payment methods for the shopper, returned in step 1.
    const configuration = {
      locale: "en-US",
      environment: "test",
      originKey: "YOUR_ORIGIN_KEY",
      paymentMethodsResponse: paymentMethodsResponse
    };
    const checkout = new AdyenCheckout(configuration);
  5. Create an instance of Drop-in and include required configuration for specific payment methods. Some payment methods require additional configuration before you can start accepting payments. See the supported payment methods and select the links for configuration details.

    • paymentMethodsConfiguration: Include other required or optional configuration here.

    Next, assign functions to handle the following events. Aside from these events, you can also use other events listed in Configuring Drop-in.

    • onSubmit: Called when the shopper selects the Pay button.
    • onAdditionalDetails: Called when additional information is required to complete the payment.

    Then, mount the container.

    const dropin = checkout
    .create('dropin', {
      paymentMethodsConfiguration: {
        applepay: { // Example required configuration for Apple Pay
          configuration: {
            merchantName: 'Adyen Test merchant', // Name to be displayed on the form
            merchantIdentifier: 'adyen.test.merchant' // Your Apple merchant identifier as described in https://developer.apple.com/documentation/apple_pay_on_the_web/applepayrequest/2951611-merchantidentifier
          },
          onValidateMerchant: (resolve, reject, validationURL) => {
          // Call the validation endpoint with validationURL.
          // Call resolve(MERCHANTSESSION) or reject() to complete merchant validation.
          }
        },
        paywithgoogle: { // Example required configuration for Google Pay
          environment: "TEST", // Change this to PRODUCTION when you're ready to accept live Google Pay payments
          configuration: {
           gatewayMerchantId: "YourCompanyOrMerchantAccount", // Your Adyen merchant or company account name. Remove this field in TEST.
           merchantIdentifier: "12345678910111213141" // Required for PRODUCTION. Remove this field in TEST. Your Google Merchant ID as described in https://developers.google.com/pay/api/web/guides/test-and-deploy/deploy-production-environment#obtain-your-merchantID
          }
        },
        card: { // Example optional configuration for Cards
          hasHolderName: true,
          holderNameRequired: true,
          enableStoreDetails: true,
          name: 'Credit or debit card'
        }
      },
      onSubmit: (state, dropin) => {
        makePayment(state.data)
          // Your function calling your server to make the /payments request
          .then(action => {
            dropin.handleAction(action);
            // Drop-in handles the action object from the /payments response
          })
          .catch(error => {
            throw Error(error);
          });
      },
      onAdditionalDetails: (state, dropin) => {
        makeDetailsCall(state.data)
          // Your function calling your server to make a /payments/details request
          .then(action => {
            dropin.handleAction(action);
            // Drop-in handles the action object from the /payments/details response
          })
          .catch(error => {
            throw Error(error);
          });
      }
    })
    .mount('#dropin');
  6. When the shopper selects the Pay button, Drop-in calls the onSubmit event, which contains a state.data. Pass the state.data to your server.

    {
    isValid: true,
    data: {
      paymentMethod: {
        type: "scheme",
        encryptedCardNumber: "adyenjs_0_1_18$k7s65M5V0KdPxTErhBIPoMPI8HlC..",
        encryptedExpiryMonth: "adyenjs_0_1_18$p2OZxW2XmwAA8C1Avxm3G9UB6e4..",
        encryptedExpiryYear: "adyenjs_0_1_18$CkCOLYZsdqpxGjrALWHj3QoGHqe+..",
        encryptedSecurityCode: "adyenjs_0_1_24$XUyMJyHebrra/TpSda9fha978+.."
        holderName: "S. Hopper"
      }
    }
    }

Step 3: Make a payment

  1. From your server, make a POST /payments request specifying:

    • amount: The currency and value of the payment.
    • reference: Your unique reference for this payment.
    • paymentMethod: The state.data.paymentMethod from the onSubmit event from your front end.
    • returnUrl: URL to where your shopper will be taken back to after a redirection. The URL should include the protocol: http:// or https://. You can also include your own additional query parameters, for example, shopper ID or order reference number.
    • merchantAccount: Your merchant account name.
      Additional parameters are required for some payment methods, native 3D Secure 2 authentication, and recurring payments. For information on the required fields, refer to the payment method integration guides.
    curl https://checkout-test.adyen.com/v50/payments \
    -H "x-API-key: YOUR_X-API-KEY" \
    -H "content-type: application/json" \
    -d '{
      "amount":{
        "currency":"EUR",
        "value":1000
      },
      "reference":"YOUR_ORDER_NUMBER",
      "paymentMethod":{hint:state.data.paymentMethod from onSubmit}state.data.paymentMethod{/hint},
      "returnUrl":"https://your-company.com/checkout?shopperOrder=12xy..",
      "merchantAccount":"YOUR_MERCHANT_ACCOUNT"
    }'
    # Set your X-API-KEY with the API key from the Customer Area.
    adyen = Adyen::Client.new
    adyen.env = :test
    adyen.api_key = "YOUR_X-API-KEY"
     
    paymentMethod = DROPIN_DATA
    # Data object passed from onSubmit event of the front end, parsed from JSON to a Hash.
    
    response = adyen.checkout.payments({
      :amount => {
        :currency => "EUR",
        :value => 1000
      },
      :reference => "YOUR_ORDER_NUMBER",
      :paymentMethod => paymentMethod,
      :returnUrl => "https://your-company.com/checkout?shopperOrder=12xy..",
      :merchantAccount => "YOUR_MERCHANT_ACCOUNT"
    })
    
    # Check if further action is needed.
    if response.body.has_key(:action)
       # Pass the action object to your front end
       # response.body[:action]
    else
       # No further action needed, pass the resultCode object to your front end
       # response.body[:resultCode]
    // Set your X-API-KEY with the API key from the Customer Area.
    Client client = new Client(xApiKey,Environment.TEST);
     
    Checkout checkout = new Checkout(client);
    PaymentsRequest paymentsRequest = new PaymentsRequest();
    paymentsRequest.setMerchantAccount("YOUR_MERCHANT_ACCOUNT");
    Amount amount = new Amount();
    amount.setCurrency("EUR");
    amount.setValue(15000L);
    paymentsRequest.setAmount(amount);
    String encryptedCardNumber = "adyenjs_0_1_18$...encryptedCardNumber";
    String encryptedExpiryMonth = "adyenjs_0_1_18$...encryptedExpiryMonth";
    String encryptedExpiryYear = "adyenjs_0_1_18$...encryptedExpiryYear";
    String encryptedSecurityCode = "adyenjs_0_1_18$...encryptedSecurityCode";
    paymentsRequest.setReference("Your order number");
    paymentsRequest.addEncryptedCardData(encryptedCardNumber,encryptedExpiryMonth, encryptedExpiryYear, encryptedSecurityCode, "John Smith");
    paymentsRequest.setReturnUrl("https://your-company.com/checkout?shopperOrder=12xy..");
    PaymentsResponse paymentsResponse = checkout.payments(paymentsRequest);
    // Set your X-API-KEY with the API key from the Customer Area.
    $client = new \Adyen\Client();
    $client->setXApiKey("YOUR_X-API-KEY");
    $service = new \Adyen\Service\Checkout($client);
    
    $paymentMethod = DROPIN_DATA;
    // Data object passed from onSubmit event of the front end parsed from JSON to an array
    
    $params = array(
      "amount" => array(
        "currency" => "EUR",
        "value" => 1000
      ),
      "reference" => "YOUR_ORDER_NUMBER",
      "paymentMethod" => $paymentMethod,
      "returnUrl" => "https://your-company.com/checkout?shopperOrder=12xy..",
      "merchantAccount" => "YOUR_MERCHANT_ACCOUNT"
    );
    
    $result = $service->payments($params);
    
    // Check if further action is needed
    if (array_key_exists("action", $result){
       // Pass the action object to your front end
       // $result["action"]
    }
    else {
       // No further action needed, pass the resultCode to your front end
       // $result['resultCode']
    }
    # Set your X-API-KEY with the API key from the Customer Area.
    adyen = Adyen.Adyen()
    adyen.client.xapikey = 'YOUR_X-API-KEY'
    
    paymentMethod = DROPIN_DATA
    # Data object passed from onSubmit event of the front end, parsed from JSON to a dictionary
    
    result = adyen.checkout.payments({
       'amount': {
          'value': 1000,
          'currency': 'EUR'
       },
       'reference': 'YOUR_ORDER_NUMBER',
       'paymentMethod': paymentMethod,
       'returnUrl': 'https://your-company.com/checkout?shopperOrder=12xy..',
       'merchantAccount': 'YOUR_MERCHANT_ACCOUNT'
    })
    
    # Check if further action is needed
    if 'action' in result.message:
       # Pass the action object to your front end
       # result.message['action']
    else:
       # No further action needed, pass the resultCode to your front end
       # result.message['resultCode']
    // Set your X-API-KEY with the API key from the Customer Area.
    var client = new Client ("YOUR_X-API-KEY", Environment.Test);
    var checkout = new Checkout(client);
    
    var amount = new Model.Checkout.Amount("EUR", 1000);
    var details = new Model.Checkout.DefaultPaymentMethodDetails{
      Type = "scheme",
      EncryptedCardNumber = "adyenjs_0_1_18$MT6ppy0FAMVMLH...",
      EncryptedExpiryMonth = "adyenjs_0_1_18$MT6ppy0FAMVMLH...",
      EncryptedExpiryYear = "adyenjs_0_1_18$MT6ppy0FAMVMLH...",
      EncryptedSecurityCode = "adyenjs_0_1_18$MT6ppy0FAMVMLH..."
    };
    var paymentsRequest = new Model.Checkout.PaymentRequest
    {
      Reference = "YOUR_ORDER_NUMBER",
      Amount = amount,
      ReturnUrl = @"https://your-company.com/checkout?shopperOrder=12xy..",
      MerchantAccount = "YOUR_MERCHANT_ACCOUNT",
      PaymentMethod = details
    };
    
    var paymentResponse = checkout.Payments(paymentsRequest);
    // Set your X-API-KEY with the API key from the Customer Area.
    const {Client, Config, CheckoutAPI} = require('@adyen/api-library');
    const config = new Config();
    // Set your X-API-KEY with the API key from the Customer Area.
    config.apiKey = '[API_KEY]';
    config.merchantAccount = '[YOUR_MERCHANT_ACCOUNT]';
    const client = new Client({ config });
    client.setEnvironment("TEST");
    const checkout = new CheckoutAPI(client);
    checkout.payments({
        amount: { currency: "EUR", value: 1000 },
        paymentMethod: {DROPIN_DATA}, // Data object passed from onSubmit event of the front end
        reference: "YOUR_ORDER_NUMBER",
        merchantAccount: config.merchantAccount,
        returnUrl: "https://your-company.com/checkout?shopperOrder=12xy.."
    }).then(res => res);

    Response

    Depending on the payment result, you receive a response containing:

    • resultCode: Provides information about the result of the request.
    • pspReference: Our unique identifier for the transaction.
    • details: This array shows the fields that you need to pass in your next request.
    • action: If you receive this object, this indicates that you need to perform an additional action on your front end to complete the payment. The type field specifies the required action. Possible values are:

      • qrCode
      • redirect
      • threeDS2Fingerprint
      • threeDS2Challenge
      • voucher
    • action.paymentData: If you receive action.type redirect, keep a copy of the paymentData. You will need to pass this in your next request.

  2. The next steps depend on if you received an action object in the response.

    • If you received an action object, pass this to your front end or client app and proceed to step 4. Make sure that you only pass the action object and not the full response.
    • If you did not get an action object, proceed to step 6 to present the payment result to your shopper.
    {
      "resultCode":"IdentifyShopper",
      "action":{
        "paymentMethodType":"scheme",
        "token":"eyJ0aHJlZURTTWV0aG9kTm90aWZpY...",
        "type":"threeDS2Fingerprint"
      },
      "authentication":{
        "threeds2.fingerprintToken":"eyJ0aHJlZURTTWV0aG9kTm90aWZpY..."
      },
      "details":[
        {
          "key":"threeds2.fingerprint",
          "type":"text"
        }
      ],
      "paymentData":"Ab02b4c0!BQABAgCuZFJrQOjSsl\/zt+..."
    }

Step 4: Perform additional actions on your front end

Drop-in uses the dropin.handleAction function to perform additional front-end actions depending on the action.type.

Your next steps depend on the type of action that Drop-in performs: redirecting shoppers to another website, presenting a voucher or QR code, or performing 3D Secure 2 native authentication.

Redirect

If you get a redirect action.type, Drop-in redirects the shopper to complete the payment. After the shopper is redirected back to your returnURL, you need to:

Voucher

If you get a voucher action.type, Drop-in displays the voucher, which the shopper will need to use to complete the payment. After Drop-in presents the voucher, you need to:

  • Proceed to step 6 and inform the shopper that you are waiting for the payment. We'll send a webhook notification to inform you of the outcome of the payment.

QR code

If you get a qrCode action.type, Drop-in presents the QR code and calls the onAdditionalDetails event. You then need to:

  1. Get the state.data from the onAdditionalDetails event and pass it your server.
  2. Proceed to step 5.

    {
     data: {
        details: {
          payload: "Ab02b4c0!BQABF..."
        },
        paymentData: "Ab02b4c0!BQABAgAKspbjN8+5..."
     }
    }

3D Secure 2 native authentication

If you get a threeDS2Fingerprint or threeDS2Challenge action.type, Drop-in performs the device fingerprinting or presents a challenge to the shopper. After performing the authentication flows, Drop-in calls the onAdditionalDetails event. You then need to:

  1. Get the state.data from the onAdditionalDetails event and pass it your server.
  2. Proceed to step 5.

    {
     data: {
        details: {
          threeds2.fingerprint: "eyJ0aHJlZURTQ29tcEluZCI6IlkifQ=="
        },
        paymentData: "Ab02b4c0!BQABAgAKspbjN8+5..."
     }
    }

Step 5: Submit additional payment details

If Drop-in presented a QR code, use the /payments/details endpoint to check the payment result. If Drop-in performed 3D Secure 2 native authentication, use the same endpoint to submit authentication results and to complete the payment.

  1. From your server, make a POST /payments/details request with the state.data from the onAdditionalDetails event.

    curl https://checkout-test.adyen.com/v50/payments/details \
    -H "x-API-key: YOUR_X-API-KEY" \
    -H "content-type: application/json" \
    -d '{
          "details":{
             "threeds2.fingerprint":"eyJ0aHJlZURTQ29tcEluZCI6IlkifQ=="
          },
          "paymentData":"Ab02b4c0!BQABAgAKspbjN8+5..."
    }'
    # Set your X-API-KEY with the API key from the Customer Area.
    adyen = Adyen::Client.new
    adyen.env = :test
    adyen.api_key = "YOUR_X-API-KEY"
    
    request = DROPIN_DATA
    # Data object passed from onAdditionalDetails event of the front end, parsed from JSON to a Hash.
    
    response = adyen.checkout.payments.details(request)
    
    # Check if further action is needed.
    if response.body.has_key(:action)
       # Pass the action object to your frontend
       puts response.body[:action]
    else
       # No further action needed, pass the resultCode to your frontend
       puts response.body[:resultCode]
    end
    // Set your X-API-KEY with the API key from the Customer Area.
    Client client = new Client(xApiKey,Environment.TEST);
    
    Checkout checkout = new Checkout(client);
    PaymentDetailsRequest paymentDetailsRequest = new PaymentDetailsRequest();
    HashMap<String, String> details = new HashMap<>();
    details.put("payload", "Ab02b4c0!BQABF...");
    paymentsDetailsRequest.setDetails(details);
    paymentsDetailsRequest.setPaymentData("Ab02b4c0!BQABAgAKspbjN8+5...");
    PaymentsResponse paymentsResponse = checkout.paymentDetails(PaymentDetailsRequest);
    // Set your X-API-KEY with the API key from the Customer Area.
    $client = new \Adyen\Client();
    $client->setXApiKey("YOUR_X-API-KEY");
    $service = new \Adyen\Service\Checkout($client);
    
    $params = DROPIN_DATA;
    // Data object passed from onAdditionalDetails event of the front end parsed from JSON to an array
    
    $result = $service->paymentDetails($params);
    
    // Check if further action is needed
    if (array_key_exists("action", $result){
       // Pass the action object to your frontend.
       // $result["action"]
    }
    else {
       // No further action needed, pass the resultCode to your front end
       // $result['resultCode']
    }
    #Set your X-API-KEY with the API key from the Customer Area.
    adyen = Adyen.Adyen()
    adyen.client.xapikey = 'YOUR_X-API-KEY'
    
    request = DROPIN_DATA
    # Data object passed from onAdditionalDetails event of the front end, parsed from JSON to a dictionary
    
    result = adyen.checkout.payments_details(request)
    
    # Check if further action is needed.
    if 'action' in result.message:
       # Pass the action object to your front end
       # result.message['action']
    else:
       # No further action needed, pass the resultCode to your front end
       # result.message['resultCode']
    // Set your X-API-KEY with the API key from the Customer Area.
    var client = new Client ("YOUR_X-API-KEY", Environment.Test);
    var checkout = new Checkout(client);
    string paymentData = "Ab02b4c0!BQABAgAKspbjN8+5...";
    
    var details = new Dictionary<string, string>
    {
      { "payload", "Ab02b4c0!BQABF..." }
    };
    var paymentsDetailsRequest = new Model.Checkout.PaymentsDetailsRequest(Details: details);
    var paymentResponse = checkout.PaymentDetails(paymentsDetailsRequest);
    // Set your X-API-KEY with the API key from the Customer Area.
    const {Client, Config, CheckoutAPI} = require('@adyen/api-library');
    const config = new Config();
    // Set your X-API-KEY with the API key from the Customer Area.
    config.apiKey = '[API_KEY]';
    config.merchantAccount = '[YOUR_MERCHANT_ACCOUNT]';
    const client = new Client({ config });
    client.setEnvironment("TEST");
    const checkout = new CheckoutAPI(client);
    checkout.paymentsDetails({
        details: {DROPIN_DATA}  // Data object passed from onAdditionalDetails event of the front end
    }).then(res => res);


    Depending on the payment result, you receive a response containing:

    • resultCode: Provides information about the result of the request.
    • pspReference: Our unique identifier for the transaction.
    • action: If you receive this object, this indicates that you need to perform step 4 again.

  2. The next steps depend on if you received an action object in the response.

    • If you received an action object, pass the action object to your front end and perform step 4 again.
    • If you did not get an action object, proceed to the next step to present the payment result to your shopper.
    {
     "pspReference": "88154795347618C",
     "resultCode": "Authorised"
    }
    {
     "pspReference": "89783918347627F",
     "refusalReason": "Not enough balance",
     "resultCode": "Refused"
    }

Step 6: Present the payment result

After the shopper completes the payment and no more further actions are required on the front end or client app, use the resultCode to inform the shopper of the payment status.

resultCode Description Action to take
Authorised The payment was successful. Inform the shopper that the payment was successful.
Error Inform the shopper that there was an error processing their payment. You'll receive a refusalReason in the same response, indicating the cause of the error.
Pending The shopper has completed the payment but the final result is not yet known. Inform the shopper that you've received their order, and are waiting for the payment to be completed.
You will receive the final result of the payment in an AUTHORISATION notification.
PresentToShopper Present the voucher or the QR code to the shopper. For a voucher payment method, inform the shopper that you are waiting for their payment. You will receive the final result of the payment in an AUTHORISATION notification.

For a qrCode payment method, wait for the AUTHORISATION notification before presenting the payment result to the shopper.
Refused The payment was refused. Inform the shopper that the payment was refused. Ask the shopper to try the payment again using a different payment method or card.
Received For some payment methods, it can take some time before the final status of the payment is known. Inform the shopper that you've received their order, and are waiting for the payment to clear.
You will receive the final result of the payment in an AUTHORISATION notification.

For other possible resultCode values and recommended messages that you can present to your shopper, see Result codes.

Alternatively, you can use the dropin.setStatus to show a customized message. For example:

  dropin.setStatus('success');
  dropin.setStatus('success', { message: 'Payment successful!' });

  dropin.setStatus('error');
  dropin.setStatus('error', { message: 'Something went wrong.'});

Handling the redirect result

If you receive an action.type redirect, Drop-in redirects your shopper to another website using an HTTP GET or HTTP POST request. The shopper will be redirected back to your website using the same method.

If a shopper completed the payment but failed to return to your website, you will receive the outcome of the payment in a notification webhook.

Checking redirect parameters

Get the redirect information from the action object in the /payments response.

  • paymentData:Value you received in the /payments response. You need submit this in your /payments/details request later.
  • details: Array that contains the key parameter names and the corresponding data type that you should expect when the shopper is redirected to your returnURL. If other parameters are appended to the returnURL or sent in the form data but are not included in the details object, ignore them. These are also the parameters that you will need to submit in a /payments/details request.
  • method: The HTTP request method used to redirect the shopper to your returnURL after they complete the payment.
The redirect method depends on your payment method configuration and the length of the data included in the request, so make sure that your integration can handle both HTTP GET and HTTP POST methods.

For example, for an iDEAL payment, you might receive the following response:

{
  "resultCode": "RedirectShopper",
  "action": {
    "method": "GET",
    "paymentData": "Ab02b4c0!B..=",
    "paymentMethodType": "ideal",
    "type": "redirect",
    "url": "https://test.adyen.com/hpp/redirectIdeal.shtml?brandCode=ideal&currencyCode=EUR..."
    },
  "details": [
    {
      "key": "payload",
      "type": "text"
    }
  ]
  ...
}

HTTP GET redirect

After the shopper is redirected back to your returnURL with an HTTP GET, you need to:

  1. URL-decode the parameters appended to your returnURL and pass the parameters to your back end. For example, a shopper can be redirected back to your website with a payload parameter:
    GET /?shopperOrder=12xy..&&payload=Ab02b4c0!BQABF... HTTP/1.1
    Host: www.your-company.com/checkout
  2. From your server, submit a /payments/details request specifying:
    • paymentData: Value you received in the /payments response.
    • details: Object that contains the URL-decoded parameters appended to the returnURL. For example, payload.
    curl https://checkout-test.adyen.com/v50/payments/details \
    -H "x-API-key: YOUR_X-API-KEY" \
    -H "content-type: application/json" \
    -d '{
         "paymentData":"Ab02b4c0!BQABAgCJN1wRZuGJmq8dMncmypvknj9s7l5Tj...",
         "details":{
           "payload":"Ab02b4c0!BQABAgCW5sxB4e/=="
         }
    }'
    # Set your X-API-KEY with the API key from the Customer Area.
    adyen = Adyen::Client.new
    adyen.api_key = "YOUR_X-API-KEY"
    
    response = adyen.checkout.payments.details({
      :paymentData => 'Ab02b4c0!BQABAgCJN1wRZuGJmq8dMncmypvknj9s7l5Tj...',
      :details => {
        :payload => 'Ab02b4c0!BQABAgCW5sxB4e/=='
      }
    })
    // Set your X-API-KEY with the API key from the Customer Area.
    Client client = new Client(xApiKey,Environment.TEST);
    
    Checkout checkout = new Checkout(client);
    PaymentDetailsRequest paymentDetailsRequest = new PaymentDetailsRequest();
    HashMap<String, String> details = new HashMap<>();
    details.put("payload", "Ab02b4c0!BQABAgCW5sxB4e/==...");
    paymentsDetailsRequest.setDetails(details);
    paymentsDetailsRequest.setPaymentData("Ab02b4c0!BQABAgCJN1wRZuGJmq8dMncmypvknj9s7l5Tj...");
    PaymentsResponse paymentsResponse = checkout.paymentDetails(PaymentDetailsRequest);
    // Set your X-API-KEY with the API key from the Customer Area.
    $client = new \Adyen\Client();
    $client->setXApiKey("YOUR_X-API-KEY");
    $service = new \Adyen\Service\Checkout($client);
    
    $params = array(
      "paymentData" => "Ab02b4c0!BQABAgCJN1wRZuGJmq8dMncmypvknj9s7l5Tj...",
      "details" => array(
        "payload" => "Ab02b4c0!BQABAgCW5sxB4e/==..."
      )
    );
    $result = $service->paymentDetails($params);
    #Set your X-API-KEY with the API key from the Customer Area.
    adyen = Adyen.Adyen()
    adyen.client.xapikey = 'YOUR_X-API-KEY'
    
    result = adyen.checkout.payments_details({
       'paymentData' : 'Ab02b4c0!BQABAgCJN1wRZuGJmq8dMncmypvknj9s7l5Tj...',
       'details': {
          'payload': 'Ab02b4c0!BQABAgCW5sxB4e/=='
       }
    })
    // Set your X-API-KEY with the API key from the Customer Area.
    var client = new Client ("YOUR_X-API-KEY", Environment.Test);
    var checkout = new Checkout(client);
    string paymentData = "Ab02b4c0!BQABAgCJN1wRZuGJmq8dMncmypvknj9s7l5Tj...";
    var details = new Dictionary<string, string>
    {
      { "payload", "Ab02b4c0!BQABAgCW5sxB4e/==..." }
    };
    var paymentsDetailsRequest = new Model.Checkout.PaymentsDetailsRequest(Details: details, PaymentData: paymentData);
    var paymentResponse = checkout.PaymentDetails(paymentsDetailsRequest);
    // Set your X-API-KEY with the API key from the Customer Area.
    const {Client, Config, CheckoutAPI} = require('@adyen/api-library');
    const config = new Config();
    // Set your X-API-KEY with the API key from the Customer Area.
    config.apiKey = '[API_KEY]';
    config.merchantAccount = '[MERCHANT_ACCOUNT]';
    const client = new Client({ config });
    client.setEnvironment("TEST");
    const checkout = new CheckoutAPI(client);
    checkout.paymentsDetails({
        details: { payload: "Ab02b4c0!BQABAgCW5sxB4e/==" },
        paymentData: "Ab02b4c0!BQABAgCJN1wRZuGJmq8dMncmypvknj9s7l5Tj...",
    }).then(res => res);
    The response contains:
      {
       "resultCode": "Authorised",
       "pspReference": "88154795347618C"
     }

HTTP POST redirect

After the shopper is redirected back to your returnURL with an HTTP POST, you need to:

  1. URL-decode the parameters from the form data and pass the parameters to your back end. For example, MD and PaRes parameters are returned after a 3D Secure authentication.
    POST / HTTP/1.1
    Host: www.your-company.com/checkout?shopperOrder=12xy..
    Content-Type: application/x-www-form-urlencoded
    MD=dXlER3BhTEVCazlLd1..&PaRes=eNrNV0mTo7gS..
  2. From your server, submit a /payments/details request specifying:
    • paymentData: Value you received in the /payments response.
    • details: Object that contains the URL-decoded parameters appended to the returnURL. For example, MD and PaRes.
    curl https://checkout-test.adyen.com/v50/payments/details \
    -H "x-API-key: YOUR_X-API-KEY" \
    -H "content-type: application/json" \
    -d '{
         "paymentData":"Ab02b4c0!BQABAgCJN1wRZuGJmq8dMncmypvknj9s7l5Tj...",
         "details":{
           "MD":"Ab02b4c0!BQABAgCW5sxB4e/==",
           "PaRes":"eNrNV0mTo7gS.."
         }
    }'
    # Set your X-API-KEY with the API key from the Customer Area.
    adyen = Adyen::Client.new
    adyen.api_key = "YOUR_X-API-KEY"
    
    response = adyen.checkout.payments.details({
      :paymentData => 'Ab02b4c0!BQABAgCJN1wRZuGJmq8dMncmypvknj9s7l5Tj...',
      :details => {
        :payload => 'Ab02b4c0!BQABAgCW5sxB4e/=='
      }
    })
    // Set your X-API-KEY with the API key from the Customer Area.
    Client client = new Client(xApiKey,Environment.TEST);
    
    Checkout checkout = new Checkout(client);
    PaymentDetailsRequest paymentDetailsRequest = new PaymentDetailsRequest();
    HashMap<String, String> details = new HashMap<>();
    details.put("MD", "Ab02b4c0!BQABAgCW5sxB4e/==");
    details.put("PaRes", "eNrNV0mTo7gS..");
    paymentsDetailsRequest.setDetails(details);
    paymentsDetailsRequest.setPaymentData("Ab02b4c0!BQABAgCJN1wRZuGJmq8dMncmypvknj9s7l5Tj...");
    PaymentsResponse paymentsResponse = checkout.paymentDetails(PaymentDetailsRequest);
    // Set your X-API-KEY with the API key from the Customer Area.
    $client = new \Adyen\Client();
    $client->setXApiKey("YOUR_X-API-KEY");
    $service = new \Adyen\Service\Checkout($client);
    
    $params = array(
      "paymentData" => "Ab02b4c0!BQABAgCJN1wRZuGJmq8dMncmypvknj9s7l5Tj...",
      "details" => array(
        "MD" => "Ab02b4c0!BQABAgCW5sxB4e/==",
        "PaRes" => "eNrNV0mTo7gS.."
      )
    );
    $result = $service->paymentDetails($params);
    #Set your X-API-KEY with the API key from the Customer Area.
    adyen = Adyen.Adyen()
    adyen.client.xapikey = 'YOUR_X-API-KEY'
    
    result = adyen.checkout.payments_details({
       'paymentData' : 'Ab02b4c0!BQABAgCJN1wRZuGJmq8dMncmypvknj9s7l5Tj...',
       'details': {
          'MD': 'Ab02b4c0!BQABAgCW5sxB4e/==',
          'PaRes': "eNrNV0mTo7gS.."
       }
    })
    // Set your X-API-KEY with the API key from the Customer Area.
    var client = new Client ("YOUR_X-API-KEY", Environment.Test);
    var checkout = new Checkout(client);
    string paymentData = "Ab02b4c0!BQABAgCJN1wRZuGJmq8dMncmypvknj9s7l5Tj...";
    var details = new Dictionary<string, string>
    {
      { "MD", "Ab02b4c0!BQABAgCW5sxB4e/==" },
      {"PaRes", "eNrNV0mTo7gS.."}
    };
    var paymentsDetailsRequest = new Model.Checkout.PaymentsDetailsRequest(Details: details, PaymentData: paymentData);
    var paymentResponse = checkout.PaymentDetails(paymentsDetailsRequest);
    // Set your X-API-KEY with the API key from the Customer Area.
    const {Client, Config, CheckoutAPI} = require('@adyen/api-library');
    const config = new Config();
    // Set your X-API-KEY with the API key from the Customer Area.
    config.apiKey = '[API_KEY]';
    config.merchantAccount = '[MERCHANT_ACCOUNT]';
    const client = new Client({ config });
    client.setEnvironment("TEST");
    const checkout = new CheckoutAPI(client);
    checkout.paymentsDetails({
        details: { MD: "Ab02b4c0!BQABAgCW5sxB4e/==", PaRes: "eNrNV0mTo7gS.." },
        paymentData: "Ab02b4c0!BQABAgCJN1wRZuGJmq8dMncmypvknj9s7l5Tj...",
    }).then(res => res);
    You receive a response containing:
      {
       "resultCode": "Authorised",
       "pspReference": "88154795347618C"
     }

Test and go live

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 are ready to go live, you need to:

  1. Apply for a live account.
  2. Configure your live account
  3. Submit a request to add payment methods in your live Customer Area .
  4. Switch from test to our live endpoints.
  5. Load Drop-in from one of our live environments closest to where your shoppers are. Set the environment configuration object to:

    • Europe: live
    • Australia: live-au
    • US: live-us

Configuring Drop-in

You can include the following additional configuration when instantiating Drop-in on your payments form:

  • amount: Amount to be displayed on the Pay Button. It expects an object with the value and currency properties. For example, { value: 1000, currency: 'USD' }.
  • openFirstPaymentMethod: When enabled, Drop-in opens the first payment method automatically on page load. Defaults to true.
  • openFirstStoredPaymentMethod: When enabled, Drop-in opens the payment method with stored card details on page load. This option takes precedence over openFirstPaymentMethod. Defaults to true.
  • showStoredPaymentMethods: Shows or hides payment methods with stored card details. Defaults to true.
  • showPaymentMethods: Shows or hides regular payment methods, useful if you only want to show payment methods with stored card details. Defaults to true.
  • showPayButton: Show or hides a Pay Button for each payment method. Defaults to true. The Pay button triggers the onSubmit event.

    If you want to disable the button and then trigger the submit flow on your own, set this to false and call the .submit() method from your own button implementation.

    dropin.submit()

Events

Use the following events to include additional logic on your checkout page:

  • onSubmit(state, dropin): Called when the shopper selects the Pay button.
  • onAdditionalDetails(state, dropin): Called when a payment method requires more details.
  • onError(error): Called when an error occurs in the Drop-in.
  • onReady(): Called when Drop-in is initialized and is ready for use.
  • onSelect(component): Called when the shopper selects a payment method.

Supported payment methods

The following payment methods are supported in Drop-in. If you have questions about payment methods not on the list below or those that do not have linked pages, contact our Support Team.

Payment method Web iOS Android
AfterPay -white_check_mark-
Apple Pay -white_check_mark- -white_check_mark-
Bancontact Mobile (Payconiq) -white_check_mark- -white_check_mark-
Boleto Bancário -white_check_mark-
Cards, including 3D Secure 1 and 3D Secure 2
authentication
-white_check_mark- -white_check_mark- -white_check_mark-
Stored card details -white_check_mark- -white_check_mark- -white_check_mark-
Dragonpay -white_check_mark-
Dotpay -white_check_mark- -white_check_mark- -white_check_mark-
Entercash -white_check_mark- -white_check_mark- -white_check_mark-
EPS -white_check_mark- -white_check_mark- -white_check_mark-
giropay -white_check_mark-
Google Pay -white_check_mark- -white_check_mark-
iDEAL -white_check_mark- -white_check_mark- -white_check_mark-
Japanese convenience stores (Konbini)/
7-Eleven Japan
-white_check_mark-
Klarna -white_check_mark- -white_check_mark- -white_check_mark-
MOLPay -white_check_mark- -white_check_mark- -white_check_mark-
Multibanco -white_check_mark-
Open banking -white_check_mark- -white_check_mark- -white_check_mark-
Online banking India -white_check_mark-
Online banking Japan -white_check_mark-
QiwiWallet -white_check_mark-
Redirect payment methods
(For example, UnionPay)
-white_check_mark- -white_check_mark- -white_check_mark-
SEPA Direct Debit -white_check_mark- -white_check_mark- -white_check_mark-
Vipps -white_check_mark-
Wallets India -white_check_mark-
WeChat Pay -white_check_mark-

We're actively adding payment methods to Drop-in. To check the latest on Drop-in and Components, see our release notes.

See also

Next steps