Overview
Icon for Juspay Hyperswitch

Juspay Hyperswitch

Unify payment providers with Juspay Hyperswitch

@juspay-tech/medusa-custom-payments

Custom payments provider plugin for Medusa v2. Enables payment processing through multiple connectors — Stripe, Adyen, PayPal, GlobalPay, Braintree, Cybersource, and Mollie — via a single Prism-powered provider.

Powered by Hyperswitch Prism, an open-source unified connector service (UCS) that abstracts connector-specific APIs behind a single interface.

Compatibility

Requirement Version Medusa Copy to clipboard>= 2.15.0 Node.js Copy to clipboard>= 20 Framework Medusa v2

Installation

npm install @juspay-tech/medusa-custom-payments

Setup

1. Environment variables

# Stripe
STRIPE_API_KEY=sk_test_...
# Adyen
ADYEN_API_KEY=AQE...
ADYEN_MERCHANT_ACCOUNT=YourMerchantAccount
ADYEN_WEBHOOK_SECRET=... # hex HMAC key — required for webhook processing
# PayPal
PAYPAL_CLIENT_ID=...
PAYPAL_CLIENT_SECRET=...
PAYPAL_WEBHOOK_ID=... # webhook ID — required for webhook processing
# GlobalPay
GLOBALPAY_APP_ID=...
GLOBALPAY_APP_KEY=...

2. Register providers in Copy to clipboardmedusa-config.ts

