腾讯云通信介绍
云通信(Instant Messaging)承载亿级 QQ 用户即时通信技术,数十年技术积累,腾讯云为您提供超乎寻常即时通信聊天服务。针对开发者的不同阶段需求及不同场景,云通信提供了一系列解决方案,包括: Android/iOS/Windows/Web 的 SDK 组件、服务端集成接口、第三方回调接口等,利用这些组件,可以在应用中构建自己的即时通信产品,解决开发者面临的高并发、高可用性的一系列问题。
服务端集成指引
服务端集成指引 - 云通信 - 文档首页 - 腾讯云文档平台 - 腾讯云
服务端集成 是 App 后台通过云通讯提供的一系列 REST API 来管理自身 App 的数据。云通信提供的 REST API 参见 REST API接口列表。
REST API 概览
REST API 概览 - 云通信 - 文档首页 - 腾讯云文档平台 - 腾讯云
REST API 是腾讯云提供给 App 后台的 HTTP 管理接口,其主要目的在于为 App 后台提供一个后台管理入口。目前云通信支持的 REST API 参见REST API 接口列表。
除了 REST API,App 控制台也可实现简单的数据管理、单发/群发消息,开发者可以在控制台上进行简单的数据管理、查看及测试。相比之下,REST API 接口较为原始,但管理能力却更为强大。
为了安全性,REST API 仅提供 HTTPS 接口。
用户名对应的签名usersig生成方法
使用Java原生接口生成签名的方法需要注意:
依赖jar包的引入(Maven方式):
├── bcpkix-jdk15on-152.jar
├── bcprov-jdk15on-152.jar
├── commons-codec-1.10.jar
├── gson-2.3.1.jar
├── json.jar
└── tls_signature.jar
其中前五个jar包的依赖声明可以通过maven仓库搜索找到:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.52</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.52</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.3.1</version>
</dependency>
tls_signature.jar由腾讯提供,可以通过官网提供的链接下载。下载后,可以将该jar包安装到本地maven仓库(mvn install:install-file -DgroupId=sun.microsystems.inc -DartifactId=rt -Dversion=1.6 -Dpackaging=jar -Dfile=rt.jar)或者安装到私有库后,在pom.xml文件中添加依赖即可:
<dependency>
<groupId>com.tls.tls_sigature</groupId>
<artifactId>tls_sigature</artifactId>
<version>1.0</version>
</dependency>
调用SDK中的方法生成签名
public String generateSignature(String identifier) {
tls_sigature.GenTLSSignatureResult result = null;
try {
result = GenTLSSignatureEx(tls.getSdkAppid(), identifier, tls.getPrivateKey());
if (0 == result.urlSig.length()) {
logger.error("GenTLSSignatureEx failed: " + result.errMessage + ",identifier:" + identifier);
throw new Exception();
}
tls_sigature.CheckTLSSignatureResult checkResult = CheckTLSSignatureEx(result.urlSig, tls.getSdkAppid(), identifier, tls.getPublicKey());
if (checkResult.verifyResult == false) {
logger.error("CheckTLSSignature failed: " + result.errMessage + ",identifier:" + identifier);
throw new Exception();
}
} catch (Exception e) {
logger.error("GenTLSSignatureEx failed,identifier:" + identifier, e);
}
return result.urlSig;
}
使用Spring RestTemplate标准方式调用“REST API”的问题
之所以使用双引号来标注REST API,是因为他们提供的API并非标准的REST风格,笔者在调用时,因为过度相信他们所声称REST风格,代码写到怀疑人生。
以独立模式账号导入接口 - 云通信 - 文档首页 - 腾讯云文档平台 - 腾讯云为例,使用POSTMAN调用接口,结果如图所示:
可以看到,返回结果并非标准的JSON格式。所以,如果使用RestTemplate的标准方法去结束结果是获取不到对象的。
通过反复测试发现,使用标准的JSON格式传输POST请求,他们的“REST API”后端也是无法获取RequestBody中的数据。
使用Spring RestTemplate调用API的方法
/**
* 构建Tim rest请求基本URL
*
* @param servicename 内部服务名,不同的servicename对应不同的服务类型。
* @param command 命令字,与servicename组合用来标识具体的业务功能。
* @return
*/
private String generateBaseUrl(String servicename, String command) {
String url = "https://console.tim.qq.com/v4/" + servicename + "/" + command +
"?sdkappid=" + tls.getSdkAppid() + "&identifier=" + tls.getAdministrator() +
"&usersig=" + this.generateSignatureForAdministrator() + "&random=" + new Date().getTime() + "&contenttype=json";
return url;
}
/**
* 封装Tim的请求过程
*
* @param servicename 内部服务名,不同的servicename对应不同的服务类型。
* @param command 命令字,与servicename组合用来标识具体的业务功能。
* @param requestBody 请求体,JSON化
* @return
* @throws CheckedException
*/
private ResultBody sendRequstToTim(String servicename, String command, String requestBody) throws CheckedException {
RestTemplate restTemplate = new RestTemplate();
String baseUrl = this.generateBaseUrl(servicename, command);
logger.debug("Tim请求:\n" + "url:\n" + baseUrl + ",\nrequest:\n" + requestBody);
String bodyStr = restTemplate.postForObject(baseUrl, requestBody, String.class);
ResultBody resultBody = new Gson().fromJson(bodyStr, ResultBody.class);
if (resultBody.getActionStatus().equals("OK") && resultBody.getErrorCode().equals("0")) {
return resultBody;
} else {
logger.error("Tim请求出错:" + "url:" + baseUrl + ",request:" + requestBody + "response:" + resultBody.toString());
throw new Exception();
}
}
postForObject方法声明:
@Nullable
public <T> T postForObject(java.lang.String url,
@Nullable
java.lang.Object request,
java.lang.Class<T> responseType,
java.lang.Object... uriVariables)
throws RestClientException
如上所示,使用postForObject方法调用API时,request不可以直接传入Java对象,必须将对象转换为Json字符串之后,作为String类型传入作为第二个参数。
返回结果类型声明responseType也必须设置为String.class。然后将返回的String转换为对象进行下一步的逻辑判断。