Wajub.js
The core browser package, what it loads, what it exports, how to call it.
@wajub/js is the package every Wajub checkout runs on. The React, Vue and Svelte packages are
wrappers around it, and this page covers the core alone: what it loads, what it exports, and the
three ways to reach the same API.
@wajub/js
Stable · GAnpm + CDN
- Version
- 1.4.0
- Runtime
- Any modern browser (ES2020+)
Covers
- Payments
- Payment Links
Not in this package: Billing, Transfers, Sync, Shield, Tax.
The npm package is a loader, not the runtime
Installing @wajub/js does not put the checkout in your bundle. The package is a small loader that
fetches the real runtime from https://js.wajub.com the first time you call it.
| What you install | Size | What it holds |
|---|---|---|
@wajub/js from npm | About 11 KB | The loader, the types, the exported helpers |
https://js.wajub.com | About 168 KB | The checkout itself, iframes, payment methods, states |
There is no offline build
Both routes end at the same origin. A card fix or a new operator reaches your checkout without a
redeploy on your side, which is the point, but a browser that cannot reach js.wajub.com has no
checkout. Plan for that origin the way you plan for the API.
Three entry points
They deliver the same API. What changes is when the runtime is fetched and whether you need a bundler.
| Entry point | Fetches the runtime | Use it when |
|---|---|---|
@wajub/js | On import | You have a bundler and the page always shows a checkout |
@wajub/js/pure | Only when you call loadWajub() | You render on the server, or the checkout is behind a click |
https://js.wajub.com | On script load | No bundler, plain HTML |
Install the package with your usual manager. It ships as an ES module only, so a CommonJS
require() will not resolve it.
npm install @wajub/jsWithout a bundler, the script tag puts wajub, Wajub and WajubError on window. The .mjs
build is the same runtime with named exports.
<script src="https://js.wajub.com"></script>
<!-- or, as a module -->
<script type="module">
import { mount } from 'https://js.wajub.com/wajub.mjs';
</script>Three ways to call the same API
Every method below exists in all three forms. Pick one per project and stay on it, because mixing them makes the loading order hard to read.
The named helpers are the shortest. Each one loads the runtime by itself and awaits it.
import { mount, open, checkout, fetchSession, confirmPayment } from '@wajub/js';
const instance = await mount('#checkout', { sessionId });loadWajub() hands you the runtime instead, so the fetch happens where you decide. It returns
null when there is no window, which is what makes a server render safe.
import { loadWajub } from '@wajub/js/pure';
const rt = await loadWajub();
if (rt) {
const instance = await rt.wajub.mount('#checkout', { sessionId });
}From the CDN, the same objects sit on window and there is nothing to await.
const instance = await wajub.mount('#checkout', { sessionId });What the package exports
Three objects, one error class, and the helpers that mirror the runtime.
| Export | What it is |
|---|---|
loadWajub() | Resolves to { wajub, Wajub, WajubError }, or null on the server |
wajub | The runtime object, every method listed below |
Wajub | The client factory, bound to a key or a session |
WajubError | The error class every rejection is an instance of |
mount, open, checkout, components, confirmPayment | The four modes, plus the fields submit |
fetchSession, preload | Read a session, or warm the runtime before you need it |
getVersion(), getCheckoutOrigin() | The loaded runtime version and the origin it came from |
preload() is the one worth knowing about: call it when the customer reaches the cart, and the
runtime is already in cache when they reach the pay button.
The Wajub() client
The runtime methods all need a sessionId on every call. The client holds it once instead, and it
is the only way to create a payment from the browser.
const client = Wajub('pk.mT9xW2kQ7vB4nL6hR1cY8dF3jS5aG0eU2pA…');
const client = Wajub.session(sessionId);
const client = Wajub({ publishableKey: 'pk.mT9xW2kQ…', sessionId });| Method | What it does |
|---|---|
createPayment(params) | POST /payments with the publishable key, returns the session |
useSession(sessionId) | Binds an existing token to the client |
fetchSession() | Amount, currency, merchant name, methods, saved methods, feature flags |
preload() | Fetches the runtime before it is needed |
mount(el, config), open(config), checkout(config) | The three hosted modes |
components(config) | The fields factory |
confirmPayment(options) | Submits a field component and waits for the outcome |
initCheckout(options) | Creates the payment and mounts it in one call |
initCheckout is the whole flow without a backend. It needs a publishable key, because the amount
is decided by the page.
await Wajub('pk.mT9xW2kQ7vB4nL6hR1cY8dF3jS5aG0eU2pA…').initCheckout({
mode: 'inline',
container: '#checkout',
payment: { amount: 35000, currency: 'XOF', customer: { email: 'buyer@example.com' } },
onSuccess: (transaction) => console.log('paid', transaction),
});A secret key in a browser is refused and reported
Any request carrying sk. or sk_test. with an Origin or Referer header is answered 403,
and the key's owner receives an alert by email. Use pk. here, or create the session on your
server and send the browser only the token.
On the server
loadWajub() and every helper return null when there is no window, so a server render never
throws. The difference is the import itself: @wajub/js fetches the script as a side effect of
being imported, @wajub/js/pure does nothing until you call it.
import { loadWajub } from '@wajub/js/pure';
payButton.addEventListener('click', async () => {
const rt = await loadWajub();
await rt?.wajub.open({ sessionId });
});The three framework packages already import from /pure for you. This matters when you wire the
core yourself.
Where each subject is documented
This page stops at the package. Everything the runtime does has its own page.
| You want to | Read |
|---|---|
| Mount, open or redirect, with every option and callback | Hosted checkout |
| Build your own layout around the fields | Payment fields |
| Create the session, and what the token may do | Sessions and security |
| Change colours, theme, locale and layout | Appearance |
| Read every method, type and checkout state | API reference |
| Type it correctly, with or without npm | TypeScript |
| Work out why nothing renders | Troubleshooting |
Use it through a framework