调用每个接口都需要携带签名,服务端会根据请求参数,对签名进行校验,签名不合法的请求将会被拒绝,目的主要是:
(1)校验每次请求参数的数据完整性
(2)验证请求者的身份
- 公共参数(除去sign)按照参数名ASCII码进行自然排序,然后按照k1v1k2v2…拼接(appKey+shopIdenty/brandId+timestamp+version),结果为parameters;
- 拼接parameters+body(请求业务参数)+token;
- 将所得字符串进行SHA-256运算,返回即为sign的值。
注意:
1.一定要按照要求的顺序排序后再组装参数字符串,将body(为空则不加)和客如云提供的token放在排序字符串后面。
2.对新组装的参数字符串进行SHA-256加密生成sign字符串。
门店授权接口与品牌授权接口加密规则一致,但所传的参数值不一样,品牌授权接口传brandId ,门店授权接口传shopIdenty
加密拼接顺序:
sign=SHA256(appKey+shopIdenty/brandId+timestamp+version+body+token)
注意: 1.sign一定要按顺序(appKey+shopIdenty/brandId+timestamp+version+body+token);
2.拼接字段 shopIdenty 和 brandId 只传其中一个。 品牌授权接口传brandId ,门店授权接口传shopIdenty;
3.version传固定值2.0;
4.加密的body体为json字符串;
参数拼接并排序示例
{
appKey:7857ca1808d370e2501290bc853eecdc
shopIdenty:810094162
timestamp:1528683797798
version:2.0
body:{"aaa":1}
token:66e53b22f1496d183e71b4ab90f4acf7
}
sign=SHA256(appKey7857ca1808d370e2501290bc853eecdcshopIdenty810094162timestamp1528683797798version2.0body{"aaa":1}66e53b22f1496d183e71b4ab90f4acf7)
参数拼接并排序示例
{
appKey:7857ca1808d370e2501290bc853eecdc
brandId:32296
timestamp:1528683797798
version:2.0
token:66e53b22f1496d183e71b4ab90f4acf7
body:{"aaa":1}
}
sign=SHA256(appKey7857ca1808d370e2501290bc853eecdcbrandId32296timestamp1528683797798version2.0body{"aaa":1}66e53b22f1496d183e71b4ab90f4acf7)
请求公共参数:
https://openapi.keruyun.com/open/v1/signTest?appKey=301001&shopIdenty=247900001&version=2.0×tamp=1425635264&sign
请求业务参数:
{"aaa":1,
“name”:周
}
通过SHA256运算得到签名sign sign=SHA256(appKey301001shopIdenty247900001timestamp1425635264version2.0body{“aaa”:1,“name”:周}66e53b22f1496d183e71b4ab90f4acf7)
如上签名计算完成后,把sign值放到URL参数里面,即可进行接口调用
https://openapi.keruyun.com/open/v1/signTest?appKey=301001&shopIdenty=247900001&version=2.0×tamp=1425635264&sign=779d704132837f6fd93178a0eff9e70ce8e365321cb5874708a05bad96a44887
public static void main(String[] args) {
Map<String, Object> params = new TreeMap<>();
params.put("appKey", "服务appKey");
//门店签名必传
params.put("shopIdenty", 810094162);
//品牌签名必传
params.put("brandId", 32296);
params.put("version", "2.0");
//时间戳s
params.put("timestamp", 1425635264);
StringBuilder sortedParams = new StringBuilder();
params.entrySet().stream().forEachOrdered(paramEntry -> sortedParams.append(paramEntry.getKey()).append(paramEntry.getValue()));
//若存在requestBody则添加body+body体json字符串 否则忽略
sortedParams.append("body").append("{\"shopIdenty\":810094162,\"ids\":[810002,810003]}");
//请替换成真实的token
sortedParams.append("TOKEN");
System.out.println(sortedParams);
try {
String sign = getSign(sortedParams.toString());
System.out.println(sign + " " + sign.length());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
/**
* @Description: SHA256加密字符串
* @param
* @return String
* @throws NoSuchAlgorithmException
*/
private static String getSign(String sortedParams) throws NoSuchAlgorithmException {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.update(sortedParams.getBytes());
byte byteBuffer[] = messageDigest.digest();
StringBuffer strHexString = new StringBuffer();
for (int i = 0; i < byteBuffer.length; i++){
String hex = Integer.toHexString(0xff & byteBuffer[i]);
if (hex.length() == 1) {
strHexString.append('0');
}
strHexString.append(hex);
}
// 得到返回結果
String SHA256Sign = strHexString.toString();
return SHA256Sign;
}