Search

Are you looking for test card numbers?

Would you like to contact support?

Plugin icon

Magento headless integration

Integrate a Magento headless storefront with the Adyen platform.

On this page we provide Adyen-specific information for building a Progressive Web Application (PWA) storefront. The PWA storefront works with a headless Magento 2 back end that has the Adyen plugin installed and configured.

Ecommerce checkout flow

With a headless Magento 2 back end, you build your own payment form for the Magento 2 PWA storefront. In the checkout flow, data passes from the PWA storefront through the Magento 2 back end to the Adyen API. Then, data passes back from the Adyen API through the Magento 2 back end to the PWA storefront. In the checkout flow, you need to do the following steps:

  1. Get the payment methods that are available on the Adyen platform, and for each of them determine the data that you need to collect.
  2. Collect shopper details by presenting the payment methods on your payment form. Then, when the shopper selects a payment method, present the fields to fill out or the options to choose from, and collect these details.
  3. Place the order.
  4. Check the payment status to see if you need to perform any extra steps before redirecting the user to the success page or showing an error message.
  5. Handle additional actions like redirecting the customer to the issue page for additional authentication, or presenting a QR code to complete the payment. If the payment fails, the following attempts will need to handle the additional actions as well

The next sections explain these steps in more detail.

Before you begin

Before you start integrating a Magento 2 PWA storefront with the Adyen platform:

  1. Make sure you have completed the procedures to configure the Magento 2 back end:

    Setting up point of sale is not required for a PWA storefront.

  2. Make sure you are using version 7.0.0 or later of the Magento 2 plugin.

For debugging purposes you can find every Adyen API request and response in the adyen/info.log file.

This page describes the integration steps for plugin versions 7.0.0 and later. For the technical details of the releases, refer to our releases notes on GitHub.

Step 1: Get available payment methods

In this step, the Magento 2 back end retrieves the available payment methods from the /paymentMethods API endpoint and adds some extra information that you will need for rendering the components on the front end.

To get the payment methods that are available to the shopper and the data that you need to collect, make a POST request to one of the following endpoints:

  • /V1/guest-carts/:cart_id/retrieve-adyen-payment-methods
    Use this endpoint when the shopper is not logged in (guest). Provide the following information:
    • cart_id: Your reference to the shopper's cart.
  • /V1/carts/mine/retrieve-adyen-payment-methods
    Use this endpoint when the shopper is logged in. Provide the following information:
    • cart_id: Your reference to the shopper's cart.
    • shippingAddress: Optional object to specify shopper shipping details. You can use this to retrieve the payment methods for the shopper's country, based on the two-character country code in shippingAddress.countryID. Alternatively, the shipping address can be set in Magento using /V1/carts/mine/shipping-information and /V1/guest-carts/:cartId/shipping-information. For more information, refer to Magento 2 documentation.

Here's a sample request to retrieve payment methods for a logged in shopper:

{
 "cart_id":"48",
 "shippingAddress":
   {
     "customerAddressId":"1",
     "countryId":"NL",
     "regionCode":null,
     "region":null,
     "customerId":"1",
     "street":["Neherkade 1 XI"],
     "telephone":"0612345678",
     "postcode":"2521VA",
     "city":"Gravenhage",
     "firstname":"Test",
     "lastname":"Test"
   }
}

The request calls the getPaymentMethods method, which then makes a POST request to the /paymentMethods endpoint.

The Magento 2 back end receives a response from Adyen API containing all available payment methods for the current session filtered by currency, amount, country, etc. For each payment method, the Adyen /paymentMethods API response includes:

  • name: Name of the payment method, which you can show to your shopper in your payments form.
  • type: Unique payment method code. Pass this back to indicate the shopper's selected payment method when you place an order.
  • details: Array that contains the required fields for the payment method.

The plugin also collects some extra information other than the /paymentMethods response. This data is included in the /retrieve-adyen-payment-methods response as the following fields:

  • icon {url, width, height} — Payment method icon details.
  • configuration — Includes any extra payment method specific configuration that the checkout component should get on the front end which is not accessible from the /paymentMethods details response.
  • isOpenInvoice (boolean) — Indicates if the payment method is an open invoice payment method. Note that this field is deprecated and will be removed later.

The /retrieve-adyen-payment-methods responds with a JSON encoded string which looks like this:

"{\"paymentMethodsResponse\":{\"paymentMethods\":[{\"details\":[{\"items\":[{\"id\":\"1121\",\"name\":\"Test Issuer\"},{\"id\":\"1154\",\"name\":\"Test Issuer 5\"},{\"id\":\"1153\",\"name\":\"Test Issuer 4\"},{\"id\":\"1152\",\"name\":\"Test Issuer 3\"},{\"id\":\"1151\",\"name\":\"Test Issuer 2\"},{\"id\":\"1162\",\"name\":\"Test Issuer Cancelled\"},{\"id\":\"1161\",\"name\":\ …"

