Skip to main content
ShadhinPay Docs
Client libraries

PHP & Laravel

Integrate ShadhinPay from PHP or Laravel today, and track the official package.

Official package — Planned

A first-party Composer package (with a Laravel service provider) is on the roadmap. Until it ships, the cURL / Guzzle examples below work in any PHP app.

Create a payment

<?php

$base = 'https://api.shadhinpay.pay/api/v1';

$ch = curl_init("$base/payments");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'Client-Id: ' . getenv('SHADHINPAY_CLIENT_ID'),
        'Business-Id: ' . getenv('SHADHINPAY_BUSINESS_ID'),
        'X-Api-Key: ' . getenv('SHADHINPAY_API_KEY'),
        'X-Idempotency-Key: ' . bin2hex(random_bytes(16)),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'amount'        => '500.00',
        'currency'      => 'BDT',
        'merchantTxnId' => 'order-7831',
        'callbackUrl'   => 'https://shop.example.com/return',
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);

if (($body['status'] ?? null) !== 'success') {
    throw new RuntimeException($body['errorType'] ?? 'request_failed'); // see /docs/developers/errors
}

$payment = $body['data']; // ['paymentId' => ..., 'paymentUrl' => ..., ...]
// redirect the customer to $payment['paymentUrl']

Verify a webhook

Use the raw request body (php://input), not a re-encoded array:

<?php

function shadhinpay_verify(string $raw, string $header, string $secret): bool
{
    parse_str(str_replace(',', '&', $header), $parts); // t=...,v1=...  ->  t / v1
    $t = (int) ($parts['t'] ?? 0);
    if ($t === 0 || abs(time() - $t) > 300) {
        return false; // replay protection
    }
    $expected = hash_hmac('sha256', "t={$t}.{$raw}", $secret);
    return hash_equals($expected, $parts['v1'] ?? '');
}

$raw    = file_get_contents('php://input');
$header = $_SERVER['HTTP_X_SHADHINPAY_SIGNATURE'] ?? '';

if (! shadhinpay_verify($raw, $header, getenv('SHADHINPAY_WEBHOOK_SECRET'))) {
    http_response_code(400);
    exit;
}

$event = json_decode($raw, true);
// dedupe on $event['eventId'], handle $event['eventType']
http_response_code(200);
echo json_encode(['status' => 'received']);

In Laravel, read the raw body with $request->getContent() and the header with $request->header('X-ShadhinPay-Signature'). The signing scheme is documented in Webhooks.

Next steps

On this page