SumUp payment provider for Medusa v2.
This plugin lets a Medusa application create and manage SumUp online checkouts from the backend. It supports:
- Hosted Checkout, where the customer is redirected to SumUp's hosted payment page.
- Payment Widget, where the storefront mounts SumUp's card widget with the checkout created by Medusa.
- Refunds through SumUp transactions.
- Medusa's built-in payment webhook route for asynchronous status updates.
The plugin never handles raw card data directly. SumUp credentials remain on the Medusa backend.
- Medusa v2.15.x
- SumUp online checkout flows
yarn add @sumup/medusa-pluginRegister the plugin and payment provider in medusa-config.ts:
import { defineConfig } from "@medusajs/framework/utils"
export default defineConfig({
plugins: [
{
resolve: "@sumup/medusa-plugin",
options: {},
},
],
modules: [
{
resolve: "@medusajs/medusa/payment",
options: {
providers: [
{
resolve: "@sumup/medusa-plugin/providers/sumup",
id: "sumup",
options: {
apiKey: process.env.SUMUP_API_KEY,
merchantCode: process.env.SUMUP_MERCHANT_CODE,
checkoutMode: "hosted",
returnUrl: `${process.env.MEDUSA_BACKEND_URL}/hooks/payment/sumup_sumup`,
redirectUrl: `${process.env.STOREFRONT_URL}/checkout/sumup/return`,
},
},
],
},
},
],
})After the application starts, enable the provider for the relevant region in Medusa Admin. Per Medusa's payment-provider model, the resulting provider identifier is pp_sumup_sumup when the service identifier is sumup and the configured provider id is sumup.
| Option | Required | Description |
|---|---|---|
apiKey |
Yes | SumUp API key or access token. Keep it server-side. |
merchantCode |
Yes | SumUp merchant code that receives the payment. |
checkoutMode |
No | Default checkout mode: hosted or widget. Defaults to hosted. |
returnUrl |
No | Backend webhook URL. For provider id: "sumup", use /hooks/payment/sumup_sumup. |
redirectUrl |
No | Storefront URL used after redirect or Strong Customer Authentication flows. |
paymentDescription |
No | Default SumUp checkout description. |
timeout |
No | SumUp SDK request timeout in milliseconds. |
maxRetries |
No | SumUp SDK retry count. |
You can override checkout_mode, description, return_url, redirect_url, and checkout_reference per payment session through provider data.
With checkoutMode: "hosted", the plugin creates a SumUp checkout with Hosted Checkout enabled. Medusa stores the returned hosted_checkout_url in the payment-session data. The storefront should redirect the customer to that URL.
Use backend state as the source of truth. The storefront should not treat the redirect alone as proof of payment success.
With checkoutMode: "widget", the plugin creates a SumUp checkout without Hosted Checkout enabled. Medusa stores the returned checkout_id in the payment-session data. The storefront is then responsible for:
- Loading SumUp's widget SDK.
- Mounting the widget with the checkout ID.
- Asking the backend to re-check the payment state after widget success.
Minimal storefront snippets are available in examples/nextjs/README.md.
Medusa provides a built-in webhook listener route for payment providers at:
/hooks/payment/[identifier]_[provider]
For this plugin, with service identifier sumup and provider id: "sumup", the webhook URL is:
https://your-medusa-backend.com/hooks/payment/sumup_sumup
The plugin's getWebhookActionAndData implementation follows Medusa's payment-webhook flow: it receives the webhook payload, retrieves the checkout from SumUp, maps the result to a Medusa payment action, and returns the payment session reference back to Medusa.
The payment-session data returned by the provider includes:
checkout_idcheckout_referencecheckout_modehosted_checkout_urlfor hosted flowstransaction_idandtransaction_codewhen availablemerchant_codeamountandcurrency
authorizePaymentchecks the remote SumUp checkout status rather than performing a separate authorization step.capturePaymentdoes not trigger a separate capture API call. It only succeeds once the SumUp checkout is already paid.- If the amount or currency changes before payment,
updatePaymentdeactivates the old checkout and creates a replacement checkout. - Refunds require a successful SumUp transaction.
- The plugin is built for SumUp online payments, not terminal or card-present flows.
- Verify one successful Hosted Checkout payment.
- Verify one successful Payment Widget payment.
- Verify at least one webhook-driven payment update.
- Verify one full refund and one partial refund.
- Test SumUp's deliberate failure path with amount
11. - Verify expired or canceled checkouts map cleanly back into Medusa session state.
- Consumer storefront snippets: examples/nextjs/README.md
- Local end-to-end playground: examples/docker/README.md
Maintainer and release workflow documentation lives in CONTRIBUTING.md.