# OTA

# 检查更新

HTTP Method:POST
请求地址:https://otav2.hivoice.cn/rest/v1/data/check_update
注意:所有参数的值都应进行URLEncode(UTF-8),参数值是数字或字母的可以不进行URLEncode。

参数 类型 必填
描述
appKey String Y 应用KEY
osType String Y 应用所在操作系统类型,包括:Android、iOS、Linux、Windows等,比如当前开发的是Android的SDK,则osType=Android
version Integer Y 当前版本号
targetVersion Integer N 目标版本号
timestamp String Y 访问时间戳,Unix时间戳
udid String N 设备唯一标识
channelCode String N 渠道编号
pkgName String N 包名
hardwareType String N 硬件类型
gps String N GPS数据,数据格式:经度,纬度,如:116.41667,39.91667
signature String Y 数据签名

返回值

参数 类型 必填
描述
returnCode String Y 响应code,具体见错误码定义
message String Y 响应描述
costTime Integer Y 响应时间,单位:毫秒
result Object Y 返回的结果数据
└config String Y 版本配置信息
└downloadUrl String Y 新版本数据的下载URL
└fileSize String Y 文件大小,单位:byte
└version String Y 当前新版本的版本号
└md5 String Y 当前新版本数据的MD5值
└releaseNote String Y 版本更新日志
└updateType String Y 更新类型,包括(0:普通更新、1:强制更新:、2:强制静默更新)

返回结果示例:

{
    "returnCode": "0001",
    "message": "有新版本",
    "costTime": 259,
    "result": {
        "config": "{\"name\": \"haha\"}",
        "downloadUrl": "http://10.30.100.1/g1/M00/07/C9/Ch5kAleM0rKAdx5_AB1tRUtE7TA470.pdf",
        "fileSize": 1928517,
        "version": 10,
        "md5": "44b8aeaea16e093a370150a4911ce4c9",
        "releaseNote": "releaseNote",
        "updateType": 0
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 检查更新签名规则

A)将所有请求参数的值放入List中,注意:计算sign时所有参数不应进行URLEncode;
B)将格式化后的参数以字典序升序排列,拼接在一起,注意字典序中大写字母在前,空值(null)使用空字符串代替;
C)将B形成字符串获取SHA1摘要,形成一个40位的十六进制(字母大写)字符串,即为本次请求signature(签名)的值;

public String buildOtaSignature(OtaRequestVO reqVO) {
    List<String> params = new ArrayList<String>();
    params.add(reqVO.getAppKey());
    params.add(reqVO.getOsType());
    params.add(String.valueOf(reqVO.getVersion()));
    params.add(String.valueOf(reqVO.getTimestamp()));
    params.add(reqVO.getUdid());
    params.add(reqVO.getChannelCode());
    params.add(reqVO.getPkgName());
    params.add(reqVO.getHardwareType());
    params.add(reqVO.getGps());
    if(reqVO.getTargetVersion()>0){   
        params.add(String.valueOf(reqVO.getTargetVersion()));  
    }
 
    String signature = buildSignature(params);
    logger.debug("generated signature: " + signature);
 
    return signature;
}
 
/**
 * 对参数列表构造响应签名
 *
 * @param params
 * @return
 */
public static String buildSignature(List<String> params) {
    if (params == null || params.isEmpty()) {
        return "";
    }
 
    // 升序排序参数值
    Collections.sort(params);
 
    StringBuilder sb = new StringBuilder();
    for (String param : params) {
        sb.append(param == null ? "" : param);
    }
 
    return getSHA1Digest(sb.toString());
}
 
/**
 * 将字符串进行SHA1获取摘要,摘要为十六进制字符串
 *
 * @param data
 * @return
 * @throws Exception
 */
public static String getSHA1Digest(String data) {
    String digest = null;
    try {
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        byte[] bytes = md.digest(data.getBytes("UTF-8"));
        digest = byte2hex(bytes);
    } catch (Exception e) {
        logger.error(e.getMessage(), e);
    }
 
    return digest;
}
 
/**
 * 二进制转十六进制字符串
 *
 * @param bytes
 * @return
 */
private static String byte2hex(byte[] bytes) {
    StringBuilder sign = new StringBuilder();
    for (int i = 0; i < bytes.length; i++) {
        String hex = Integer.toHexString(bytes[i] & 0xFF);
        if (hex.length() == 1) {
            sign.append("0");
        }
        sign.append(hex.toUpperCase());
    }
 
    return sign.toString();
}
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

# 错误码定义及描述

returnCode message 描述
0000 没有更新 没有找到要更新的数据包
0001 有更新
1000 请求时间戳超出了请求有效期 设备端时间和当前时间的差值绝对值不能超过10分钟
1001 签名错误
9999 其他错误 联系管理员