1 调用方添加请求签名

1.1 请求需添加的 Header 说明

Header 说明 报错信息 备注
S-Ca-App 必填 如果缺失会报错:请求没有签名app 从网关申请的 APP 名称
S-Ca-Signature 必填 如果缺失会报错:请求没有签名信息 签名字符串(下面说明如何生成)
S-Ca-Timestamp 必填 如果缺失会报错:请求没有签名时间戳
校验失败会报错:请求时间戳已过期
API 调用者传递时间戳,值为当前时间的毫秒数(1970年1月1日起至今的时间转换为毫秒),时间戳有效时间为 2分钟(网关平台可以修改)。

该参数防止重放攻击。
Content-MD5 POST/PUT 必填
GET 无
如果缺失会报错:Content-MD5 is empty
校验失败会报错:body md5值不一致
Body MD5,服务端会校验 Body 内容是否被篡改(下面有说明)
S-Ca-Signature-Headers 必填 必须包含 S-Ca-Timestamp,如果缺失会报错:请求没有签名请求头
校验失败会报错:签名请求头无必填请求Header
将需要签名的 header 使用英文逗号分割放到 Request 的 Header 中(下面有说明),其中必须包括 S-Ca-Timestamp,建议将 S-Ca-App 也添加进去,例如 S-Ca-Timestamp,S-Ca-App

1.2 签名字符串说明

JAVA 格式:

String stringToSign =
HTTPMethod + "\n" +
Content-MD5 + "\n" +
Headers +
Url

HTTPMethod 为全大写,如 POST。Content-MD5 如果为空也需要添加换行符 \n,Headers 如果为空不需要添加 \n

Content-MD5 说明

Content-MD5 是指 Body 的 MD5 值,计算方式为:

Java 格式:

String content-MD5 = Base64.encodeBase64(MD5(bodyStream.getbytes("UTF-8")));

1.5 Headers 说明

Headers 是指参与 Headers 签名计算的 Header 的 Key、Value 拼接的字符串。建议对自定义 Header 计算签名,注意如下参数不参与 Headers 签名计算:S-Ca-SignatureS-Ca-Signature-HeadersContent-MD5

Headers 组织方法:

先对参与 Headers 签名计算的 Header 的 Key 按照字典排序后使用如下方式拼接,如果某个 Header 的 Value 为空,则使用 HeaderKey + ":" + "\n" 参与签名,需要保留 Key 和英文冒号。

Java 格式代码:

String headers =
HeaderKey1 + ":" + HeaderValue1 + "\n" +
HeaderKey2 + ":" + HeaderValue2 + "\n" +
...
HeaderKeyN + ":" + HeaderValueN + "\n"
将 Headers 签名中 Header 的 Key 使用英文逗号分割放到 Request 的 Header 中,Key 为:S-Ca-Signature-Headers。其中必须包括 S-Ca-Timestamp,建议将 S-Ca-App 也添加进去,例如 S-Ca-Timestamp,S-Ca-App

1.6 Url 说明

Url 指 Path + Query 参数,组织方法:对 Query 参数按照字典对 Key 进行排序后按照如下方法拼接,如果 Query 参数为空,则 Url = Path,不需要添加 "?",如果某个参数的 Value 为空只保留 Key 参与签名,等号不需要再加入签名。

Java 格式代码:

String url =
Path +
"?" +
Key1 + "=" + Value1 +
"&" + Key2 + "=" + Value2 +
...
"&" + KeyN + "=" + ValueN
注意1:Path 只是简单的路径信息,如 /meituan/api/v1
注意2:接口有 Query 参数,Url 则需要拼接上 Query 参数,如 /meituan/api/v1?name=xiaoming;如果接口没有 Query 参数,Url 则不需要拼接,Url = Path,如 /meituan/api/v1

1.7 计算签名

Java 格式代码:

Mac hmacSha256 = Mac.getInstance("HmacSHA256");
byte[] keyBytes = secret.getBytes("UTF-8");
hmacSha256.init(new SecretKeySpec(keyBytes, 0, keyBytes.length, "HmacSHA256"));
String sign = new String(Base64.encodeBase64(hmacSha256.doFinal(stringToSign.getBytes("UTF-8")),"UTF-8"));
注意:secret 为 APP 的密钥,在 PC 端获取。

1.8 传递签名

将计算的签名结果放到 Request 的 Header 中,Key 为:S-Ca-Signature

3 订单推送 API 签名

签名规则

  1. 请求参数按照 key 进行排序
  2. sign 参数不参与签名
  3. 参数和密钥拼接为字符串:先拼接密钥,然后将 key、value 键值对拼接
  4. 再次在字符串结尾拼接密钥
  5. 最后对字符串进行 MD5 加密

Java 格式代码:

Map<String, String> paramsMap = new TreeMap<>();
for (String key : json.keySet()) {
    if (!"sign".equals(key)) {
        paramsMap.put(key, json.getStr(key));
    }
}
StringBuilder signBuilder = new StringBuilder(salt);
for (String key : paramsMap.keySet()) {
    signBuilder.append(key).append(paramsMap.get(key));
}
signBuilder.append(salt);
String sign = SecureUtil.md5(signBuilder.toString());