Payment Lifecycle
This page describes the complete flow from session creation to payment confirmation.
Flow overview
Your Server ZevPay API Customer
│ │ │
│ POST /initialize │ │
│─────────────────────────────▶│ │
│ { session_id, checkout_url }│ │
│◀─────────────────────────────│ │
│ │ │
│ Return checkout_url or │ │
│ pass public key to SDK │ │
│─────────────────────────────────────────────────────────▶│
│ │ │
│ │ POST /payment-method │
│ │◀─────────────────────────│
│ │ { account_number, ... } │
│ │─────────────────────────▶│
│ │ │
│ │ Customer pays │
│ │◀─────────────────────────│
│ │ │
│ Webhook: charge.success │ │
│◀─────────────────────────────│ │
│ │ │
│ GET /verify (optional) │ │
│─────────────────────────────▶│ │
│ { status: "completed" } │ │
│◀─────────────────────────────│ │Step-by-step
1. Initialize session
Your server calls POST /v1/checkout/session/initialize with your secret key, the amount, and customer email.
2. Customer selects payment method
The checkout UI (inline modal or standard page) presents the available payment methods. When the customer selects one, the SDK calls POST /v1/checkout/session/:id/payment-method.
For bank transfer, this returns a virtual account number. For PayID, this returns a dynamic PayID.
3. Customer completes payment
The customer transfers money (via bank or ZevPay app). ZevPay detects the transfer automatically.
4. Payment confirmed
ZevPay:
- Marks the session as
completed - Sends a
charge.successwebhook to your server - The checkout UI detects the completion via polling and shows a success screen
5. You verify and fulfill
Your server verifies the payment via the webhook or the /verify endpoint, then fulfills the order.
Polling
Both the inline and standard checkout SDKs poll the /verify endpoint every 5 seconds after the customer selects a payment method. When the status changes to completed, the success screen is shown automatically.
Idempotency
- Each session can only be completed once
- Duplicate bank transfers to the same virtual account are rejected
- The
referenceparameter on initialization helps you prevent duplicate sessions
Error handling
| Scenario | What happens |
|---|---|
| Session expires (30 min) | Status set to expired, customer shown expiry screen |
| Transfer amount mismatch | Transfer may not be matched to the session |
| Network error during polling | SDK retries silently on next poll interval |
| Webhook delivery fails | Logged in dashboard, you should poll /verify as backup |