Search by

hyprdev / usimpay-laravel

syazwizaili

Framework-agnostic PHP and Laravel SDK for USIMPay

v0.1.0 2026-09-14 02:39 UTC

This package is auto-updated.

Last update: 2026-09-14 02:40:29 UTC


README

A small PHP 8.2+ SDK for the USIMPay API. The core client is framework-independent; Laravel package discovery, configuration, and a facade are included.

Installation

composer require hyprdev/usimpay-laravel

Laravel discovers the service provider automatically. Publish its configuration:

php artisan vendor:publish --tag=usimpay-config

Configure credentials in .env (never commit real keys):

USIMPAY_ENVIRONMENT=sandbox
USIMPAY_API_KEY=usim_test_...
USIMPAY_SECRET_KEY=...
USIMPAY_WEBHOOK_SIGNING_KEY=whsec_test_...

The optional USIMPAY_SANDBOX_BASE_URL and USIMPAY_PRODUCTION_BASE_URL variables override the API hosts.

By default, the SDK uses https://sandbox-api.usimpay.com.my/v1 for Sandbox and https://api.usimpay.com.my/v1 for Production. Overrides may contain either the API origin or the full /v1 API base.

Laravel usage

Type-hint the client in a controller or service:

use Hyprdev\UsimPay\UsimPayClient;

public function store(UsimPayClient $usimPay)
{
    $payment = $usimPay->createPayment([
        'reference' => 'ORD-10001',
        'amount' => '150.00',
        'currency' => 'MYR',
        'description' => 'Order ORD-10001',
        'customer' => [
            'name' => 'Ahmad Ali',
            'email' => 'ahmad@example.com',
        ],
    ], 'order-10001-attempt-1');

    return redirect()->away($payment['data']['payment_url']);
}

The UsimPay facade is also auto-discovered. Other methods are ping(), getPayment(), listBanks(), listCollections(), createCollection(), getCollection(), updateCollection(), and deactivateCollection().

Standalone PHP usage

use Hyprdev\UsimPay\UsimPayClient;
use Hyprdev\UsimPay\UsimPayConfig;

$config = new UsimPayConfig('sandbox', $_ENV['USIMPAY_API_KEY'], $_ENV['USIMPAY_SECRET_KEY']);
$client = new UsimPayClient($config);
$banks = $client->listBanks('b2c');
$availableB2cBanks = $banks['data']['b2c'];

Failed HTTP responses throw ApiException, transport failures throw TransportException, and invalid local input throws ValidationException.

Verify webhooks

Always verify the exact raw request bytes before decoding JSON:

use Hyprdev\UsimPay\WebhookVerifier;

$payload = $request->getContent();
$timestamp = (string) $request->header('X-USIMPay-Timestamp');
$signature = (string) $request->header('X-USIMPay-Signature');

$verifier = new WebhookVerifier(config('usimpay.webhook_signing_key'));
if (!$verifier->verify($payload, $timestamp, $signature, toleranceSeconds: 300)) {
    abort(401, 'Invalid webhook signature');
}

$event = json_decode($payload, true, flags: JSON_THROW_ON_ERROR);

Store processed event_id values to make webhook handling idempotent. A timestamp tolerance helps reject replayed deliveries.

USIMPay sends merchant webhooks only for verified terminal PayNet decisions: payment.success, payment.failed, and payment.cancelled. Use getPayment() when reconciliation is required.

Development

composer install
composer test