Version 8 of the plugin will be deprecated in January 2025. This means that there will be no security updates and you will no longer receive support from Adyen. We recommend to migrate the latest major version.
On this page we provide Adyen-specific information for building a Progressive Web Application (PWA) storefront. The PWA storefront works with a headless Adobe Commerce back end that has the Adyen plugin installed and configured.
Two web APIs can be used to utilize the Adyen functionality:
- REST - This is the most widely used web API. All of the functionalities provided by the Adyen plugin can be accessed using this method.
- GraphQL - This is an alternative way to interact with web APIs. The Adyen plugin utilizes the
/graphql
endpoint exposed by the Adobe Commerce back-end and adds the functionality that is related to the plugin. All of the essential functionalities provided by the Adyen plugin can be accessed using this method. For more information, checkout the Adobe Commerce GraphQL documentation.GraphQL is only available on plugin v8.2.0 or later.
Ecommerce checkout flow
With a headless Adobe Commerce back end, you build your own payment form for the Adobe Commerce PWA storefront. In the checkout flow, data passes from the PWA storefront through the Adobe Commerce back end to the Adyen API. Then, data passes back from the Adyen API through the Adobe Commerce back end to the PWA storefront. In the checkout flow, you need to do the following steps:
- Get the payment methods that are available on the Adyen platform, and for each of them determine the data that you need to collect.
- 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.
- Place the order.
- 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.
- 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.
Requirements
Before you start integrating a Adobe Commerce PWA storefront with the Adyen platform:
-
Make sure that you have completed the procedures to configure the Adobe Commerce back end:
- Set up the Adyen Customer Area.
- Set up the plugin in Adobe Commerce.
- Set up the payment methods in Adobe Commerce.
- Get familiar with the front end components implementation. We suggest using the components to gather the payment related information in a secure way.
Setting up point of sale is not required for a PWA storefront.
V8.0.0 of the plugin includes breaking changes.
-
From version 8.0.0 onwards, you have to use a Adobe Commerce OAuth authenticated API integration. To do this, follow the Adobe Commerce developer documentation:
- Add a new integration.
- For Resource Access select Custom. Select all the resources under the Adyen directory. Select Save.
- Activate your integration.
- When you send a request to one of the Adyen resources, include the Access Token of your integration in the Authorization header as a bearer token.
- Add a new integration.
For debugging purposes you can find every Adyen API request and response in the adyen/info.log
file.
Step 1: Get available payment methods
In this step, the Adobe Commerce 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. If you are using REST, the endpoint differs per use case. If you are using GraphQL, the endpoint is /graphql
.
/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.shopperLocale
: Optional parameter for 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 is available.
/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/region, based on the two-character country code inshippingAddress.countryID
. Alternatively, the shipping address can be set in Adobe Commerce using/V1/carts/mine/shipping-information
and/V1/guest-carts/:cartId/shipping-information
. For more information, refer to Adobe Commerce 2 documentation.shopperLocale
: Optional parameter for 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 is available.
Here's a sample request to retrieve payment methods for a logged in shopper:
{ "cart_id":"48", "shopperLocale":"nl_NL" "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 Adobe Commerce back end receives a response from Adyen API containing all available payment methods for the current session filtered by currency, amount, country/region, 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
response is 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
: Includes the full and unmodified response object from the Adyen/paymentMethods
API endpoint.paymentMethodsExtraDetails
: Holds the extra information that the plugin gathered for each payment method that is available in thepaymentMethodsResponse
.
Here's an example /retrieve-adyen-payment-methods
response after parsing:
{ "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:
-
Use the
name
values from the /paymentMethods response to show all available payment methods to your shopper. You can access thepaymentMethodsResponse
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. -
After the shopper selects a payment method, render the input fields to get the required payment details. This can be done in two ways:
Render the input fields using our Drop-in or Components
We provide two front end solutions that can render the necessary fields and do the validations for you:
- Web Drop-in.
- Web Components. Recommended
If you decide to use Web Components, we recommend to pass the full paymentMethodsResponse
object to the Web Component configuration when implementing multiple payment methods in your PWA storefront. After creating the new AdyenCheckout object, you can loop through the methods and generate the components instead of creating components manually for each payment method. This also ensures that your integration can handle new payment methods when enabled in your Customer Area.
Render 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. Otherwise, you need to use our solution to encrypt card data. |
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 Adobe Commerce 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 Adobe Commerce checkout flow requires. To do so:
- Create a data object to send in the Adobe Commerce API request.
- Place the order with the created object.
Create a data object
First, create a data object that you can later send in the Adobe Commerce /payment-information
Adobe Commerce 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 Adobe Commerce. For example,adyen_cc
,adyen_hpp
, oradyen_oneclick
.cc_type
(only foradyen_cc
andadyen_oneclick
): Card type. Get the card type available in Adobe Commerce based on thestate.data.paymentMethod.brand
orstate.brand
as you can find in the example here. Thebrand
can be found in thestate.data
as the fieldstate.data.paymentMethod.brand
or if you implement theonBrand
callback for the checkout component then also asstate.brand
as seen in the example here.brand_code
(only foradyen_hpp
):state.data.paymentMethod.type
fieldrecurringProcessingModel
(optional, only foradyen_cc
andadyen_hpp
): Defines the recurring processing model for the request, and overwrites the default value in the plugin configuration. This field accepts one of the following values:Subscription
,CardOnFile
, orUnscheduledCardOnFile
.stateData
: JSON.stringify() thestate.data
object that you get from the Web Component or Drop-in. For example, this is how it is done in the plugin. Thestate.data
object can be saved in a separate call to accommodate special checkout flows.
Example request for a card payment method:
{ "method": "adyen_cc", "additional_data": { "cc_type": "MC", "recurringProcessingModel": "Subscription", "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", "recurringProcessingModel": "Subscription", "stateData": "{\"riskData\":{\"clientData\":\"eyJ2ZXJz...\"},\"paymentMethod\":{\"type\":\"ideal\",\"issuer\":\"1121\"},\"clientStateDataIndicator\":true}" } }
Place an order
Place the order with the /payment-information
endpoint from the Adobe Commerce 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 Adobe Commerce API documentation.
The response of the /payment-information
Adobe Commerce 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:
- Make a POST request to the
/V1/adyen/orders/payment-status
endpoint. In the body, use theorderId
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.
-
Parse the JSON response and evaluate it. 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 with400
HTTP result code and a default Adobe Commerce localized error response which looks like this:
- If the
{ "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:- The
action
field is present and is not empty, then handle the action using the Web Component.
- The
{ "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, follow the Web Components documentation or find specific documentation for each payment method in this list.
Note that all payment methods use the createFromAction
method, except for PayPal. The PayPal Component uses the handleAction
method to process additional action from the PayPal pop-up window.
Optional: Validate the state.data
from the action component
In case the shopper is already redirected to the success page, you do not 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 webhooks 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.
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 thestate.data
field after you add theorderId
as well.
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 with400
HTTP result code and a default Adobe Commerce 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:
- The
action
field is present and is not empty, then handle the action using the Web Component.
{ "isFinal": false, "resultCode":"IdentifyShopper", "action":{"paymentData":"Ab02b4c0…"} }
Setting the payment state.data
in a separate request
Plugin v7.2.0 and later support setting the payment's state.data
by using the /adyen/stateData
endpoint. This is useful for checkout flows where this information cannot be sent using the /payment-information
Adobe Commerce REST API endpoint.
The /adyen/stateData
endpoint receives the following parameters:
Parameter | Description |
---|---|
state_data | state.data from the Web Component. |
quote_id | The ID of the Adobe Commerce quote related to state.data . |
state.data
saved with this endpoint is used in the payment request if no state.data
was supplied in the /payment-information
request.
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 that you select the API version that the Adobe Commerce plugin uses. Check the library and API versions you are using.
Checking library and API versions
The Adobe Commerce 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 Adobe Commerce 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 is still missing then:
-
Go to the Adyen Adobe Commerce (formerly Magento 2) plugin on GitHub. In the Branch dropdown, on the Tags tab, select the version of your Adobe Commerce plugin.
-
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"
. -
Go to the Adyen PHP library. In the Branch dropdown, on the Tags tab, select the library version you have just found.
-
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"
.