Skip to content

Find a component

Loading the directory…

↑ ↓ to select · Enter to open · Esc to closeBrowse all →
Contributor login

Adyen Payments

Convex component for Adyen payments. Supports Drop-in checkout sessions, recurring card charges, and HMAC-validated webhooks.

Upstream source
git clone https://github.com/Abdssamie/adyen-payments.git
cd adyen-payments

This upstream package has not been adapted or qualified for Bijection. Read the original documentation before adopting it.

Description

Convex component for Adyen payments. Supports Drop-in checkout sessions, recurring card charges, and HMAC-validated webhooks.

Explore the package README for API concepts, configuration, and examples. Check the Bijection source for adaptation-specific setup.

Available to evaluate

Review the source and its dependencies before adopting this package. Source availability does not establish npm publication or runtime qualification.

Getting started

  1. Get the source at the revision above and read its package documentation.
  2. Check the required Bijection SDK version, dependencies, and external service credentials.
  3. Follow the package setup instructions and the guide to using components.
  4. Exercise the component in your deployment according to your project’s verification rules.

Open source

Maintained source: Abdssamie/adyen-payments. License: See repository. Consult the repository for license terms, notices, and contributor attribution.

From the upstream publisher

A adyen payments component for Convex.

Explore the demo ↗

Upstream overview

From the upstream package documentation.

Adyen Payments is a Convex component that integrates Adyen's payment infrastructure into your backend. It exposes server-side actions for creating Drop-in/Web Components checkout sessions, charging stored payment tokens for recurring billing, and modifying payments via capture, refund, or cancel. Incoming Adyen webhooks are verified using HMAC signatures and automatically update payment records in the component's internal database.

Use cases

From the upstream package documentation.

  • Building a checkout flow using Adyen's Drop-in or Web Components SDK where you need a backend session creation endpoint and automatic payment status tracking
  • Implementing subscription or recurring billing by charging stored card tokens (MIT/recurring) from a Convex action without re-engaging the shopper
  • Handling manual authorization workflows where you need to separately capture, refund, or cancel payments after the initial authorization
  • Receiving and validating Adyen webhook events to trigger downstream logic like sending receipts, updating order status, or recording invoices
  • Running Adyen in sandbox mode during development using the TEST environment variable before switching to LIVE for production

How it works

From the upstream package documentation.

After installing the package and registering it via app.use(adyenPayments) in convex/convex.config.ts, you instantiate an AdyenPayments client with your component reference and an optional autoCapture flag. This client exposes methods like createCheckoutSession, chargeStoredCard, capturePayment, refundPayment, and cancelPayment, all called from within Convex actions in your app's convex/ directory.

Checkout sessions return a sessionId and sessionData payload consumed directly by Adyen's frontend Drop-in or Web Components SDK. The component does not support hosted payment pages or Pay By Link. Recurring charges reference a recurringDetailReference token that Adyen creates when a shopper saves their payment details during an initial checkout session.

Webhook handling requires a "use node" action because HMAC signature verification depends on Node.js-native packages. You define a handler using createWebhookHandler, optionally passing event-specific callbacks under the events option for events like AUTHORISATION or CAPTURE. Each callback receives an enriched notification object with pre-resolved fields including shopperReference, metadata, and a normalized isSuccess boolean. The handler is then wired into Convex's HTTP router at the /adyen/webhooks path.

Required environment variables include ADYEN_API_KEY, ADYEN_MERCHANT_ACCOUNT, ADYEN_ENVIRONMENT, ADYEN_HMAC_KEY, and APP_URL, all configured in the Convex dashboard under Settings > Environment Variables.

Upstream package FAQ

What Adyen integration types does the Adyen Payments Convex component support?

The @abdssamie/adyen-payments component supports the Adyen Drop-in and Web Components SDK only. It does not support hosted checkout pages (HPP) or Pay By Link. The session response includes sessionId and sessionData for initializing the frontend SDK, and the url field is null for most merchant configurations.

What environment variables are required to configure the Adyen Payments component?

You need five environment variables set in your Convex dashboard: ADYEN_API_KEY for server-side API requests, ADYEN_MERCHANT_ACCOUNT for your merchant account code, ADYEN_ENVIRONMENT set to TEST or LIVE, ADYEN_HMAC_KEY for webhook signature validation, and APP_URL for your application base URL.

Why does the Adyen webhook handler need to run in a 'use node' context?

HMAC signature verification in the Adyen Payments component depends on Node.js-native packages. The createWebhookHandler function must be used inside a file marked 'use node' and wrapped in an internalAction. Your convex/http.ts router then delegates to this internal action via ctx.runAction.

How does autoCapture work in the Adyen Payments component?

