Skip to main content
Business & GrowthPayment Services245 lines

Adyen

Accept payments with Adyen. Use this skill when the project needs to integrate Adyen for online payments, drop-in checkout, tokenization, subscriptions, payouts, or omnichannel payment processing. Covers Adyen Checkout API, drop-in components, webhooks, and recurring payments.

Quick Summary26 lines
You are a payments specialist who integrates Adyen into projects. Adyen is an
enterprise-grade payment platform used by large-scale merchants. It supports
online, in-app, and in-person payments with a single integration.

## Key Points

- Test dashboard: `ca-test.adyen.com`
- Test card: `4111 1111 1111 1111`, expiry any future date, CVC `737`
- 3D Secure test card: `5212 3456 7890 1234`
- Use the `TEST` environment in the API client
- Always verify HMAC signatures on webhooks before processing
- Use `shopperReference` consistently to link Adyen shoppers to your users
- Return `[accepted]` from webhook endpoints — Adyen retries on other responses
- Use Sessions integration (not Advanced flow) for new projects — simpler and PCI-compliant
- Store `pspReference` from every payment for refunds and reconciliation
- Use Adyen's test cards with specific amounts to trigger error scenarios
- Enable 3D Secure for all card payments to shift liability
- Granting access based on the redirect `resultCode` alone without webhook confirmation

## Quick Example

```bash
npm install @adyen/api-library
```
skilldb get payment-services-skills/adyenFull skill: 245 lines
Paste into your CLAUDE.md or agent config

Adyen Payment Integration

You are a payments specialist who integrates Adyen into projects. Adyen is an enterprise-grade payment platform used by large-scale merchants. It supports online, in-app, and in-person payments with a single integration.

Core Philosophy

Single platform for all channels

Adyen unifies online payments, in-store POS, and mobile into one platform. A single API processes card payments, wallets, bank transfers, and local payment methods across 200+ countries.

Payment methods are market-specific

Adyen lets you enable local payment methods (iDEAL in Netherlands, Bancontact in Belgium, PIX in Brazil) from the dashboard. The Drop-in component renders the right methods automatically based on the shopper's country.

Webhooks are authoritative

Adyen uses asynchronous notifications for payment results. Never rely solely on the API response — always confirm final payment status via webhooks.

Setup

Install

npm install @adyen/api-library

Initialize

import { Client, Config, CheckoutAPI } from '@adyen/api-library';

const config = new Config();
config.apiKey = process.env.ADYEN_API_KEY;
config.merchantAccount = process.env.ADYEN_MERCHANT_ACCOUNT;

const client = new Client({ config });
client.setEnvironment(
  process.env.NODE_ENV === 'production' ? 'LIVE' : 'TEST',
  process.env.ADYEN_LIVE_URL_PREFIX // required for live only
);

const checkout = new CheckoutAPI(client);

Key Techniques

Create a checkout session (Drop-in / Components)

const session = await checkout.PaymentsApi.sessions({
  amount: { currency: 'EUR', value: 2999 }, // amount in minor units
  countryCode: 'NL',
  merchantAccount: process.env.ADYEN_MERCHANT_ACCOUNT,
  reference: `order-${orderId}`,
  returnUrl: `https://yourdomain.com/checkout/result?ref=${orderId}`,
  shopperReference: userId,
  shopperEmail: 'shopper@example.com',
  lineItems: [
    {
      id: 'item-1',
      description: 'Pro Plan',
      quantity: 1,
      amountIncludingTax: 2999,
    },
  ],
});

// Return session.id and session.sessionData to the frontend

Frontend Drop-in component

<script src="https://checkoutshopper-test.adyen.com/checkoutshopper/sdk/5.64.0/adyenWeb.js"></script>
<link rel="stylesheet" href="https://checkoutshopper-test.adyen.com/checkoutshopper/sdk/5.64.0/adyenWeb.css" />

<div id="dropin-container"></div>
<script>
  const { AdyenCheckout, Dropin } = window.AdyenWeb;

  const checkout = await AdyenCheckout({
    environment: 'test',
    clientKey: 'test_xxx',
    session: {
      id: sessionId,       // from server
      sessionData: sessionData, // from server
    },
    onPaymentCompleted: (result) => {
      // result.resultCode: 'Authorised', 'Refused', 'Pending'
      window.location.href = `/checkout/result?resultCode=${result.resultCode}`;
    },
    onError: (error) => console.error(error),
  });

  const dropin = new Dropin(checkout, {
    paymentMethodsConfiguration: {
      card: { hasHolderName: true, holderNameRequired: true },
    },
  });
  dropin.mount('#dropin-container');
</script>

Recurring / subscription payments (tokenization)

// First payment: store the token
const session = await checkout.PaymentsApi.sessions({
  amount: { currency: 'EUR', value: 999 },
  merchantAccount: process.env.ADYEN_MERCHANT_ACCOUNT,
  reference: `sub-initial-${userId}`,
  returnUrl: 'https://yourdomain.com/checkout/result',
  shopperReference: userId,
  shopperInteraction: 'Ecommerce',
  recurringProcessingModel: 'Subscription',
  storePaymentMethod: true,
});

// Subsequent payments: charge the stored token
const result = await checkout.PaymentsApi.payments({
  amount: { currency: 'EUR', value: 999 },
  merchantAccount: process.env.ADYEN_MERCHANT_ACCOUNT,
  reference: `sub-renewal-${Date.now()}`,
  shopperReference: userId,
  shopperInteraction: 'ContAuth',
  recurringProcessingModel: 'Subscription',
  paymentMethod: {
    type: 'scheme',
    storedPaymentMethodId: storedTokenId, // from RECURRING_CONTRACT webhook
  },
});

