Skip to main content

checkout.js Widget

The checkout.js widget is an embeddable payment solution that allows merchants to accept Bitcoin Lightning payments on any website. It uses the BYOA (Bring Your Own API Key) model - funds flow directly to your OpenNode account.

Architecture

Your Website → checkout.js → OpenNode API → Your OpenNode Account

Lightning Network

Key points:

  • Lightning Enable never touches your funds
  • OpenNode facilitates custody and settlement
  • You provide your OpenNode API key
  • Widget works on any website (static HTML, React, Vue, etc.)

Quick Start

1. Get Your OpenNode API Key

  1. Sign up at app.opennode.com/signup
  2. Complete KYB verification
  3. Navigate to Settings → API Keys
  4. Create a new API key with invoices permission

2. Include the Script

<script src="https://api.lightningenable.com/checkout/v1/checkout.js"></script>

3. Add a Payment Button

<button id="pay-with-lightning"
data-opennode-key="YOUR_OPENNODE_API_KEY"
data-amount="1000"
data-currency="USD"
data-description="Premium Content Access">
Pay $10 with Lightning ⚡
</button>

<script>
LightningCheckout.init({
onSuccess: function(payment) {
console.log('Payment complete!', payment.id);
// Unlock content, redirect, etc.
},
onCancel: function() {
console.log('Payment cancelled');
}
});
</script>

Configuration Options

Button Attributes

AttributeRequiredDescription
data-opennode-keyYesYour OpenNode API key
data-amountYesPayment amount (in smallest unit, e.g., cents for USD)
data-currencyNoCurrency code (default: USD)
data-descriptionNoPayment description shown to customer
data-success-urlNoRedirect URL after successful payment
data-cancel-urlNoRedirect URL if payment cancelled
data-webhook-urlNoYour webhook endpoint for payment notifications

JavaScript Options

LightningCheckout.init({
// Callbacks
onSuccess: function(payment) { }, // Called after successful payment
onCancel: function() { }, // Called if user cancels
onError: function(error) { }, // Called on error

// UI Options
theme: 'light', // 'light' or 'dark'
primaryColor: '#F7931A', // Bitcoin orange default
showQRCode: true, // Show QR code
showPaymentOptions: true, // Show wallet app buttons

// Behavior
autoClose: true, // Auto-close modal on success
closeDelay: 3000, // Delay before auto-close (ms)
});

Payment Flow

sequenceDiagram
participant User
participant checkout.js
participant OpenNode
participant Merchant

