@bobospay/bobospay-checkout
v1.2.1
Published
Secure, embeddable TypeScript payment checkout SDK for Bobospay (iframe-based, CDN-ready)
Maintainers
Readme
@bobospay/bobospay-checkout
Secure, embeddable TypeScript payment checkout SDK for Bobospay. The SDK renders a hosted Bobospay payment form inside a sandboxed <iframe> and communicates with the parent page via validated postMessage events.
Only the public
clientIdis used in the browser. Never expose your private API key / client secret on the client side.
Table of contents
- Installation
- Quick start (CDN)
- Quick start (npm / ESM)
- Two init modes
- React
- Vue 3
- UI options
- Customer object
- Security
- CDN URLs reference
Installation
npm install @bobospay/bobospay-checkout
# or
yarn add @bobospay/bobospay-checkoutQuick start (CDN)
<script src="https://cdn.jsdelivr.net/npm/@bobospay/[email protected]/dist/bobospay.iife.js"></script>
<script>
const sdk = BobospayCheckout.createBobospayCheckout();
sdk.init({ clientId: 'ci_test_xxx' }, {
transaction: { amount: 5000, currency: 'XOF' },
customer: { firstname: 'Jane', lastname: 'Doe', email: '[email protected]' },
callback: (result) => console.log('Payment result:', result),
ui: { closeButton: true, overlayClose: true }
});
document.getElementById('pay-btn').addEventListener('click', () => sdk.open());
</script>Quick start (npm / ESM)
import { createBobospayCheckout } from '@bobospay/bobospay-checkout'
const sdk = createBobospayCheckout()
sdk.init({ clientId: 'ci_test_xxx' }, {
transaction: { amount: 5000, currency: 'XOF' },
customer: { id: 'cust_abc123' }, // or provide firstname/lastname/email
callback: (result) => console.log(result),
ui: { closeButton: true }
})
await sdk.open()Two init modes
Mode 1 — API mode (init)
The SDK calls POST /v2/checkout-js on the Bobospay API to create the checkout session, then opens the returned URL in the iframe.
sdk.init(
{ clientId: 'ci_test_xxx' }, // public client ID (identifies live vs sandbox)
{
transaction: {
amount: 5000, // amount in minor units (e.g. cents / kobo / centimes)
currency: 'XOF',
note: 'Order #1042', // optional
channels: ['card', 'mobile_money'], // optional: restrict payment channels
},
customer: {
// Option A — customer already exists on your backend
id: 'cust_abc123',
// Option B — provide minimal customer info
// firstname: 'Jane',
// lastname: 'Doe',
// email: '[email protected]',
// phone: '+22601234567', // optional
},
callback: (result) => {
// result is the decoded payment object from the hosted page
console.log(result)
},
ui: { closeButton: true, overlayClose: true }
}
)
await sdk.open()Base URLs by environment (derived from the clientId prefix):
| clientId prefix | Environment | API base URL |
|---|---|---|
| ci_live_ | Production | https://bobospay.com/api/v2 |
| ci_test_ | Sandbox | https://sandbox.bobospay.com/api/v2 |
| other | Local dev | http://127.0.0.1:8000/api/v2 |
Mode 2 — URL mode (initWithUrl)
Use this when your backend already created the checkout session (via the Bobospay server SDK or a direct API call) and returned the hosted payment URL. No clientId, transaction or customer data is needed in the browser.
// 1. Your backend calls POST /v2/checkout-js and returns the URL to the frontend.
const paymentUrl = await fetchPaymentUrlFromYourBackend()
// 2. Pass it directly to initWithUrl().
sdk.initWithUrl(paymentUrl, {
callback: (result) => console.log('Payment result:', result),
ui: { closeButton: true }
})
await sdk.open()The SDK validates that paymentUrl belongs to a trusted Bobospay domain before opening the iframe. Accepted hostnames:
| Hostname | Environment |
|---|---|
| checkout.bobospay.com | Production (HTTPS required) |
| checkout-sandbox.bobospay.com | Sandbox (HTTPS required) |
| localhost / 127.x.x.x | Local development |
Any other domain will throw immediately — an arbitrary URL can never be injected into the iframe.
React
The package ships a useReactCheckout hook. Both init modes are available:
import React from 'react'
import { useReactCheckout } from '@bobospay/bobospay-checkout'
export function PayButton() {
const { init, initWithUrl, open } = useReactCheckout()
// --- Mode 1: API mode ---
const handleApiPay = React.useCallback(async () => {
init({ clientId: 'ci_test_xxx' }, {
transaction: { amount: 5000, currency: 'XOF' },
customer: { firstname: 'Jane', lastname: 'Doe', email: '[email protected]' },
callback: (result) => console.log('paid', result),
ui: { closeButton: true }
})
await open()
}, [init, open])
// --- Mode 2: URL mode (server-side created session) ---
const handleUrlPay = React.useCallback(async () => {
const paymentUrl = await fetch('/api/create-payment').then(r => r.json()).then(d => d.url)
initWithUrl(paymentUrl, {
callback: (result) => console.log('paid', result),
ui: { closeButton: true }
})
await open()
}, [initWithUrl, open])
return (
<>
<button onClick={handleApiPay}>Pay (API mode)</button>
<button onClick={handleUrlPay}>Pay (URL mode)</button>
</>
)
}Vue 3
The package ships a useVueCheckout composable. Both init modes are available:
<template>
<button @click="handleApiPay">Pay (API mode)</button>
<button @click="handleUrlPay">Pay (URL mode)</button>
</template>
<script setup lang="ts">
import { useVueCheckout } from '@bobospay/bobospay-checkout'
const { init, initWithUrl, open } = useVueCheckout()
// --- Mode 1: API mode ---
async function handleApiPay() {
init({ clientId: 'ci_test_xxx' }, {
transaction: { amount: 5000, currency: 'XOF' },
customer: { id: 'cust_abc123' },
callback: (result) => console.log('paid', result),
ui: { closeButton: true }
})
await open()
}
// --- Mode 2: URL mode (server-side created session) ---
async function handleUrlPay() {
const { url } = await fetch('/api/create-payment').then(r => r.json())
initWithUrl(url, {
callback: (result) => console.log('paid', result),
ui: { closeButton: true }
})
await open()
}
</script>UI options
All ui fields are optional:
| Option | Type | Default | Description |
|---|---|---|---|
| width | number \| string | 420 | Iframe width (px or CSS string) |
| height | number \| string | 680 | Iframe height (px or CSS string) |
| closeButton | boolean | false | Show a close button above the iframe |
| overlayClose | boolean | false | Click on the backdrop to close |
| containerSelector | string \| null | null | CSS selector for the mount container (defaults to document.body) |
Customer object
Required when using API mode (init). You must provide either an id or minimal contact details:
// Option A — existing customer id
customer: { id: 'cust_abc123' }
// Option B — new / guest customer
customer: {
firstname: 'Jane', // required if no id
lastname: 'Doe', // required if no id
email: '[email protected]', // required if no id, must be valid
phone: '+22601234567', // optional
country: 'CI', // optional, ISO 3166-1 alpha-2
}Not needed in URL mode (initWithUrl) — the customer is already attached to the session server-side.
Security
- Never expose your private API key in client-side code. Only the public
clientId(prefixci_live_orci_test_) belongs in the browser. - The SDK validates
postMessageorigins against a strict whitelist of Bobospay-owned hosts. - In URL mode the payment URL is validated against trusted Bobospay domains before being set as the iframe
src. - The iframe is rendered with
referrerpolicy="no-referrer"and theallow="payment"permission policy. - Apply a strict Content-Security-Policy (
frame-src) on merchant pages that restricts iframe sources to Bobospay checkout domains.
CDN URLs reference
Replace 1.1.0 with the version you want to pin, or omit for the latest release.
| Format | jsDelivr | unpkg |
|---|---|---|
| IIFE (CDN / global) | https://cdn.jsdelivr.net/npm/@bobospay/[email protected]/dist/bobospay.iife.js | https://unpkg.com/@bobospay/[email protected]/dist/bobospay.iife.js |
| ES Module | https://cdn.jsdelivr.net/npm/@bobospay/[email protected]/dist/bobospay.es.js | https://unpkg.com/@bobospay/[email protected]/dist/bobospay.es.js |
| CommonJS | https://cdn.jsdelivr.net/npm/@bobospay/[email protected]/dist/bobospay.cjs.js | https://unpkg.com/@bobospay/[email protected]/dist/bobospay.cjs.js |
| TypeScript types | dist/index.d.ts (included in npm package) | — |
The IIFE build exposes a global BobospayCheckout object with the createBobospayCheckout factory.
License
MIT © Bobospay
