Overview
Icon for Adyen

Adyen

Accept payments with Adyen

Adyen Payment Provider

Table of Contents

  • Introduction
  • Installation and Setup
    • Install the Package
    • Configure the Plugin
    • Plugin Options
      • Required Options
      • Optional Options
  • Webhooks
    • Asynchronous Payment Operations
      • How the Plugin Handles This
      • Important Considerations
  • PCI Compliance Considerations
  • Development
    • Integration Tests
    • Example Storefront
    • Known Issues

Introduction

This plugin implements a Medusa payment provider for Adyen, delivering backend (payment server) integration for Adyen's Advanced flow. It handles server-side payment operations such as payment session creation, authorization, capture, refunds, and webhook processing.

The plugin is frontend-agnostic and compatible with any Advanced flow frontend implementation supported by Adyen, including Web Components, Drop-in, and custom integrations. A dedicated section with frontend code examples is provided below.

⚠️ Production Readiness: This plugin is not currently considered safe or ready for production use. Fundamental differences between Medusa's payment module design, which assumes synchronous payment operations, and Adyen's asynchronous payment protocol introduce challenges in maintaining accurate payment state synchronization. Additionally, the integration requires storing sensitive payment data on the Medusa server, which may pose PCI compliance risks. These issues are explained in more detail in the Webhooks and PCI Compliance Considerations sections.

⚠️ Version Compatibility: Due to its webhook workflow implementation, this plugin is brittle and tightly coupled to a specific Medusa version. There is no guarantee it will function correctly with other Medusa versions, as it relies on internal payment module methods to manipulate payment models. These methods and underlying models may change between Medusa releases, potentially breaking the plugin.

Installation and Setup

Install the Package

Install the plugin beta using npm (recommended for early adopters):

npm install @minimall.io/medusa-plugin-adyen@beta

Install a specific beta version (recommended for reproducible deployments):

npm install @minimall.io/medusa-plugin-adyen@0.0.1-beta.0

Install the latest stable release (will be available once a stable version is published to the Copy to clipboardlatest tag):

npm install @minimall.io/medusa-plugin-adyen

Configure the Plugin

Configure the Medusa Payment Module Options with the Adyen payment provider in your Medusa instance by updating the Copy to clipboardmedusa-config.ts file:

