数据签名过程

签名以及验证

1,准备

  • 涉及接口:适用本文档(API Explorer)的所有接口

  • 申请签名key:商户需要申请签名key,用于数据签名和结果验签,签名key请妥善保管勿对外泄露

  • 签名与验证:不建议在web前端存储和进行数据签名验签,推荐在服务端进行签名和响应结果的验签

2,通用签名规则

数据定义

header参数:指httpRequest header里的参数,如Request HeaderResponse Header

path参数:指 API 文档,URL中带有占位符的为path参数;在接口文档描述中,该参数在path栏位

例如:https://host/V2022-03/payment_methods/{customerPaymentMethodId}

该URL中 customerPaymentMethodId 带有占位符

https://host/V2022-03/payment_methods/pm_1526760521989763072

此时pm_1526760521989763072为参数

query参数:指直接跟在请求地址后方的key=value数据(GET方式表单提交、url后追加的参数如:url?key1=val1&key2=val2)

body参数:httpRequest body中的json对象

通用签名步骤

1,将header参数:gateway-no request-id request-time 字段按ascii排序,取其非空值累加,得到数据H

2,将path参数按照参数名的ascii排序,取其值累加得到数据P

3,将query参数按照参数名的ascii排序,取其值累加得到数据Q

4,将body中的数据转为字符串(json对象转为字符串),此为数据B

注意:webhook 请求头中的header参数包含:gateway-no request-id request-time version,比较其他接口多一个 version 字段,则数据H的获取方式:

将header参数:gateway-no request-id request-time version 字段按ascii排序,取其非空值累加,得到数据H

//bodyJson为接口发送在body中的json对象数据,转为字符串,即为上述的数据B
JSON.stringify(bodyJson);

此步骤特别注意:上述代码为转换字符串示意,一定要确保发送的bodyJson(http发送时一般会将json对象序列化)与转换后的字符串一致

5,以上四项,如数据项存在内容(字符长度大于0),则使用点号连接,得到待签名数据H.P.Q.B

6,采用商户key,对待签名数据进行HMAC-SHA256签名:HMAC-SHA256(H.P.Q.B , key),得到签名结果16进制字符串signValue(不区分大小写)

7,将signValue设置到HttpRequest header的sign字段中,发送该请求

4,对请求数据签名

# post请求示例
curl -X POST "https://api.asiabill.com/V2022-03/refund" 
-H 'Content-Type: application/json' 
-H 'request-id:123456'
-H 'request-time:1646648307486'
-H 'gateway-no:1000001'
-d '{"refundReason":"test refund","tradeNo":"2021212123123123"}'

对于以上请求,生成签名过程如下:

1,得到header参数的ascii顺序值的字符串H:10000011234561646648307486

2,path参数没有,略过该步骤

3,query参数没有,略过该步骤

4,body的json内容转字符串为{"refundReason":"test refund","tradeNo":"2021212123123123"}

5,上述各项非空数据,点号连接:10000011234561646648307486.{"refundReason":"test refund","tradeNo":"2021212123123123"}

6,使用商户key,比如12345678,进行hmac-sha256签名,得到签名结果:

8eb28572747479aedf3cbc4b59a70b5be180841a527449149ef52d480e12951b

7,将上述签名结果,放入header的sign-info字段中即可

5,对结果数据签名(接口响应,webHook通知)

发送请求,服务端处理后,会在http响应header中原样返回gateway-no response-id response-time version 等信息,同时使用上述签名规则,对响应header和body进行签名,签名结果放在响应header的sign-info字段。客户端收到结果后,推荐对结果数据进行签名验证

签名验证步骤

  1. 读取请求响应header,解析得到gateway-no request-id request-time字段的值,并按照上述签名顺序将存在的值累加,得到字符串H

  2. 读取响应body,得到json字符串B

  3. 使用点号连接,得到待签名数据H.B

  4. 使用商户key,进行hmac-sha256签名得到结果checkSignValue

  5. 比较响应header中的sign的值是否与4中的checkSignValue相等,如不相等则数据异常,或验证流程未匹配上

注意:webhook 请求头中的header参数包含:gateway-no request-id request-time version,比较其他接口多一个 version 字段,则数据H的获取方式:

将header参数:gateway-no request-id request-time version 字段按ascii排序,取其非空值累加,得到数据H

6,签名代码示例

// 生成签名,HmacSha256后转为16进制字符串,javascript类似
// 引入crypto-js
import CryptoJS from 'crypto-js/crypto-js'
// 按照签名数据规则拼接数据
let sign_info = "";
// 使用key进行签名
let hash = CryptoJS.HmacSHA256(sign_info, key);

Last updated