HG Hulo Global

Payments — User Manual

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.

ProviderWhat to pasteWhere it comes from
StripeSecret key, publishable keyDashboard → Developers → API keys (test or live pair)
AdyenAPI key, merchant account, client key, live URL prefix (live only)Customer Area → Developers → API credentials; Account → Merchant accounts
PayPalClient ID, client secretdeveloper.paypal.com → Apps & Credentials → REST app
MollieAPI keyDashboard → Developers → API keys
SquareAccess token, application ID, location IDdeveloper.squareup.com → your app → Credentials / Locations
BraintreeMerchant ID, public key, private keyControl Panel → Settings → API
GoCardlessAccess token (+ webhook secret)Dashboard → Developers → Access tokens / Webhook endpoints
Checkout.comSecret key, public key, processing channel IDDashboard → Developers → Keys; Settings → Channels
Coinbase CommerceAPI key (+ webhook shared secret)Settings → Security / Notifications
Bank transferAccount name, sort code / account number or IBANYour bank
Pay laterPayment 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 } } }
ProviderClientmetadata for addPaymentToOrder
StripePayment Element with clientSecret{ paymentIntentId }
AdyenDrop-in with sessionId + sessionData{ sessionId, sessionResult }
PayPalButtons, createOrder: () => sessionId{ paypalOrderId }
MollieRedirect 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.

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.