PHP SDK
Official PHP SDK for Scan & Pay — accept PayTo PayID payments via QR code from any PHP backend (Laravel, Symfony, Magento, plain PHP, …).
Install
composer require scanandpay/phpRequires PHP 8.1+ with the curl, json, and hash extensions.
Quickstart
use ScanAndPay\ScanAndPay;
use ScanAndPay\Exceptions\WebhookSignatureException;
$client = new ScanAndPay(
merchantId: getenv('SCANANDPAY_MERCHANT_ID'),
apiSecret: getenv('SCANANDPAY_API_SECRET'),
webhookSecret: getenv('SCANANDPAY_WEBHOOK_SECRET'), // optional
);
// 1. Create a session at checkout. Amount is float dollars.
$session = $client->createSession(
amount: 19.90, // $19.90
platformOrderId: 'order_456',
payId: 'merchant@example.com.au',
merchantName: 'Acme Coffee',
);
// 2. Render the QR widget on the page.
echo scanandpay_checkout($session, pollUrl: '/scanandpay/status');
// 3. In your webhook handler, verify and consume the event.
try {
$event = $client->webhooks()->verify(
signature: $_SERVER['HTTP_X_SCANPAY_SIGNATURE'] ?? '',
body: file_get_contents('php://input'),
);
if ($event->isPaid()) {
// Mark order paid using $event->orderId, $event->txId, ...
}
} catch (WebhookSignatureException $e) {
http_response_code(401);
exit('Invalid webhook');
}Amount format
amount is always float dollars (e.g. 19.90 for $19.90). This matches the Scan & Pay API directly — no multiplication or division needed.
$client->createSession(amount: 19.90, ...); // ✓ $19.90
$client->createSession(amount: 0.50, ...); // ✓ $0.50
$client->createSession(amount: 1000.00, ...); // ✓ $1,000.00
$client->createSession(amount: -1, ...); // ✗ ValidationException
$client->createSession(amount: 0, ...); // ✗ ValidationExceptionFor display, use $session->amount directly:
$display = number_format($session->amount, 2); // "19.90"Error handling
All thrown errors extend ScanAndPay\\Exceptions\\ScanAndPayException.
| Class | When |
|---|---|
| ValidationException | Bad input rejected before any HTTP call. |
| AuthenticationException | API rejected API Secret (rotate your keys). |
| ApiException | Non-2xx response from the API. |
| NetworkException | Transport failure after exhausting retries. |
| WebhookSignatureException | Webhook signature or timestamp check failed. |