Are you looking for test card numbers?

Would you like to contact support?

Default icon

iOS Drop-in integration guide

Accept popular payment methods in your iOS app with a single client-side implementation.

Drop-in is our pre-built UI solution for accepting payments on your app. Drop-in shows all payment methods as a list, in the same block.

Adding new payment methods usually doesn't require more development work. Drop-in supports cards, wallets, and most local payment methods.

This guide explains our simplified Drop-in integration introduced in v5.0.0. If you implemented Drop-in before v5.0.0 and want to upgrade your Drop-in version, refer to our guide for Drop-in integrated before v5.0.0.

How it works

Try it out!

From an implementation perspective, a Drop-in integration contains:

  • Server-side: a single API call which creates the payment sessions.
  • Client-side: Drop-in, which uses the payment session data to make the payment request and to handle any other actions like redirects or 3D Secure authentication.
  • Webhook server: receives webhook notifications which tell you what is the outcome of each payment.

If you need to handle advanced use cases, you need to implement additional endpoints and client-side configuration.
The payment flow is the same for all payments:

  1. The shopper goes to the checkout page.
  2. Your server uses the shopper's country and currency information from your client to create a payment session.
  3. Your client creates an instance of Drop-in using the session data from the server.
  4. Drop-in shows the available payment methods, collects the shopper's payment details, handles additional actions, and presents the payment result to the shopper.
  5. Your webhook server receives the notification containing the payment outcome.

Before you begin

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:

Step 1: Create a payment session

A payment session is a resource with information about a payment flow initiated by the shopper. This resource has all the information Drop-in needs to handle all the stages of a payment flow. You can configure this resource with information like available payment methods, payment amount, or line items.

To create a payment session, make a /sessions 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. This is used to filter the list of available payment methods to your shopper.
returnUrl -white_check_mark- URL to where the shopper should be taken back to after a redirection. The URL can contain a maximum of 1024 characters and should include the protocol: http:// or https://. You can also include your own additional query parameters, for example, shopper ID or order reference number.
reference -white_check_mark- Your unique reference for the payment. Must be 3 characters or more.
expiresAt The session expiry date in ISO8601 format, for example 2023-11-23T12:25:28Z, or 2023-05-27T20:25:28+08:00. When not specified, the expiry date is set to 1 hour after session creation. You cannot set the session expiry to more than 24 hours after session creation.
countryCode The shopper's country code. This is used to filter the list of available payment methods to your shopper.
shopperLocale The language that the payment methods will appear in. Set it to the shopper's language and country code. The default is en-US. The front end also uses this locale if it's available.
shopperEmail The shopper's email address. Strongly recommended because this field is used in a number of risk checks, and for 3D Secure.
shopperReference Your reference to uniquely identify this shopper. Strongly recommended because this field is used in a number of risk checks.
applicationInfo If you're building an Adyen solution for multiple merchants, include some basic identifying information, so that we can offer you better support. For more information, refer to Building Adyen solutions.

Here's an example of how you would create a session for a payment of 10 EUR:

curl https://checkout-test.adyen.com/v68/sessions \
-H "x-API-key: YOUR_X-API-KEY" \
-H "content-type: application/json" \
-d '{
  "merchantAccount": "YOUR_MERCHANT_ACCOUNT",
  "amount": {
      "value": 1000,
      "currency": "EUR"
  },
  "returnUrl": "my-app://",
  "reference": "YOUR_PAYMENT_REFERENCE",
  "countryCode": "NL"
}'
Client client = new Client("YOUR_X-API-KEY", Environment.TEST);

Checkout checkout;
checkout = new Checkout(client);

