开发文档

验证付款回调签名

使用 Webhook 密钥对时间戳和请求体原文计算 HMAC-SHA256,验证付款通知签名。核对时间戳、订单和实付信息,持久化事件并去重处理后返回 HTTP 2xx,避免重复发货或入账。

本页订单 API(创建、查询与重发)使用 HMAC-SHA256 请求签名;GET /api/v1/ping 仅需 API Key。付款回调也携带签名。HMAC 使用商户 Webhook 配置中的密钥,而不是 API Key。

01. 请求头规范

01. 发送订单 API 请求

Client to Server

创建、查询与重发请求同时携带 X-Bolt-Key。请求时间戳与服务器时间相差不能超过 5 分钟;重试时重新生成时间戳和签名。

Unix 毫秒时间戳必填
X-Bolt-Timestamp
HMAC-SHA256 十六进制签名必填
X-Bolt-Signature

02. 接收付款回调

Server to Merchant

回调时间戳与签名由 BoltUtil 生成。接收端应验证请求体原文、检查时间戳窗口,并按 eventId 和业务订单进行幂等处理。

Unix 毫秒时间戳必填
X-Bolt-Webhook-Timestamp
HMAC-SHA256 十六进制签名必填
X-Bolt-Webhook-Signature

02. 签名计算

1

构造待签名内容

使用请求头中的时间戳与点号连接请求体原文:timestamp + "." + raw_body。按 UTF-8 编码;空请求体也保留点号。

// 1. Construct payload: timestamp + "." + body
String payload = timestamp + "." + body;
2

计算 HMAC-SHA256

以商户 Webhook 配置中的密钥计算 HMAC-SHA256。发送 API 请求时,参与签名的正文必须与实际发送的正文一致。

// JDK standard library: javax.crypto.Mac and SecretKeySpec
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
byte[] hash = mac.doFinal(payload.getBytes(StandardCharsets.UTF_8));
3

编码为小写十六进制

将 32 字节摘要转换为 64 个小写十六进制字符。API 请求写入 X-Bolt-Signature;收到回调时与 X-Bolt-Webhook-Signature 进行常量时间比较。

// JDK 17+: java.util.HexFormat
String signature = HexFormat.of().formatHex(hash);

03. 验签注意事项

  • 不要先解析 JSON 再序列化验签。空格、换行、字段顺序和字符编码都影响签名。
  • HMAC 验证请求内容完整性,不能单独防止重放。时间戳窗口与事件去重仍不可少。
  • 签名正确不等于业务订单已交付;还须核对订单关联、付款状态、金额、币种和结算类型。
查看付款回调处理流程 →
signature / cURL
# Calculate a request signature without sending a request.
# BOLTUTIL_WEBHOOK_SECRET is your merchant Webhook secret, not API Key.
: "${BOLTUTIL_WEBHOOK_SECRET:?Set your Webhook secret}"
timestamp=$(python3 -c 'import time; print(int(time.time()*1000))')
body='{"externalOrderId":"INV-20260209-99281"}'
signature=$(printf '%s.%s' "$timestamp" "$body" | openssl dgst -sha256 -hmac "$BOLTUTIL_WEBHOOK_SECRET" | awk '{print $NF}')
printf 'X-Bolt-Timestamp: %s\nX-Bolt-Signature: %s\n' "$timestamp" "$signature"
# Send this SAME body with the above headers and X-Bolt-Key.
# Callback header names are X-Bolt-Webhook-Timestamp and
# X-Bolt-Webhook-Signature. Verify raw bytes before parsing JSON.

地址、交易哈希及订单均为示例。请替换为您自己的测试数据。

Base URL

PROD
https://api.boltutil.com