To use the details from the response, parse this string to get a JSON object. For example, using JSON.parse();.

After parsing the response, you get two root objects:

  • paymentMethodsResponse which includes the full and unmodified response object from the Adyen /paymentMethods API endpoint
  • paymentMethodsExtraDetails which holds the extra information that the plugin gathered for each payment method that are available in the paymentMethodsResponse (we have described it in the “The plugin also gathers some extra information” part)

Here's an example /retrieve-adyen-payment-methods response:

{
    "paymentMethodsExtraDetails": {
        "applepay": {
            "icon": {
                "url": "full url for icon",
                "width": 1,
                "height": 1
            },
            "configuration": {
                "amount": {
                    "value": 1,
                    "currency": "currency ISO code like EUR"
                }
            }
        },
        "ideal": {
       ...
        },
        "klarna": {
       ...
        },
        "klarna_paynow": {
       ...
        },
    ...
    },
    "paymentMethodsResponse": {
        "paymentMethods": [
            {
                "details": [
                    {
                        "items": [
                            {
                                "id": "1121",
                                "name": "Test Issuer"
                            },
                            {
                                "id": "1154",
                                "name": "Test Issuer 5"
                            },
                            {
                                "id": "1153",
                                "name": "Test Issuer 4"
                            },
                            "..."
                        ],
                        "key": "issuer",
                        "type": "select"
                    }
                ],
                "name": "iDEAL",
                "type": "ideal"
            },
            {
                "brands": [
                    "mc",
                    "visa",
                    "maestro"
                ],
                "details": [
                    {
                        "key": "number",
                        "type": "text"
                    },
                    {
                        "key": "expiryMonth",
                        "type": "text"
                    },
                    {
                        "key": "expiryYear",
                        "type": "text"
                    },
                    {
                        "key": "cvc",
                        "type": "text"
                    },
                    {
                        "key": "holderName",
                        "optional": true,
                        "type": "text"
                    }
                ],
                "name": "Credit Card",
                "type": "scheme"
            },
            {
                "configuration": {
                    "intent": "capture",
                    "merchantId": "Merchant id"
                },
                "name": "PayPal",
                "type": "paypal"
            },
            {
                "name": "Pay later with Klarna.",
                "type": "klarna"
            },
            {
                "details": [
                    {
                        "key": "sepa.ownerName",
                        "type": "text"
                    },
                    {
                        "key": "sepa.ibanNumber",
                        "type": "text"
                    }
                ],
                "name": "SEPA Direct Debit",
                "type": "sepadirectdebit"
            },
            {
                "configuration": {
                    "merchantId": "Merchant id",
                    "merchantName": "Merchant name"
                },
                "details": [
                    {
                        "key": "applepay.token",
                        "type": "applePayToken"
                    }
                ],
                "name": "Apple Pay",
                "type": "applepay"
            },
       ...
        }
    }
}

Step 2: Collect shopper details

Next, present the available payment methods on your front end, and collect the shopper details that are required for the payment method selected by the shopper. To do so:

  1. Use the name values from the /paymentMethods response to show all available payment methods to your shopper. You can access the paymentMethodsResponse by using /retrieve-adyen-payment-methods described in the previous step.

    If you need payment methods and issuer logos for your payment form, use the paymentMethodsExtraDetails.icon from the /retrieve-adyen-payment-methods response as described in the previous step.

  2. After the shopper selects a payment method, render the input fields to get the required payment details. This can be done in two ways:

Rendering the input fields using our Drop-in or Components

We provide multiple front end components which render the necessary fields and even do the validations for you. To find more information about this, check our Web Components. In case you don't want to customize any payment method form, use the Web Drop-in which makes the integration even easier.

To decide whether you need to choose the Web Components or the Web Drop-in solution, refer to Pre-built UI options page.

When you are implementing multiple payment methods on your PWA storefront we suggest that you pass full paymentMethodsResponse object to the Web Component configuration, and then after creating the new AdyenCheckout object you can loop through the methods and generate the components instead of doing it manually one by one. With this approach, you make sure that your solution can handle new payment methods that you enable in your Customer Area. For example, this is how the plugin handles it on the regular Magento front end.

Rendering the input fields manually