CreateCheckoutSessionRequest checkoutSessionRequest = new CreateCheckoutSessionRequest();
Amount amount = new Amount();
amount.setCurrency("EUR");
amount.setValue(1000L);
checkoutSessionRequest.setAmount(amount);
checkoutSessionRequest.setMerchantAccount("YOUR_MERCHANT_ACCOUNT");
checkoutSessionRequest.setReturnUrl("my-app://");
checkoutSessionRequest.setReference("YOUR_PAYMENT_REFERENCE");
checkoutSessionRequest.setCountryCode("NL");
CreateCheckoutSessionResponse checkoutSessionResponse = checkout.sessions(checkoutSessionRequest);
$client = new \Adyen\Client();
$client->setApplicationName('Test Application');
$client->setEnvironment(\Adyen\Environment::TEST);
$client->setXApiKey('YOUR_X-API-KEY');
$service = new \Adyen\Service\Checkout($client);
$params = array(
   'amount' => array(
       'currency' => "EUR",
       'value' => 1000
   ),
   'countryCode' => 'NL',
   'merchantAccount' => 'YOUR_MERCHANT_ACCOUNT',
   'reference' => 'YOUR_PAYMENT_REFERENCE',
   'returnUrl' => 'my-app://'
);
$result = $service->sessions($params);
def test_sessions_success(self):
    ady = Adyen.Adyen()
    client = ady.client
    client.xapikey = config.xapikey
    client.platform = "test"
    client.app_name = "appname"
    request = {}
    request['amount'] = {"value": "1000", "currency": "EUR"}
    request['reference'] = "YOUR_PAYMENT_REFERENCE"
    request['merchantAccount'] = "YOUR_MERCHANT_ACCOUNT"
    request['returnUrl'] = "my-app://"
    request['countryCode'] = "NL"

    result = self.ady.checkout.sessions(request)
var checkoutSessionRequest = new CreateCheckoutSessionRequest
  {
      merchantAccount = ClientConstants.MerchantAccount,
      reference = "YOUR_PAYMENT_REFERENCE",
      returnUrl = "my-app://",
      amount = new Amount("EUR", 1000L),
      countryCode = "NL"
  };
var client = new Client("YOUR_X-API-KEY", Model.Enum.Environment.Test);
var checkout = new Checkout(client);
var createCheckoutSessionResponse = checkout.Sessions(checkoutSessionRequest);
const { Client, CheckoutAPI } = require('@adyen/api-library');

const client = new Client({ apiKey: "YOUR_API_KEY", environment: "TEST" });
const checkout = new CheckoutAPI(client);

checkout.sessions({
    amount: { currency: "EUR", value: 1000 },
    reference: "YOUR_PAYMENT_REFERENCE",
    returnUrl: "https://your-company.com/checkout?shopperOrder=12xy..",
    merchantAccount: 'YOUR_MERCHANT_ACCOUNT',
    countryCode: "NL"
})
    .then((response) => {
        console.log(response);
    })
    .catch((e) => {
        console.log(e);
    });

The response contains:

  • sessionData: the payment session data you need to pass to your front end.
  • id: a unique identifier for the session data.
  • The request body.

HTTP 201 /sessions response body
{
    "amount": {
        "currency": "EUR",
        "value": 1000
    },
    "countryCode": "NL",
    "expiresAt": "2021-08-24T13:35:16+02:00",
    "id": "CSD9CAC34EBAE225DD",
    "merchantAccount": "YOUR_MERCHANT_ACCOUNT",
    "reference": "YOUR_PAYMENT_REFERENCE",
    "returnUrl": "https://your-company.com/checkout?shopperOrder=12xy.",
    "sessionData": "Ab02b4c..."
}

If you don't get an HTTP 200 response, use the errorCode field and the list of API error codes to troubleshoot.

Step 2: Set up Drop-in

1. Get Adyen iOS

Choose how you want to install the Adyen iOS client-side library:

To install iOS Drop-in using Swift Package Manager, follow the Apple guide and specify:
  • The repository URL as https://github.com/Adyen/adyen-ios.
  • The Adyen iOS client-side library version to be at least 5.0.0.

2. Create the context

First, create an instance of APIContext that contains:

Then, create an instance of AdyenContext that contains:

  • The instance of APIContext.
  • Payment information.
  • Optional analytics configuration.
// Set the client key and environment in an instance of APIContext.
let apiContext = APIContext(clientKey: clientKey, environment: Environment.test) // Set the environment to a live one when going live.
// Create the amount with the value in minor units and the currency code.
let amount = Amount(value: 1000, currencyCode: "EUR")
// Create the payment object with the amount and country code.
let payment = Payment(amount: amount, countryCode: "NL")
// Create an instance of AdyenContext, passing the instance of APIContext, payment object, and optional analytics configuration.
let adyenContext = AdyenContext(apiContext: apiContext, payment:payment, analyticsConfiguration: analyticsConfiguration)

3. Create a configuration object

Use the fields from the /sessions response to configure and create an instance of AdyenSession:

let configuration = AdyenSession.Configuration(sessionIdentifier: sessionId, // The id from the API response.
                                               initialSessionData: data, // The sessionData from the API response.
                                               adyenContext: adyenContext)