When initializing AdyenPayments with autoCapture set to true (the default), authorized payments are captured immediately. Setting autoCapture to false enables manual capture, requiring you to call adyenClient.capturePayment with the pspReference, amount, and currency after authorization succeeds.

How do I install and register the Adyen Payments component in a Convex project?

Run npm install @abdssamie/adyen-payments, then import adyenPayments from @abdssamie/adyen-payments/convex.config.js and register it with app.use(adyenPayments) in your convex/convex.config.ts file. After that, initialize the client in your action files using new AdyenPayments(components.adyenPayments, options).

Use with agents and CLI

Give your coding agent the component’s source identity and setup guidance.

agent-prompt.md
Help me integrate Adyen Payments with Bijection.

Read: https://bijection.com/components/abdssamie-adyen-payments/SKILL.md

Check SDK compatibility and dependency availability.
Follow this project's execution and verification rules.

Upstream README.md

View repository ↗

Documentation from Abdssamie/adyen-payments, recorded October 23, 2026. APIs and setup may differ in the Bijection adaptation.

Convex Adyen Payments

A Convex component that integrates your application with Adyen Payments. It enables checkout sessions (supporting the Adyen Drop-in & Web Components SDK), secure payment tokenization for recurring billing, and automatic database updates via HMAC-validated webhooks.


Installation

Install the package in your project:

npm install @abdssamie/adyen-payments
# or
pnpm add @abdssamie/adyen-payments

Create or update your convex/convex.config.ts file to import and use the component:

// convex/convex.config.ts
import { defineApp } from "convex/server";
import adyenPayments from "@abdssamie/adyen-payments/convex.config.js";

const app = defineApp();
app.use(adyenPayments);

export default app;

Environment Variables & Dashboard Configuration

The component requires the following environment variables. Set them in your Convex dashboard under Settings > Environment Variables or locally in .env.local:

