Overview
Payments puts eleven payment systems — Stripe, Adyen, PayPal, Mollie, Square, Braintree, GoCardless, Checkout.com, Coinbase Commerce, bank transfer and pay-later — behind one contract, and serves a hosted checkout page so a storefront needs no provider code at all. The storefront asks which providers to offer and gets a session; the provider's own client renders cards, Apple Pay, Google Pay, iDEAL, Klarna and the rest with 3-D Secure handled by the provider; the plugin re-reads the result from the provider (amount, currency, order code) before Vendure records the payment. Automatic or manual capture, partial captures and refunds, disputes, saved cards, subscriptions, pay-by-link, routing rules and surcharges work the same way on every provider, and everything lands in one ledger with a dashboard under Sales → Payments.
Install & configure
yarn add @huloglobal/vendure-plugin-payments
import { HuloPaymentsPlugin } from '@huloglobal/vendure-plugin-payments';
plugins: [
HuloPaymentsPlugin.init({
publicBaseUrl: 'https://shop.example.com', // webhook + return URLs
licenceKey: process.env.HULO_LICENCE_KEY_PAYMENTS, // optional — or activate in the admin
ops: { email: '[email protected]', webhookUrl: process.env.OPS_SLACK_WEBHOOK },
}),
]
Add HuloPaymentsPlugin.uiExtensions to compileUiExtensions and recompile the admin UI. Tables are created on boot. The plugin adds three custom fields to ProductVariant for subscriptions, so installs that use migrations need one: npx vendure migrate.
Connecting a provider
Open Sales → Payments → Providers and click Connect on a provider card. Paste the keys from its dashboard (each card links to the exact page), click Test connection to see which account they belong to, then Connect. The plugin verifies the keys with the provider, registers the webhook through the provider's API and stores the signing secret, and creates the Vendure payment method on the channel you chose. Mollie needs no webhook setup; Adyen creates the webhook and HMAC key when the API credential has the Management API webhook role, otherwise the card tells you exactly what to add by hand.
| Provider | What to paste | Where it comes from |
|---|---|---|
| Stripe | Secret key, publishable key | Dashboard → Developers → API keys (test or live pair) |
| Adyen | API key, merchant account, client key, live URL prefix (live only) | Customer Area → Developers → API credentials; Account → Merchant accounts |
| PayPal | Client ID, client secret | developer.paypal.com → Apps & Credentials → REST app |
| Mollie | API key | Dashboard → Developers → API keys |
| Square | Access token, application ID, location ID | developer.squareup.com → your app → Credentials / Locations |
| Braintree | Merchant ID, public key, private key | Control Panel → Settings → API |
| GoCardless | Access token (+ webhook secret) | Dashboard → Developers → Access tokens / Webhook endpoints |
| Checkout.com | Secret key, public key, processing channel ID | Dashboard → Developers → Keys; Settings → Channels |
| Coinbase Commerce | API key (+ webhook shared secret) | Settings → Security / Notifications |
| Bank transfer | Account name, sort code / account number or IBAN | Your bank |
| Pay later | Payment terms in days | — |
Prefer the standard route? Settings → Payment methods → Create and pick the handler HULO Payments — Stripe / Adyen / PayPal / Mollie; every field explains where its value comes from. Attach the HULO Payments rules eligibility checker to any method to limit it by order total, currency, country, customer group or signed-in customers.
Hosted checkout page (simplest)
mutation { huloHostedCheckout(returnUrl: "https://shop.example.com/checkout/return", cancelUrl: "https://shop.example.com/checkout") { url expiresAt } }
Redirect the customer to url. The page lists every enabled method in the order set under Settings, drives each provider's own client (cards, wallets, redirects, bank-transfer instructions), records the payment through Vendure and sends the customer back to returnUrl?order=CODE&result=paid|pending. Brand it (shop name, colour, logo) under Settings → Hosted checkout page. Links are single-use and expire after two hours.
Embedded integration (advanced)
# 1. Providers to offer for the active order (preferred first)
query { huloPaymentProviders { methodCode provider name publicConfig capabilities surcharge preferred } }
# 2. A session for the active order
mutation { huloCreatePaymentSession(methodCode: "stripe", options: { returnUrl: "https://shop.example.com/checkout/return" }) {
provider clientSecret sessionId sessionData checkoutUrl publicKey environment config amount currency } }
# 3. After the provider's client reports success — the normal Vendure step
mutation { addPaymentToOrder(input: { method: "stripe", metadata: { paymentIntentId: "pi_…" } }) { ... on Order { state } ... on ErrorResult { message } } }
| Provider | Client | metadata for addPaymentToOrder |
|---|---|---|
| Stripe | Payment Element with clientSecret | { paymentIntentId } |
| Adyen | Drop-in with sessionId + sessionData | { sessionId, sessionResult } |
| PayPal | Buttons, createOrder: () => sessionId | { paypalOrderId } |
| Mollie | Redirect to checkoutUrl | { molliePaymentId } |
Also available: huloSavedPaymentMethods, huloRemoveSavedPaymentMethod, huloMySubscriptions, huloCancelSubscription and huloApplyPaymentSurcharge.
Subscriptions
Set Subscription billing interval (daily / weekly / monthly / yearly), optionally every N intervals and free trial days, on a product variant. Its price is the price per period. When an order containing it is paid through a HULO method the plugin creates the subscription: Stripe, PayPal and Mollie bill natively; Adyen renewals are charged hourly by the plugin's scheduler from the stored card. Failed renewals mark the subscription past due, alert ops and cancel after the number of failed daily attempts set in Settings. Customers see and cancel their subscriptions through the shop API; admins pause, resume and cancel from the Subscriptions tab, which also shows MRR.
Pay by link
From the Pay by link tab, enter any order code that still needs payment — a draft order built in the admin, an accepted quotation, a phone order — pick a provider and an expiry, and copy the link. The customer pays on the provider's hosted page and the webhook moves the order to PaymentSettled.
Admin UI
Sales → Payments: Overview (volume by day and provider, success rate, refunds, disputes, subscriptions), Transactions (the ledger, filterable by kind, status and order), Subscriptions, Pay by link, Providers (Connect, capabilities, webhook URLs, recent webhook deliveries) and Settings (provider order and fallback, saved cards, surcharges, ops email, dunning), plus the Licence & billing card. Refunds are issued from the order page as usual and appear in the ledger automatically.
Licensing & tiers
Free tier: Stripe (sessions, wallets, 3-D Secure, captures, refunds, disputes, signed webhooks), the ledger, the dashboard and the rules checker. Adyen, PayPal, Mollie, subscriptions, saved cards, pay-by-link, provider routing and surcharges require a licence. Unlicensed installs run everything for 14 days; start the card-backed trial or buy from the admin banner.
Troubleshooting
- Payment shows Authorized but never Settled: for automatic-capture methods that means the provider is still processing or the webhook is not arriving — check the Providers tab's webhook log and the endpoint in the provider dashboard. Manual-capture payments are settled from the order page.
- Webhook returns 400 "signature mismatch": the secret on the payment method is not the one for that endpoint. Reconnect the provider from the Providers tab; it re-registers the webhook and stores the fresh secret.
- Webhook returns 404 "no enabled … payment method": the method for that provider is disabled or missing on every channel.
- Adyen payment stays Authorized with transaction "adyen-session:…": the AUTHORISATION webhook has not been received yet; it carries the pspReference and settles immediate-capture methods.
- Subscription never created: subscriptions need a licence, the variant needs a billing interval, and the first payment must have gone through a HULO method that supports subscriptions.