1、签名验证说明
1、网络环境
| 环境 | 域名 |
|---|---|
| 线上环境 | https://wpk.uc.cn |
2、HTTP 提交数据说明
除了特殊说明接口外当 POST, PUT 请求的时候,请确保 Request Content-Type是 application/json 类型。
3、签名验证协议 1)、签名公共参数说明
| 名称 | 是否必须 | 描述 | 来源 |
|---|---|---|---|
| clientId | 是 | 应用标识 | 首次访问可联系技术人员获取 |
| secret | 是 | 应用秘钥 | 首次访问可联系技术人员获取 |
| timestamp | 是 | 请求时间戳 从 1970 年 1 月 1 日开始计算到现在的毫秒数 | 调用时客户端自行生成 |
4、公共参数
| 名称 | 描述 | 是否必填 | 传参位置 |
|---|---|---|---|
| clientId | 应用标识 | 是 | url |
| timestamp | 时间戳 | 是 | url |
| signature | 签名参数 | 是 | url |
4、签名生成方法
signStr = MD5(clientId+secret+timestamp+k1=v1+k2=v2+...+kn=vn+body={})
说明:
- MD5 使用RFC 1321 规范
- 表达式中的“+”号表示字符串接,实际并不存在。
- 业务参数按(除了公共签名参数外所有参数,如k1=v1)按排序树排序
- body={}标识post&put等请求中带有json body时的处理方式,即:key=body,value= Request Body 字符串
- 签名有效期5分钟
5、java签名类:
package com.uc.meg.wpk.openapi.util;import java.util.Map;import java.util.Map.Entry;import java.util.TreeMap;import lombok.Data;import org.apache.commons.codec.digest.DigestUtils;import org.apache.commons.lang3.StringUtils;/*** 功能描述:签名builder* @version v1.0.0* @create on: 2018/4/9*/@Datapublic class SignBuilder {private Map<String, String> params = new TreeMap<>();// json bodyprivate String body;private String clientId;private String secret;private Long timestamp;// 旧版1.0用的是随机串,并且不校验时常private String nonce;public SignBuilder params (Map<String, String> params) {this.params.clear();this.params.putAll(params);return this;}public SignBuilder addParam(String name, String value) {params.put(name, value);return this;}public SignBuilder body (String body) {this.addParam("body", body);return this;}public SignBuilder clientId(String clientId) {this.clientId = clientId;return this;}public SignBuilder secret(String secret) {this.secret = secret;return this;}public SignBuilder timestamp(Long timestamp) {this.timestamp = timestamp;return this;}public SignBuilder nonce(String nonce) {this.nonce = nonce;return this;}/*** 构建签名信息* @return*/public String buildSign() {StringBuilder singBuilder = new StringBuilder(clientId).append(secret).append(timestamp);singBuilder.append(this.buildParams());return DigestUtils.md5Hex(singBuilder.toString());}/*** 拼接请求参数* @return*/private StringBuilder buildParams () {StringBuilder rst = new StringBuilder();for (Entry<String, String> entry : params.entrySet()) {if (StringUtils.isBlank(entry.getKey())) {continue;}if (null == entry.getValue()) {rst.append(entry.getKey()).append("=");} else {String value = entry.getValue();rst.append(entry.getKey()).append("=").append(value);}}return rst;}}
4、签名获取示例:
/*** 签名验证,以创建app的/rest/v1/api/app/create接口为例*//*** 签名*/@Testpublic void testCreateApp() {String clientId = "clientId";String secert = "12345678901234567890";Long timestamp = 1526432218000L;Map<String, String> map = new HashMap<>();map.put("app", "wpktest20181031");map.put("name", "wpktest");map.put("type", "html5");map.put("src", "h5");map.put("aggType", "url");map.put("accessType", "jssdk");map.put("description", "测试联调");String jsonBody = ObjectMapperUtil.toJSONString(map);SignBuilder signBuilder = new SignBuilder();String sign = signBuilder.body(jsonBody).clientId(clientId).secret(secert).timestamp(timestamp).buildSign();System.out.println(sign);// 正确的签名:5de415bed120dfcd1e3c4f8616444719String url = host + "/rest/v1/api/app/create?clientId=clientId×tamp=1526432218000&signature=5de415bed120dfcd1e3c4f8616444719"// sendRequestUseRestTemplate(url, jsonBody)// sendRequestUseHttpClient(url, jsonBody)}/*** 使用 restTemplate的发送请求** @param url* @param reqBody*/public String sendRequestUseRestTemplate(String url, String reqBody) {HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_JSON);HttpEntity<String> reqEntity = new HttpEntity<>(reqBody, headers);ResponseEntity<String> retEntity = restTemplate.postForEntity(url, reqEntity, String.class);return retEntity.getBody();}/*** 使用原生httpclient发送请求* @param url* @param jsonBody* @return* @throws IOException*/public String sendRequestUseHttpClient(String url, String jsonBody) throws IOException {CloseableHttpClient httpClient = HttpClients.createDefault();HttpPost httpPost = new HttpPost(url);httpPost.addHeader("Content-Type", "application/json");httpPost.setEntity(new StringEntity(jsonBody));CloseableHttpResponse response = httpClient.execute(httpPost);org.apache.http.HttpEntity entity = response.getEntity();String responseContent = EntityUtils.toString(entity, "UTF-8");response.close();httpClient.close();return responseContent;}
得到签名后,需要把签名信息,连同其它参数信息传递至对应访问接口中即可正常访问接口!
2、符号表
2.1、符号表上传
api url:
POST: /rest/v1/api/symbol/upload
content-type: multipart/form-data;
request字段说明:
| 字段名 | 说明 | 示例 | 是否必填 |
|---|---|---|---|
| clientId | 调用方的clientId | 是 | |
| app | 应用标识 | mobile/IPhXXX | 是 |
| version | 版本号(若版本不存在,会为其创建该版本) | 12.1.0.12、12.1.0.12(123456) | 是 |
| symbolType | 类型,测试版传test、正式版传release | test、release | 是 |
| file | 符号文件,使用zip压缩 | 是 |
response:
{"id": "8cbdbe8a-173c-466c-82a2-41be0c2ef0f9","code": "200","message": "OK","data": 123, // 符号表的唯一id"error": null}
2.2、符号表提取状态查询
api url:
GET: /rest/v1/api/symbol/status?id=xxx
request字段说明:
| 字段名 | 说明 | 示例 | 是否必填 |
|---|---|---|---|
| id | 上传符号表时返回的唯一id | 123 | 是 |
response:
{"id": "8cbdbe8a-173c-466c-82a2-41be0c2ef0f9","code": "200","message": "OK","data": {"status": 1,"msg": "完成处理"},"error": null}返回值status字段说明:1:完成处理; 2:正在上传; 3:等待处理; 4:正在处理; 5:处理失败; -1:符号表ID不存在
3、创建版本(只创建版本,不上传符号表)
api url:
POST: /rest/v1/api/version/save?clientId=xxx
request:
// post json{"app": "test",// 必填,对应的应用唯一标识(bid,appid)"version": "12.1.1.992(xxxx)", // 必填,版本 如:12.1.1.992(xxxx)"subVerSuffix": "test", // 子版本"parseenddate": "20190117", // 必填,解析结束时间 如:20191207"remark": "测试",// 说明}
response:
{"id": "fd8d79bb-d5f7-4585-a2c3-68aefce7460b","code": 200,"message": "OK","data": {"id": 115421,"platform": "test","version": "12.1.1.992(xxxx)","appName": "12_1_1test","sver": null,"tag": null,"coretag": null,"remark": "测试","publishdate": "2018-08-17 00:00:00","parseenddate": "20190117","logtype": null,"ismonitor": 0,"currentparsingminute": null,"priority": 1,"deltaparseminute": null,"isparse": 1,"ispush": 0,"pushmaillist": null,"pushhour": null,"pushdays": null,"monitorrules": null,"uploadSymbolDate": null,"uploadSymbolBy": null,"uploadSymbolByName": null,"createAt": "2019-01-17 14:26:55","createBy": null,"updateAt": "2019-01-17 14:26:55","updateBy": null,"parseStatus": 0,"subVerSuffix": "test"},"error": null}
code说明:
200,正常返回
其它,系统异常,可参照error中的type下message
