Official JavaScript SDK for integrating GlomoPay payment checkout flows into your web applications. The Unified SDK supports standard payments, LRS (Liberalised Remittance Scheme) payments, subscriptions, and payment sessions — automatically detecting the correct flow based on your configuration.
Before using this SDK, you need:
- API credentials (Public Key) from your GlomoPay dashboard
- A created order (
order_id), subscription (subscription_id), or payment session (paymentSessionId+paymentSessionToken) - A modern browser with ES module support
Import the SDK directly from the hosted URL using an ES module import:
<script type="module">
import { GlomoCheckoutApi } from 'https://unified-sdk.glomopay.com/index.js';
</script>The SDK supports three integration journeys. Choose the one that matches your use case.
Use this when you have created a payment session via the GlomoPay API. Payment sessions bundle the LRS checkout flow with integrated KYC verification. When using a payment session, you do not need a publicKey or orderId.
What you need:
paymentSessionId— the payment session ID returned when you create a payment sessionpaymentSessionToken— the JWT token returned alongside the payment session ID
<button id="pay-button">Pay with Payment Session</button>
<script type="module">
import { GlomoCheckoutApi } from 'https://unified-sdk.glomopay.com/index.js';
const checkout = new GlomoCheckoutApi({
paymentSessionId: 'ps_679a16457aP6K', // Payment session ID from your server
paymentSessionToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI...', // JWT token from your server
});
checkout.on('payment.success', function (response) {
console.log('Payment successful:', response);
// response contains: { paymentId, orderId, signature, status }
});
checkout.on('payment.failure', function (response) {
console.log('Payment failed:', response);
});
checkout.on('checkout.closed', function () {
console.log('Checkout closed by user');
});
document.getElementById('pay-button').addEventListener('click', () => {
checkout.open();
});
</script>Use this when you have created an order via the GlomoPay API and have an orderId. The SDK automatically detects whether the order is a standard payment or an LRS payment — no additional configuration is needed.
What you need:
publicKey— your public key from the GlomoPay dashboardorderId— the order ID returned when you create an order on your server (starts withorder_)
<button id="buy-button">Buy Now</button>
<script type="module">
import { GlomoCheckoutApi } from 'https://unified-sdk.glomopay.com/index.js';
const checkout = new GlomoCheckoutApi({
publicKey: 'live_687b0151Bid24PAI', // Your public key from the dashboard
orderId: 'order_679a16457aP6K', // Order ID from your server
});
// Called when the payment completes successfully.
// Send the response to your server for signature verification.
checkout.on('payment.success', function (response) {
console.log('Payment successful:', response);
// response contains: { paymentId, orderId, signature, status }
});
// Called when the payment fails.
checkout.on('payment.failure', function (response) {
console.log('Payment failed:', response);
// response contains: { paymentId, orderId, signature, status }
});
// Called when the user closes the checkout without completing payment.
checkout.on('checkout.closed', function () {
console.log('Checkout closed by user');
});
// For bank transfer payments only:
// Emitted when the user submits their bank transfer details.
// This does NOT mean the payment is complete — wait for a webhook to confirm.
checkout.on('payment.bank_transfer_submitted', function (response) {
console.log('Bank transfer submitted:', response);
// response contains: { orderId, senderAccountNumber, transactionReference }
});
document.getElementById('buy-button').addEventListener('click', () => {
checkout.open();
});
</script>If you prefer to handle the payment result server-side via a redirect instead of in JavaScript, pass callbackUrl. The SDK will redirect the user to your URL with the payment result as query parameters. Terminal .on() events (payment.success, payment.failure, payment.bank_transfer_submitted) will not fire.
<button id="buy-button">Buy Now</button>
<script type="module">
import { GlomoCheckoutApi } from 'https://unified-sdk.glomopay.com/index.js';
const checkout = new GlomoCheckoutApi({
publicKey: 'live_687b0151Bid24PAI', // Your public key from the dashboard
orderId: 'order_679a16457aP6K', // Order ID from your server
callbackUrl: 'https://yourwebsite.com/payment-result', // Redirect URL for payment result
});
// No payment.success or payment.failure listeners needed —
// when callbackUrl is set, the SDK redirects instead of emitting these events.
// checkout.closed still fires, so you can handle abandonment.
checkout.on('checkout.closed', function () {
console.log('Checkout closed by user');
});
document.getElementById('buy-button').addEventListener('click', () => {
checkout.open();
});
</script>Use this when you have created a subscription and want to collect the first payment or set up recurring billing.
What you need:
publicKey— your public key from the GlomoPay dashboardsubscriptionId— the subscription ID returned when you create a subscription on your server
Important: You cannot pass both
orderIdandsubscriptionId— use one or the other.
<button id="subscribe-button">Subscribe</button>
<script type="module">
import { GlomoCheckoutApi } from 'https://unified-sdk.glomopay.com/index.js';
const checkout = new GlomoCheckoutApi({
publicKey: 'live_687b0151Bid24PAI', // Your public key from the dashboard
subscriptionId: 'sub_679a16457aP6K', // Subscription ID from your server
});
checkout.on('payment.success', function (response) {
console.log('Subscription payment successful:', response);
// response contains: { paymentId, orderId, signature, status }
});
checkout.on('payment.failure', function (response) {
console.log('Subscription payment failed:', response);
});
checkout.on('checkout.closed', function () {
console.log('Checkout closed by user');
});
document.getElementById('subscribe-button').addEventListener('click', () => {
checkout.open();
});
</script>The GlomoCheckoutApi constructor accepts a configuration object. The required parameters depend on which journey you are using:
| Parameter | Type | Journey 1 (Payment Session) | Journey 2 (Order) | Journey 3 (Subscription) | Description |
|---|---|---|---|---|---|
paymentSessionId | string | Required | Not used | Not used | Payment session identifier. |
paymentSessionToken | string | Required | Not used | Not used | JWT token for the payment session. Required when paymentSessionId is provided. |
publicKey | string | Not used | Required | Required | Your GlomoPay public key. If it starts with test_, mock mode is enabled automatically. |
orderId | string | Not used | Required | Not used | The order ID for this transaction. Must start with order_. |
subscriptionId | string | Not used | Not used | Required | Subscription ID for subscription payments. Cannot be used together with orderId. |
callbackUrl | string | Optional | Optional | Optional | URL to redirect the user after a terminal payment event (payment.success, payment.failure, payment.bank_transfer_submitted). When set, .on() listeners for these events are not invoked — only the redirect fires. Must be an http: or https: URL. |
Validation rules:
- Journey 1: Both
paymentSessionIdandpaymentSessionTokenare required.publicKeyandorderIdare not needed - Journey 2: Both
publicKeyandorderIdare required - Journey 3: Both
publicKeyandsubscriptionIdare required. Cannot be combined withorderId - callbackUrl (all journeys): When provided, the SDK navigates the parent window to this URL on payment completion, failure, or bank transfer submission. The event payload fields are appended as query string parameters. Terminal event listeners (
.on('payment.success', ...),.on('payment.failure', ...),.on('payment.bank_transfer_submitted', ...)) are not invoked — handle the result server-side via the redirect query parameters instead. Non-terminal events (checkout.closed) still fire normally. Onlyhttp:andhttps:URLs are accepted.
Opens the checkout in a modal overlay. Automatically detects the correct checkout flow (standard, LRS, or payment session) based on your configuration. A loading spinner is shown while initializing.
await checkout.open();Closes the checkout and cleans up all resources. Triggers the checkout.closed event.
checkout.close();Registers an event listener. Returns an unsubscribe function to remove the listener.
const unsubscribe = checkout.on('payment.success', (data) => {
console.log('Payment succeeded:', data);
});
// Later: remove the listener
unsubscribe();| Event | Description | Payload |
|---|---|---|
payment.success | Payment completed successfully. Not emitted when callbackUrl is set. | { paymentId, orderId, signature, status } |
payment.failure | Payment failed. Not emitted when callbackUrl is set. | { paymentId, orderId, signature, status } |
payment.bank_transfer_submitted | User submitted bank transfer details. Does NOT confirm payment — await a webhook for confirmation. Not emitted when callbackUrl is set. | { orderId, senderAccountNumber, transactionReference } |
checkout.closed | Checkout was closed by the user or programmatically | {} |
Instead of handling terminal payment events in JavaScript, you can pass a callbackUrl to redirect the user after payment completion. The SDK navigates the parent window to callbackUrl with the event payload fields appended as query string parameters. When callbackUrl is set:
.on()listeners forpayment.success,payment.failure, andpayment.bank_transfer_submittedare not invoked.callbackUrland JS callbacks are mutually exclusive for terminal payment events — this prevents merchants from double-handling the same event.- Non-terminal events (
checkout.closed) continue to fire.on()listeners normally. - Only
http:andhttps:callback URLs are accepted.
Query parameters by event:
| Event | Query parameters appended |
|---|---|
payment.success | paymentId, orderId, status, signature |
payment.failure | paymentId, orderId, status, signature, customerErrorMessage (when available) |
payment.bank_transfer_submitted | orderId, status, senderAccountNumber, transactionReference |
status reflects the payment lifecycle and varies by payment method (e.g. success, pending, failed, bank_transfer_submitted). Treat it as an opaque string and rely on the event type for branching logic.
Example redirect after successful payment:
https://yourwebsite.com/payment-result?paymentId=payment_abc123&orderId=order_abc123&status=success&signature=abc123def456Important: Verify the
signaturequery parameter on your server exactly as you would for the.on()payload. See Signature Verification.
Note: This differs from the checkout-sdk, which emits
.on()events and redirects whencallbackUrlis set. The Unified SDK only redirects — registering.on()listeners for terminal events alongsidecallbackUrlhas no effect.
interface PaymentPayload {
paymentId: string; // Payment ID from GlomoPay
orderId: string; // Order identifier (e.g., "order_abc123")
signature: string; // Signature for server-side verification
status: string; // Payment status
}
interface BankTransferPayload {
orderId: string; // The order ID
senderAccountNumber: string; // Account number provided by the user
transactionReference: string; // Reference number provided by the user
}After receiving a payment.success or payment.failure event, verify the signature on your server using your secret key. Send the response payload to your server and generate the signature using:
data = order_id + "|" + payment_id + "|" + status
signature = HMAC-SHA256(data, secret_key)For detailed instructions and sample code in PHP, Ruby, Go, JavaScript, and Python, see Verify checkout response and signature.
Mock mode is automatically enabled based on your publicKey:
- If your
publicKeystarts withtest_, mock mode is enabled and the checkout URL will includemode=mock - Otherwise, live mode is used
Example:
// Mock mode (publicKey starts with "test_")
const checkout = new GlomoCheckoutApi({
publicKey: 'test_abc123',
orderId: 'order_xyz789',
});
// Live mode
const checkout = new GlomoCheckoutApi({
publicKey: 'live_abc123',
orderId: 'order_xyz789',
});If the checkout fails to open in production, your website's Cross-Origin-Opener-Policy header may be blocking popups. See Checkout Popup Blocked in Production Environment for solutions.
If you see CORS errors in the browser console when the checkout loads, browser extensions may be interfering. See CORS Error on Checkout Load for troubleshooting steps.
If the checkout iframe or SDK scripts fail to load due to CSP headers, you need to allow the Glomo domains in your CSP configuration. See Content Blocked by CSP for setup instructions.
To detect when a user closes the checkout without completing payment, listen for the checkout.closed event:
let paymentCompleted = false;
checkout.on('payment.success', () => {
paymentCompleted = true;
});
checkout.on('payment.failure', () => {
paymentCompleted = true;
});
checkout.on('checkout.closed', () => {
if (!paymentCompleted) {
console.log('User closed checkout without completing payment');
// Prompt the user to retry or log the abandonment
}
});When using
callbackUrl, thecheckout.closedevent still fires, so this pattern works regardless of whether you are using redirect mode or event-listener mode.
If you are embedding the checkout inside a native iOS/Android app via a WebView (rather than using this JavaScript SDK on a web page), see Web Checkout in a Mobile App (WebView). Note that the native Flutter and React Native SDKs are the recommended path.