如何调用API
构造请求
API 的请求方式仅支持POST
请求URL由如下部分构成:{URI-scheme} :// {address} / {path} ? {param}
- URI-scheme:表示用于传输请求的协议,当前所有API均采用HTTPS协议。
- address:指定承载REST服务端点的服务器域名或IP。
- path:资源路径,也即API访问路径。从具体API的URI模块获取,例如“查询设备详情”API的path为".....todo(待补充)"。
请求签名
调用接口时必须携带请求签名,平台会对根据签名值对调用方进行身份核验
调用方使用约定的签名计算方法计算出本次请求的签名值,
计算签名sign
计算sign值,是发起调用请求的第一步。post请求的content-type当前支持两种方式application/json和multipart/form-data,下面将分开展示两种方式下的sign计算方式。
什么是sign
sign是使用MD5算法,通过对appId,appSecret,随机数和请求参数,通过md5算法进行摘要,得到的一个字符串,具体签名算法见<签名示例>。为了安全考虑,客户端每次请求, 都需要根据随机数生成新的sign,同一个sign在1小时内只能调用一次。 计算方法如下: sign = MD5(appId+appSecret+jsonString+nonce) jsonString 为POST 请求的body的jsonString格式。
计算sign 示例
java 计算签名示例1 (content-type:application/json)
@Test
public void test() {
RestTemplate restTemplate = new RestTemplate();
// 随机数
Long nonce = System.currentTimeMillis();
// 创建api应用生成的appId
String appId = "601a91306a534b23a414049b";
// 创建api应用生成的appSecret
String appSecret = "371E4CDEB67B87786D649DACEB175D60";
// 请求体 body
JSONObject body = new JSONObject();
body.put("aaa", "ligen");
body.put("bbb", 20);
body.put("ccc", "500");
// 请求头header
MultiValueMap<String, String> header = new HttpHeaders();
header.add("appId", appId);
header.add("nonce", nonce.toString());
header.add("sign", getSign(appId, appSecret, nonce.toString(), body.toJSONString()));
HttpEntity<Object> entry = new HttpEntity<>(body, header);
// 发起请求
ResponseEntity<String> response = restTemplate.postForEntity("http://address(地址)/path(api)", entry, String.class);
}
/**
* @ desc : 计算签名,采用MD5摘要方式 不加盐,不迭代
* @ params [appId(应用Id), appSecret(密钥), nonce(随机数), jsonString(请求body的json字符串)]
* @ return
* @ date 2021/2/4
* @ author ligen
*/
private String getSign(String appId, String appSecret, String nonce, String jsonString) {
StringBuilder dataString = new StringBuilder()
.append(appId)
.append(appSecret)
.append(jsonString)
.append(nonce);
MessageDigest digest = MessageDigest.getInstance("MD5");
byte[] md5 = digest.digest(dataString.toString().getBytes());
return Hex.encodeHexString(md5);
}
java 计算签名示例 2 (content-type:multipart/form-data)
特别注意: 请求时应当设置如下参数
header.setContentType(MediaType.MULTIPART_FORM_DATA);
requestBody.add("file", file.getResource());
content-type的参数格式用于上传文件,如固件添加接口。计算签名示例如下
// 1 formdata 参数中除了file 文件参数外,其他参数拼接成字符串,如下
请求参数:
name:api测试上传
hardVer:V2.0.0
productId:EF1D793B
remark:api上传固件3a
softVer:V1.1.1
拼接后:
"name:api测试上传,hardVer:V2.0.0,productId:EF1D793B,remark:api上传固件3a,softVer:V1.1.1"
// 2 appId+appSecret+body(即上面参数拼接出的字符串)+nonce(随机数) 拼接新的字符串,得到
"601a91306a534b23a414049b371E4CDEB67B87786D649DACEB175D60name:api测试上传,hardVer:V2.0.0,productId:EF1D793B,remark:api上传固件3a,softVer:V1.1.1asdfasdfasd"
// 3 对上述字符串计算sign值,按照上一个示例相同计算sign值的方法,计算sign得到:"df8281600653cc20c6ea7383d0754677"
// 4 Header上添加计算完成的sing,nonce,appId请求即可,
返回结果
状态码
请求发送以后,您会收到响应,包含状态码、响应消息头和消息体。 状态码是一组从4xxx到8xxx的数字代码,状态码表示了请求响应的状态,完整的状态码列表请参见状态码。 对于创建产品接口,如果调用后返回状态码为"8001",则表示请求成功。
响应消息头
对应请求消息头,响应同样也有消息头,如“Content-type”等。
响应消息体
响应消息体通常以结构化格式返回,与响应消息头中Content-type对应,传递除响应消息头之外的内容。 响应示例
{
"code":"4001",
"msg":"操作成功",
"data": {
"id": "5fe5a3d4d08e6e44501d82c7",
"companyId": "3EB2EC5A",
"companyName": "测试",
"industry": "物联网",
"contact": "xxx",
"contactEmail": "xx1xxx@xxxx",
"phone": "18161272708",
"website": "http://senthink.com",
"address": "文一西路",
"remark": "备注信息xxxxxx",
"permissionId": "5fe1bc1d9ef54f2f9227aa20",
"deviceMax": 100,
"status": 1,
"createAt": "2020-12-25 16:33:24",
"updateAt": "2020-12-25T08:33:24.712+0000"
}
}
当接口调用出错时,会返回错误码及错误信息说明,错误响应的Body体格式如下所示。
{
"code": "4902",
"msg": "sign不能为空",
"data": null
}