PHP SDK
Official server-side SDK for integrating ZevPay Checkout in PHP applications. Provides full REST API coverage with Guzzle HTTP client.
Installation
bash
composer require zevpay/zevpay-phpRequires PHP 8.1 or later.
Quick start
php
use ZevPay\ZevPay;
$zevpay = new ZevPay('sk_test_your_secret_key');
// Initialize a checkout session
$session = $zevpay->checkout->initialize([
'amount' => 500000, // ₦5,000 in kobo
'email' => 'customer@example.com',
'reference' => 'ORDER-123',
'callback_url' => 'https://yoursite.com/callback',
]);
echo $session['checkout_url'];Configuration
php
$zevpay = new ZevPay('sk_live_xxx', [
'base_url' => 'https://api.zevpaycheckout.com', // default
'timeout' => 30, // 30s request timeout (default)
'max_retries' => 2, // retries on 5xx errors (default)
]);| Option | Type | Default | Description |
|---|---|---|---|
base_url | string | https://api.zevpaycheckout.com | API base URL |
timeout | int | 30 | Request timeout in seconds |
max_retries | int | 2 | Max retries on server errors |
Secret keys only
The SDK only accepts secret keys (sk_live_* or sk_test_*). Public keys cannot be used server-side.
Checkout sessions
Initialize a session
php
$session = $zevpay->checkout->initialize([
'amount' => 500000,
'email' => 'customer@example.com',
'currency' => 'NGN',
'reference' => 'ORDER-123',
'callback_url' => 'https://yoursite.com/callback',
'metadata' => ['order_id' => '123'],
'payment_methods' => ['bank_transfer', 'payid'],
]);
// Redirect your customer to:
echo $session['checkout_url'];Verify a payment
php
$result = $zevpay->checkout->verify($session['session_id']);
if ($result['status'] === 'completed') {
echo 'Payment confirmed at: ' . $result['paid_at'];
}Get session details
php
$details = $zevpay->checkout->get('ses_abc123');Transfers
Bank transfer
php
$transfer = $zevpay->transfers->create([
'type' => 'bank_transfer',
'amount' => 1000000, // ₦10,000
'account_number' => '0123456789',
'bank_code' => '044',
'account_name' => 'John Doe',
'narration' => 'Payout',
'reference' => 'TXN-123',
]);PayID transfer
php
$transfer = $zevpay->transfers->create([
'type' => 'payid',
'amount' => 500000,
'pay_id' => 'johndoe',
'narration' => 'Payment',
]);List, verify, resolve
php
// List transfers
$transfers = $zevpay->transfers->list([
'page' => 1,
'page_size' => 20,
'status' => 'completed',
]);
// Verify a transfer
$result = $zevpay->transfers->verify('TXN-123');
// List banks
$banks = $zevpay->transfers->listBanks();
// Resolve bank account
$account = $zevpay->transfers->resolveAccount([
'account_number' => '0123456789',
'bank_code' => '044',
]);
echo $account['account_name']; // 'JOHN DOE'
// Calculate fees
$charges = $zevpay->transfers->calculateCharges(['amount' => 1000000]);
// Get wallet balance
$balance = $zevpay->transfers->getBalance();Invoices
php
// Create
$invoice = $zevpay->invoices->create([
'customer_name' => 'Jane Doe',
'customer_email' => 'jane@example.com',
'due_date' => '2026-04-01',
'line_items' => [
['description' => 'Web Design', 'quantity' => 1, 'unit_price' => 5000000],
['description' => 'Hosting (1yr)', 'quantity' => 1, 'unit_price' => 1200000],
],
'tax_rate' => 7.5,
]);
// Send (draft → sent)
$zevpay->invoices->send($invoice['public_id']);
// List
$invoices = $zevpay->invoices->list(['status' => 'sent']);
// Cancel
$zevpay->invoices->cancel($invoice['public_id']);Static PayIDs
php
// Create
$payid = $zevpay->staticPayId->create([
'pay_id' => 'mystore',
'name' => 'My Store',
'description' => 'Accept payments to my store',
]);
// Deactivate / Reactivate
$zevpay->staticPayId->deactivate($payid['id']);
$zevpay->staticPayId->reactivate($payid['id']);Dynamic PayIDs
php
// Create a time-limited payment link
$dpayid = $zevpay->dynamicPayId->create([
'amount' => 1000000,
'name' => 'Donation Drive',
'expires_in_minutes' => 60,
]);
echo $dpayid['full_pay_id']; // e.g. 'donation-drive-xyz.dpay'
// Deactivate
$zevpay->dynamicPayId->deactivate($dpayid['id']);Virtual accounts
php
// Create
$va = $zevpay->virtualAccounts->create([
'amount' => 1000000,
'validity_minutes' => 60,
]);
echo $va['account_number']; // Customer pays to this account
// List
$accounts = $zevpay->virtualAccounts->list(['status' => 'pending']);Wallet
php
// Get wallet details
$wallet = $zevpay->wallet->get();
// List members
$members = $zevpay->wallet->listMembers();
// Add / remove members
$zevpay->wallet->addMember(['pay_id' => 'johndoe']);
$zevpay->wallet->removeMember('johndoe');Webhook verification
Verify incoming webhook signatures using your webhook secret:
php
use ZevPay\Webhook;
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_ZEVPAY_SIGNATURE'] ?? '';
$secret = getenv('ZEVPAY_WEBHOOK_SECRET');
try {
$event = Webhook::constructEvent($payload, $signature, $secret);
switch ($event['event']) {
case 'charge.success':
// Handle successful checkout payment
break;
case 'transfer.success':
// Handle successful transfer
break;
case 'transfer.failed':
// Handle failed transfer
break;
case 'invoice.paid':
// Handle paid invoice
break;
}
http_response_code(200);
echo 'OK';
} catch (\ZevPay\Exceptions\ZevPayException $e) {
http_response_code(400);
echo 'Invalid signature';
}Always verify
Never process webhook events without verifying the signature. See Verifying Signatures for details.
Error handling
All API errors throw typed exceptions:
php
use ZevPay\Exceptions\ValidationException;
use ZevPay\Exceptions\AuthenticationException;
use ZevPay\Exceptions\NotFoundException;
use ZevPay\Exceptions\ConflictException;
use ZevPay\Exceptions\RateLimitException;
use ZevPay\Exceptions\ApiException;
try {
$zevpay->transfers->create([/* ... */]);
} catch (ValidationException $e) {
// 400 — invalid parameters
echo $e->errorCode; // e.g. 'VALIDATION_ERROR'
echo $e->getMessage(); // Human-readable message
print_r($e->details); // Field-level errors
} catch (AuthenticationException $e) {
// 401 — invalid API key
} catch (NotFoundException $e) {
// 404 — resource not found
} catch (ConflictException $e) {
// 409 — duplicate transaction
} catch (RateLimitException $e) {
// 429 — rate limit exceeded
echo $e->retryAfter; // seconds to wait
} catch (ApiException $e) {
// 500+ — server error
}| Exception class | Status | When |
|---|---|---|
ValidationException | 400 | Invalid request parameters |
AuthenticationException | 401 | Invalid or missing API key |
PermissionException | 403 | Insufficient permissions |
NotFoundException | 404 | Resource not found |
ConflictException | 409 | Duplicate resource |
RateLimitException | 429 | Too many requests |
ApiException | 500+ | Server error |
Full example — Laravel
php
// routes/web.php
use Illuminate\Http\Request;
use ZevPay\ZevPay;
use ZevPay\Webhook;
Route::post('/api/pay', function (Request $request) {
$zevpay = new ZevPay(config('services.zevpay.secret'));
$session = $zevpay->checkout->initialize([
'amount' => $request->input('amount'),
'email' => $request->input('email'),
'reference' => 'ORDER-' . time(),
'callback_url' => url('/api/callback'),
]);
return response()->json(['checkout_url' => $session['checkout_url']]);
});
Route::get('/api/callback', function (Request $request) {
$zevpay = new ZevPay(config('services.zevpay.secret'));
$result = $zevpay->checkout->verify($request->query('session_id'));
if ($result['status'] === 'completed') {
return 'Payment successful!';
}
return 'Payment not completed yet.';
});
Route::post('/webhooks/zevpay', function (Request $request) {
try {
$event = Webhook::constructEvent(
$request->getContent(),
$request->header('x-zevpay-signature', ''),
config('services.zevpay.webhook_secret'),
);
logger()->info('Webhook received', $event);
return response('OK', 200);
} catch (\Exception $e) {
return response('Invalid signature', 400);
}
});Resources
- API Reference — Full endpoint documentation
- Webhook Events — All event types
- Packagist — Package registry