Use the details array from the paymentMethodsResponse for the selected payment method to determine what you need to collect from the shopper.

  • key: Shopper detail you need to collect using your payments form.
  • type: Input type for collecting the payment detail from the shopper:

    Type Description
    emailAddress Email address.
    radio Radio buttons showing the options specified within the items array.
    select A list showing the options specified within the items array. Usually the options represent issuer (bank) names. Present each name in this array to the shopper.
    tel Telephone number.
    text Generic string. For "type": "scheme", if you are fully PCI compliant you can alternatively collect and submit raw card data. See Collecting raw card data for more information. Otherwise, you need to generate encrypted card data using our custom card integration.

    If a payment method does not have a details array, you do not need to collect any shopper details in your form. This usually means that the shopper must be redirected to another site to complete the payment.

Step 3: Place the order

Now that the customer has filled in their data, you can place the order. In this step, the storefront makes a request to the Magento 2 back end which then makes a payment request to the /payments endpoint.

To start the payment process, place the order from your front end in a way that the default Magento checkout flow requires. To do so:

  1. Create a data object to send in the Magento API request.
  2. Place the order with the created object.

Create a data object

First, create a data object that you can later send in the Magento /payment-information Magento 2 REST API request.

To get the necessary details for this object, you can either use state.data from the Web component or replicate the request object yourself based on the documentation for the /payments endpoint. To replicate the object, follow this structure:

  • method: Payment method name in Magento. For example, adyen_cc, adyen_hpp, or adyen_oneclick.
  • cc_type (only for adyen_cc and adyen_oneclick): Card type. Get the card type available in Magento based on the state.data.paymentMethod.brand or state.brand as you can find in the example here. The brand can be found in the state.data as the field state.data.paymentMethod.brand or if you implement the onBrand callback for the checkout component then also as state.brand as seen in the example here.
  • brand_code (only for adyen_hpp): state.data.paymentMethod.type field
  • stateData: JSON.stringify() the state.data that you get from the Web Component or Drop-in. For example, this is how it is done in the plugin.

Example request for a card payment method:

{
    "method": "adyen_cc",
    "additional_data": {
        "cc_type": "MC",
        "stateData": "{\"riskData\":{\"clientData\":\"eyJ2ZXJz...\"},\"paymentMethod\":{\"type\":\"scheme\",\"holderName\":\"Holder name\",\"encryptedCardNumber\":\"adyenjs_0_1_25...\",\"encryptedExpiryYear\":\"adyenjs_0_1_25...\",\"encryptedSecurityCode\":\"adyenjs_0_1_25...\",\"brand\":\"mc\"},\"browserInfo\":{\"acceptHeader\":\"*/*\",\"colorDepth\":30,\"language\":\"en-US\",\"javaEnabled\":false,\"screenHeight\":900,\"screenWidth\":1440,\"userAgent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X)\",\"timeZoneOffset\":-120},\"clientStateDataIndicator\":true}\"
    }
}

Example request for an alternative payment method:

{
    "method": "adyen_hpp",
    "additional_data": {
        "brand_code": "ideal",
        "stateData": "{\"riskData\":{\"clientData\":\"eyJ2ZXJz...\"},\"paymentMethod\":{\"type\":\"ideal\",\"issuer\":\"1121\"},\"clientStateDataIndicator\":true}"
    }
}

Place an order

Place the order with the /payment-information endpoint from the Magento 2 REST API. Use the object created in the previous step.

Full example of the /payment-information request:

{
    "email": "email address",
    "billingAddress": {
        "city": "Gravenhage",
        "company": "",
        "countryId": "NL",
        "firstname": "Testperson-nl",
        "lastname": "Approved",
        "postcode": "2521VA",
        "region": "Netherlands",
        "saveInAddressBook": null,
        "street": [
            "Neherkade 1 XI"
        ],
        "telephone": "0612345678"
    },
    "paymentMethod": {
        "method": "adyen_hpp",
        "additional_data": {
            "brand_code": "ideal",
            "stateData": "{\"riskData\":{\"clientData\":\"eyJ2ZXJz...\"},\"paymentMethod\":{\"type\":\"ideal\",\"issuer\":\"1121\"},\"clientStateDataIndicator\":true}"
        }
    }
}

For more information, refer to the Magento 2 API documentation.

The response of the /payment-information Magento contains orderId in the integer format that you need for the next step.

Step 4: Check payment status

