# 验签
# 公共参数简介
计算签名会使用以下的公共参数。在调用接口时,必须以URL方式传递以下公共参数:
参数名称 | 类型 | 说明 | 备注 |
---|---|---|---|
ts | bigint | 本次请求的毫秒时间戳。 | 毫秒时间戳,请确保服务器时间不能比北京时间快, 并且不能比北京时间慢超过5分钟 否则会导致接口校验失败,报“时间戳错误”。 |
appId | string | 分配给您的appId | |
nonce | string | 一次性随机字符串,长度不超过32位。 | 请确保每次请求的的nonce的唯一性。否则会报"重复请求"错误。 |
sign | string | 计算出的签名 | 请按照以下步骤进行签名计算。注意sign参数不参与签名 |
# 步骤
1.设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接待签名字符串stringA。特别注意以下重要规则:
参数名按ASCII码从小到大排序(自然序);
如果参数的值为空不参与传参和签名;
参数名区分大小写;
get 和 post 参数均参与签名(注意:签名时不要对 get 和 post 的参数进行urlencode);
sign 参数不参与签名;
根据HTTP协议要求,传递参数的值中如果存在特殊字符(如:&、@等),那么该值需要做URL Encoding,这样请求接收方才能接收到正确的参数值。这种情况下,待签名数据应该是原始值而不是encoding之后的值。例如:调用某接口需要对请求参数email进行数字签名,那么待签名数据应该是email=test@msn.com,而不是email=test%40msn.com。
2.在stringA最后拼接上“&appSecret=YourAppSecret(或开发者密钥、授权密钥)”得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值。
3.拼接sign签名,得到最终请求字符串。
# 签名示例
假设传送的参数如下:
{
"schoolId":6107210001,
"appId":"ucm",
"nonce":"1235",
"ts":1599463167000,
"sign":"378F1B430D0F3B1D8F02F13E3D01AACF"
}
1.对参数按照key=value的格式,并按照参数名ASCII字典序排序如下, 生成待签名字符串strToSign:
private static String generateStrToSign(Map<String, String> params) {
TreeMap<String, String> paramsToSort = new TreeMap<>(Comparator.naturalOrder());
paramsToSort.putAll(params);
return paramsToSort.entrySet().stream()
.filter(e -> !e.getKey().equalsIgnoreCase("sign")) //sign字段不参与签名
.filter(e -> StringUtils.isNotBlank(e.getValue())) //值为空字符串的不参与签名
.map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining("&"));
}
2.拼接API密钥,md5加密并转成大写,生成sign:
public static String generateSign(String appSecret, String strToSign) {
String signStrTemp = strToSign + "&appSecret=" + appSecret;
return Hashing.md5().hashString(signStrTemp, Charset.defaultCharset()).toString().toUpperCase();//注意这里引入了guava的lib
}
3.对请求的数据拼接sign签名:最终请求如下:
https://open.xuejj.com/openapi/class/v1/types?schoolId=6107210001&appId=ucm&nonce=1235&ts=1599463167000&sign=378F1B430D0F3B1D8F02F13E3D01AACF
注意:密钥appSecret仅作加密使用,为了保证数据安全请不要在请求参数中传递,并对密钥appSecret进行保密。