Skip to content

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-php

Requires 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)
]);
OptionTypeDefaultDescription
base_urlstringhttps://api.zevpaycheckout.comAPI base URL
timeoutint30Request timeout in seconds
max_retriesint2Max 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 classStatusWhen
ValidationException400Invalid request parameters
AuthenticationException401Invalid or missing API key
PermissionException403Insufficient permissions
NotFoundException404Resource not found
ConflictException409Duplicate resource
RateLimitException429Too many requests
ApiException500+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

ZevPay Checkout Developer Documentation