Inline / embed checkout
Keep customers on your site with an embeddable MoMo checkout modal — same hosted checkout, without a full-page redirect.
Choose how checkout opens
| Parameter | Type | Description |
|---|---|---|
embed: true | modal | Recommended for “pay on your site”. Opens an overlay + iframe of /pay/… with ?embed=1. |
(default) | redirect | Navigates the current window to authorization_url. Simplest path — see Redirect checkout. |
popup: true | window | Opens a 480×720 popup. Ignored when embed is true. Useful if you cannot use iframes. |
Modes
<script src="https://waaguan.com/waaguan-pay.js"></script>
<script>
var url = data.authorization_url; // from Initialize
// A) Embed modal on your site (recommended for “stay on page”)
WaaguanPay.checkout({
authorizationUrl: url,
embed: true,
onSuccess: function (p) { console.log(p.reference); },
onClose: function () {},
});
// B) Full-page redirect (simplest)
// WaaguanPay.checkout({ authorizationUrl: url });
// C) Browser popup window
// WaaguanPay.checkout({ authorizationUrl: url, popup: true });
// D) Open by reference only (same origin as the script)
// WaaguanPay.checkout({ reference: "wa-6281126272", embed: true });
</script>Full example (server + embed)
- Your backend calls Initialize with
Bearer sk_live_…. - Your frontend receives
authorization_urlandreference(never the secret key). - Call
WaaguanPay.checkout({ embed: true, … }. - Customer completes MoMo payment in the modal; the charge becomes
paid. - Use
onSuccessfor UI only. Fulfill after webhook or Verify.
Embed + callbacks
<!-- 1) Load once on your checkout page -->
<script src="https://waaguan.com/waaguan-pay.js"></script>
<script>
// 2) After your server returns initialize → data.authorization_url
async function payNow() {
const res = await fetch("/api/your-backend/create-charge", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ amount: 50, customer_name: "AMA MENSAH" }),
});
const { authorization_url, reference } = await res.json();
WaaguanPay.checkout({
authorizationUrl: authorization_url,
embed: true,
onSuccess: function (payment) {
// UX only — still verify / wait for webhook before fulfilling
console.log("paid", payment.reference, payment.status);
window.location.href = "/orders/thank-you?reference=" + payment.reference;
},
onClose: function () {
// Modal closed (paid or dismissed)
},
});
}
document.getElementById("pay-btn").addEventListener("click", payNow);
</script>Script URL
Hosted at https://waaguan.com/waaguan-pay.js. Load it from your Waaguan deployment origin so the helper can resolve checkout URLs and validate origins correctly.
Options reference
| Parameter | Type | Description |
|---|---|---|
authorizationUrl | string | Full checkout URL from Initialize (recommended). Must be this app’s /pay/… URL. |
reference | string | Alternative to authorizationUrl. Opens /pay/{reference} on the script origin. |
embed | boolean | If true, opens the modal iframe. Adds ?embed=1 to the checkout URL. |
popup | boolean | If true (and embed is not set), opens a popup window instead of redirecting. |
onSuccess | function | Called after charge.success (embed only). Receives { reference, status, event }. UX only. |
onClose | function | Called when the modal closes — after success or when the user dismisses it (after confirm if payment is still pending). |
closeOnBackdrop | boolean | Default false. If true, clicking the dimmed backdrop can dismiss (still asks to confirm while payment is pending). |
Return value
WaaguanPay.checkout(…) returns { close() }. In embed mode, close() asks for confirmation if payment is still pending (same as the X / Escape). Opening a new embed closes any existing one first.
Success callbacks
In embed mode, when payment is confirmed the checkout page notifies the parent window:
postMessage payload
{
"source": "waaguan-pay",
"event": "charge.success",
"reference": "wa-6281126272",
"status": "paid"
}waaguan-pay.jslistens forsource: "waaguan-pay"from the Waaguan origin.- On
charge.successit shows “Payment successful”, then callsonSuccessandonClose. If the tab was in the background (customer in MoMo), it waits until they return before auto-closing. - Closing via X, Escape, or
close()only runsonClose(noonSuccess) after the user confirms. callback_urlbrowser redirects are skipped while embedded — useonSuccessplus webhook / Verify instead.
onSuccess(data) argument
{
"reference": "wa-6281126272",
"status": "paid",
"event": "charge.success"
}Security notes
- Secret keys never go in
waaguan-pay.jsor page JS. - Only pass
authorization_url/referencefrom your server's Initialize response. - Prefer HTTPS on your site in production so the modal and iframe load cleanly.
UX tips
- Prefer
embed: trueoverpopupon mobile — popups often die when the customer opens the MoMo app. - The embed modal stays open while they send MoMo. Closing X / Escape asks for confirmation. Backdrop click does not dismiss by default (set
closeOnBackdrop: trueif you want that). - Checkout keeps checking in the background when the tab is hidden. Still wire webhooks or Verify — if they leave your site entirely, fulfillment must not depend on the modal.
- On
onClosewithout success, offer “Try again” with a new Initialize (do not reuse expired references). - Branding (template / color) from Dashboard → Checkout applies inside the embed the same as hosted checkout.
Embed vs redirect vs payment links
- Embed (this page) — stay on your site; best for apps and custom checkouts.
- Redirect — simplest; full-page
/pay/wa-…. - Payment links — no code; share a URL from the dashboard.