Search by

zionpe / zionpe-php

zionpe

ZionPe Payments and ZionPe Billing for PHP: signed checkout sessions, refunds, and the Billing API (customers, plans, subscriptions, invoices, quotes, hosted links, webhook endpoints) with webhook verification. No dependencies beyond curl and json.

v1.1.0 2026-09-06 00:20 UTC

This package is auto-updated.

Last update: 2026-09-06 00:20:59 UTC


README

ZionPe Payments for PHP 8. Signed checkout sessions, signed session reads, refunds and webhook verification. Needs only curl and json.

composer require zionpe/zionpe-php

Setup

use ZionPe\ZionPe;

$zionpe = new ZionPe(getenv('ZIONPE_SITE_KEY'), getenv('ZIONPE_SITE_SECRET'));

Both values are on Dashboard → ZionPe Payments → Custom Website (live) and Developers → Sandbox (sandbox). Every request is signed for you.

Check the signing works

$zionpe->ping(); // returns the ping response, throws ZionPeException otherwise

Create a checkout session

Amounts are in the main unit: 29.99 is £29.99.

$session = $zionpe->createCheckoutSession([
    'line_items'     => [['name' => 'Premium Plan', 'amount' => 29.99, 'quantity' => 1]],
    'currency'       => 'GBP',
    'customer_email' => $order->email,
    'success_url'    => 'https://yoursite.com/orders/' . $order->id . '/thanks',
    'cancel_url'     => 'https://yoursite.com/cart',
    'metadata'       => ['order_id' => (string) $order->id],
], 'order-' . $order->id); // idempotency key: a retry returns the same session

header('Location: ' . $session['checkout_url'], true, 303);
exit;

Read a session from your server

$s = $zionpe->retrieveCheckoutSession($sessionId);
if ($s['status'] === 'completed' && $s['metadata']['order_id'] === (string) $order->id) { /* paid */ }

Refund

$zionpe->createRefund('pi_…', 10.00, 'Damaged item');

Webhooks

use ZionPe\ZionPe;
use ZionPe\ZionPeException;

$raw = file_get_contents('php://input');
try {
    $event = ZionPe::constructWebhookEvent($raw, $_SERVER['HTTP_X_ZIONPE_SIGNATURE'] ?? null, getenv('ZIONPE_WEBHOOK_SECRET'));
} catch (ZionPeException $e) {
    http_response_code(400);
    exit('bad signature');
}
if (already_seen($event['id'])) { http_response_code(200); exit; }
remember($event['id']);

if ($event['type'] === 'checkout.session.completed') {
    fulfil($event['data']['object']['metadata']['order_id'] ?? null, $event['data']['object']);
}
http_response_code(200);

Laravel

Bind it once and inject it:

// AppServiceProvider::register()
$this->app->singleton(ZionPe::class, fn () => new ZionPe(config('services.zionpe.key'), config('services.zionpe.secret')));

Exclude /webhooks/zionpe from CSRF and read $request->getContent() as the raw body.

Errors

Every failed call throws ZionPeException with errorCode (stable, e.g. signature_invalid, rate_limited), status and body. Full list: https://docs.zionpe.com/api-reference/errors

License

MIT

ZionPe Billing

$billing = new \ZionPe\Billing(getenv('ZIONPE_BILLING_KEY')); // zionpe_live_sk_… or zionpe_test_sk_…

$customer = $billing->customers()->create(['email' => 'ada@example.com', 'name' => 'Ada Lovelace']);
$plan     = $billing->plans()->create(['name' => 'Pro', 'product_family' => 'saas', 'amount' => 19, 'currency' => 'GBP', 'interval' => 'monthly']);
$sub      = $billing->subscriptions()->create(['customer' => $customer['id'], 'plan' => $plan['id']]);

$invoice  = $billing->invoices()->list(['subscription_id' => $sub['id']])['data'][0];
$link     = $billing->checkoutSessions()->create(['type' => 'invoice', 'invoice' => $invoice['id']]);
echo $link['url']; // a ZionPe Billing pay page on your domain

$billing->subscriptions()->action($sub['id'], 'cancel', ['at_period_end' => true]);
$billing->invoices()->action($invoice['id'], 'record-payment', ['method' => 'bank_transfer', 'reference' => 'BACS-1042']);

Money is in the main unit (19 is £19.00). Every write sends an Idempotency-Key (pass your own as the last argument). Errors throw \ZionPe\ZionPeException with errorCode and status.

Webhooks (billing.* events) verify with the same helper as Payments:

$event = \ZionPe\Billing::constructWebhookEvent(file_get_contents('php://input'), $_SERVER['HTTP_X_ZIONPE_SIGNATURE'] ?? null, getenv('ZIONPE_BILLING_WHSEC'));