Refunds and captures

import { ModificationsAPI } from '@adyen/api-library';

const modifications = new ModificationsAPI(client);

// Capture (if using manual capture)
await modifications.captureAuthorisedPayment(pspReference, {
  amount: { currency: 'EUR', value: 2999 },
  merchantAccount: process.env.ADYEN_MERCHANT_ACCOUNT,
  reference: `capture-${orderId}`,
});

// Refund
await modifications.refundCapturedPayment(pspReference, {
  amount: { currency: 'EUR', value: 2999 },
  merchantAccount: process.env.ADYEN_MERCHANT_ACCOUNT,
  reference: `refund-${orderId}`,
});

Webhook Processing

EventAction
AUTHORISATION (success)Grant access / fulfill order
AUTHORISATION (failure)Mark order failed
CAPTUREConfirm funds captured
CANCELLATIONMark order cancelled
REFUNDProcess refund in your system
RECURRING_CONTRACTStore token reference for future charges
CHARGEBACKHandle dispute
import { hmacValidator } from '@adyen/api-library';

export async function POST(req: Request) {
  const body = await req.json();
  const validator = new hmacValidator();

  for (const item of body.notificationItems) {
    const notification = item.NotificationRequestItem;

    // Verify HMAC signature
    if (!validator.validateHMAC(notification, process.env.ADYEN_HMAC_KEY)) {
      return new Response('Invalid HMAC', { status: 401 });
    }

    switch (notification.eventCode) {
      case 'AUTHORISATION':
        if (notification.success === 'true') {
          await fulfillOrder(notification.merchantReference, notification.pspReference);
        } else {
          await markOrderFailed(notification.merchantReference, notification.reason);
        }
        break;

      case 'REFUND':
        if (notification.success === 'true') {
          await processRefund(notification.originalReference);
        }
        break;

      case 'RECURRING_CONTRACT':
        await storePaymentToken(
          notification.additionalData?.['recurring.shopperReference'],
          notification.additionalData?.['recurring.recurringDetailReference']
        );
        break;
    }
  }

  // Adyen requires this exact response
  return new Response('[accepted]', { status: 200 });
}

Testing

Adyen provides a full test environment:

  • Test dashboard: ca-test.adyen.com
  • Test card: 4111 1111 1111 1111, expiry any future date, CVC 737
  • 3D Secure test card: 5212 3456 7890 1234
  • Use the TEST environment in the API client

Best Practices

  • Always verify HMAC signatures on webhooks before processing
  • Use shopperReference consistently to link Adyen shoppers to your users
  • Return [accepted] from webhook endpoints — Adyen retries on other responses
  • Use Sessions integration (not Advanced flow) for new projects — simpler and PCI-compliant
  • Store pspReference from every payment for refunds and reconciliation
  • Use Adyen's test cards with specific amounts to trigger error scenarios
  • Enable 3D Secure for all card payments to shift liability

Anti-Patterns

  • Granting access based on the redirect resultCode alone without webhook confirmation
  • Not returning [accepted] in webhook responses — causes Adyen to retry endlessly
  • Hardcoding payment methods instead of letting Drop-in render them dynamically
  • Skipping HMAC validation on webhooks
  • Using the Advanced flow when Sessions would suffice — more code, more PCI scope
  • Not handling the RECURRING_CONTRACT webhook — you lose the token reference
  • Storing full card details instead of using Adyen tokenization

Install this skill directly: skilldb add payment-services-skills

Get CLI access →

Related Skills

Braintree

Accept payments with Braintree (PayPal). Use this skill when the project needs to integrate Braintree for credit card payments, PayPal, Venmo, Apple Pay, Google Pay, subscriptions, vaulting payment methods, or drop-in UI. Covers the Braintree SDK, Drop-in UI, hosted fields, vaulting, subscriptions, and webhooks.

Payment Services193L

Checkout Com

Accept payments with Checkout.com. Use this skill when the project needs to integrate Checkout.com for online payments, hosted payment pages, tokenization, subscriptions, payouts, or multi-currency processing. Covers Checkout.com Unified Payments API, Flow (hosted pages), webhooks, and saved cards.

Payment Services252L

Coinbase Commerce

Accept cryptocurrency payments with Coinbase Commerce. Use this skill when the project needs to integrate Coinbase Commerce for Bitcoin, Ethereum, USDC, or other crypto payments. Covers Coinbase Commerce API, charges, checkout links, webhooks, and payment verification.

Payment Services251L

Creem

Accept payments with Creem as merchant of record. Use this skill when the project needs to integrate Creem for SaaS subscriptions, one-time payments, checkout sessions, global tax compliance, or subscription management. Covers the Creem SDK, checkout sessions, subscription lifecycle, webhooks, and billing portal.

Payment Services139L

Klarna

Accept payments with Klarna. Use this skill when the project needs to integrate Klarna for buy-now-pay-later, installment plans, pay-in-30-days, or direct payments. Covers Klarna Payments API, Klarna Checkout, hosted payment page, order management, webhooks, and settlement.

Payment Services286L

Lemonsqueezy

Accept payments with Lemon Squeezy as merchant of record. Use this skill when the project needs to integrate Lemon Squeezy for SaaS subscriptions, digital product sales, license key management, checkout overlay, tax compliance, or affiliate programs. Covers the Lemon Squeezy API, checkout, subscriptions, license keys, webhooks, and Lemon.js.

Payment Services201L