# 授权认证
# 授权流程
授权包括获取事务ID、授权认证和授权确认,请按照顺序走授权流程,授权确认完成后代表授权成功,设备才有权限对接协议。
# STEP1:获取事务ID
HTTP Method:GET和POST
请求地址:http://product-auth.hivoice.cn/product-test/rest/v1/app_auth/trans
参数 | 类型 | 必填 | 描述 |
---|---|---|---|
clientName | String | N | 产品渠道 |
appKey | String | Y | appKey |
prodBatchCode | String | N | 生产批次 |
sign | String | Y | 签名串 |
返回值
参数 | 类型 | 必填 | 描述 |
---|---|---|---|
errorCode | String | Y | 响应code,成功为0,具体见错误码定义 |
errorMsg | String | Y | 响应描述 |
costTime | Integer | Y | 响应时间,单位:毫秒 |
result | Object | Y | 返回的结果数据 |
└transId | String | Y | 当前授权事务ID |
返回结果示例
{
"costTime": 2,
"errorCode": "0",
"errorMsg": "success",
"result": {
"transId": "599329c6f33f4710b1d830e9effd7ae1"
}
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# STEP2:授权认证
HTTP Method:GET和POST
请求地址:http://product-auth.hivoice.cn/product-test/rest/v1/app_auth/auth
参数 | 类型 | 必填 | 描述 |
---|---|---|---|
transId | String | Y | 当前事务时间戳(授权事务ID) |
authFlag | Integer | Y | 云端授权标记(1:授权成功 0:未成功),转授权时,该值为1 |
clientName | String | N | 产品渠道 |
prodBatchCode | String | N | 生产批次 |
appKey | String | Y | appKey |
productModel | String | Y | 产品型号 |
wifi | String | N | wifi信息 |
deviceId | String | Y | 芯片唯一号 |
sign | String | Y | 签名串 |
返回值
参数 | 类型 | 必填 | 描述 |
---|---|---|---|
errorCode | String | Y | 响应code,成功为0,具体见错误码定义 |
errorMsg | String | Y | 响应描述 |
costTime | Integer | Y | 响应时间,单位:毫秒 |
result | Object | Y | 返回的结果数据 |
└transId | String | Y | 当前授权事务ID |
└udid | String | Y | 授权码(为空表示未授权) |
返回结果示例
{
"costTime": 16,
"errorCode": "0",
"errorMsg": "success",
"result": {
"transId": "1524487322336",
"udid": "0af2dc8a3a164f828b71cc5324c3880d"
}
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# STEP3:授权确认
HTTP Method:GET和POST
请求地址:http://product-auth.hivoice.cn/product-test/rest/v1/app_auth/confirm
参数 | 类型 | 必填 | 描述 |
---|---|---|---|
transId | String | Y | 当前事务时间戳(授权事务ID) |
clientName | String | N | 产品渠道 |
prodBatchCode | String | N | 生产批次 |
appKey | String | Y | appKey |
udid | String | Y | 授权码 |
sign | String | Y | 签名串 |
返回值
参数 | 类型 | 必填 | 描述 |
---|---|---|---|
errorCode | String | Y | 响应code,成功为0,具体见错误码定义 |
errorMsg | String | Y | 响应描述 |
costTime | Integer | Y | 响应时间,单位:毫秒 |
result | Object | Y | 返回的结果数据 |
└transId | String | Y | 当前授权事务ID |
└udid | String | Y | 授权码(为空表示未授权) |
返回结果示例
{
"costTime": 16,
"errorCode": "0",
"errorMsg": "success",
"result": {
"transId": "1524487322336",
"udid": "0af2dc8a3a164f828b71cc5324c3880d"
}
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 签名规则
1)将格式化后的参数以字典序升序排列,拼接在一起,注意字典序中大写字母在前,空值(null)不参与签名;
注意:计算sign时所有参数也需要进行URLEncode;
如排序后的字符串为:A="transId=1524477063548&udid=21221c025e0846fb97bceb5b55d814ac"
2)将第一步中形成字符串进行BASE64编码;此时B=BASE64(A)
3)将第二步中形成字符串进行MD5加密,形成一个32位的十六进制字符串,即为本次请求sign(签名)的值;此时sign=md5(B)
然后再POST请求时,所有参数的值都应进行URLEncode;(参数值是数字或字母的可以不进行URLEncode)
该签名值基本可以保证请求是合法者发送且参数没有被修改,但无法保证不被偷窥。
# 签名示例
/**
* 签名算法
*
* @param params
* 要参与签名的数据对象
* @return 签名
* @throws IllegalAccessException
*/
public static String getSign(Map<String, String> params) throws Exception {
if (null == params || params.isEmpty() ) {
return null;
}
params.remove("sign");
// 格式化并排序请求参数
String result = formatAndSortParams(params);
// Base64编码
result = CoderUtil.encryptBASE64(result).replace("\r\n", "");
// MD5运算
result = new String(DigestUtils.md5Hex(result));
return result;
}
/**
* 格式化并排序请求参数
*
* @param obj
* @throws Exception
* @return String
* @throws
*
*/
private static String formatAndSortParams(Map<String, String> map) throws Exception {
if (null == map || map.size() == 0) {
return null;
}
ArrayList<String> list = new ArrayList<String>();
for (Map.Entry<String, String> entry : map.entrySet()) {
if (StringHandler.isNullOrEmpty(entry.getKey()) || StringHandler.isNullOrEmpty(entry.getValue())) {
continue;
}
list.add(entry.getKey().trim() + "=" + UrlCoder.encode(entry.getValue().trim()) + "&");
}
int size = list.size();
String[] arrayToSort = list.toArray(new String[size]);
Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < size; i++) {
sb.append(arrayToSort[i]);
}
String params = sb.toString();
if (params.endsWith("&")) {
params = params.substring(0, params.length() - 1);
}
return params;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# 错误码定义及描述
errorCode | errorMsg | 描述 |
---|---|---|
0 | 请求正常 | 成功 |
1001 | 不支持的服务 | 不支持的服务 |
1002 | 参数校验失败 | 包括参数缺失、参数格式错误等情况 |
1003 | 连接超时 | 连接超时 |
1004 | 读取数据超时 | 读取数据超时 |
1005 | 渠道授权数超限 | 渠道授权数超限 |
1006 | 该设备无授权记录 | 该设备无授权记录 |
1007 | 客户编码不存在 | 客户编码不存在 |
1012 | 调用设备中心返回数据为空或错误信息 | 调用设备中心返回数据为空或错误信息 |
1013 | 调用设备中心异常 | 调用设备中心异常 |
1014 | 应用不存在 | 应用不存在 |
9999 | 服务器内部异常 | 服务器内部异常 |