BigCommerce
BigCommerce's native Payments API won't take an offsite provider, so this uses a custom checkout button plus the Checkout and Orders APIs to finalize the order and mark it paid once BoomPay confirms.
BigCommerce’s native Payments API is the natural place to look first, but it’s built for card processors and similar gateways with a specific session contract — it doesn’t support hosted or offsite providers like BoomPay (confirmed against BigCommerce’s own Payments API docs). The working alternative, used by a number of crypto and alternative-payment integrations in practice, is a custom checkout button paired with the Checkout and Orders REST APIs.
Architecture
Custom button renders
A small script injected via Script Manager adds a “Pay with Boomcoin” button to the checkout payment step.
Checkout becomes an order
Clicking it calls your backend, which converts the BigCommerce checkout into an order via the v3 Checkout API.
Intent created, customer redirected
Your backend calls createIntent() and hands the browser BoomPay’s hosted link.
Signed return
BoomPay redirects back with paymentIntentId and X-Boom-Signature.
Order marked paid
Your backend verifies the signature, PUTs the order to status 11 (Awaiting Fulfillment) via the v2 Orders API, and redirects to BigCommerce’s own order-confirmation page.
Files
const express = require('express');
const BoomPay = require('boom-pay-sdk');
const app = express();
app.use(express.json());
const boomPay = new BoomPay({
apiKey: process.env.BOOMPAY_API_KEY,
sandbox: process.env.NODE_ENV !== 'production',
});
app.use('/boompay', require('./routes/boompay-checkout')(boomPay));
app.use('/boompay', require('./routes/boompay-return')(boomPay));
app.listen(process.env.PORT || 3000);
const express = require('express');
const BC_STORE_HASH = process.env.BC_STORE_HASH;
const BC_AUTH_TOKEN = process.env.BC_ACCESS_TOKEN; // from a BigCommerce private/custom app
const BC_API = `https://api.bigcommerce.com/stores/${BC_STORE_HASH}`;
module.exports = function (boomPay) {
const router = express.Router();
// Called by the custom checkout button once shipping/billing are filled in
// and the customer is ready to pay.
router.post('/checkout', async (req, res) => {
const { checkoutId, checkoutToken } = req.body;
// Converts the checkout into an order, flagged as paid by an external
// provider rather than one of BigCommerce's built-in gateways.
const orderRes = await fetch(`${BC_API}/v3/checkouts/${checkoutId}/orders`, {
method: 'POST',
headers: { 'X-Auth-Token': BC_AUTH_TOKEN, 'Content-Type': 'application/json' },
body: JSON.stringify({ payment: { payment_method: 'BoomPay (Boomcoin)' } }),
});
const order = await orderRes.json();
const orderId = order.data.id;
const intent = await boomPay.payments.createIntent({
amount: Number(order.data.total_inc_tax),
successUrl: `${process.env.APP_URL}/boompay/return?status=success&order_id=${orderId}&t=${checkoutToken}`,
failureUrl: `${process.env.APP_URL}/boompay/return?status=failure&order_id=${orderId}&t=${checkoutToken}`,
label: `BigCommerce order ${orderId}`,
metadata: { bigcommerceOrderId: orderId },
});
res.json({ redirect: intent.link });
});
return router;
};
const express = require('express');
const BC_STORE_HASH = process.env.BC_STORE_HASH;
const BC_AUTH_TOKEN = process.env.BC_ACCESS_TOKEN;
const BC_API = `https://api.bigcommerce.com/stores/${BC_STORE_HASH}`;
module.exports = function (boomPay) {
const router = express.Router();
// boomPay.webhooks() validates paymentIntentId + X-Boom-Signature before
// this handler runs.
router.get('/return', boomPay.webhooks(), async (req, res) => {
const { order_id, t, status } = req.query;
const payment = await boomPay.payments.getPayment(req.query.paymentIntentId);
if (status === 'success' && payment.paidAt) {
// The v2 Orders API is still the documented way to update order
// status after the fact.
await fetch(`${BC_API}/v2/orders/${order_id}`, {
method: 'PUT',
headers: { 'X-Auth-Token': BC_AUTH_TOKEN, 'Content-Type': 'application/json' },
body: JSON.stringify({
payment_method: 'BoomPay (Boomcoin)',
payment_provider_id: 'boompay',
status_id: 11, // Awaiting Fulfillment
}),
});
return res.redirect(`${process.env.STORE_URL}/checkout/order-confirmation/${order_id}?t=${t}`);
}
res.redirect(`${process.env.STORE_URL}/cart.php`);
});
return router;
};
<!-- Injected via Storefront -> Script Manager, scoped to the checkout page -->
<script>
document.addEventListener('DOMContentLoaded', function () {
var btn = document.createElement('button');
btn.textContent = 'Pay with Boomcoin';
btn.onclick = function () {
fetch('https://your-app.example.com/boompay/checkout', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
// Supplied by your checkout customization (e.g. the Checkout.js SDK) --
// BigCommerce doesn't expose these as globals out of the box.
checkoutId: window.checkoutId,
checkoutToken: window.checkoutToken,
}),
})
.then(function (r) { return r.json(); })
.then(function (json) { window.location = json.redirect; });
};
document.querySelector('#checkout-payment-continue')?.parentNode.appendChild(btn);
});
</script>
The exact payload shape for converting a checkout into an order via POST /v3/checkouts/{id}/orders has some version-specific nuance around how you flag an external/manual payment method. The fields shown work in practice; if BigCommerce changes this contract, their Checkout API reference is the source of truth to recheck against.
Setup
Create a private app under Settings → API → API accounts with Orders and Checkouts Modify scopes to get the access token used as BC_AUTH_TOKEN above. Add the button snippet through Storefront → Script Manager, scoped to the checkout page, and point it at your deployed backend’s URL.
Testing in sandbox
With sandbox: true on the BoomPay client, walk through a real checkout, click Pay with Boomcoin, and confirm you land on a sapi.boom.market page. Approve the test payment and verify the order shows Awaiting Fulfillment in Orders with the right payment method label. Cancel a second test payment and confirm the customer is sent back to the cart rather than a half-finished order.
Go-live checklist
- Switch the BoomPay client out of sandbox mode and swap in a live API key once a full test order has gone through.
- Confirm
window.checkoutIdandwindow.checkoutTokenare actually populated by whatever checkout customization you’re running — they’re placeholders for values your specific setup needs to supply. - BoomPay settles in BMC only; convert your order total before calling
createIntentif your store prices in another currency. - Confirm your private app’s token is stored server-side only — never in the checkout page script itself.