PaymonetraDocs

Inline checkout

A payment in a popup on your own page. One script, your public key, no redirect.

A payment started on the merchant's own page with their public key, shown in a Paymonetra popup over that page instead of a redirect. Bank transfer only for now. Beta: switched on per business, so ask us to turn it on for yours.

#Quick start

Example
<script src="https://pay.paymonetra.com/inline.js"></script>
<button id="pay">Pay with Paymonetra</button>
<script>
  document.getElementById("pay").onclick = function () {
    MonetraPay.pay({
      key: "pk_live_...",            // your public key, never the sk_ one
      amount: 5000,                   // naira
      reference: "ORDER-1042",        // your order id; one per attempt
      email: "ada@example.com",       // optional; asked in the popup if missing
      name: "Ada Obi",                // optional; asked with the email
      description: "Wallet top-up",   // optional, shown under the amount
      onSuccess: function (tx) { /* ask YOUR server to verify tx.reference */ },
      onClose: function (tx) { /* tx.status says how it ended */ },
      onError: function (err) { /* err.code, err.message, err.field */ }
    });
  };
</script>

MonetraPay.pay() also returns a Promise that resolves with the same tx as onClose, and rejects only when the call itself is wrong (no key, a secret key, no amount, a window already open). MonetraPay.close() closes it.

The public key is visible to anyone, so a payer can start a payment for any amount and a browser can be told anything. Before you credit, ship or unlock, your server must confirm with your secret key:

Example
GET https://paymonetra.com/api/gateway/v1/payments/{tx.reference}
Authorization: Bearer sk_live_...

and check status is paid and amount is what you charged, or act on the collection.success webhook, which fires for inline payments exactly as for any checkout. onSuccess is for updating the screen.

#Callbacks

callbackwhenargument
onLoadthe popup is showing the paymenttx
onSuccessthe payment arrived (once)tx with status: "paid"
onClosethe popup closed, for any reasontx
onErrorthe payment could not start{ code, message, field }

tx is { reference, status, amount, merchant_reference, mode }. reference is ours (the same one GET /payments/{reference} and the webhook use); merchant_reference is the reference you passed.

tx.status on close:

statusmeaning
paidreceived in full
pendingthe payer says they already sent it; wait for the webhook
cancelledthe payer cancelled before paying (a late transfer still credits you)
expiredthe 20 minutes ran out
underpaid / overpaidarrived, but not the exact amount
dismissedclosed before the payment window loaded
failedit never started; onError already said why

#References

Pass your own reference (letters, numbers, . _ : -, up to 80). The same reference returns the same payment, so a double click or a page reload opens the payment already in progress rather than a second one, and its amount cannot be changed by calling again. Use a new reference for each new attempt (after a payment expires or is cancelled). A reference already used by a payment your server created cannot be reopened in the popup (invalid_request, field: reference).

#Which sites

  • Live keys start payments only from the sites registered for the business, over https, and only those sites can show the popup. Exact hosts: example.com does not cover pay.example.com.
  • Test keys work from any https page and from localhost, once the business is switched on. The popup then shows test buttons that complete a payment and fire your test webhook. Try it at https://paymonetra.com/inline-demo.html with a pk_test_ key.

#Errors

codewhy
invalid_keyno key, or a secret key passed (rotate it)
unauthorizedthe public key is unknown or revoked
not_enabledinline checkout is not switched on for the business
origin_not_alloweda live key on a site that is not registered, or a test key on a plain http page
not_verifiedlive key, business not verified
invalid_requestfield names it: amount (at least NGN 100), email, reference
amount_over_limit, too_many_pendingas for POST /payments
rate_limitedmore than 30 starts in 10 minutes from one address, or 600 an hour on one key
network_errorthe payer is offline

#Under the hood

Nothing here needs calling directly. It is here for a page with its own CSP.

The script calls POST https://pay.paymonetra.com/api/gateway/v1/inline/payments with the public key and the fields above, then frames https://pay.paymonetra.com/{reference}?embed=1&o={your origin}, which sends Content-Security-Policy: frame-ancestors {your origin} only when that origin is allowed. The two talk with postMessage, checked by origin both ways. Nothing here needs calling directly.