4. Initialize AdyenSession

Call the static initialize function of the AdyenSession, setting:

  • configuration: the configuration object you created in the previous step.
  • delegate: your delegate object. For example, self.
  • presentationDelegate: your delegate object. For example, self.

This asynchronously creates and returns an instance of the session.

AdyenSession.initialize(with: configuration, delegate: self, presentationDelegate: self) { [weak self] result in
        switch result {
        case let .success(session):
            //Store the session object.
            self?.session = session
        case let .failure(error):
            //Handle the error.
        }
    }

5. Configure Drop-in

Create a Drop-in configuration object (DropInComponent.Configuration), setting the adyenContext. Some payment methods require additional configuration, and you can add optional configuration.

let dropInConfiguration = DropInComponent.Configuration(adyenContext: adyenContext)
// Some payment methods have additional required or optional configuration.
// For example, an optional configuration to show the cardholder name field for cards.
dropInConfiguration.card.showsHolderNameField = true

6. Initialize the DropInComponent class

Set the instance of AdyenSession you created in the previous step as the delegate and, if you accept gift cards, partialPaymentDelegate of the DropInComponent instance.

let dropInComponent = DropInComponent(paymentMethods: session.sessionContext.paymentMethods,
                                      configuration: dropInConfiguration)

// Keep the instance of Drop-in to so that it doesn't get destroyed after the function is executed.
self.dropInComponent = dropInComponent

// Set the session as the delegate.
dropInComponent.delegate = session
// If you support gift cards, set the session as the partial payment delegate.
dropInComponent.partialPaymentDelegate = session

7. Show Drop-in in your app

Call the present method, passing the configured viewController.

present(dropInComponent.viewController, animated: true)

Your instance of AdyenSession handles all actions to complete the payment.

8. Handle the result

Drop-in either handles a result code or error object.

Result code

When the payment flow is finished, your instance of AdyenSession calls the didComplete method.
Implement this in your Drop-in configuration object:

func didComplete(with resultCode: SessionPaymentResultCode, // The result code from the API response.
                 component: Component, // The Drop-in component.
                 session: AdyenSession) // Your instance of AdyenSession.

Use the result code to tell your shopper the result of the payment. Possible result codes:

Result code Description Action to take
authorised The payment was successfully authorised. Inform the shopper that the payment was successful.
refused The payment was refused.
The response also contains a refusal reason that indicates why it was refused.
Inform the shopper that the payment was refused.
pending The final status of the payment isn't available yet. This is common for payments with an asynchronous flow, such as Boleto or iDEAL. Inform the shopper that you've received their order, and are waiting for them to complete the payment.
When the shopper completes the payment, you get the payment outcome.
cancelled The payment was cancelled (by either the shopper or your system) before processing was completed. Inform the shopper that the payment was cancelled.
error An error occurred during payment processing.
The response also contains an error code that gives more details about the error.
Inform the shopper that an error occurred during payment processing.
received The payment request was received, but the final status of the payment isn't available yet. Some payments, like SEPA Direct Debit, take time to process. Inform the shopper that you've received their order, and are waiting for the final payment result.

When the final payment status is available, you get the payment outcome.
presentToShopper Show the voucher or QR code to the shopper. Inform the shopper that you've received their order, and are waiting for them to complete the payment.
When the shopper completes the payment, you get the payment outcome.

Error

If an error occurs during the payment flow, your instance of AdyenSession calls the didFail method containing the error.
Implement this in your Drop-in configuration object:

func didFail(with error: Error, // The error object.
             from component: Component, // The Drop-in component.
             session: AdyenSession) // Your instance of AdyenSession.

The error tells you the type of error and contains a message with details. Use the information to tell the shopper what happened and use the message to troubleshoot the error.

Step 3: Get the payment outcome

You get the outcome of each payment asynchronously, in a notification webhook with eventCode: AUTHORISATION. Use this to update your order management system.
For a successful payment, the notification contains success: true.

Example webhook for a successful payment
{
  "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",
          "checkoutSessionId":"CSF46729982237A879"
        },
        "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
{
  "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",
          "checkoutSessionId":"861631540104159H"
        },
        "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. 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 Drop-in from one of our live environments and set the environment to match your live endpoints:

    Endpoint region environment value
    Europe liveEurope
    Australia liveAustralia
    US liveUnitedStates
    Asia Pacific South East liveApse

Next steps