Standard Checkout
Redirect customers to a hosted checkout page on ZevPay. Create a session on your server with your secret key, then redirect the customer to the checkout URL.
How it works
- Your server creates a checkout session via the API (using your secret key)
- You redirect the customer to the returned
checkout_url - Customer selects a payment method and completes payment on the ZevPay checkout page
- Customer is redirected back to your
callback_urlwith the payment status
Integration
Step 1: Create a session (server-side)
js
const response = await fetch('https://api.zevpaycheckout.com/v1/checkout/session/initialize', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': 'sk_test_your_secret_key',
},
body: JSON.stringify({
amount: 500000, // ₦5,000 in kobo
currency: 'NGN',
email: 'customer@example.com',
customer_name: 'John Doe', // optional
callback_url: 'https://yoursite.com/payment/callback',
reference: 'order_12345', // optional
metadata: { orderId: '12345' }, // optional
}),
});
const { data } = await response.json();
// data.checkout_url → "https://secure.zevpaycheckout.com/{sessionId}"
// data.session_id → save this for verificationpython
import requests
response = requests.post(
"https://api.zevpaycheckout.com/v1/checkout/session/initialize",
headers={
"Content-Type": "application/json",
"x-api-key": "sk_test_your_secret_key",
},
json={
"amount": 500000,
"currency": "NGN",
"email": "customer@example.com",
"customer_name": "John Doe",
"callback_url": "https://yoursite.com/payment/callback",
"reference": "order_12345",
},
)
data = response.json()["data"]
checkout_url = data["checkout_url"]
session_id = data["session_id"]php
$ch = curl_init('https://api.zevpaycheckout.com/v1/checkout/session/initialize');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'x-api-key: sk_test_your_secret_key',
],
CURLOPT_POSTFIELDS => json_encode([
'amount' => 500000,
'currency' => 'NGN',
'email' => 'customer@example.com',
'customer_name' => 'John Doe',
'callback_url' => 'https://yoursite.com/payment/callback',
'reference' => 'order_12345',
]),
CURLOPT_RETURNTRANSFER => true,
]);
$response = json_decode(curl_exec($ch), true);
$checkoutUrl = $response['data']['checkout_url'];
$sessionId = $response['data']['session_id'];Step 2: Redirect the customer
Redirect the customer to the checkout_url returned from the initialization call:
js
// Browser redirect
window.location.href = data.checkout_url;Or link directly:
html
<a href="https://secure.zevpaycheckout.com/ecc48011-e36e-4741-9b99-657f4a1ee86e">
Complete Payment
</a>Step 3: Handle the callback
After the customer completes (or cancels) payment, they are redirected to your callback_url with query parameters:
https://yoursite.com/payment/callback?status=success&reference=ZVP-CKO-S-abc123Callback query parameters:
| Parameter | Values | Description |
|---|---|---|
status | success | Payment completed |
status | cancelled | Customer cancelled/closed checkout |
status | expired | Session expired |
reference | string | Transaction reference (only on success) |
Step 4: Verify the payment (server-side)
Always verify
Never trust the callback query parameters alone. Always verify payment on your server.
js
// Your callback route handler
app.get('/payment/callback', async (req, res) => {
const { status, reference } = req.query;
if (status === 'success') {
// Verify with ZevPay
const verification = await fetch(
`https://api.zevpaycheckout.com/v1/checkout/session/${sessionId}/verify`,
{
headers: { 'x-api-key': 'sk_test_your_secret_key' },
}
);
const { data } = await verification.json();
if (data.status === 'completed') {
// Payment confirmed — fulfill the order
await fulfillOrder(data.reference, data.amount);
res.redirect('/order/success');
} else {
res.redirect('/order/pending');
}
} else if (status === 'cancelled') {
res.redirect('/checkout');
} else if (status === 'expired') {
res.redirect('/checkout?error=expired');
}
});Initialization parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
amount | integer | Yes | Amount in kobo |
currency | string | Yes | Currency code ("NGN") |
email | string | Yes | Customer's email address |
callback_url | string | Yes | URL to redirect after payment |
reference | string | No | Your unique transaction reference |
customer_name | string | No | Customer's name — displayed in the dashboard instead of "Anonymous" |
metadata | object | No | Custom data attached to the session |
payment_methods | string[] | No | Enabled methods: ["bank_transfer", "payid"] |
Checkout page states
| State | Description |
|---|---|
| Loading | Fetching session details |
| Ready | Payment methods displayed, awaiting selection |
| Expired | Session has timed out, option to return to merchant |
| Not Found | Invalid session ID |
| Error | API or network error |
Full example (Express.js)
js
const express = require('express');
const app = express();
// Create checkout session
app.post('/create-checkout', async (req, res) => {
const response = await fetch('https://api.zevpaycheckout.com/v1/checkout/session/initialize', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.ZEVPAY_SECRET_KEY,
},
body: JSON.stringify({
amount: req.body.amount * 100, // Convert Naira to kobo
currency: 'NGN',
email: req.body.email,
callback_url: `${req.protocol}://${req.get('host')}/payment/callback`,
reference: `order_${Date.now()}`,
metadata: { userId: req.user.id },
}),
});
const { data } = await response.json();
// Save session_id for later verification
await saveSessionId(req.user.id, data.session_id);
// Redirect to checkout
res.redirect(data.checkout_url);
});
// Handle callback
app.get('/payment/callback', async (req, res) => {
const { status, reference } = req.query;
if (status !== 'success') {
return res.redirect('/checkout?error=' + status);
}
// Verify payment
const sessionId = await getSessionIdForUser(req.user.id);
const verification = await fetch(
`https://api.zevpaycheckout.com/v1/checkout/session/${sessionId}/verify`,
{ headers: { 'x-api-key': process.env.ZEVPAY_SECRET_KEY } }
);
const { data } = await verification.json();
if (data.status === 'completed') {
await fulfillOrder(data);
res.redirect('/order/success');
} else {
res.redirect('/order/pending');
}
});
app.listen(3000);Compared to Inline Checkout
| Aspect | Standard | Inline |
|---|---|---|
| Session creation | Server-side (secret key) | Client-side (public key) |
| User experience | Full-page redirect | Modal overlay |
| Backend required | Yes | No |
| Callback method | URL redirect | JavaScript function |
| Best for | E-commerce, invoices | Quick checkouts, SPAs |
Resources
- API Reference — Full endpoint documentation
- Initialize Session — Session creation endpoint
- Verify Session — Verification endpoint
- Inline Checkout — Modal-based alternative
- Webhook Events — All event types