BitPay
Add Boomcoin (BMC) to BitPay's cryptocurrency invoice flow: both platforms are crypto-native, and the integration is about co-existence — giving merchants who use BitPay access to BMC payments through BoomPay's hosted page alongside BitPay's existing coins.
BitPay and BoomPay are both crypto payment processors, which makes this the most natural partner relationship on this site — and also means the integration is about co-existence rather than one wrapping the other. BitPay handles Bitcoin, Ethereum, and a handful of other coins via its invoice system; BoomPay handles Boomcoin (BMC). For merchants who want to accept both, you present them as parallel hosted options on the same checkout page. Each runs its own independent flow, and your platform reconciles both through the same order confirmation layer.
BitPay’s invoice API currently lists the currencies it supports — BMC is not in BitPay’s own coin catalogue (it’s settled on BoomPay’s own rail). This integration does not add BMC inside BitPay’s invoice; it runs BoomPay in parallel. If BitPay adds native BMC support in future, the BoomPay-side integration here still applies, just with different routing logic on the checkout page.
Flow
Two options prepared
Your server creates a BitPay invoice (for BTC/ETH etc.) and a BoomPay intent (for BMC) in parallel.
Customer chooses
Checkout shows 'Pay with BitPay' and 'Pay with Boomcoin' as separate buttons.
Each path resolves independently
BitPay handles its own hosted invoice flow. BoomPay handles its own hosted page.
Returns come back separately
BitPay fires its own webhook. BoomPay redirects to your return handler with a signed paymentIntentId.
Unified confirmation
Your platform marks the order paid via whichever provider completed it and fires a single merchant notification.
Code
const BoomPay = require('boom-pay-sdk');
const BitPay = require('bitpay-sdk'); // BitPay's Node SDK
// BitPay handles Bitcoin, Ethereum, and other coins via its invoice API.
// BoomPay handles Boomcoin (BMC). For merchants who want both, present
// them as parallel checkout options -- each resolves through its own flow.
async function createCryptoCheckoutOptions(merchant, order) {
// BitPay invoice for BTC/ETH/etc.
const bitpayClient = new BitPay.Client(merchant.bitpayToken);
const bitpayInvoice = await bitpayClient.createInvoice({
price: order.total,
currency: order.currency,
orderId: order.id,
redirectURL: `${process.env.PSP_BASE}/bitpay/return?order=${order.id}`,
notificationURL: `${process.env.PSP_BASE}/bitpay/webhook`,
extendedNotifications: true,
});
// BoomPay intent for BMC, running in parallel.
const boomPay = new BoomPay({
apiKey: merchant.boompayApiKey,
sandbox: process.env.NODE_ENV !== 'production',
});
const boompayIntent = await boomPay.payments.createIntent({
amount: toBmc(order.total, order.currency),
successUrl: `${process.env.PSP_BASE}/boompay/return?status=success&order=${order.id}&mid=${merchant.id}`,
failureUrl: `${process.env.PSP_BASE}/boompay/return?status=failure&order=${order.id}&mid=${merchant.id}`,
label: `${merchant.name} Order ${order.reference}`,
metadata: { orderId: order.id, merchantId: merchant.id },
});
return {
bitpayInvoiceUrl: bitpayInvoice.url, // BitPay's hosted page
boompayLink: boompayIntent.link, // BoomPay's hosted page
};
}
function toBmc(fiatAmount, currency) {
return fiatAmount; // placeholder -- replace with real BMC conversion rate
}const crypto = require('crypto');
// BoomPay's return handler -- runs when the customer returns from BoomPay's
// hosted page (the BMC payment path). BitPay has its own separate return
// handler and webhook for the BTC/ETH path.
async function handleBoompayReturn(req, res) {
const { order: orderId, mid, status } = req.query;
const intentId = req.query.paymentIntentId;
const signature = (req.query['X-Boom-Signature'] || '').replace(/ /g, '+');
const merchant = await db.getMerchant(mid);
const expected = crypto
.createHmac('sha1', merchant.boompayApiKey)
.update(intentId)
.digest('base64');
if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature))) {
return res.status(403).send('Invalid signature');
}
const boomPay = new BoomPay({ apiKey: merchant.boompayApiKey, sandbox: process.env.NODE_ENV !== 'production' });
const payment = await boomPay.payments.getPayment(intentId);
if (status === 'success' && payment.paidAt) {
await db.markOrderPaid(orderId, { provider: 'boompay-bmc', reference: intentId });
await notifyMerchant(merchant, 'CRYPTO_PAYMENT_COMPLETE', orderId, { coin: 'BMC', provider: 'boompay' });
return res.redirect(merchant.successUrl);
}
await db.markOrderFailed(orderId);
res.redirect(merchant.failureUrl);
}Go-live checklist
- Implement
toBmc()with a real BMC conversion rate — BitPay and BoomPay settle in different cryptocurrencies, so amounts need independent conversion. - Ensure the BitPay and BoomPay paths can’t both fulfill the same order — apply an idempotency lock once either completes.
- BitPay’s webhook fires asynchronously; BoomPay’s confirmation is synchronous on return. Your order confirmation logic should handle both timings correctly.