Medusa v2 payment provider plugin for the NMI Gateway — card + ACH/eCheck + Apple/Google Pay via the NmiPayments tokenization component
A Medusa v2 payment provider for the NMI Gateway — card, ACH/eCheck, and Apple/Google Pay through one provider, collected with NMI's official component (). The card PAN / bank number is tokenized in the browser and never touches your server.
You register a single NMI payment method; the customer picks card or bank (or a wallet) inside the payment element, and the provider runs the right lifecycle:
npm install medusa-payment-nmiOr straight from GitHub (the script builds on install):
npm install github:Kaelbroersma/medusa-payment-nmiRequires: Medusa , Node .
This package is a standard Medusa plugin built with , so it follows the official exports layout — resolves the payment module provider.
1module.exports = defineConfig({2 modules: [3 {4 resolve: "@medusajs/medusa/payment",5 options: {6 providers: [7 {8 resolve: "medusa-payment-nmi/providers/nmi",9 options: {10 securityKey: process.env.NMI_SECURITY_KEY,11 tokenizationKey: process.env.NMI_TOKENIZATION_KEY,12 webhookSecret: process.env.NMI_WEBHOOK_SECRET,13 captureMethod: "auth", // card/wallet: "auth" or "sale"14 secCode: "WEB", // ACH SEC code (internet-initiated consumer debit)15 sandbox: process.env.NODE_ENV !== "production",16 },17 },18 ],19 },20 },21 ],22})| Option | Required | Notes |
|---|---|---|
| ✅ | Private API key for . | |
| ✅ | Public key; sent to the storefront component. | |
| ✅ | Webhook signing key (HMAC-SHA256). | |
| — | Card/wallet: (default) or . | |
| — | ACH: (default), , , . | |
| — | Use . |
Medusa exposes one webhook route for the provider:
In NMI Merchant Portal → Settings → Webhooks, add that URL, paste the signing key (your ), and subscribe to these events:
| Events |
|---|
| , , , , , , |
The handler verifies the HMAC and maps each event to the right action, disambiguating card vs ACH by the event body. NMI requires public HTTPS — for local dev, tunnel (e.g. , ) to your backend.
Note on async outcomes: Medusa's built-in payment-webhook subscriber acts on the and outcomes. ACH settlement (→ captured) works out of the box. ACH returns and voids are detected and mapped by this provider but, like all / webhook outcomes in current Medusa core, do not auto-transition the payment — add your own subscriber on the event if you need automated return/void reconciliation.
See for the copy-paste component and checkout wiring.
The repo uses the official Medusa plugin toolchain:
1npm install # also builds .medusa/server via prepare2npm run dev # medusa plugin:develop — watch + publish to the local registry3npm test # vitest unit testsTo try local changes inside a Medusa app, use the local plugin workflow:
1# in this repo2npx medusa plugin:publish3
4# in your Medusa app5npx medusa plugin:add medusa-payment-nmiSaved cards / NMI Customer Vault. The account-holder methods are implemented as no-ops around a synthetic holder; no card is stored. (Easy to add later.)
MIT