PaymentResult.
There is no browser tab, no redirect, and no URL scheme. The camera scanner,
slide-to-pay physics, quote refresh, retries, and status polling are all inside
the sheet.

One payment, end to end, in the sample wallet app — all rendered by the SDK.
The flow, screen by screen
These are real captures from the sample wallet app paying a VietQR merchant in the sandbox.Your app: the user taps Scan & Pay

The partner app owns everything up to this point — wallet, balance, entry point.
PaymentSheet: scan the merchant QR

Native camera scanner with torch, gallery, and paste-QR fallbacks. The raw payload is validated server-side.
PaymentSheet: amount + FX quote

₫3,500,000 to the merchant, $140.00 from the user's wallet. Quotes refresh silently on expiry.
PaymentSheet: slide to pay → result

Slide-to-pay fires the confirm exactly once; the sheet polls to a terminal state and shows a shareable receipt.
Your app: back in control

The sheet dismisses and your onResult callback fires — debit your ledger, render the activity row.
Pick your platform
present call in, one PaymentResult
out — completed / canceled / failed / pending (delivered when the user
leaves while the payout is still processing, or when polling times out; the
payment resolves asynchronously and unspent funds are released automatically).
How it works
Per payment, your backend makes one HMAC-signed call — it creates the intent (passing the user’s KYC + sanctions attestations) — and Zennopay returns a short-lived session token bound to that intent. Your app passes the intent ID and token to the SDK; the SDK talks to the Zennopay API directly with the session token asAuthorization: Bearer.
Creating the intent and returning the session token is the only backend work.
It is documented end to end, with a complete Node.js reference
implementation, in Build your session endpoint.
pk_...) identifies your app and
is safe to ship in a binary. Your secret key (sk_...) HMAC-signs
server-to-server calls and never leaves your backend. The session token the
SDK holds is minted by Zennopay, scoped to a single intent, short-lived, and
opaque to you. There is no partner key pair to generate. Both keys come from
the Zennopay Console → Developers tab.What you don’t build
The SDK owns the entire payment surface, so you never build:- A QR scanner — camera capture, torch, gallery import, and a paste-QR fallback (which also makes the flow testable on simulators).
- EMVCo parsing — the raw payload is validated authoritatively server-side (CRC, tags, merchant extraction). VietQR today, PromptPay next.
- FX quoting UI — the sheet shows the bound local amount and the exact USD wallet debit, and silently re-quotes when a quote expires.
- A confirm surface — slide-to-pay fires the confirm exactly once, with an idempotency key persisted before the network call.
-
Status polling, retries, and recovery — including re-minting an expired
session via your
refreshSessionhook and recovering the true terminal state after a process death mid-confirm. Slow payouts get a processing state with honest copy, a “taking longer than usual” escalation, and apendingresult if the user leaves early:
Payouts are asynchronous. The sheet says so instead of spinning silently, and the user can safely leave.
- Per-user regulatory limits — Zennopay enforces corridor limits automatically (Vietnam: ₫5,000,000 per transaction, ₫10,000,000 per day, ₫25,000,000 per month per user) and the sheet renders the right copy.
- New corridors — when a corridor lights up (Thailand PromptPay is next), existing integrations get it with zero client work.
-
The receipt surface — you keep your own transaction-history list, but you
never build the authoritative receipt view. When a user taps a past payment,
presentReceiptreopens the branded Zennopay receipt with its live status (pending, captured, failed, or refunded).
Sample app
The screenshots above come from the Zennopay sample wallet app — a reference integration that exercises the session endpoint contract and thepresentCheckout call against the sandbox. Ask your Zennopay
integration engineer for the sample project.