Skip to content

签名

所有 Open API 请求都必须签名。签名用于确认商户身份、防止请求被篡改,并配合 X-Nonce 防重放。

请求头

Header必填说明
X-Mch-Id平台商户号 merchant_no
X-TimestampUnix 秒,允许 5 分钟时间窗。
X-Nonce随机串,用于防重放。
X-SignatureHMAC-SHA256 小写 hex。
X-Request-Id商户侧请求追踪 ID。

签名串

签名串固定 6 行,用换行符 \n 拼接:

text
METHOD
PATH
MCH_ID
TIMESTAMP
NONCE
PAYLOAD_DIGEST

字段规则:

字段说明
METHOD大写 HTTP method,例如 GETPOST
PATH不带域名、不带 query 的路径,例如 /api/v1/open/pay/order
MCH_ID请求头 X-Mch-Id 的值。
TIMESTAMP请求头 X-Timestamp 的值。
NONCE请求头 X-Nonce 的值。
PAYLOAD_DIGESThex(sha256(canonical_payload))

最终签名:

text
hex(HMAC-SHA256(secret_key, sign_text))

GET canonical_payload

GET 请求的 canonical_payload 是规范化 query string:

  1. 排除 signaturesign 参数。
  2. 参数名按 ASCII 升序排列。
  3. 参数值按 RFC3986 百分号编码。
  4. 使用 key=value&key2=value2 拼接。
  5. 空 query 的 canonical payload 是空字符串。

示例:

text
GET /api/v1/open/pay/query?trade_no=260703000842100181368386&trade_type=1

canonical_payload:
trade_no=260703000842100181368386&trade_type=1

POST canonical_payload

POST 请求的 canonical_payload 是规范化后的加密信封 JSON。签名覆盖最终传输的 encrypted_keybiz_content,不覆盖业务明文 JSON。

示例信封:

json
{"biz_content":"base64...","encrypted_key":"base64..."}

业务 JSON 在加密前可以有空白和字段顺序差异,但最终用于签名的信封 JSON 必须稳定。建议 SDK 使用固定 JSON 序列化方式:字段按 biz_contentencrypted_key 或确定顺序输出,无多余空白。

响应验签

Open POST 成功响应也会返回签名头:

text
X-Timestamp
X-Nonce
X-Signature
X-Request-Id

商户应先验证平台响应签名,再解密 data 中的响应信封。响应验签同样使用 6 行签名串,MCH_ID 使用商户号,PAYLOAD_DIGEST 基于响应 body 的规范化 payload。

常见失败

现象处理
Open API 签名请求头不能为空检查必填签名头是否缺失。
签名错误检查 PATH 是否包含 query、payload digest 是否基于正确内容。
nonce 重放每次请求使用新的 X-Nonce
时间戳过期使用 Unix 秒并校准服务器时间。