BoomPay/partners

WeChat Pay

Surface BoomPay alongside WeChat Pay in merchant checkout: WeChat Pay handles its own wallet flow, BoomPay handles Boomcoin, and your platform presents both to the customer.

WalletWeChat Pay Open PlatformParallel checkout option

WeChat Pay’s merchant platform does not expose an API for registering third-party settlement rails inside the WeChat Pay wallet flow itself. The workable pattern is presenting WeChat Pay and BoomPay as two distinct options on the same checkout page — WeChat Pay’s JSSDK or QR code handles the WeChat wallet path, and BoomPay’s redirect handles Boomcoin. Your existing WeChat Pay integration is unchanged; BoomPay is additive.

Flow

01

Checkout prepared

Your server creates a WeChat Pay unified order (unchanged) and a BoomPay intent in parallel, and passes both to the page.

02

Customer chooses

Checkout renders the WeChat Pay button/QR and a separate Boomcoin button.

03

BoomPay path

Customer clicks Boomcoin — browser redirects to BoomPay's hosted page.

04

Customer pays

The customer approves from their Boom wallet.

05

Signed return

BoomPay redirects to your return URL with paymentIntentId and X-Boom-Signature.

06

Confirm

Your handler verifies the signature, confirms via getPayment(), and notifies the merchant.

Code

wechatpay/prepare-checkout.js
const BoomPay = require('boom-pay-sdk');

// For merchants accepting WeChat Pay, add a BoomPay option in parallel.
// WeChat Pay uses its own JS SDK/JSSDK for the WeChat wallet flow;
// BoomPay uses a plain redirect.
async function prepareCheckout(merchant, order) {
  const boomPay = new BoomPay({
    apiKey: merchant.boompayApiKey,
    sandbox: process.env.NODE_ENV !== 'production',
  });

  // WeChat Pay: generate your prepay_id / code_url via WeChat Pay's
  // Unified Order API as normal. This is unchanged by adding BoomPay.
  const wechatOrder = await createWechatOrder(merchant, order);

  // BoomPay: create an intent for the Boomcoin option.
  const intent = 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 {
    wechatPrepayId: wechatOrder.prepay_id,
    wechatCodeUrl: wechatOrder.code_url, // for QR-code display outside WeChat
    boompayLink: intent.link,
  };
}

function toBmc(amount, currency) {
  return amount; // placeholder
}

async function createWechatOrder(merchant, order) {
  // Your existing WeChat Pay Unified Order API call -- unchanged.
  // Returns { prepay_id, code_url } as normal.
}
wechatpay/boompay-return.js
const crypto = require('crypto');

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', reference: intentId });
    await notifyMerchant(merchant, 'PAYMENT_COMPLETE', orderId);
    return res.redirect(merchant.successUrl);
  }

  await db.markOrderFailed(orderId);
  res.redirect(merchant.failureUrl);
}

Go-live checklist

  • BoomPay’s hosted page opens in the customer’s default browser — confirm this works correctly from within WeChat’s in-app browser if your checkout is embedded there.
  • Implement toBmc() with a real conversion rate.
  • Lock the order once either the WeChat Pay flow or BoomPay flow starts, to prevent double-fulfillment.