BoomPay/partners

PayPal / Braintree

Surface BoomPay through Braintree's Local Payment Methods framework: your server creates a BoomPay intent alongside the localPayment flow, and a shared return handler confirms both.

WalletBraintree Local PaymentsPayPal Commerce Platform

PayPal’s Braintree SDK has a formal concept of Local Payment Methods — non-card, non-PayPal options that the checkout surfaces alongside PayPal’s own button. BoomPay integrates as a redirect-based local method: your server creates the intent, your checkout page shows a Boomcoin button next to the PayPal one, and a shared return handler confirms whichever the customer chose. From the merchant’s perspective, both appear together in the same Braintree-powered checkout without any extra integration work on their side.

Flow

01

Checkout loads

Your server pre-generates a BoomPay intent link for the order alongside the Braintree client token, and passes both to the page.

02

Customer chooses

PayPal's button launches the PayPal flow. The Boomcoin button redirects to BoomPay's hosted page.

03

Customer pays

The customer approves from their Boom wallet on BoomPay's hosted page.

04

Signed return

BoomPay redirects to your successUrl/failureUrl with paymentIntentId and X-Boom-Signature.

05

Confirm and notify

Your handler verifies the signature, confirms via getPayment(), and fires your merchant notification.

Code

paypal/boompay-intent.js
const BoomPay = require('boom-pay-sdk');
const braintree = require('braintree');

// Your server creates both a Braintree local payment and a BoomPay intent
// in parallel. The checkout UI presents both options; whichever the customer
// selects, your return handler resolves that path.
async function createBoompayIntent(merchant, order) {
  const boomPay = new BoomPay({
    apiKey: merchant.boompayApiKey,
    sandbox: process.env.NODE_ENV !== 'production',
  });

  const intent = await boomPay.payments.createIntent({
    amount: toBmc(order.amount, 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 { boompayLink: intent.link, intentId: intent.id };
}

function toBmc(amount, currency) {
  // Replace with a real fiat-to-BMC rate source.
  return amount; // placeholder
}
checkout.html
<!-- Client side: present PayPal and BoomPay as separate options.
     The Braintree JS SDK handles the PayPal button; BoomPay is a plain
     redirect via the server-generated link. -->

<div id="paypal-button-container"></div>

<div id="boompay-option">
  <button id="boompay-btn" >Pay with Boomcoin</button>
</div>

<script>
async function startBoompay() {
  const res = await fetch('/checkout/boompay-link', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ orderId: window.ORDER_ID }),
  });
  const { boompayLink } = await res.json();
  window.location = boompayLink;
}
</script>
paypal/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);
}
i

The Braintree SDK’s own localPayment.create() is designed for methods that Braintree directly processes (iDEAL, Bancontact, etc.). BoomPay is not natively integrated in Braintree’s payment method list — this pattern adds it alongside Braintree’s own local methods rather than registering it within the Braintree framework itself. Both paths share your return handler.

Go-live checklist

  • Implement toBmc() with a real conversion rate before going live.
  • Generate the BoomPay intent link server-side, not in client-side JavaScript — the API key must never touch the browser.
  • Test that the Braintree PayPal flow and BoomPay flow can’t both be triggered simultaneously for the same order — apply a lock once either option is selected.
  • Confirm your notifyMerchant() fires the same webhook event shape for BoomPay as for Braintree-native methods.