Appearance
签名与幂等
日期: 2026-09-18
状态: HMAC v2 已发布
1. HMAC v2 签名
1.1 签名原文
按以下顺序拼接六行,最后一行后不加换行:
text
HTTP_METHOD\n
NORMALIZED_PATH\n
CANONICAL_QUERY\n
BODY_SHA256\n
TIMESTAMP\n
NONCEHTTP_METHOD:大写 HTTP 方法,例如POST。NORMALIZED_PATH:不含域名和查询串的完整路径,例如/open/v1/checkout-sessions。CANONICAL_QUERY:当前已发布的支付 API 不使用查询参数,因此填写空字符串,并在路径行后保留一个空行。BODY_SHA256:实际发送请求体原始字节的 SHA-256 小写十六进制摘要。GET 请求对空字节串计算摘要。TIMESTAMP:Unix 秒级时间戳。与 SmartPay 服务器时间的偏差必须不超过 300 秒。NONCE:调用方为每次请求生成的随机字符串;同一应用在 300 秒窗口内不可重复。
使用应用凭证的 Secret 计算:
text
signature = hex(HMAC-SHA256(appSecret, canonicalRequest))X-Signature 必须是 64 位十六进制字符串。服务端使用恒定时间比较验证签名。
1.2 请求头
text
X-App-Id: <应用 App ID>
X-Key-Id: <当前活动凭证 Key ID>
X-Timestamp: <Unix 秒级时间戳>
X-Nonce: <本次请求唯一随机值>
X-Signature: <64 位 HMAC-SHA256 十六进制签名>
Idempotency-Key: <写操作必填>
Content-Type: application/json查询接口同样必须携带前五个认证头,但不需要 Idempotency-Key。
1.3 原始请求体要求
SmartPay 对网络收到的原始请求字节计算摘要。签名后不得改变 JSON 的空格、换行、字段顺序或字符编码。推荐客户端先生成 UTF-8 请求体字符串,再用同一字节数组计算摘要并发送。
1.4 凭证轮换
应用可以同时保留多把未撤销且未过期的活动凭证,并通过 X-Key-Id 指定本次请求使用的凭证。轮换流程在商户工作台完成:创建新凭证、安全保存一次性展示的 Secret、激活新凭证、验证调用,再撤销旧凭证。不要在新凭证验证成功前撤销旧凭证。
2. 幂等
创建支付会话、门店终端付款码支付和创建退款等写操作必须携带 Idempotency-Key。建议使用 UUID,或使用“业务类型 + 商户业务单号”生成稳定且不可复用的键。付款码请求重试必须保持原请求体和幂等键不变,严禁把 authCode 另行持久化为重试任务。
幂等范围由租户、应用、API 操作和 Idempotency-Key 共同确定:
- 同一范围内,相同键和相同原始请求体会返回首次成功执行保存的响应,不重复执行业务。
- 同一范围内,相同键但请求体摘要不同会返回
IDEMPOTENCY_CONFLICT,HTTP 状态码为 409。 - 首次请求仍在处理中,或失败后尚未达到安全恢复窗口时,重复请求也会返回冲突,调用方应稍后查询或重试。
- 平台为写请求设置 24 小时幂等保留时间;调用方不应在 24 小时后复用旧键,因为平台为审计或安全目的可能延迟清理记录。
3. 超时和重试
- HTTP 超时不代表业务失败。先使用原业务单号或 SmartPay 资源 ID 查询,再决定是否重试。
- 重试同一业务操作时,必须保持请求体和
Idempotency-Key不变;每次网络请求仍需生成新的X-Nonce和X-Timestamp,并重新计算签名。 - 不要在结果未知时更换业务单号或幂等键重新创建支付、退款或其他写操作。
4. 客户端安全
- App Secret 只允许保存在客户服务端的密钥管理系统中;小程序、H5 和 APP 不得直接持有生产 Secret。
- Secret 不得出现在 URL、浏览器存储、客户端日志、监控明文字段或代码仓库中。
- 凭证明文只在签发恢复期内展示;控制台列表不会回显 Secret。
- mTLS 和客户 IP 白名单尚未作为 HMAC v2 公共能力发布。未在控制台和开发文档中明确启用前,不应将其作为生产接入前提。