Bitcoin Lightning payment module for MedusaJS eCommerce via the CLINK protocol.
- β‘ Lightning Payments - Accept Bitcoin Lightning payments via CLINK protocol
- π Self-Custodial - Your node, your funds, no third-party
- π Nostr-Native - All communication via Nostr relays, no web server needed
- π± Auto Conversion - CoinGecko, Kraken, Fixed rate, or Manual
- π Subscriptions - Auto-renewal via CLINK Debits (nDebit)
- π± QR + Copy - Beautiful QR codes with one-click copy for invoices
- π Privacy - Ephemeral Nostr keys for payment requests
- π‘οΈ Dual Confirmation - Webhook (primary) + Polling (backup)
- π Admin Dashboard - Configure everything from the Medusa admin panel
| Component | Description |
|---|---|
ClinkPaymentProviderService |
Core payment provider with CLINK SDK integration |
CurrencyService |
Fiat-to-sats conversion (CoinGecko, Kraken, Fixed, Manual) |
SubscriptionService |
Recurring payments via nDebit protocol |
| Admin Settings Widget | Configure noffer, currency source, subscriptions, refunds |
| Storefront Component | QR code + copy + countdown timer + payment status polling |
| Webhook Endpoint | Real-time payment confirmations from CLINK relay |
| Status Endpoint | Backup polling for payment verification |
npm install medusa-plugin-bitcoin-lightning-via-clinkAdd to your -config.ts:
import { Modules } from "@medusajs/framework/utils"
module.exports = defineConfig({
modules: [
{
resolve: "@medusajs/medusa/payment",
options: {
providers: [
{
resolve: "medusa-plugin-bitcoin-lightning-via-clink",
id: "clink",
options: {
noffer: "noffer1...", // Your CLINK offer string
currencySource: "coingecko",
invoiceTimeout: 600,
debug: false
}
}
]
}
}
]
})- Go to Settings > Regions
- Edit your region
- Enable Lightning (CLINK) as a payment provider
Customers can now pay with Lightning at checkout.
Full documentation lives on the GitHub Wiki:
- Getting Started
- Configuration
- Guide for Merchants
- Guide for Customers
- Guide for Subscriptions
- Currency Sources
- Troubleshooting
- FAQ
- Changelog
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β CHECKOUT FLOW β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Customer selects "Pay with Lightning" β
β β β
β βΌ β
β Medusa requests invoice β
β β β
β βΌ β
β CLINK SDK decodes nOffer β requests BOLT11 from your node β
β β β
β βΌ β
β QR code + invoice displayed to customer β
β β β
β βΌ β
β Customer scans QR with Lightning wallet β
β β β
β βΌ β
β Payment confirmed via Webhook (primary) OR Polling (backup) β
β β β
β βΌ β
β Order confirmed! β‘ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
No web server needed for your Lightning node. All communication flows over Nostr. See the Wiki architecture page for the full data flow.
- Medusa v2.x
- Node.js >= 18.0.0
- A CLINK-compatible Lightning wallet/node:
- ShockWallet (iOS/Android/Desktop)
- Lightning.Pub (self-hosted)
- ZEUS (iOS/Android)
- Amethyst (Android)
- Electrum with CLINK plugin (Desktop)
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
noffer |
string | Yes | - | Your CLINK offer string |
currencySource |
string | No | coingecko |
Exchange rate source |
fixedBtcRate |
number | No | - | Fixed BTC rate (if using fixed source) |
invoiceTimeout |
number | No | 600 |
Invoice expiry in seconds |
pollInterval |
number | No | 5000 |
Polling interval in ms |
enableSubscriptions |
boolean | No | false |
Enable nDebit subscriptions |
merchantPubkey |
string | Only for subscriptions | - | Merchant Nostr pubkey (64-hex); required when enableSubscriptions |
webhookSecret |
string | No | - | HMAC secret to verify webhook payloads (see Security below) |
refundContactEmail |
string | No | - | Merchant email for refunds |
refundContactNostr |
string | No | - | Merchant Nostr for refunds |
debug |
boolean | No | false |
Enable debug logging |
v1.0.2 hardened the plugin against common payment and network attacks:
- BOLT11 validation - Invoices returned by your node are validated before being shown to customers: mainnet
bcprefix, amount matches the requested total, and a reasonable expiry. Invalid invoices are rejected and the payment session is failed. - SSRF protection - Relay URLs are validated (
wss://only) and IP addresses are checked for safety. Localhost,.localdomains, private/loopback/CGNAT/link-local IPs, and unsafe IPv6 ranges (ULA, link-local, multicast, IPv4-mapped) are rejected. - Webhook signature verification - Confirmations sent to the webhook endpoint are verified with an HMAC-SHA256 signature before the order is confirmed. Set a shared secret and the plugin will reject unsigned or tampered webhooks.
- nDebit validation - Subscription debit pointers are decoded and validated (pubkey, relay) before use. A
k1correlation key ties each debit request to the originating subscription. - Payment hash correlation - The webhook verifies the payment's
payment_hashmatches the expected session before confirming the order.
Two ways to set it (env var takes precedence):
# Option 1: environment variable
CLINK_WEBHOOK_SECRET=your-secret npm start// Option 2: plugin option
options: {
webhookSecret: "your-secret"
}If no secret is configured, webhook signatures are not checked (single-tenant setups behind a firewall). Configure one in production. See the Configuration Wiki page for details.
See the Configuration Wiki page for details on each option.
For Merchants (to get your nOffer):
- ShockWallet - Menu > Static Offer
- Lightning.Pub - Dashboard > Offers
- ZEUS - Settings > CLINK
For Customers (to pay):
# Install dependencies
npm install
# Run tests
npm test
# Build
npm run build
# Watch mode
npm run devContributions are welcome! Please see CONTRIBUTING.md for details.
GPL-3.0 - See LICENSE for details.
- Open GH Issues: https://github.com/WoompaLoompa/medusa-clink/issues
- GH Discussions: https://github.com/WoompaLoompa/medusa-clink/discussions
- In Medusa Discord: https://discord.com/channels/876835651130097704/1529853260276437123/1533081096026067014
- In SN announcement: https://stacker.news/items/1534561/r/06bc1a977d
- More about CLINK Protocol
- More about Medusa Documentation
- In Medusa GH forum: medusajs/medusa#16162
- In Medusa Discord: https://discord.com/channels/876835651130097704/1529853260276437123
