Use cases
Real-world integration patterns — e-commerce, SaaS billing, overlay checkout, Mobile Money, and custom payment forms.
E-commerce — inline checkout with cart sync
Keep your product page and cart summary. Embed checkout below the cart and sync totals with
onBreakdown.
<header>
<p>Cart total: <strong id="cart-total">—</strong></p>
</header>
<div id="checkout" style="min-height:480px"></div>
<script src="https://js.wajub.com"></script>
<script>
(async () => {
const { sessionId } = await fetch('/api/checkout/session', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ cartId: 'cart_123' }),
}).then(r => r.json());
wajub.mount('#checkout', {
sessionId,
layout: 'tabs',
appearance: { primaryColor: '#0f172a' },
onBreakdown: (b) => {
document.getElementById('cart-total').textContent =
b.total.toLocaleString() + ' ' + b.currency;
},
onSuccess: () => { window.location.href = '/order/complete'; },
onError: (e) => showToast(e.message),
});
})();
</script>Why inline: customer stays on your domain, full OTP/coupons/shipping, cart UI stays yours.
Set merchant-wide colors and logo in the Dashboard branding or
pass theming when creating the payment. Override per page with appearance on mount().
Redirect — fastest go-live
Minimal front-end — redirect to authorization_url:
// After POST /payments on your server
window.location.href = authorization_url;
// Or with the SDK when you already have sessionId
wajub.checkout({ sessionId });Best for: landing pages, mobile web, MVPs, when you don't need an embedded UI.
Overlay modal — pay without leaving the page
Open checkout in a modal over your app (settings, upgrade flow, one-click top-up):
document.getElementById('upgrade-btn').onclick = async () => {
const { sessionId } = await fetch('/api/billing/upgrade', { method: 'POST' })
.then(r => r.json());
wajub.open({
sessionId,
closeOnOverlay: false,
onSuccess: (txn) => {
showSuccess('Plan upgraded!');
refreshAccount();
},
onClose: () => console.log('Modal dismissed — session still active'),
onCancel: () => console.log('Payment cancelled'),
});
};Note: Closing the overlay (×, Escape) dismisses the UI only — the session remains open until cancelled or completed inside checkout.
SaaS billing — custom form + card fields
You own the plan selector and "Subscribe" button. Wajub renders only the card fields:
'use client';
import { useRef, useState } from 'react';
import type { ComponentInstance } from '@wajub/js';
import { WajubProvider, CardComponent, useConfirmPayment } from '@wajub/react';
export function Subscribe({ sessionId }: { sessionId: string }) {
const confirm = useConfirmPayment(sessionId);
const cardRef = useRef<ComponentInstance | null>(null);
const [canPay, setCanPay] = useState(false);
return (
<WajubProvider>
<h2>Pro plan — 25 000 XAF / month</h2>
<CardComponent
sessionId={sessionId}
appearance={{ primaryColor: '#6366f1', labels: 'floating' }}
onInstance={(c) => { cardRef.current = c; }}
onReady={(inst) => {
inst.on('change', (e) => setCanPay(Boolean(e.complete)));
}}
/>
<button
disabled={!canPay}
onClick={() => cardRef.current && confirm(cardRef.current)}
>
Subscribe
</button>
</WajubProvider>
);
}Limitation: no coupons or OTP in payment-field mode — use hosted checkout if you need those.
Mobile Money — payment selector
Use the payment field for method tabs (card + Mobile Money + wallet):
const factory = wajub.components(sessionId, {
appearance: { primaryColor: '#16a34a' },
layout: 'tabs',
});
const payment = factory.create('payment', {
collectName: true,
}).mount('#payment');
document.getElementById('pay').onclick = () =>
wajub.confirmPayment({ sessionId, components: payment });Preload for faster display
Warm the checkout UI while the customer reviews the cart:
// On cart page load
wajub.preload(sessionId);
// When customer clicks Checkout
wajub.mount('#checkout', { sessionId }); // appears fasterSession preview before mount
Show amount and available methods before embedding:
const preview = await wajub.fetchSession(sessionId);
document.getElementById('amount').textContent =
preview.amount.toLocaleString() + ' ' + preview.currency;
if (preview.environment === 'sandbox') {
showSandboxBanner();
}Choosing a pattern
| Scenario | Pattern |
|---|---|
| Standard shop checkout | Inline mount + onBreakdown |
| Quick launch, minimal JS | Redirect authorization_url |
| In-app upgrade / top-up | open() overlay |
| Existing multi-step funnel | Payment fields + your CTA |
| WordPress / static HTML | CDN script + mount |
| Next.js / Nuxt / SvelteKit | Framework provider — React · Vue · Svelte |