surepay-one/sdk 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

surepay-one/sdk

最新稳定版本:v0.1.0

Composer 安装命令:

composer require surepay-one/sdk

包简介

Official PHP SDK for the SurePay Payment Gateway API

README 文档

README

Official PHP client library for the SurePay Merchant API.

CI Packagist

Requirements

  • PHP 8.1+
  • ext-curl
  • ext-json
  • Zero non-stdlib dependencies

Install

composer require surepay-one/sdk

Quick start

use SurePay\SurePay;
use SurePay\Request\CreateDepositRequest;
use SurePay\Request\CreatePayoutRequest;

$client = SurePay::builder(
    getenv('SUREPAY_API_KEY'),    // tpay_live_... or tpay_test_...
    getenv('SUREPAY_API_SECRET'), // tpay_sec_... — enables auto HMAC signing
)->build();

// Check wallet balance
$balance = $client->balance->get();
echo "Available: {$balance->available} VND\n";

// Create a deposit order (thu hộ)
$deposit = $client->deposits->create(
    CreateDepositRequest::builder(100_000)
        ->withRequestId('ORD-20260610-001')
        ->build()
);
echo "Checkout URL: {$deposit->checkoutUrl}\n";

// Create a payout (chi hộ)
try {
    $payout = $client->payouts->create(
        CreatePayoutRequest::builder(500_000, 'VCB', '1234567890', 'NGUYEN VAN A', 'Salary June 2026')
            ->build()
    );
    echo "Payout ID: {$payout->id}\n";
} catch (SurePayException $e) {
    if ($e->isInsufficientBalance()) {
        echo "Not enough balance — top up first\n";
    }
}

Configuration

$client = SurePay::builder($apiKey, $apiSecret)
    ->baseUrl('https://api.surepay.one/merchant/v1') // override for local/staging
    ->timeout(15)                                     // seconds
    ->maxRetries(3)                                   // retries on 5xx and network errors
    ->build();
Option Default Description
baseUrl(string) https://api.surepay.one/merchant/v1 Override base URL for local dev or staging
timeout(int) 30 HTTP request timeout in seconds
maxRetries(int) 3 Retry attempts on 5xx and network errors

Authentication

Every request requires an API key sent as an X-API-Key header. When apiSecret is provided to builder(), every outgoing request is automatically signed with HMAC-SHA256 — the X-Signature and X-Timestamp headers are attached with no extra code needed.

API reference

Balance

$client->balance->get()

Get current wallet balance. Requires: balance:read scope.

$balance = $client->balance->get();
// $balance->balance   — total wallet balance in VND
// $balance->hold      — reserved for in-flight transactions
// $balance->available — balance - hold
// $balance->currency  — always "VND"

Deposits

$client->deposits->list(params)

Paginated list of deposit (thu hộ) orders. Requires: deposits:read scope.

use SurePay\Params\DepositsListParams;

$result = $client->deposits->list(
    DepositsListParams::create()
        ->page(1)
        ->pageSize(20)
        ->status('success')       // pending|processing|success|failed|expired|cancelled
        ->fromDate('2026-06-01')  // YYYY-MM-DD
        ->toDate('2026-06-30')
);
// $result->items      — Deposit[]
// $result->total      — total matching records
// $result->totalPages — total pages

$client->deposits->create(req)

Create a new deposit order. Returns a checkoutUrl (redirect) and qrCode (VietQR). Requires: deposits:write scope.

use SurePay\Request\CreateDepositRequest;

$deposit = $client->deposits->create(
    CreateDepositRequest::builder(100_000)         // amount in VND, required
        ->withRequestId('ORD-20260610-001')        // your order ID — optional, for idempotency
        // Chính chủ verification — all optional:
        ->withSenderBankId('970436')
        ->withSenderBankName('Vietcombank')
        ->withSenderAccount('1234567890')
        ->withSenderName('NGUYEN VAN A')
        ->build()
);
echo $deposit->checkoutUrl;
echo $deposit->qrCode;

Response fields:

Field Type Description
id string SurePay transaction UUID
requestId string Your order ID
amount int Amount in VND
status string pending, processing, success, failed, expired, cancelled
checkoutUrl string Redirect URL for payer
qrCode string VietQR data string
createdAt string ISO 8601 timestamp
updatedAt string ISO 8601 timestamp

$client->deposits->get(id)

Fetch a single deposit order by UUID. Requires: deposits:read scope.

$deposit = $client->deposits->get('uuid-here');
// $deposit->status: 'pending' | 'success' | ...

Payouts

