bahaa-io / gateway-php-sdk
Official PHP SDK for Bahaa Gateway.
Requires
- php: >=7.4
- ext-curl: *
- ext-json: *
README
Official PHP SDK for Bahaa Gateway — accept crypto payments on TRON and TON networks. Create invoices, track payments, manage withdrawals, and securely verify webhooks with just a few lines of code.
Requirements
- PHP 7.4 or later
ext-curlext-json
Installation
composer require bahaa-io/gateway-php-sdk
Quick Start
<?php require __DIR__ . '/vendor/autoload.php'; use Bahaa\Gateway\Client; $gateway = new Client( 'pk_your_api_key', // API key 'sk_your_api_secret' // API secret ); // Create a $50 USDT invoice $invoice = $gateway->createInvoice(50.00, 'USDT', [ 'description' => 'Order #1234', ]); echo $invoice['payment_url']; // → https://gateway.bahaa.io/abc123...
Authentication
All merchant endpoints are signed automatically. The SDK computes an HMAC-SHA256 signature from your API secret on every request — you don't need to do anything manually.
| Header | Description |
|---|---|
X-API-Key |
Your merchant API key (pk_...) |
X-Timestamp |
Current UNIX epoch |
X-Signature |
HMAC-SHA256 of timestamp\nmethod\npath\nbody |
API Reference
Public Endpoints
These don't require authentication.
// Health check $gateway->health(); // → ['status' => 'ok'] // List supported networks $networks = $gateway->getNetworks(); // → ['networks' => [['name' => 'tron', ...], ['name' => 'ton', ...]]] // List supported symbols (optionally filter by network) $symbols = $gateway->getSymbols(); $symbols = $gateway->getSymbols('tron');
Merchant Profile
$profile = $gateway->getProfile(); // → ['id' => 1, 'email' => '...', 'fee_percent' => 1.0, ...]
Invoices
// Create invoice $invoice = $gateway->createInvoice(100.00, 'USDT', [ 'description' => 'Premium Plan', 'fee_payer' => 'user', // or 'merchant' (default) 'allow_networks' => ['tron', 'ton'], // restrict networks 'allow_symbols' => ['USDT'], // restrict symbols ]); echo $invoice['id']; // "f7a8b..." echo $invoice['payment_url']; // full URL to the payment page // Build a payment URL with language/theme $url = $gateway->paymentUrl($invoice['id'], 'fa', 'dark'); // → https://gateway.bahaa.io/f7a8b...?lang=fa&theme=dark // Get invoice $invoice = $gateway->getInvoice('f7a8b...'); // List invoices (with optional filters) $list = $gateway->getInvoices(['status' => 'completed', 'limit' => 10]); foreach ($list['invoices'] as $inv) { echo $inv['id'] . ' — ' . $inv['status'] . "\n"; } // Cancel invoice $result = $gateway->cancelInvoice('f7a8b...'); // → ['id' => 'f7a8b...', 'status' => 'cancelled']
Hosted checkout (public, no HMAC)
Same routes as the browser payment page: GET /{invoice_id}, POST …/select, GET …/status, POST …/cancel, and GET …/ws over WebSocket. These do not use your API key — safe to call from a server building a custom checkout.
$id = $invoice['id']; // After the shopper picks chain + token $selected = $gateway->checkoutSelect($id, 'tron', 'USDT'); // Poll status $live = $gateway->checkoutStatus($id); // Shopper cancels from checkout $gateway->checkoutCancel($id);
WebSocket (live updates) — blocking call until the gateway closes the connection (e.g. invoice completed / expired / cancelled). Each text frame is JSON like the /status response.
$gateway->listenCheckoutUpdates($id, function (array $frame) { $data = $frame['data'] ?? $frame; // inspect status, confirmations, tx_hash, … }, 300); // optional read timeout in seconds (default max(120, HTTP timeout)) // Or build the URL yourself (e.g. for another WS client): $url = $gateway->checkoutWebSocketUrl($id);
wss:// needs PHP openssl (see composer.json suggest). Self-hosted gateway: pass a fourth constructor argument to Client:
$gateway = new Client($pk, $sk, 30, 'https://pay.example.com');
Balance
$balance = $gateway->getBalance(); foreach ($balance['balances'] as $b) { echo $b['symbol'] . ': ' . $b['available'] . "\n"; }
Withdrawals
// Create withdrawal $wd = $gateway->createWithdrawal('tron', 'USDT', 50.0, 'TQd8...'); echo $wd['id']; // withdrawal ID echo $wd['status']; // "pending" // Get withdrawal $wd = $gateway->getWithdrawal('wd_abc...'); // List withdrawals $list = $gateway->getWithdrawals(['limit' => 20]);
Transactions
// Get transaction $tx = $gateway->getTransaction(42); // List transactions $list = $gateway->getTransactions(['limit' => 50]);
Webhooks
When an invoice status changes, Bahaa Gateway sends a POST request to your configured webhook URL. The SDK provides a simple way to verify and parse these requests.
Receiving Webhooks
<?php // webhook.php require __DIR__ . '/vendor/autoload.php'; use Bahaa\Gateway\Webhook; use Bahaa\Gateway\Exception\GatewayException; $webhook = new Webhook('sk_your_api_secret'); try { $payload = $webhook->verify(); } catch (GatewayException $e) { http_response_code(400); exit('Invalid webhook: ' . $e->getMessage()); } $event = $payload['event']; $data = $payload['data']; switch ($event) { case 'invoice.confirming': // Payment detected, waiting for confirmations // $data['invoice_id'], $data['tx_hash'], ... break; case 'invoice.completed': // Payment confirmed! Fulfill the order. markOrderAsPaid($data['invoice_id']); break; case 'invoice.cancelled': // Cancelled via API, checkout, or policy — release holds, stop polling. break; case 'invoice.expired': // TTL passed with no payment — treat as abandoned checkout. break; } http_response_code(200); echo 'OK';
Using via the Client
You can also create a webhook verifier from an existing client instance:
$gateway = new Client('pk_...', 'sk_...'); $payload = $gateway->webhook()->verify();
Webhook Payload
{
"event": "invoice.completed",
"timestamp": 1708790400,
"data": {
"invoice_id": "abc123",
"amount": 50.00,
"symbol": "USDT",
"status": "completed",
"tx_hash": "0x...",
"crypto_amount": 50.123456,
"crypto_symbol": "TRX",
"crypto_network": "tron"
}
}
Webhook Events
| Event | Description |
|---|---|
invoice.confirming |
Payment detected on-chain, waiting for block confirmations. |
invoice.completed |
Payment fully confirmed, merchant balance credited. |
invoice.cancelled |
Invoice cancelled (merchant API, hosted checkout, or operator) before completion. |
invoice.expired |
Invoice TTL elapsed with no qualifying payment. |
Signature Verification (Manual)
If you prefer to verify manually without the SDK:
$timestamp = $_SERVER['HTTP_X_GATEWAY_TIMESTAMP']; $signature = $_SERVER['HTTP_X_GATEWAY_SIGNATURE']; $body = file_get_contents('php://input'); $expected = hash_hmac('sha256', $timestamp . '.' . $body, $apiSecret); if (!hash_equals($expected, $signature)) { die('Invalid signature'); }
Error Handling
The SDK throws specific exceptions for different error types:
use Bahaa\Gateway\Exception\GatewayException; use Bahaa\Gateway\Exception\AuthenticationException; use Bahaa\Gateway\Exception\ValidationException; use Bahaa\Gateway\Exception\NotFoundException; try { $invoice = $gateway->getInvoice('nonexistent'); } catch (NotFoundException $e) { echo 'Not found: ' . $e->getMessage(); } catch (AuthenticationException $e) { echo 'Auth error: ' . $e->getMessage(); } catch (ValidationException $e) { echo 'Validation: ' . $e->getMessage(); echo 'Code: ' . $e->getErrorCode(); } catch (GatewayException $e) { echo 'Gateway error: ' . $e->getMessage(); echo 'HTTP status: ' . $e->getHttpStatus(); }
| Exception | HTTP Status | When |
|---|---|---|
AuthenticationException |
401 | Invalid API key, expired timestamp, or bad signature. |
ValidationException |
400, 422 | Invalid request parameters. |
NotFoundException |
404 | Resource not found. |
GatewayException |
Any | Base class for all gateway errors. |
Full Example
A complete payment flow:
<?php require __DIR__ . '/vendor/autoload.php'; use Bahaa\Gateway\Client; $gateway = new Client( 'pk_your_api_key', 'sk_your_api_secret' ); // 1. Create invoice $invoice = $gateway->createInvoice(25.00, 'USDT', [ 'description' => 'Monthly subscription', ]); // 2. Redirect user to payment page (Farsi, dark theme) $url = $gateway->paymentUrl($invoice['id'], 'fa', 'dark'); header('Location: ' . $url); // 3. Later, check status programmatically $status = $gateway->getInvoice($invoice['id']); echo 'Status: ' . $status['status']; // pending → awaiting_payment → confirming → completed // 4. Check your balance $balance = $gateway->getBalance(); print_r($balance['balances']); // 5. Withdraw funds $wd = $gateway->createWithdrawal('tron', 'USDT', 20.0, 'TQd8...'); echo 'Withdrawal: ' . $wd['status'];
Links
- Website: bahaa.io
- API Gateway: gateway.bahaa.io
- GitHub: github.com/bahaa-io
Contributing
Contributions are welcome! Please open an issue or submit a pull request.
License
MIT