Sign in
简介/Webhook 通知

Webhook 通知

通过 HMAC 签名的 webhook 实时接收支付与提现状态更新。

每当支付状态变更时,2328.io 会向您配置的 url_callback 发送 webhook。这是获取支付状态通知的推荐方式。

请求格式

  • 方法: POST
  • Content-Type: application/json
  • 签名: 请求体中的 sign 字段

载荷

webhook 请求体与 /v1/payment/info 响应一致,并额外包含一个用于签名校验的 sign 字段。

支付成功

JSON
{
  "uuid": "db17d490-15b6-47b9-9015-91d1d8b119f2",
  "order_id": "ORDER-12345",
  "amount": "180.00000000",
  "currency": "RUB",
  "url": "https://go.2328.io/db17d490-15b6-47b9-9015-91d1d8b119f2",
  "expires_at": "2026-05-09T16:56:58+03:00",
  "created_at": "2026-05-09T15:56:58+03:00",
  "payer_currency": "TON",
  "payer_amount": "0.95256917",
  "network": "TON",
  "address": "UQA0RevhkCQx-EltyNgPPeG8dqtnCz7ZslOzMdNQlLxVaNBb",
  "payment_status": "paid",
  "txid": "41c2a327323480af8e705d05deb09c238a41779928832abef4bb77c862357b11",
  "payment_amount": "0.95256917",
  "merchant_amount": "0.949711462490000000",
  "amount_usd": "2.41324380",
  "exchange_rate": "0.01340691",
  "sign": "6f8c15b6e53b506d5bfa38ed3fb3b50697af73434262153c02e412541372f04d"
}

已取消 / 失败的支付

未到达终态 paid 时,txidpayment_amountmerchant_amountnull

JSON
{
  "uuid": "48edaf2d-2c49-4638-8f86-88636f661c1f",
  "order_id": "ORDER-12345",
  "amount": "2800.00000000",
  "currency": "RUB",
  "url": "https://go.2328.io/48edaf2d-2c49-4638-8f86-88636f661c1f",
  "expires_at": "2026-05-09T06:19:04+03:00",
  "created_at": "2026-05-09T05:19:04+03:00",
  "payer_currency": "ETH",
  "payer_amount": "0.01620968",
  "network": "ETH-ERC20",
  "address": "0x37c20d6d96d130Bc5B33D832e43b8e16aACe0c59",
  "payment_status": "cancel",
  "txid": null,
  "payment_amount": null,
  "merchant_amount": null,
  "amount_usd": "37.53934800",
  "exchange_rate": "0.01340691",
  "sign": "40ce68ad9691ad54e684329d75ab5adaf5b01409a2d18d3e0110b8c1be605342"
}

字段说明

