跳转至

Webhook 集成指南

触发事件

当交易进入以下状态时,系统将发送 Webhook 通知。每个通知会在未收到有效成功响应前,进行多次重试,直至达到最大重试次数。

Webhook 事件 tradeType 字段值 requestStatus 字段值 描述
DepositTransactionInProgress Deposit InProgress 客户已标记存款订单为已支付,当前正在进行支付确认。
DepositTransactionFinished Deposit Finished 存款订单已成功完成。
DepositTransactionFailed Deposit Failed 存款订单支付失败。失败原因可通过 message 字段获取。
DepositTransactionCancelled Deposit Cancelled 存款订单已取消。取消原因可通过 message 字段获取。
WithdrawTransactionInProgress Withdraw InProgress 提现订单正在进行中,系统正在处理客户的出款。
WithdrawTransactionFinished Withdraw Finished 提现订单已成功完成。
WithdrawTransactionFailed Withdraw Failed 提现订单支付失败。失败原因可通过 message 字段获取。
WithdrawTransactionCancelled Withdraw Cancelled 提现订单已取消。取消原因可通过 message 字段获取。

重要安全注意事项

收到 webhook 请求后,务必对“签名”和“时间戳”字段进行验证,以确保请求的真实性并防止外部攻击。

验证步骤:

  1. 签名验证:确保请求中的“签名”与使用密钥和有效负载生成的预期签名相匹配。
  2. 时间戳检查:验证“时间戳”是否在可接受的范围内,以避免重放攻击(例如,确保时间戳在当前服务器时间的几分钟内)。

这一额外的安全层可确保 webhook 请求来自可信来源,并防止未经授权或欺诈性访问。

Webhook 请求体结构

Webhook 请求使用如下 JSON 结构,通过 HTTP POST 方式发送,Content-Type 设为 application/json

请求体字段说明

参数名称 类型 描述
tradeType TradeType 交易类型:Deposit(存款)或 Withdraw(提现)
requestCode String 系统生成的唯一请求编号
merchantOrderNo String 商户自定义的唯一订单编号
internalOrderNo String 系统生成的内部订单编号
source SourceFrom 请求来源:MerchantBackendAPI_V1API_V2
clientName String 客户姓名
requestAmount BigDecimal 请求的交易金额
requestCurrency String 交易币种(如 MTC、CNY、HKD)
message String 状态信息或其他附加说明
paymentMethod PaymentOption? 支付方式(如适用):BankCardWeChatPay
requestStatus RequestStatus 当前交易状态
unitPrice BigDecimal 所用汇率(法币/MTC)
transactionAmount BigDecimal 实际交易金额(MTC)
receivedAmount BigDecimal 客户实际收到或商户被扣除的金额
transactionFee BigDecimal 扣除的交易手续费
paymentAmount BigDecimal 客户实际支付的最终金额(法币)
fiatCurrency CurrencyCode 法币币种代码:CNY、HKD

Webhook 请求示例

存款进行中

POST https://{MERCHANT_CALLBACK_HOST}/{MERCHANT_CALLBACK_ROUTE}
Host: {MERCHANT_CALLBACK_HOST}
Content-Type: application/json; charset=utf-8

{
  "signature": "101EECC76667EBE8A6A252FCE493CFA97CAEBE1935666CF0B2C7ADE424B64D09",
  "timestamp": 1742147003264,
  "data": {
    "tradeType": "Deposit", <-- Current trade type is [Deposit]
    "requestCode": "7a4170465c994e8fa313efada0b0e4b6",
    "merchantOrderNo": "ORDER_ID_HERE",
    "internalOrderNo": "AT-D-3UNT8SRUN",
    "source": "API_V2",
    "clientName": "USER_REAL_NAME",
    "requestAmount": 3213.44,
    "requestCurrency": "CNY",
    "message": "",
    "paymentMethod": "BankCard",
    "requestStatus": "InProgress", <-- Current status is [InProgress]
    "unitPrice": 7.47,
    "transactionAmount": 430.18,
    "receivedAmount": 417.27,
    "transactionFee": 12.91,
    "paymentAmount": 3213.44,
    "fiatCurrency": "CNY"
  }
}

存款完成

POST https://{MERCHANT_CALLBACK_HOST}/{MERCHANT_CALLBACK_ROUTE}
Host: {MERCHANT_CALLBACK_HOST}
Content-Type: application/json; charset=utf-8

{
  "signature": "86C70FA0D62BAA24EA35D6116BFF93A66336C856495DD4E0FA22F82E1556C5AE",
  "timestamp": 1742147325570,
  "data": {
    "tradeType": "Deposit", <-- Current trade type is [Deposit]
    "requestCode": "7a4170465c994e8fa313efada0b0e4b6",
    "merchantOrderNo": "ORDER_ID_HERE",
    "internalOrderNo": "AT-D-3UNT8SRUN",
    "source": "API_V2",
    "clientName": "USER_REAL_NAME",
    "requestAmount": 3213.44,
    "requestCurrency": "CNY",
    "message": "",
    "paymentMethod": "BankCard",
    "requestStatus": "Finished", <-- Current status is [Finished]
    "unitPrice": 7.47,
    "transactionAmount": 430.18,
    "receivedAmount": 417.27,
    "transactionFee": 12.91,
    "paymentAmount": 3213.44,
    "fiatCurrency": "CNY"
  }
}

响应处理

服务器将根据您的系统返回值验证 webhook 的响应。

响应验证逻辑

  1. 响应必须返回以下两种之一:
    • 返回的纯文本字符串等于 success,或
    • 返回的 JSON 对象中包含一个字段名为 success 且其值为 true
  2. 如果响应不符合上述任一条件,系统将重试发送 webhook,直至达到最大重试次数。

示例响应(纯文本)

success

示例响应(JSON)

{
  "success": true
}

Webhook 重试逻辑

为了确保可靠的传递,webhook 通知在回调失败时支持自动重试。以下是重试机制及其配置的说明。

为了确保最终的数据一致性,请确保您的回调接口实现了 幂等性

回调执行流程

当触发 webhook 时,系统会尝试将请求发送到配置的 webhookUrl。根据响应,系统将确定回调是否成功,或是否需要重试。

重试状态逻辑

  • 成功:如果回调响应有效(见 回调响应验证),状态将标记为 success,并且不会进行进一步的重试。
  • 需要重试:如果响应无效且仍有重试机会,状态将标记为 NeedRetry,并计算下次重试的时间。
  • 失败:如果所有重试机会都已耗尽,状态将标记为 Failed

重试计划

重试系统采用基于失败次数的渐进延迟策略。以下是重试时间表:

尝试次数 重试前延迟(分钟)
1 1
2 1
3 1
4 5
5 30
6 30
7-16 60
  • 系统允许每个 webhook 事件最多进行 16 次重试。
  • 如果所有重试都失败,将不再尝试进一步的回调。