Drop a branded MyroPay button into any page and start accepting payments — one‑off, escrow‑protected, or recurring — in minutes, without building a checkout flow yourself.
Each type maps to something Checkout Sessions already does — the button is just the fastest way to trigger it from a page.
One‑off payments. Card, bank transfer (NGN only), USSD, or wallet — whatever payment methods your session allows.
Funds are held until the buyer confirms the order, same as the escrow flow in Checkout Sessions.
Recurring billing, backed by Subscription Plans — the button starts the first invoice.
These are the real buttons, loaded from the SDK below — resize your window or view source to see them render.
Demo buttons above use placeholder sessions and won't complete a real checkout.
The button never sees your secret key and never calls the Checkout Sessions or Subscriptions API directly — that call has to happen on your server, same as every other MyroPay integration. The button's job is everything after that: rendering, the loading state, and sending the customer to checkout.myropay.com.
createSession function, which hits your own backend./api/sessions.php (or /api/subscriptions.php) with your app secret, and returns that response to the browser.success_url / cancel_url when they're done — set those when you create the session, exactly as you would without the button.sessions.php or subscriptions.php straight from browser JS with your app secret in it. The whole reason step 3 happens on your server is that the secret must never reach a browser.<div id="myropay-button"></div>
<script src="https://checkout.myropay.com/buttons/mrp-button.js"></script>
<script>
MyroPay.Button({
type: 'pay',
createSession: async () => {
// calls YOUR backend, not MyroPay directly
const res = await fetch('/api/create-myropay-session', { method: 'POST' });
return res.json(); // forward MyroPay's response as-is
}
}).render('#myropay-button');
</script>
<?php // api/create-myropay-session.php — this is the only place your secret key lives $res = file_get_contents('https://checkout.myropay.com/api/sessions.php', false, stream_context_create([ 'http' => [ 'method' => 'POST', 'header' => "Content-Type: application/json\r\nAuthorization: Bearer {$_ENV['MYROPAY_SECRET_KEY']}\r\n", 'content' => json_encode([ 'amount' => 5000, 'currency' => 'NGN', 'description' => 'Order #1042', 'success_url' => 'https://yourshop.com/thank-you', 'cancel_url' => 'https://yourshop.com/cart', ]), ], ])); header('Content-Type: application/json'); echo $res; // forward MyroPay's JSON straight through
Same pattern — the only difference is the escrow flag your backend sends when creating the session.
MyroPay.Button({
type: 'escrow',
createSession: async () => {
const res = await fetch('/api/create-myropay-escrow-session', { method: 'POST' });
return res.json();
}
}).render('#myropay-escrow-button');
{
"amount": 45000,
"currency": "NGN",
"description": "Custom furniture — 3 seater sofa",
"escrow": true,
"escrow_condition": "Buyer confirms delivery and inspects the item",
"escrow_deadline_days": 7,
"success_url": "https://yourshop.com/thank-you",
"cancel_url": "https://yourshop.com/cart"
}
For recurring billing, your backend calls the Subscriptions API's subscribe action instead of Checkout Sessions directly — it creates the subscription and the first invoice's checkout session in one call.
MyroPay.Button({
type: 'subscribe',
createSession: async () => {
const res = await fetch('/api/create-myropay-subscription', { method: 'POST' });
return res.json(); // { subscription, invoice: { checkout_url, ... } }
}
}).render('#myropay-subscribe-button');
subscription_plans row once (in your dashboard or via create-plan) — your backend then just calls subscribe with that plan_id and the customer's email each time this button is clicked.If you already have a reusable session_id or checkout URL — a fixed‑price payment link, or a subscription invoice you generated elsewhere — skip createSession entirely.
<div data-myropay-button
data-type="pay"
data-session-id="cs_live_xxxxxxxxxxxx"></div>
<script src="https://checkout.myropay.com/buttons/mrp-button.js"></script>
MyroPay.Button({ type: 'pay', sessionId: 'cs_live_xxxxxxxxxxxx' }).render('#btn');
// or, with a full URL you already have:
MyroPay.Button({ type: 'pay', checkoutUrl: 'https://checkout.myropay.com/?session=cs_live_xxx' }).render('#btn');
| Option | Type | Description |
|---|---|---|
type | string | One of 'pay', 'escrow', 'subscribe'. Defaults to 'pay'. |
createSession | function | Sync, async, or Promise‑returning. Called on click; its return value is read for a checkout URL (see below). |
sessionId | string | Use instead of createSession when you already have a session id. |
checkoutUrl | string | Use instead of the above when you already have a full checkout URL. |
label | string | Override the default button text. |
color | string | Override the accent color (hex). Defaults per type. |
target | string | '_self' (default, same tab) or '_blank' (new tab). |
hideBadge | boolean | Escrow buttons show an "Escrow protected" badge under the button; set true to hide it. |
badgeLabel | string | Override the escrow badge text. |
onBeforeRedirect | function(url) | Fires right before redirecting — useful for analytics. |
onError | function(error) | Fires if createSession throws or returns something unusable. If omitted, the button shows a generic inline error. |
createSession() can returnWhatever your backend proxy forwards from MyroPay's API — the SDK checks these shapes in order, so the simplest possible backend route just echoes the response body:
| Shape | Matches |
|---|---|
"cs_live_xxx" (a string) | Treated as a session_id. |
{ checkout_url } | Used directly — the shape sessions.php's create action returns. |
{ session_id } | A checkout URL is built from it. |
{ session: { session_id } } | Same, one level nested. |
{ invoice: { checkout_url } } | The shape subscriptions.php's subscribe action returns. |
| Method | Description |
|---|---|
.render(target) | Renders into a CSS selector string or a DOM element. Returns the button instance. |
The SDK injects its own scoped CSS (prefixed .mrp-btn) and inline SVG icons — no external stylesheet, no webfont dependency, so it renders correctly on any page regardless of your site's own CSS or fonts. Use the color option for simple accent overrides; for anything more involved, target .mrp-btn in your own CSS after the button renders.
createSession endpoint and then redirects to checkout.myropay.com.createSession route.