字段类型说明
uuidstring支付 UUID
order_idstring您的订单 ID
amountdecimal (8 位小数)currency 对应的法币金额
currencystring商户请求的法币币种
urlstring托管支付页面 URL
expires_atstring (ISO 8601)支付会话的过期时间
created_atstring (ISO 8601)支付会话的创建时间
payer_currencystring付款人使用的加密货币
payer_amountdecimal (8 位小数)预期支付的加密货币数量
networkstring区块链网络
addressstring收款地址
payment_statusstring取值之一:pendingcheckpaidunderpaid_checkunderpaidoverpaidcancelaml_lock(详见 References
txidstring | null链上交易哈希,仅在支付确认后才有值
payment_amountdecimal | null实际支付金额,仅在支付到账后才有值
merchant_amountdecimal (18 位小数) | null扣除手续费后入账给商户的金额
amount_usddecimal (8 位小数)创建时的美元等值
exchange_ratedecimal创建时使用的加密货币 / 法币汇率
signstring (hex)载荷的 HMAC-SHA256 签名

验证签名

验证 webhook 签名的步骤:

  1. 从载荷中提取 sign 字段
  2. 从对象中移除 sign 字段
  3. 将剩余字段编码为 JSON
  4. 将 JSON 进行 Base64 编码
  5. 使用您的 API_KEY 对 Base64 字符串计算 HMAC-SHA256
  6. 使用恒定时间比较函数(如 hash_equals)将计算结果与收到的 sign 比较
PHP
<?php
function verifyWebhookSign(array $data, string $apiKey): bool {
    $receivedSign = $data['sign'] ?? '';
    unset($data['sign']);

    $json = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    $base64 = base64_encode($json);
    $calculated = hash_hmac('sha256', $base64, $apiKey);

    return hash_equals($calculated, $receivedSign);
}

$apiKey = 'YOUR_API_KEY';
$payload = json_decode(file_get_contents('php://input'), true);

if (!verifyWebhookSign($payload, $apiKey)) {
    http_response_code(401);
    exit;
}

switch ($payload['payment_status']) {
    case 'paid':
    case 'overpaid':
        // Credit the order — check idempotency by order_id first
        break;
    case 'underpaid_check':
    case 'underpaid':
    case 'cancel':
        break;
}

http_response_code(200);

为用户入账资金前务必校验签名。 未签名或签名错误的 webhook 可能是伪造请求。

提现 webhook

当提现的 status 发生变化时,系统会向创建提现时传入的 url_callback 发送 POST webhook。如果未提供 url_callback,则不会为该提现发送任何 webhook。

提现 webhook 必须使用 Payout API key 校验签名,不是普通 API key。签名算法与支付 webhook 完全相同(移除 sign → JSON → Base64 → HMAC-SHA256),仅签名密钥不同。

载荷

JSON
{
  "uuid": "019dff1f-0dbd-7277-8d45-271e7775388f",
  "order_id": "4dfdcc84402b1185b71cbe399321533e",
  "status": "completed",
  "currency": "TRX",
  "network": "TRX-TRC20",
  "amount": "3.00",
  "merchant_amount": "3.00",
  "network_amount": "3.00",
  "amount_usd": "1.04",
  "to_address": "THauRv5tcucQRohXg8NiyGTk16DX1XQG5x",
  "memo": null,
  "txid": "9242e533703704ef3eaba840f70b4a26333e72c943377ee375fea17badb53def",
  "block_number": null,
  "error_type": null,
  "created_at": "2026-05-07T00:08:38+03:00",
  "updated_at": "2026-05-07T00:08:54+03:00",
  "from_currency": "USDT",
  "debited_amount": "1.050735",
  "debited_currency": "USDT",
  "sign": "925ad7bf3d6841864101f7cc2c7e30652e70a06cdb04dbe07a0129480000ce4a"
}

字段说明

字段类型说明
uuidstring提现 UUID
order_idstring您提供的幂等性 / 业务 ID(如有)
statusstringpendingcompletedfailedcancelled(详见 References
currencystring提现币种
networkstring区块链网络
amountdecimal提现金额(以 currency 为单位)
merchant_amountdecimal从商户余额扣除的金额
network_amountdecimal实际链上发送的金额
amount_usddecimal提现时的美元等值
to_addressstring收款方区块链地址
memostring | null备注 / destination tag(如使用)
txidstring | null链上交易哈希,completed 时设置
block_numberinteger | null链上交易所在区块高度
error_typestring | nullstatus = failed 时的失败原因(例如 aml_risk,详见 References
created_atstring (ISO 8601)提现创建时间
updated_atstring (ISO 8601)状态最近一次变更时间
from_currencystring使用自动兑换时,提现实际扣款的源余额(例如 BTC 提现的 USDT
debited_amountdecimalfrom_currency 余额扣除的金额
debited_currencystring扣款币种
signstring (hex)载荷的 HMAC-SHA256 签名,使用 Payout API key 计算

最佳实践

  • 幂等性 — 务必检查支付是否已被处理(按 order_iduuid)。webhook 可能被多次发送。
  • 快速响应 — 尽快返回 HTTP 200。耗时操作转交后台队列。
  • 重试 — 若系统未收到 HTTP 200,2 分钟后会重新发送,最多重试 5 次。
  • 异步处理 — 异步处理 webhook 事件,避免阻塞响应。
  • 安全 — 在信任载荷之前务必验证 sign 签名。

webhook 可能乱序到达。不要假设第一条 webhook 即是最终状态 — 如需确认,可通过 /v1/payment/info(或 /v1/payout/status/{uuid})重新拉取。