PHP SDK

Official PHP client with retries, idempotency and webhook verification

The official PHP SDK wraps the same REST API documented here. It only needs ext-curl and ext-json and adds retries, idempotency keys, auto-pagination and webhook signature verification.

Status: the package is not on Packagist yet. Until the first release lands you can install it from the repository, or use the plain REST examples in the other articles.

Install

composer require southbill/southbill-php

Requires PHP 7.4 or newer.

Create a checkout session

use Southbill\Southbill;

$southbill = new Southbill(['api_key' => getenv('SOUTHBILL_API_KEY')]);

$session = $southbill->checkout->sessions->create([
    'amount' => 4900,
    'currency' => 'EUR',
    'customer_email' => 'ada@acme.com',
    'success_url' => 'https://acme.com/thanks',
]);

echo $session['checkout_url'];

All merchant API keys are live keys (sk_live_...). Southbill has no test mode. $southbill->isLivemode() is false for them.

Resources

Namespace Methods
checkout->sessions create, retrieve, all, expire
customers create, retrieve, update, all, delete
invoices create, retrieve, update, all, send, void, markPaid
products create, retrieve, update, all
payments retrieve, all
refunds create
subscriptions create, retrieve, all, cancel
events retrieve, all, replay

Payouts, bank details, KYC and API-key management stay merchant-controlled in the dashboard and are intentionally not part of the API surface.

Idempotency

Every POST sends an Idempotency-Key header (random UUID). Pass your own for safe retries across processes:

$southbill->invoices->create($params, "inv-{$orderId}");

Pagination

foreach ($southbill->invoices->autoPagingEach(['status' => 'open']) as $invoice) {
    echo $invoice['id'];
}

Errors and retries

Network errors, 429 and 5xx are retried twice with exponential backoff (configurable via max_retries). Everything else throws Southbill\SouthbillError:

use Southbill\SouthbillError;

try {
    $southbill->refunds->create(['payment' => 'pi_123', 'amount' => 500]);
} catch (SouthbillError $e) {
    error_log("{$e->status} {$e->type} {$e->param} {$e->requestId}");
}

Webhooks

Verify the raw request body — never a re-serialized array.

use Southbill\Webhooks;
use Southbill\SouthbillSignatureError;

$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_SOUTHBILL_SIGNATURE'] ?? '';

try {
    $event = Webhooks::constructEvent($payload, $signature, getenv('SOUTHBILL_WEBHOOK_SECRET'));
} catch (SouthbillSignatureError $e) {
    http_response_code(400);
    exit;
}

if ($event['type'] === 'invoice.paid') {
    // handle it
}

http_response_code(200);

Signature scheme: Southbill-Signature: t=<unix seconds>,v1=<hex> where the hex digest is HMAC-SHA256(secret, "<timestamp>.<raw body>"). Default clock tolerance is 300 seconds.

Configuration

new Southbill([
    'api_key' => getenv('SOUTHBILL_API_KEY'),
    'base_url' => 'https://api.southbill.com',
    'timeout' => 30,
    'max_retries' => 2,
]);