User->>checkout.js: Click "Pay with Lightning"
checkout.js->>OpenNode: Create invoice (using merchant's API key)
OpenNode-->>checkout.js: Invoice with Lightning address
checkout.js->>User: Display QR code + payment info

loop Poll for status
checkout.js->>OpenNode: Check invoice status
OpenNode-->>checkout.js: pending/paid
end

User->>OpenNode: Pay invoice via Lightning wallet
OpenNode-->>checkout.js: paid status
checkout.js->>Merchant: onSuccess callback
checkout.js->>User: Success confirmation

Supported Currencies

checkout.js supports all currencies that OpenNode supports:

  • USD - US Dollar (default)
  • EUR - Euro
  • GBP - British Pound
  • BTC - Bitcoin (satoshis)
  • CAD - Canadian Dollar
  • And many more...

Example: E-commerce Integration

<!DOCTYPE html>
<html>
<head>
<title>My Store - Checkout</title>
</head>
<body>
<h1>Premium Membership - $29/month</h1>

<button id="pay-lightning"
data-opennode-key="your-opennode-key"
data-amount="2900"
data-currency="USD"
data-description="Premium Membership - 1 Month"
data-webhook-url="https://yoursite.com/api/webhooks/opennode">
Pay with Bitcoin Lightning ⚡
</button>

<script src="https://api.lightningenable.com/checkout/v1/checkout.js"></script>
<script>
LightningCheckout.init({
onSuccess: function(payment) {
// Verify on your backend, then:
window.location.href = '/membership/success?payment=' + payment.id;
},
theme: 'dark',
primaryColor: '#10B981' // Custom green
});
</script>
</body>
</html>

Security Considerations

API Key Scope

Your OpenNode API key is exposed in the browser. Ensure it only has invoices permission:

  • ✅ Create invoices
  • ❌ Withdraw funds
  • ❌ Access account settings
  • ❌ View transaction history

Verify Payments Server-Side

Always verify payments on your backend before fulfilling orders:

// Frontend: onSuccess callback
onSuccess: function(payment) {
// Send payment ID to your backend
fetch('/api/verify-payment', {
method: 'POST',
body: JSON.stringify({ paymentId: payment.id })
}).then(response => {
if (response.ok) {
// Payment verified, fulfill order
}
});
}
// Backend: Verify with OpenNode
const response = await fetch(
`https://api.opennode.com/v1/charge/${paymentId}`,
{ headers: { 'Authorization': process.env.OPENNODE_SECRET_KEY } }
);
const charge = await response.json();

if (charge.data.status === 'paid') {
// Payment confirmed, fulfill order
}

Webhook Verification

If using webhooks, verify the signature:

// Your webhook endpoint
app.post('/api/webhooks/opennode', (req, res) => {
const signature = req.headers['x-opennode-signature'];
const payload = JSON.stringify(req.body);

const expectedSig = crypto
.createHmac('sha256', process.env.OPENNODE_WEBHOOK_SECRET)
.update(payload)
.digest('hex');

if (signature !== expectedSig) {
return res.status(401).send('Invalid signature');
}

// Process verified webhook
const { id, status } = req.body;
if (status === 'paid') {
// Fulfill order
}
});

Framework Examples

React

import { useEffect } from 'react';

function CheckoutButton({ amount, description }) {
useEffect(() => {
// Load checkout.js
const script = document.createElement('script');
script.src = 'https://api.lightningenable.com/checkout/v1/checkout.js';
script.onload = () => {
window.LightningCheckout.init({
onSuccess: (payment) => {
console.log('Paid!', payment.id);
}
});
};
document.body.appendChild(script);

return () => document.body.removeChild(script);
}, []);

return (
<button
data-opennode-key={process.env.REACT_APP_OPENNODE_KEY}
data-amount={amount}
data-currency="USD"
data-description={description}
>
Pay with Lightning ⚡
</button>
);
}

Vue

<template>
<button
:data-opennode-key="openNodeKey"
:data-amount="amount"
data-currency="USD"
:data-description="description"
>
Pay with Lightning ⚡
</button>
</template>

<script>
export default {
props: ['amount', 'description'],
data() {
return {
openNodeKey: process.env.VUE_APP_OPENNODE_KEY
};
},
mounted() {
const script = document.createElement('script');
script.src = 'https://api.lightningenable.com/checkout/v1/checkout.js';
script.onload = () => {
window.LightningCheckout.init({
onSuccess: (payment) => {
this.$emit('payment-success', payment);
}
});
};
document.body.appendChild(script);
}
};
</script>

Customization

CSS Variables

:root {
--le-primary: #F7931A; /* Primary button color */
--le-background: #ffffff; /* Modal background */
--le-text: #1a1a2e; /* Text color */
--le-border-radius: 12px; /* Border radius */
--le-font-family: system-ui; /* Font family */
}

Custom Styling

<style>
.lightning-checkout-modal {
/* Your custom modal styles */
}

.lightning-checkout-qr {
/* Custom QR code container */
}

.lightning-checkout-button {
/* Custom button styles */
}
</style>

Troubleshooting

"Invalid API Key"

  • Verify your OpenNode API key is correct
  • Ensure the key has invoices permission
  • Check if key is for correct environment (dev vs production)

Invoice Not Creating

  • Check browser console for errors
  • Verify amount is a valid number
  • Ensure currency is supported

Payment Not Detected

  • OpenNode polls every 2 seconds by default
  • Check OpenNode dashboard for payment status
  • Verify webhook URL is accessible

Included in Plans

checkout.js is included in all Lightning Enable subscription plans:

PlanPricecheckout.js
Kentico Commerce$249/month✅ Included
Agentic Commerce$299/month✅ Included

Next Steps