# 验签

# 公共参数简介

计算签名会使用以下的公共参数。在调用接口时,必须以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进行保密。

Last Updated: 9/8/2020, 11:54:05 AM