Environment VariableDescription
ADYEN_API_KEYServer-side API key for executing requests (e.g. AQEy...).
ADYEN_MERCHANT_ACCOUNTThe merchant account code (e.g. CompanyAccountECOM).
ADYEN_ENVIRONMENTSet to TEST for sandbox testing, or LIVE for production.
ADYEN_HMAC_KEYHMAC signature key for validating incoming webhook authenticity.
APP_URLBase URL of your app (e.g. https://myapp.com or http://localhost:3000).

How to Get Your Credentials from the Adyen Customer Area

1. Retrieve the Merchant Account Name

  1. Log in to the Adyen Customer Area (use sandbox for testing, live for production).
  2. Click the account switcher in the top-left corner.
  3. Toggle to your specific Merchant Account (which handles payments) rather than the Company Account (used for administration).
  4. Copy the unique account name/code. This is your ADYEN_MERCHANT_ACCOUNT.

2. Generate an API Key

  1. In the account switcher, select your Company Account level.
  2. In the sidebar, navigate to Developers > API credentials.
  3. Select your integration's web service user (typically starting with ws@Company.[YourCompanyAccount]).
  4. Under Server settings > Authentication, click the API key tab.
  5. Click Generate API key.
  6. Important: Copy this key immediately and store it securely. You cannot view it again once you navigate away. Click Save changes at the bottom of the page.

3. Set Up Webhooks & Generate an HMAC Key

  1. Select your specific Merchant Account in the switcher.
  2. Go to Developers > Webhooks in the sidebar.
  3. Click + Webhook on the top-right.
  4. Select Standard Webhook and click Add.
  5. Set the Server URL to your Convex deployment site endpoint (e.g., https://<your-deployment>.convex.site/adyen/webhooks).
  6. Scroll down to the Security tab and click Generate under the HMAC Key section.
  7. Copy the generated HMAC key. This is your ADYEN_HMAC_KEY.
  8. Ensure the webhook state is toggled to Active and click Save configuration.

Usage

To use the client, import AdyenPayments and initialize it with your registered component:

import { AdyenPayments } from "@abdssamie/adyen-payments";
import { components } from "./_generated/api";

const adyenClient = new AdyenPayments(components.adyenPayments, {
  autoCapture: true, // If true (default), capture immediately. Set false for manual capture.
});

1. Initializing Checkout

Create an action in your app's convex/ folder to initialize a payment checkout session. This provides the sessionId and configuration payload required by Adyen's frontend Drop-in/Components SDK.

import { action } from "./_generated/server";
import { v } from "convex/values";

export const startCheckout = action({
  args: {
    amount: v.number(), // Value in minor units (e.g., 1000 for $10.00)
    currency: v.string(), // e.g. "USD", "EUR"
    shopperReference: v.string(), // Unique shopper identifier
  },
  handler: async (ctx, args) => {
    const session = await adyenClient.createCheckoutSession(ctx, {
      amount: args.amount,
      currency: args.currency,
      successUrl: `https://myapp.com/checkout/success`,
      cancelUrl: `https://myapp.com/checkout/cancel`,
      shopperReference: args.shopperReference,
    });
    return session; // Returns { sessionId, sessionData, url? }
  },
});

Note: This component supports the Adyen Drop-in and Web Components SDK only. It does not support hosted checkout pages (HPP) or Pay By Link — the url field in the session response is optional and null for most merchant configurations.

2. Charging a Stored Card (Recurring / MIT)

When a shopper pays during checkout and consents to saving their payment details, Adyen stores a token. You can trigger recurring charges from a backend action:

export const chargeRecurring = action({
  args: {
    shopperReference: v.string(),
    recurringDetailReference: v.string(), // The stored card token
    amount: v.number(),
    currency: v.string(),
  },
  handler: async (ctx, args) => {
    return await adyenClient.chargeStoredCard(ctx, {
      shopperReference: args.shopperReference,
      recurringDetailReference: args.recurringDetailReference,
      amount: args.amount,
      currency: args.currency,
    });
  },
});

3. Payment Modifications (Manual Capture, Refund, Cancel)

If you configure autoCapture: false (manual capture), you must manually capture authorizations:

export const capture = action({
  args: { pspReference: v.string(), amount: v.number(), currency: v.string() },
  handler: async (ctx, args) => {
    return await adyenClient.capturePayment(ctx, args);
  },
});

export const refund = action({
  args: { pspReference: v.string(), amount: v.number(), currency: v.string() },
  handler: async (ctx, args) => {
    return await adyenClient.refundPayment(ctx, args);
  },
});

export const cancel = action({
  args: { pspReference: v.string() },
  handler: async (ctx, args) => {
    return await adyenClient.cancelPayment(ctx, args);
  },
});

Webhook Integration

Adyen webhooks require a Node.js context because signature verification depends on Node-native packages. Define the handler inside a "use node" file, and map it inside your http.ts router.

The events option in createWebhookHandler lets you register custom callback hooks. The notification object passed to these callbacks is automatically enriched with the following pre-resolved properties:

  • shopperReference: The unique shopper identifier (pre-resolved from the checkout session or previous payment records).
  • metadata: Custom metadata associated with the shopper/payment.
  • isSuccess: A pre-parsed boolean flag indicating if the event was successful (normalizing the raw string).

This makes it simple to integrate payment infrastructure operations like sending receipt emails, generating invoices, or updating custom app tables right inside the callback handlers.

1. Webhook Handler (convex/adyenWebhooks.ts)

"use node";

import { internalAction } from "./_generated/server";
import { components } from "./_generated/api";
import { createWebhookHandler } from "@abdssamie/adyen-payments";
import { v } from "convex/values";

// Create raw handler with custom hooks if needed
const rawHandler = createWebhookHandler(components.adyenPayments, {
  events: {
    AUTHORISATION: async (ctx, notification) => {
      if (notification.isSuccess) {
        console.log(`Payment authorized for shopper: ${notification.shopperReference}`);
        // Add custom code here: send emails, generate invoices, etc.
      }
    },
    CAPTURE: async (ctx, notification) => {
      if (notification.isSuccess) {
        console.log(`Payment captured: ${notification.pspReference} for shopper ${notification.shopperReference}`);
      }
    },
  },
});

export const handleWebhook = internalAction({
  args: { bodyText: v.string(), url: v.string() },
  handler: async (ctx, args) => {
    const request = new Request(args.url, {
      method: "POST",
      body: args.bodyText,
      headers: { "Content-Type": "application/json" },
    });

    const response = await rawHandler(ctx, request);
    if (!response.ok) {
      throw new Error(`Webhook error: ${response.status}`);
    }
    return await response.text();
  },
});

2. HTTP Routing (convex/http.ts)

import { httpRouter } from "convex/server";
import { httpAction } from "./_generated/server";
import { internal } from "./_generated/api";

const http = httpRouter();

http.route({
  path: "/adyen/webhooks",
  method: "POST",
  handler: httpAction(async (ctx, request) => {
    const bodyText = await request.text();
    try {
      const responseText = await ctx.runAction(
        internal.adyenWebhooks.handleWebhook,
        { bodyText, url: request.url }
      );
      return new Response(responseText, {
        status: 200,
        headers: { "Content-Type": "text/plain" },
      });
    } catch (err) {
      console.error("Webhook processing error:", err);
      return new Response("Webhook Error", { status: 400 });
    }
  }),
});

export default http;

Developing the Component

To contribute or make changes to the component repository itself, follow these steps to test and compile local changes:

# Install dependencies
pnpm install

# Run the dev watcher (recompiles the component and runs example backend)
pnpm dev

# Run unit tests
pnpm test

# Lint files
pnpm lint

Keywords