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,
]);