To see if there are any additional steps required after placing the order, call the payment status endpoint:

  1. Make a GET request to the /V1/adyen/orders/:orderId/payment-status endpoint. In the URL, use the orderId that you received in the response from the /payment-information endpoint in the previous step. For an example, refer to our credit card method renderer.

  2. Evaluate the response. There are two main paths that you can follow based on the isFinal response field.

    If the isFinal field is true:

    • If the resultCode field is Authorised, Received or PresentToShopper then the payment was successful and you can redirect the customer to the success page.
    • If the resultCode field is Refused, Error or unhandled, the API responds with 400 HTTP result code and a default Magento localized error response which looks like this:
    {
        "message": "The payment is REFUSED.",
        "trace": "#0 [internal function]..."
    }
    • If the action field is present and is not empty, then handle the action using the Web Component. This is, for example, to provide the additional information to the shopper in order to finalize the payment.

    If the isFinal field is false:

    {
        "isFinal": false,
        "resultCode":"IdentifyShopper",
        "action":{"paymentData":"Ab02b4c0…”}
    }

Step 5: Handle additional actions

This step is only needed if there is action in the response of the previous step.

Based on the previous step response, you can see if the payment status is final or not, and whether you need any additional steps to finish the payment process.

Handle action from the /payment-status or /payment-details response

Some payment methods require additional action from the shopper such as, to scan a QR code, to authenticate a payment with 3D Secure, or to log in to their bank's website to complete the payment. To handle these additional front-end actions, use the generic Web Component documentation or find specific documentation for each payment method in this list.

Note that some payment methods use the createFromAction method while others use the handleAction function so be mindful when implementing this step.

Optional: Validate the state.data from the action component

In case the shopper is already redirected to the success page, you don’t need to validate anything because the Component just presents a QR code or additional information to the customer, and there are no additional steps required from your side. Adyen is going to send a notification to your system as soon as the customer finishes the payment.

The plugin handles notifications on its own.

In case the shopper is still in the checkout process, you need to perform additional checks of the state.data that you get back from the Component. To do this, implement the onAdditionalDetails callback when creating the new AdyenCheckout component. Here's an example.

To validate the state.data, use the /adyen/paymentDetails endpoint exposed by the plugin.

Create your request

Create your request with the following field:

  • payload: JSON.stringify() the object that you get from the action component in the state.data field after you add the orderId as well. Here's an example.

Example request:

{
"payload": "{\"details\":{\"threeDSResult\":\"eyJ0cmFuc1N..."},\"orderId\":\"175\"}"
}

Handling the paymentsDetails response

Evaluate the response. There are 2 main paths that you can follow based on the isFinal response field.

If the isFinal field is true:

  • If the resultCode field is Authorised, Received or PresentToShopper then the payment was successful and you can redirect the customer to the success page.
  • If the resultCode field is Refused, Error or unhandled, the API responds with 400 HTTP result code and a default Magento localized error response which looks like this:

    {
      "message": "The payment is REFUSED.",
      "trace": "#0 [internal function]..."
    }
  • If the action field is present and is not empty, then handle the action using the Web Component. This is, for example, to provide the additional information to the shopper in order to finalize the payment.

If the isFinal field is false:

Retrieving an origin key

Use the client key instead of the origin key because this endpoint is deprecated and is going to be removed in the next major release.

To securely collect and encrypt sensitive cardholder data, and also to handle various other payment methods, the Adyen Magento 2 plugin requires an origin key for the base URL (the website domain) where the payment request comes from.

To get the origin key, make a GET request to the /V1/adyen/originKey endpoint.

You can send an empty JSON request to receive the origin key. The response contains only originKey.

Troubleshooting

When you get unexpected results, you can:

  • Check the endpoints on Adyen’s GitHub as a starting point to see if there are any changes. In addition, check your /swagger where all the endpoints are listed.

  • Use our API Explorer to try out calls to the Adyen API endpoints and for example see what kind of errors you might get. Make sure you select the API version that the Magento 2 plugin uses. Check the library and API versions you are using.

Checking library and API versions

The Magento 2 plugin uses a specific version of the Adyen PHP library, which in its turn uses specific versions of the Adyen APIs. You can try out calls to the Adyen APIs in our API Explorer. The API Explorer is versioned, so before trying a call you need to select the API version that your Magento 2 plugin version is using.

To look up which PHP library and Adyen API versions you are using, refer to the release notes. Or if it’s still missing then:

  1. Go to the Adyen Magento 2 plugin on GitHub. In the Branch dropdown, on the Tags tab, select the version of your Magento 2 plugin.

  2. At adyen/php-api-library, find the version of the Adyen PHP library that the plugin uses. For example, "adyen/php-api-library": "~2.1".

  3. Go to the Adyen PHP library. In the Branch dropdown, on the Tags tab, select the library version you've just found.

  4. Refer to the API constants to find the versions of the Adyen APIs that the PHP library uses, for example const API_CHECKOUT_VERSION = "v41".

See also