Skip to content

签名规范

OPS 的签名规范以传统易支付 MD5 签名为基础,同时定义 HMAC-SHA256 和 RSA-SHA256,方便平台逐步升级安全能力。

通用规则

无论使用哪种签名方式,待签名参数都必须遵循以下规则:

  1. 移除 sign 字段。
  2. 移除 sign_type 字段,除非平台在配置中显式声明 include_sign_type=true
  3. 移除值为空字符串、null 或未定义的字段。
  4. 按字段名 ASCII 升序排序。
  5. 将参数拼接为 key=value,不同参数之间使用 & 连接。
  6. 使用配置中声明的字符集编码,默认 utf-8

示例参数:

json
{
  "pid": "1000",
  "type": "alipay",
  "out_trade_no": "ORDER202606140001",
  "name": "Test",
  "money": "9.90",
  "notify_url": "https://merchant.example.com/notify",
  "return_url": "https://merchant.example.com/return",
  "sign_type": "MD5"
}

待签名字符串:

txt
money=9.90&name=Test&notify_url=https://merchant.example.com/notify&out_trade_no=ORDER202606140001&pid=1000&return_url=https://merchant.example.com/return&type=alipay

MD5

MD5 是传统易支付平台的默认兼容算法。

签名计算:

txt
md5(canonical_string + merchant_key)

输出格式:

  • 32 位小写十六进制字符串。
  • 平台可以接受大写签名,但生成方应使用小写。

示例:

txt
canonical_string = money=9.90&name=Test&notify_url=https://merchant.example.com/notify&out_trade_no=ORDER202606140001&pid=1000&return_url=https://merchant.example.com/return&type=alipay
merchant_key = abc123
source = money=9.90&name=Test&notify_url=https://merchant.example.com/notify&out_trade_no=ORDER202606140001&pid=1000&return_url=https://merchant.example.com/return&type=alipayabc123
sign = md5(source)

HMAC-SHA256

HMAC-SHA256 用于比 MD5 更严格的共享密钥签名。

签名计算:

txt
hmac_sha256(secret=merchant_key, message=canonical_string)

输出格式:

  • 默认输出小写十六进制。
  • 平台如果使用 Base64,必须在配置中声明 output=base64

RSA-SHA256

RSA-SHA256 用于非对称签名场景。

签名计算:

txt
base64(rsa_sha256_sign(private_key, canonical_string))

验签:

txt
rsa_sha256_verify(public_key, canonical_string, base64_signature)

配置中必须说明公钥获取方式:

json
{
  "signing": {
    "supported": ["RSA-SHA256"],
    "rsa": {
      "merchant_public_key_upload": true,
      "platform_public_key_url": "https://pay.example.com/.well-known/openpayment-public-keys.json"
    }
  }
}

金额规范化

金额必须使用十进制字符串,默认保留两位小数:

txt
9.9   -> 9.90
9     -> 9.00
0.01  -> 0.01

禁止使用浮点数参与签名。实现方应使用 Decimal、BigDecimal 或字符串金额。

URL 字段处理

签名时使用参数的原始值,不对 URL 再次编码。表单提交时的 URL 编码只属于 HTTP 传输层,不改变签名源字符串。

例如:

txt
notify_url=https://merchant.example.com/notify

不能签成:

txt
notify_url=https%3A%2F%2Fmerchant.example.com%2Fnotify

除非平台在配置中声明 url_encode_before_sign=true

通知验签

商户处理异步通知时必须:

  1. 读取平台传入的全部字段。
  2. 移除 sign 和默认移除 sign_type
  3. 按配置声明的签名算法重算签名。
  4. 比较签名。
  5. 查询本地订单,校验商户订单号、金额、商户号和支付状态。
  6. 验证通过后更新订单并返回 success

验签失败时不能返回 success

密钥轮换

平台支持密钥轮换时,应在配置中声明:

json
{
  "signing": {
    "key_rotation": true,
    "key_id_field": "key_id"
  }
}

请求或通知中携带 key_id 后,验签方根据 key_id 选择对应密钥。

兼容建议

  • OPS 基础兼容平台必须支持 MD5
  • 新平台建议同时支持 HMAC-SHA256
  • 涉及开放平台、多商户代签或高风险交易时,建议支持 RSA-SHA256
  • 平台应拒绝未知 sign_type,不能静默降级为 MD5。

展示可发现、可实现、可兼容的开放规范。