import { defineConfig, Modules } from "@medusajs/framework/utils"
export default defineConfig({
modules: [
{
key: Modules.PAYMENT,
resolve: "@medusajs/payment",
options: {
providers: [
{
resolve: "@juspay-tech/medusa-custom-payments",
id: "stripe",
options: {
connector: "stripe",
connectorConfig: {
apiKey: { value: process.env.STRIPE_API_KEY ?? "" },
// Publishable key (not a secret) — surfaced in the payment
// session as `publishableKey` for the storefront's Elements.
publishableKey: process.env.STRIPE_PUBLISHABLE_KEY ?? "",
},

3. Assign providers to regions

In the Medusa Admin, assign each provider to the regions where it should be available.

4. Switch to production

Change Copy to clipboardenvironment per provider when going live:

environment: process.env.NODE_ENV === "production" ? "PRODUCTION" : "SANDBOX",

5. Start the backend

npx medusa develop

Plugin Options

Option Type Required Default Description Copy to clipboardconnector Copy to clipboardstring Yes — Copy to clipboard"stripe", Copy to clipboard"adyen", Copy to clipboard"paypal", Copy to clipboard"globalpay", Copy to clipboard"braintree", Copy to clipboard"cybersource", Copy to clipboard"mollie" Copy to clipboardconnectorConfig Copy to clipboardobject Yes — Connector-specific credentials (see examples above) Copy to clipboardenvironment Copy to clipboardstring No Copy to clipboard"SANDBOX" Copy to clipboard"SANDBOX" or Copy to clipboard"PRODUCTION" Copy to clipboardcapture Copy to clipboardboolean No Copy to clipboardfalse Auto-capture on authorization

Connector Credentials Reference

Connector Required fields in Copy to clipboardconnectorConfig Copy to clipboardstripe Copy to clipboardapiKey, Copy to clipboardpublishableKey (optional — surfaced to the storefront) Copy to clipboardadyen Copy to clipboardapiKey, Copy to clipboardmerchantAccount, Copy to clipboardpublishableKey (optional Adyen client key — surfaced to the storefront) Copy to clipboardpaypal Copy to clipboardclientId, Copy to clipboardclientSecret, Copy to clipboardshippingPreference (optional) Copy to clipboardglobalpay Copy to clipboardappId, Copy to clipboardappKey Copy to clipboardbraintree Copy to clipboardpublicKey, Copy to clipboardprivateKey Copy to clipboardcybersource Copy to clipboardapiKey, Copy to clipboardmerchantAccount, Copy to clipboardapiSecret Copy to clipboardmollie Copy to clipboardapiKey

Each credential value is provided as Copy to clipboard{ value: string } to support secret manager integrations.

Connector Support Matrix

Connector Authorize Capture Void Refund Webhook Copy to clipboardadyen ✅ ✅ ✅ ✅ ✅ Copy to clipboardpaypal — ✅ ✅ ✅ ✅ Copy to clipboardstripe ✅ ✅ ✅ ✅ ○ Copy to clipboardglobalpay — ✅ ✅ ✅ ○ Copy to clipboardbraintree ✅ ✅ ✅ ✅ ○ Copy to clipboardcybersource ✅ ✅ ✅ ✅ ○ Copy to clipboardmollie ✅ ✅ ✅ ✅ ○

Legend

Symbol Meaning ✅ Supported ○ Not supported — state driven by synchronous flows — Not a separate step: connector captures funds immediately at authorize time (Copy to clipboardCaptureMethod.AUTOMATIC); payment goes straight to CAPTURED so only Refund is available afterward

Authorize result by connector

  • Copy to clipboardadyen, Copy to clipboardstripe, Copy to clipboardbraintree, Copy to clipboardcybersource, Copy to clipboardmollie → payment lands as AUTHORIZED (funds reserved; Capture or Void available next)
  • Copy to clipboardpaypal, Copy to clipboardglobalpay → payment lands as CAPTURED (funds collected immediately; Refund only)
Note: All flows in the matrix above are tested and verified under the sandbox / test environment of each connector. Production behavior should be validated separately before go-live.

Webhooks

All webhook processing goes through the hyperswitch-prism connector service (Copy to clipboardEventService.HandleEvent) — this provider contains no connector-specific webhook parsing or signature code.

Webhook URL pattern:

  • Medusa: Copy to clipboard{backend_url}/hooks/payment/{provider_id}

Connector Webhook events Source verification Copy to clipboardwebhookSecret value Copy to clipboardadyen payment + refund HMAC-SHA256 Hex HMAC key from Customer Area → Webhooks → Additional settings (required) Copy to clipboardpaypal payment + refund + dispute PayPal Copy to clipboardverify-webhook-signature API Webhook ID from the developer dashboard (required) Copy to clipboardstripe, Copy to clipboardglobalpay, Copy to clipboardbraintree, Copy to clipboardcybersource, Copy to clipboardmollie not supported — unused

For unsupported connectors, incoming webhooks are acknowledged and ignored (Copy to clipboardNOT_SUPPORTED); payment state is driven by the synchronous flows (Copy to clipboardauthorizePayment / Copy to clipboardgetPaymentStatus).

Verification is mandatory

Webhook events that cannot be source-verified are always rejected — in development and production alike. There is no bypass option:

  • Without a configured Copy to clipboardwebhookSecret, adyen/paypal webhooks are rejected before reaching the connector service.
  • An event whose signature fails verification (wrong key, tampered payload, forged request) is acknowledged but never mapped to a payment action.

Setup

Adyen — in the Customer Area create a Standard webhook pointing at your webhook URL, generate an HMAC key under Additional settings, and configure it (hex string, exactly as displayed) as Copy to clipboardwebhookSecret. Set Copy to clipboardADYEN_WEBHOOK_SECRET in your environment.

PayPal — in the developer dashboard create a webhook for your app pointing at your webhook URL, then configure the generated webhook ID as Copy to clipboardwebhookSecret. Set Copy to clipboardPAYPAL_WEBHOOK_ID in your environment.

Configuration example

The webhook URL is derived from the provider Copy to clipboardid you set in Copy to clipboardmedusa-config.ts. With Copy to clipboardidentifier = "hyperswitch-prism", a provider registered as Copy to clipboardid: "adyen" is reachable at:

{backend_url}/hooks/payment/hyperswitch-prism_adyen

1. Add the secrets to your environment

# Adyen — hex HMAC key from Customer Area → Developers → Webhooks → Additional settings
ADYEN_WEBHOOK_SECRET=AB12CD34EF...
# PayPal — webhook ID from the developer dashboard
PAYPAL_WEBHOOK_ID=WH-1AB23456CD789...

2. Pass Copy to clipboardwebhookSecret in the provider options (Copy to clipboardmedusa-config.ts)

{
resolve: "@juspay-tech/medusa-custom-payments",
id: "adyen",
options: {
connector: "adyen",
connectorConfig: {
apiKey: { value: process.env.ADYEN_API_KEY ?? "" },
merchantAccount: { value: process.env.ADYEN_MERCHANT_ACCOUNT ?? "" },
},
webhookSecret: process.env.ADYEN_WEBHOOK_SECRET, // required for webhook processing
environment: "SANDBOX",
},
},
{
resolve: "@juspay-tech/medusa-custom-payments",
id: "paypal",
options: {
connector: "paypal",
connectorConfig: {
clientId: { value: process.env.PAYPAL_CLIENT_ID ?? "" },

3. Register the URL at the connector dashboard

Connector Provider Copy to clipboardid Webhook URL to register Adyen Copy to clipboardadyen Copy to clipboard{backend_url}/hooks/payment/hyperswitch-prism_adyen PayPal Copy to clipboardpaypal Copy to clipboard{backend_url}/hooks/payment/hyperswitch-prism_paypal

Local development — connector dashboards must reach your backend over the public internet. Expose your local server with a tunnel (e.g. Copy to clipboardngrok http 9000) and register the tunnel URL, for example Copy to clipboardhttps://abcd-1234.ngrok.io/hooks/payment/hyperswitch-prism_adyen.

The connector is taken from each provider's Copy to clipboardconnector

Note: Adyen refunds are asynchronous — the REFUND webhook is the settlement confirmation and is logged by the provider (Medusa has no refund webhook action, so it is acknowledged as Copy to clipboardNOT_SUPPORTED).

Test Cards

Stripe

Card Number Expiry CVV Copy to clipboard4242 4242 4242 4242 Copy to clipboard03/2030 Copy to clipboard737

Adyen

Card Number Expiry CVV Copy to clipboard4111 1111 4555 1142 Copy to clipboard03/2030 Copy to clipboard737

GlobalPay

Card Number Expiry CVV Copy to clipboard4263 9700 0000 5262 Copy to clipboard03/2030 Copy to clipboard737

PayPal

Card Number Expiry CVV Copy to clipboard4032 0366 9170 5063 Copy to clipboard10/2028 Copy to clipboard901

Storefront Integration

For React/Next.js storefront integration, see the companion package Copy to clipboard@juspay-tech/medusa-custom-payments-react.

License

Apache-2.0

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?