SumUp
Process payments in your store with SumUp
SumUp Payments for Medusa
A SumUp payment provider plugin for Medusa V2. Inspired by https://github.com/VariableVic/mollie-payments-medusa and mostly implemented by Claude.
[!WARNING] This plugin has not been tested on a live store. Please conduct thorough testing before using it in a production environment. I am not responsible for any missed or failed payments resulting from the use of this plugin. If you encounter any issues, please report them here.
Table of Contents
- Features
- Prerequisites
- Installation
- Configuration
- Configuration Options
- Environment Variables
- Usage
- Client-Side Integration
- License
Features
- SumUp Checkout: Creates a hosted SumUp checkout session that customers complete via the SumUp Card Widget or a custom card form.
- Webhook Support: Receives real-time checkout status updates via SumUp webhooks.
- Refunds: Supports full and partial refunds via the SumUp Transactions API.
- Amount verification: A PAID checkout only authorizes/captures the session it was created for — its amount and currency must match the ones stored in the session data.
- No extra dependencies: Uses the native Node.js Copy to clipboard
fetchAPI — no additional HTTP client needed.
Prerequisites
- Medusa server v2.3.0 or later
- Node.js v20 or later
- A SumUp merchant account with a valid API key and merchant code
[!NOTE] You can find your API key and merchant code in your SumUp Dashboard under Settings → Developer → API Keys.
Installation
123npm install medusa-payment-sumup# oryarn add medusa-payment-sumup
Configuration
Add the provider to the Copy to clipboard@medusajs/payment module in your Copy to clipboardmedusa-config.ts file:
1234567891011121314151617181920modules: [// ... other modules{resolve: "@medusajs/payment",options: {providers: [// ... other providers{resolve: "medusa-payment-sumup/providers/sumup",id: "sumup",options: {apiKey: process.env.SUMUP_API_KEY,merchantCode: process.env.SUMUP_MERCHANT_CODE,medusaUrl: process.env.MEDUSA_BACKEND_URL,redirectUrl: process.env.SUMUP_REDIRECT_URL,},},],},},
Configuration Options
Option Description Required Default Copy to clipboardapiKey Your SumUp API key (e.g. Copy to clipboardsup_sk_...) ✅ — Copy to clipboardmerchantCode Your SumUp merchant code (e.g. Copy to clipboardMXXXXXXX) ✅ — Copy to clipboardmedusaUrl The public URL of your Medusa backend ✅ — Copy to clipboardredirectUrl The default storefront URL to redirect the customer to after payment. Must be a valid Copy to clipboardhttp/Copy to clipboardhttps URL. ✅ — Copy to clipboardredirectUrlAllowedHosts Extra hostnames permitted when a payment session supplies its own Copy to clipboarddata.redirect_url. The host of Copy to clipboardredirectUrl is always allowed. Any override on a non-allowed host is rejected (open-redirect protection). ❌ Copy to clipboard[redirectUrl host] Copy to clipboarddebug Enable verbose debug logging ❌ Copy to clipboardfalse
Per-session redirect URL
A payment session may override the redirect target by passing Copy to clipboarddata.redirect_url (e.g. a locale-specific Copy to clipboardhttps://shop.example.com/us/checkout/complete). The override is accepted only when its host is the same as Copy to clipboardredirectUrl's host or appears in Copy to clipboardredirectUrlAllowedHosts, and its scheme is Copy to clipboardhttp/Copy to clipboardhttps; otherwise the checkout is rejected with Copy to clipboardINVALID_DATA. When omitted, Copy to clipboardredirectUrl is used.
[!IMPORTANT] The storefront's own origin must be an allowed redirect host. A typical storefront sends Copy to clipboarddata.redirect_url = \${location.origin}/${countryCode}/checkout/complete`Copy to clipboardon every payment session. If the storefront's domain is **not** the host of the backend's configuredredirectUrlCopy to clipboard**and** is not listed inredirectUrlAllowedHosts`, session creation fails and customers cannot pay.
This bites most often when the backend Copy to clipboardredirectUrlenv and the storefront domain drift apart between environments (e.g. a Copy to clipboard*.sslip.ioor preview deploy, or a separate admin vs. storefront domain). Whenever you add a storefront origin, add it to Copy to clipboardredirectUrlAllowedHosts. Example:
12345678options: {redirectUrl: "https://shop.example.com/checkout/complete",redirectUrlAllowedHosts: ["shop.example.com","staging.shop.example.com","my-preview.sslip.io",],}
Environment Variables
Add the following to your Copy to clipboard.env file:
1234SUMUP_API_KEY=sup_sk_your_api_keySUMUP_MERCHANT_CODE=YOUR_MERCHANT_CODEMEDUSA_BACKEND_URL=https://your-medusa-server.comSUMUP_REDIRECT_URL=https://your-store.com/checkout/payment
Usage
Once installed and configured, the SumUp payment method will be available in your Medusa Admin. To enable it:
- Log in to your Medusa Admin
- Go to Settings → Regions
- Add or edit a region and select SumUp from the payment providers dropdown
The provider ID for the SumUp checkout is:
1pp_sumup_sumup
Client-Side Integration
SumUp checkouts are created server-side by Medusa. After a payment session is initiated, the session data will contain a SumUp checkout Copy to clipboardid that you pass to the SumUp Card Widget on your storefront to render the payment form.
Basic flow:
- Customer reaches the payment step — Medusa creates a SumUp checkout via Copy to clipboard
initiatePayment - Your storefront receives the checkout Copy to clipboard
idfrom the payment session data - Render the SumUp Card Widget with the checkout ID
- SumUp processes the payment and calls the Medusa webhook (Copy to clipboard
/hooks/payment/sumup_sumup) - Because SumUp auto-captures, a Copy to clipboard
PAIDcheckout is reported to Medusa as captured at authorize time — the order's payment is marked captured immediately on completion, without waiting for the webhook. The webhook (which the plugin always re-verifies against the SumUp API, since SumUp webhooks are unsigned) acts as a backstop that reconciles status if the browser flow is interrupted.
Example Card Widget integration:
12345678910111213<script src="https://gateway.sumup.com/gateway/ecom/card/v2/sdk.js"></script><div id="sumup-card"></div><script>SumUpCard.mount({checkoutId: "<checkout-id-from-session-data>",onResponse: function (type, body) {if (type === "success") {// Redirect or poll for order completion}},});</script>
For APMs (iDEAL, Bancontact, etc.), the Copy to clipboardredirectUrl option handles the post-payment redirect automatically.
License
MIT