$client->payouts->list(params)

Paginated list of payout (chi hộ) orders. Requires: payouts:read scope.

use SurePay\Params\PayoutsListParams;

$result = $client->payouts->list(
    PayoutsListParams::create()
        ->page(1)
        ->pageSize(20)
        ->status('success')   // pending|processing|success|failed
        ->fromDate('2026-06-01')
        ->toDate('2026-06-30')
);

$client->payouts->create(req)

Initiate a payout bank transfer. Funds are deducted from your wallet immediately on success. Requires: payouts:write scope.

Payouts are irreversible once status moves past pending. Verify bank details with $client->bankInquiry->verify() first.

use SurePay\Request\CreatePayoutRequest;

$payout = $client->payouts->create(
    CreatePayoutRequest::builder(
        500_000,        // amount in VND, required
        'VCB',          // bank code, required (VCB, MB, TCB, ACB, ...)
        '1234567890',   // bank account, required
        'NGUYEN VAN A', // full name in UPPERCASE, required
        'Salary June'   // description / transfer memo, required
    )
    ->withBankName('Vietcombank') // optional
    ->build()
);

$client->payouts->get(id)

Fetch a single payout by UUID. Requires: payouts:read scope.

$payout = $client->payouts->get('uuid-here');
// $payout->status: 'pending' | 'success' | ...

Bank Inquiry

$client->bankInquiry->verify(req)

Look up the account holder name for a bank account. Call this before creating a payout to confirm the recipient. Requires: payouts:read scope.

use SurePay\Request\BankInquiryRequest;

$result = $client->bankInquiry->verify(
    BankInquiryRequest::of('VCB', '1234567890')
);
echo "Account name: {$result->accountName}\n";

Idempotency

Pass an idempotency key as the second argument to any create() method. The key is forwarded as an Idempotency-Key header — safe to retry on network errors without risk of duplicate transactions.

$deposit = $client->deposits->create(
    CreateDepositRequest::builder(100_000)->withRequestId('ORD-001')->build(),
    'ORD-001'  // idempotency key
);

Webhook verification

Every inbound webhook event from SurePay is HMAC-signed. Pass the raw request body string (before any JSON parsing) to $client->webhooks->verify():

// Laravel example
Route::post('/webhook/surepay', function (Request $request) {
    $body = $request->getContent();

    if (!$client->webhooks->verify($body)) {
        abort(401, 'Invalid signature');
    }

    $event = json_decode($body, true);

    match ($event['event']) {
        'deposit.success', 'deposit.failed' => handleDeposit($event),
        'payout.success',  'payout.failed'  => handlePayout($event),
        default => null,
    };

    return response()->noContent();
});

Or pass the X-Surepay-Signature header value explicitly:

$sig   = $request->header('X-Surepay-Signature');
$valid = $client->webhooks->verifyWithSignature($body, $sig);

Error handling

use SurePay\Exception\SurePayException;

try {
    $payout = $client->payouts->create($req);
} catch (SurePayException $e) {
    // Convenience helpers
    if ($e->isNotFound())            { /* 404 not_found */ }
    if ($e->isRateLimit())           { /* 429 rate_limit_exceeded */ }
    if ($e->isInsufficientBalance()) { /* 422 insufficient_balance */ }
    if ($e->isDuplicate())           { /* 409 duplicate_request */ }

    // Full details
    printf("HTTP %d  code=%s  %s\n",
        $e->getHttpStatus(), $e->getErrorCode(), $e->getMessage());
}

Error codes:

HTTP getErrorCode() Meaning
400 validation_error Invalid request body or parameters
401 unauthorized Missing or invalid API key
401 signature_invalid HMAC signature failed or timestamp > 5 min
403 permission_denied API key lacks required scope
403 ip_not_allowed Request IP not in allowlist
404 not_found Resource not found
409 duplicate_request Idempotency key conflict
422 insufficient_balance Top up wallet first
422 invalid_state_transition Operation not allowed for current status
429 rate_limit_exceeded Slow down — back off and retry
500 internal_error Server error

HMAC signing

When apiSecret is set, all requests are signed automatically. The signing algorithm for manual use:

signingString = UNIX_TIMESTAMP . "\n" . METHOD . "\n" . PATH . "\n" . hex(sha256(body))
signature     = "sha256=" . hex(hash_hmac('sha256', signingString, apiSecret))

Attach as headers: X-Signature: <signature> and X-Timestamp: <unix_timestamp>.

Signatures expire after 300 seconds — generate per-request, never cache or reuse.

License

MIT

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 3
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-06-10

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固