import { defineConfig } from '@medusajs/framework/utils'
export default defineConfig({
// ... other configurations
plugins: [
{
resolve: '@minimall.io/medusa-plugin-adyen',
options: {},
},
],
modules: [
{
resolve: '@medusajs/medusa/payment',
options: {
providers: [
{
resolve: '@minimall.io/medusa-plugin-adyen/providers/adyen',
id: 'adyen', // Your provider ID
options: {
apiKey: process.env.ADYEN_API_KEY,

Plugin Options

The following options are available for configuring the Adyen payment provider.

Required Options

  • Copy to clipboardapiKey (string): Your Adyen API key, used to authenticate API requests. See the Adyen documentation.
  • Copy to clipboardhmacKey (string): HMAC key used to validate webhook notifications. Required for secure webhook processing. See the Adyen documentation.
  • Copy to clipboardmerchantAccount (string): Your Adyen merchant account identifier. See the Adyen documentation.
  • Copy to clipboardliveEndpointUrlPrefix (string): Your live endpoint URL prefix. Required when using the live environment. See the Adyen documentation.

Optional Options

  • Copy to clipboardenvironment (string): The Adyen environment to use. Defaults to Copy to clipboardTEST. Set to Copy to clipboardLIVE for production. This must match the environment of your API credentials.
  • Copy to clipboardshopperInteraction (string): Shopper interaction type for payments. Refer to the Adyen documentation for available values and token creation.
  • Copy to clipboardrecurringProcessingModel (string): Recurring processing model for stored payment methods. Refer to the Adyen documentation for available values and token creation.
  • Copy to clipboardapiInitialRetryDelay (number): Initial delay, in milliseconds, before retrying failed API requests. Defaults to Copy to clipboard1000 (1 second).
  • Copy to clipboardapiMaxRetries (number): Maximum number of retry attempts for failed API requests. Defaults to Copy to clipboard3.

Note: Provider-level Copy to clipboardshopperInteraction and Copy to clipboardrecurringProcessingModel options override values specified in individual payment requests. If these options are not set at the provider level, the values from the payment request will be used.

Webhooks

Webhooks are a critical component of the Adyen payment provider integration. While the Medusa payment module assumes payment operations return definitive results synchronously, Adyen operates using an asynchronous model.

Asynchronous Payment Operations

When merchant infrastructure (a Medusa server) sends a payment operation API request to Adyen—such as authorization, cancellation, capture, or refund—Adyen typically responds only with an acknowledgement of receipt. It does not immediately indicate whether the operation succeeded or failed. The final outcome is delivered later via a webhook notification from Adyen to the Medusa server.

How the Plugin Handles This

To accommodate Medusa's synchronous assumptions, the plugin implements the following approach:

  1. Treats request acknowledgements as initial success states: When the Adyen API acknowledges a payment operation request with the response Copy to clipboardstatus field set to Copy to clipboardreceived, the plugin updates the payment (Copy to clipboardPayment) Copy to clipboarddata field to reflect the current response state and returns it, along with other relevant information, to the Medusa Payment Module to indicate a successful operation.
  2. Finalizes payment state via webhooks: When the corresponding webhook is received, the plugin's Adyen webhook workflow processes the notification and updates the final state of the relevant Medusa entities, including payment collections, payment sessions, payments, captures, refunds, and related records.

This approach helps keep Medusa's payment records synchronized with Adyen's actual payment states.

Important Considerations

Operations may initially appear successful but ultimately fail. A payment operation that is initially recorded as successful may later fail when the webhook notification is processed.

Currently, the plugin does not provide a notification mechanism to alert merchants when webhooks are received. As a result, the transaction's state must be determined by manually inspecting the payment Copy to clipboarddata field in the order's JSON structure (Copy to clipboardpayment_collections[i].payments[j].data.events[k].status). The Copy to clipboardstatus field can have one of the following values: Copy to clipboardREQUESTED, Copy to clipboardFAILED, or Copy to clipboardSUCCEEDED. A Copy to clipboardstatus value of Copy to clipboardREQUESTED indicates that the operation request has been received by Adyen and corresponds to Adyen's response Copy to clipboardstatus value of Copy to clipboardreceived; however, the corresponding webhook has not yet been received. Merchants should rely on webhook-confirmed payment states when processing orders and must avoid taking irreversible actions until webhook notifications confirm that payment operations have completed successfully. While the plugin automatically synchronizes payment states, merchant business logic should explicitly wait for webhook confirmation before proceeding.

PCI Compliance Considerations

Adyen's Advanced flow expects the Copy to clipboard/payments Checkout API request (the payment authorization), which carries sensitive payment data, to originate from merchant infrastructure (a Medusa server). To ensure security, Adyen provides frontend-side encryption of sensitive payment data, which can be used when making the request.

However, Medusa's payment module Copy to clipboardauthorizePaymentSession method, which initiates payment authorization, does not accept frontend-provided Copy to clipboarddata value at the time of invocation. Instead, it retrieves and forwards the Copy to clipboarddata value already stored in the associated payment session (Copy to clipboardPaymentSession). This requires sensitive payment data to be present in the session's Copy to clipboarddata field prior to authorization.

Consequently, sensitive payment data must be transmitted from the frontend and stored on the Medusa server before authorization is initiated, through Medusa Payment Module APIs (for example, Copy to clipboardupdatePayment). This results in sensitive payment data persisting on the Medusa server, which may introduce PCI compliance risks.

To minimize the retention period of sensitive data, the plugin reacts upon receiving the first related webhook notification by overwriting the payment session Copy to clipboarddata field with values drawn from the corresponding payment (Copy to clipboardPayment) Copy to clipboarddata field, which do not contain payment details.

To improve the chances of PCI compliance clearance, it is highly advised to leverage Adyen's frontend encryption for sensitive payment data fields.

Development

Integration Tests

Integration tests depend on the following environment variables:

  • Copy to clipboardADYEN_PROVIDER_ID (required): Represents the Copy to clipboardid portion of the payment provider's unique identifier (Copy to clipboardpp_{identifier}_{id}). Payment module service calls used by the integration tests rely on this value. It must match the value defined in Copy to clipboardconfig.modules[i].options.providers[j].id within the Copy to clipboardmedusa-config.ts file.
  • Copy to clipboardADYEN_API_LIVE_TESTS (optional): A boolean flag that determines whether integration tests use live Adyen API endpoints. Set to Copy to clipboard'true' to use live endpoints, or Copy to clipboard'false' (or leave undefined) to use mocked responses. Using mocks is recommended for consistent and reliable testing.

Example Storefront

The Copy to clipboardexamples folder contains a Medusa storefront with Adyen integration. This example is based on the Medusa Next.js Starter Storefront and is not intended for production use. However, it can be useful for manual end-to-end testing of the plugin and as a reference for integrating Adyen payments into Medusa storefronts.

Known Issues

The Copy to clipboardBUGS.md file documents issues with Medusa that were encountered during plugin development. These include problems with the payment module's design, method implementations, and integration test infrastructure. The file also contains recommended fixes and workarounds for some of these issues.

You may also like

Browse all integrations

Build your own

Develop your own custom integration

Build your own integration with our API to speed up your processes. Make your integration available via npm for it to be shared in our Library with the broader Medusa community.

gift card interface

Ready to build your custom commerce setup?