最近公司需要做一个腾讯会议API的对接,经过查看官方文档和腾讯相关技术人员周旋~~以及不断踩坑,终于在我的不懈努力下,成功将API接口调通了

腾讯会议API接口文档:https://cloud.tencent.com/document/product/1095/42407

文章目录

  • 一、腾讯会议JWT鉴权
    • 1、公共参数
    • 2、签名算法
  • 二、封装获取公共请求头方法
  • 三、封装HTTP请求方法
    • 1、GET方法
    • 2、POST方法
  • 四、调用REST APIs
    • 1、创建会议
    • 2、查询会议
    • 3、取消会议

一、腾讯会议JWT鉴权

  • 腾讯会议API接口文档中详细写了使用API需要做的准备: 包括-创建应用,以及获取相应应用的SecretId,SecretKey,AppId等
  • 根据不同的应用创建方式,选择的鉴权方式也不同。
  • 腾讯会议API提供了两套鉴权方式,在这里我只介绍企业自建应用鉴权(JWT)

1、公共参数

公共参数是用于标识用户和接口鉴权目的的参数,如非必要,在每个接口单独的接口文档中不再对这些参数进行说明,但每次请求均需要携带这些参数,才能正常发起请求。
API 采用 TC3-HMAC-SHA256 签名方法,公共参数需要统一放到 HTTP Header 请求头部中。

参数名称 类型 必选 描述
Content-Type String 内容类型,传入格式必须为 application/json。
X-TC-Action String 操作的接口名称。取值参考接口文档中输入参数公共参数 Action 的说明。例如云服务器的查询实例列表接口,取值为 DescribeInstances。
X-TC-Region String 地域参数,用来标识希望操作哪个地域的数据。接口接受的地域取值参考接口文档中输入参数公共参数 Region 的说明。注意:某些接口不需要传递该参数,接口文档中会对此特别说明,此时即使传递该参数也不会生效。
X-TC-Key String 此参数参与签名计算。腾讯云 API 接入,申请的安全凭证密钥对中的 SecretId,其 Secretkey 用于签名。企业管理员可以登录 腾讯会议官网,单击右上角用户中心,在左侧菜单栏中的企业管理 > 高级 > restApi中进行查看。
X-TC-Timestamp String 此参数参与签名计算。当前 UNIX 时间戳,可记录发起 API 请求的时间。例如1529223702,单位为秒。注意:如果与服务器时间相差超过5分钟,会引起签名过期错误。
X-TC-Nonce String 此参数参与签名计算。随机正整数。
X-TC-Version String 应用 App 的版本号,建议设置,以便灰度和查找问题。
X-TC-Signature String 放置由下面的签名方法产生的签名。
X-TC-Token String 临时证书所用的 Token ,需要结合临时密钥一起使用。临时密钥和 Token 需要到访问管理服务调用接口获取。长期密钥不需要 Token。
AppId String 腾讯会议分配给三方开发应用的 App ID。企业管理员可以登录 腾讯会议官网,单击右上角用户中心,在左侧菜单栏中的企业管理 > 高级 > restApi中进行查看。
SdkId String 用户子账号或开发的应用 ID,企业管理员可以登录 腾讯会议官网,单击右上角用户中心,在左侧菜单栏中的企业管理 > 高级 > restApi中进行查看(如存在 SdkId 则必须填写,早期申请 API 且未分配 SdkId 的客户可不填写)。
X-TC-Registered String 启用账户通讯录,传入值必须为1,创建的会议可出现在用户的会议列表中。 启用账户通讯录说明: 1. 通过 SSO 接入腾讯会议账号体系。 2. 通过调用接口创建企业用户。 3. 通过企业管理后台添加或批量导入企业用户。

2、签名算法

可参考腾讯会议API-企业自建应用鉴权(JWT)

https://cloud.tencent.com/document/product/1095/42413

import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;/*** 生成签名,开发版本oracle jdk 1.8.0_221** @param secretId        邮件下发的secret_id* @param secretKey       邮件下发的secret_key* @param httpMethod      http请求方法 GET/POST/PUT等* @param headerNonce     X-TC-Nonce请求头,随机数* @param headerTimestamp X-TC-Timestamp请求头,当前时间的秒级时间戳* @param requestUri      请求uri,eg:/v1/meetings* @param requestBody     请求体,没有的设为空串* @return 签名,需要设置在请求头X-TC-Signature中* @throws NoSuchAlgorithmException e* @throws InvalidKeyException      e*/static String sign(String secretId, String secretKey, String httpMethod, String headerNonce,String headerTimestamp, String requestUri, String requestBody)throws NoSuchAlgorithmException, InvalidKeyException {String tobeSig =httpMethod + "\nX-TC-Key=" + secretId + "&X-TC-Nonce=" + headerNonce + "&X-TC-Timestamp="+ headerTimestamp + "\n" + requestUri + "\n" + requestBody;Mac mac = Mac.getInstance(HMAC_ALGORITHM);SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8),mac.getAlgorithm());mac.init(secretKeySpec);byte[] hash = mac.doFinal(tobeSig.getBytes(StandardCharsets.UTF_8));String hexHash = bytesToHex(hash);return new String(Base64.getEncoder().encode(hexHash.getBytes(StandardCharsets.UTF_8)));}private static String HMAC_ALGORITHM = "HmacSHA256";private static char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c','d', 'e', 'f'};static String bytesToHex(byte[] bytes) {char[] buf = new char[bytes.length * 2];int index = 0;for (byte b : bytes) {buf[index++] = HEX_CHAR[b >>> 4 & 0xf];buf[index++] = HEX_CHAR[b & 0xf];}return new String(buf);}

有了签名算法,我们可以生成公共请求头了

二、封装获取公共请求头方法

JWT鉴权方式需要在每次请求时加入公共请求头参数,以及通过签名算法生成的签名也需携带入请求头,借此,我封装了生成请求头的方法。

其中secretIdsecretKeyappIdsdkId是创建企业自建应用生成的,参考腾讯会议API文档-创建企业自建应用

需要注意的地方:

1、Timestamp参数是Unix时间戳,单位是秒

2、GET方法请求体需传""

/*** 获取公共请求头** @param httpMethod  请求方式:POST|GET* @param requestUri  请求uri* @param requestBody 请求体 GET方法请求体需传""* @return 拼接好的请求头*/public static Map<String, String> getHeader(String httpMethod, String requestUri,String requestBody) {HashMap<String, String> header = new HashMap<>(8);
//      请求随机数String headerNonce = String.valueOf(new Random().nextInt(999999));//  当前时间的UNIX时间戳String headerTimestamp = String.valueOf(System.currentTimeMillis() / 1000);String signature = null;try {signature = sign(secretId, secretKey, httpMethod, headerNonce, headerTimestamp, requestUri,requestBody);} catch (Exception e) {log.error("签名生成异常", e);}header.put("Content-Type", "application/json");header.put("X-TC-Key", secretId);header.put("X-TC-Timestamp", headerTimestamp);header.put("X-TC-Nonce", headerNonce);header.put("AppId", appId);header.put("X-TC-Version", "1.0");header.put("X-TC-Signature", signature);header.put("SdkId", sdkId);header.put("X-TC-Registered", "1");return header;}

三、封装HTTP请求方法

为了方便调用API,我封装了GET和POST方法

1、GET方法

/*** 发起get请求* @param uri    请求uri 生成签名使用* @param address 请求路径* @return        请求结果的JsonStr*/public static String sendGet(String address,String uri) {//get请求,请求体为""Map<String, String> header = getHeader("GET",uri,"");String result = "";String logInfo = "";GetMethod getMethod = null;try {// 创建httpClient实例对象HttpClient httpClient = new HttpClient();// 设置httpClient连接主机服务器超时时间:15000毫秒httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(15000);// 创建GET请求方法实例对象getMethod = new GetMethod(address);// 设置post请求超时时间getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 60000);if (header != null) {for (Map.Entry<String, String> entry : header.entrySet()) {getMethod.addRequestHeader(entry.getKey(), entry.getValue());}}logInfo = "HTTP调用接口:" + address;httpClient.executeMethod(getMethod);result = getMethod.getResponseBodyAsString();} catch (Exception e) {log.info("HTTP调用接口出错:" + logInfo + e, e);} finally {if (null != getMethod) {getMethod.releaseConnection();}}return result;}

2、POST方法

 /*** 腾讯会议发送post请求  携带生产签名和公共请求头参数** @param address     请求地址* @param uri         请求uri生产签名使用* @param requestBody 请求参数* @return           请求响应结果*/public static String sendPost(String address, String uri, String requestBody) {//生成公共请求头参数和签名HashMap<String, String> headerMap = getHeaderTest("POST", uri, requestBody);CloseableHttpClient httpClient = HttpClients.createDefault();HttpPost httpPost = new HttpPost(address);String jsonStr = "";try {for (Entry<String, String> header : headerMap.entrySet()) {httpPost.setHeader(header.getKey(), header.getValue());}httpPost.setEntity(new StringEntity(requestBody));CloseableHttpResponse httpResponse = null;httpResponse = httpClient.execute(httpPost);HttpEntity httpEntity = httpResponse.getEntity();if (httpEntity != null) {jsonStr = EntityUtils.toString(httpEntity, "UTF-8");}log.info("腾讯会议httpPost请求相应信息{}", jsonStr);} catch (IOException e) {log.info("腾讯会议httpPost发送异常", e);} finally {httpPost.releaseConnection();try {httpClient.close();} catch (IOException e) {log.error("httpClient关闭异常", e);}}return jsonStr;}

有了公共请求头,我们就可以调用API了

四、调用REST APIs

REST APIs:https://cloud.tencent.com/document/product/1095/42414

1、创建会议

  • 传参参考官方文档(https://cloud.tencent.com/document/product/1095/42417),我这里只传了必要参数

需要注意的是会议主题 subject,直接传入中文,会报API签名验证失败,这个是一个坑点,当初搞了我好久,一直没查到原因。

解决办法是取中文的Unicode

/*** 创建预约腾讯会议** @param subject   主题* @param startTime 开始时间戳* @param duration  持续时间(单位分钟)* @param userId    企业注册时的用户名* @return 创建结果*/public static Map<String, Object> creatMeeting(String subject, Long startTime,Integer duration, String userId) {//    Unix时间戳,单位为秒startTime = startTime / 1000;String endTime = String.valueOf(startTime + (duration * 60));HashMap<String, Object> resultMap = new HashMap<>(8);
//    请求体,get方法请求体需传""String resultBody = "{" +//会议结束时间"\"end_time\": \"" + endTime + "\"" + "," +//会议开始时间戳(单位秒)。"\"start_time\": \"" + startTime + "\"," +//用户的终端设备类型 1:PC"\"instanceid\": " + "1" + "," +// 会议类型:0:预约会议 1:快速会议"\"type\": " + "0" + "," +//腾讯会议用户唯一标识 不能为1--9内的数字"\"userid\": \"" + userId + "\"," +//会议主题"\"subject\": \"" + getUnicode(subject) + "\"" +"}";//    创建会议uriString uri = "/v1/meetings";String address = MEETING_DOMAIN_URL + uri;try {String jsonStr = requestPost(address, uri, resultBody);JSONObject jsonObject = JSONObject.parseObject(jsonStr);if (null == jsonObject.getJSONObject("error_info")) {JSONObject meetingInfo = jsonObject.getJSONArray("meeting_info_list").getJSONObject(0);resultMap.put("success", "true");resultMap.put("message", "创建预约会议成功");resultMap.put("meetingId", meetingInfo.getString("meeting_id"));resultMap.put("meetingCode", meetingInfo.getString("meeting_code"));resultMap.put("joinUrl", meetingInfo.getString("join_url"));} else {resultMap.put("success", "false");resultMap.put("message", "创建预约会议失败");resultMap.put("errorInfo", jsonObject.getJSONObject("error_info"));}} catch (Exception e) {resultMap.put("success", "false");resultMap.put("message", e.getMessage());log.error("创建预约会议发生异常", e);}return resultMap;}/*** 防止api请求中传入中文导致的报错问题* @param s 中文字符串* @return Unicode码*/
public static String getUnicode(String s) {try {StringBuffer out = new StringBuffer("");byte[] bytes = s.getBytes("unicode");for (int i = 0; i < bytes.length - 1; i += 2) {out.append("\\u");String str = Integer.toHexString(bytes[i + 1] & 0xff);for (int j = str.length(); j < 2; j++) {out.append("0");}String str1 = Integer.toHexString(bytes[i] & 0xff);out.append(str1);out.append(str);}return out.toString();} catch (UnsupportedEncodingException e) {e.printStackTrace();return null;}}

2、查询会议

  • 官方文档:https://cloud.tencent.com/document/product/1095/42418
  /*** 根据meetingId查询腾讯会议** @param meetingId 创建腾讯会议生成的meetingId* @param userId    创建人的id* @return 查询结果*/public static Map<String, Object> queryMeetings(String meetingId, String userId) {HashMap<String, Object> resultMap = new HashMap<>(8);try {String uri = "/v1/meetings/" + meetingId + "?userid=" + userId + "&instanceid=1";//    https://api.meeting.qq.com/v1/meetings/{meetingId}?userid={userid}&instanceid={instanceid}
//      String address = url + "/" + meetingId;String address = MEETING_DOMAIN_URL + uri;String jsonStr = sendGet(address, uri);JSONObject jsonObject = JSONObject.parseObject(jsonStr);resultMap.put("message", jsonObject.getString("error_info"));} catch (Exception e) {log.error("获取会议信息异常", e);resultMap.put("success", "false");resultMap.put("message", e.getMessage());}return resultMap;}

3、取消会议

  • 官方文档:https://cloud.tencent.com/document/product/1095/42422
/*** 取消预约的会议** @param userId    预定人id* @param meetingId 会议id* @return 取消结果*/public static Map<String, Object> cancelMeeting(String userId, String meetingId) {HashMap<String, Object> resultMap = new HashMap<>(8);
//    https://api.meeting.qq.com/v1/meetings/{meetingId}/cancelString address;
//    创建会议uriString uri = "/v1/meetings/" + meetingId + "/cancel";address = MEETING_DOMAIN_URL + uri;try {//    请求体,get方法请求体需传""String resultBody = "{\n"+ "     \"meetingId\" : \"" + meetingId + "\",\n"+ "     \"userid\" : \"" + userId + "\",\n"+ "     \"instanceid\" : 1,\n"+ "     \"reason_code\" : 1\n"+ "}";String jsonStr = requestPost(address, uri, resultBody);JSONObject jsonObject = JSONObject.parseObject(jsonStr);if (null == jsonObject.getJSONObject("error_info")) {resultMap.put("message", "取消会议成功");resultMap.put("success", "true");} else {resultMap.put("message", "取消会议失败");resultMap.put("errorInfo", jsonObject.getJSONObject("error_info"));resultMap.put("success", "false");}} catch (Exception e) {resultMap.put("success", "false");resultMap.put("message", e.getMessage());log.error("取消会议异常:", e);}return resultMap;}

到此我的文章就结束了,希望可以帮助到大家,少走一些弯路。

大家还有一些不懂的地方,可以到腾讯云提交工单(https://console.cloud.tencent.com/workorder/category),找腾讯售后寻求技术支持,客服还是很负责任的。

Java腾讯会议api接口,创建会议、查询会议,取消会议调用实例,以及踩过的坑相关推荐

  1. Java: 聚合数据API接口调用城市天气预报

    Java: 聚合数据API接口调用城市天气预报 点击进入[数据聚合_数据接口调用_开发者数据API开放平台](官网) 在pom文件中,加入依赖 <!--返回json数据--><dep ...

  2. python调用(百度云、腾讯云)API接口表格识别并保存为excel

    Python表格识别 图像识别具有较高的商业价值,本节主要通过python调用(百度云.腾讯云)API接口表格识别并保存为excel分析表格识别的能力: 提示:需分别申请密钥,在相应位置添加自己密钥即 ...

  3. 一款基于 Java 的可视化 HTTP API 接口开发神器

    今天推荐的 5 个项目是: magic-api :一款基于 Java 的可视化 HTTP API 接口开发神器. LanguageTool : 一款基于 Java 语言编写的开源语言校正工具. toB ...

  4. 微信小程序+OLAMI自然语言API接口制作智能查询工具--快递、聊天、日历等

    微信小程序最近比较热门,再加上自然语义理解也越来越被人关注,于是我想赶赶潮流,做一个小程序试试.想来想去快递查询应该是一种比较普遍的需求. 如果你也在通过自然语言接口做点什么,希望我的这篇博客能帮到你 ...

  5. 腾讯云API接口鉴权v3 鉴权失败问题 AuthFailure.SignatureFailure

    最近我开发的CRM项目正好在做营销短信的功能,这个功能需要对接腾讯云的第三方短信接口.众所周知,对接接口最难的就是鉴权部分了,毕竟为了安全嘛.云API鉴权一直是比较晦涩难懂的,建议大家还是去githu ...

  6. 新型冠状病毒全国疫情新浪腾讯网易API接口json

    一.新浪提供的接口地址: https://interface.sina.cn/news/wap/fymap2020_data.d.json 二.163提供的接口地址: 官方展示: https://ne ...

  7. java山海经_山海经API接口_免费数据接口 - 极速数据

    package api.jisuapi.shanhaijing; import java.net.URLEncoder; import api.util.HttpUtil; import net.sf ...

  8. java微信支付 [统一下单接口] 与 [订单查询接口] 调用成功完整代码与结果

    公司最近要搞微信支付, 之前也没有做过, 但是搞过阿里云, 想来也不是很难. 在网上找了很多贴子, 在eclipse里做了5个测试工程, 没有测试成功, 后来下了微信SDK, 也做了个测试样例, 期间 ...

  9. 电商API接口-电商OMS不可或缺的一块 调用代码展示

    电商后台管理系统关键的一环就是实现电商平台数据的抓取,以及上下架商品.订单修改等功能的调用.这里就需要调用电商API接口.接入电商API接口后再根据自我的需求进行功能再开发,实现业务上的数字化管理. ...

最新文章

  1. 怎么将算法改成程序_多肉烂根怎么办?将土培改成水培,长势好,叶子变得更水灵...
  2. 设计模式:命令模式(Command)
  3. matlab13节点线路模型,13节点配电网的建模与仿真.doc
  4. YOLO+PaddleOCR实现车牌检测识别
  5. 快捷方式全部变成LNK文件修复方法
  6. f分布表完整图a=0.01_R语言具有Student-t分布改进的GARCH(1,1)模型的贝叶斯估计...
  7. 白萝卜烘干技术,白萝卜的干燥过程
  8. NFT平台开发部署应该选择哪条区块链?
  9. 基于冷冻电镜图像的低通滤波(Lowpass Filter)算法
  10. excel单元格斜线_个人永久性免费-Excel催化剂功能第74波-批量排版格式利器,瞬间美化表格...
  11. 网站系统维护通知美化页面
  12. 韩语 计算机术语,韩语计算机、互联网术语(1)
  13. 书单 | 双十一薅当当羊毛4折囤书攻略
  14. Django--手机号注册生成验证码
  15. Linux 的 top命令参数详解 PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
  16. 项目开发团队分配管理软件
  17. 网客 网络真正的守护神!!!!!
  18. /mmcv/_ext.cpython-37m-x86_64-linux-gnu.so: undefined symbol
  19. 2023年第三届纳米材料与纳米技术国际会议(NanoMT 2023)
  20. 华中与北航计算机,华中科技大和北航哪个好

热门文章

  1. 量化交易入门笔记-策略回测与评估
  2. 这些神奇的AI智能机器人很早就已出现过,你确定你不了解?
  3. 直击代驾行业痛点,优化客户体验
  4. 硬核浪漫!用python在圣诞节给对象送礼的5个最没用小技巧
  5. 设置Chrome谷歌浏览器默认无痕模式登陆
  6. 鼎捷T100开窗查询程序详解
  7. 微信键盘 0.9 内测发布:丝滑流畅,快来体验~
  8. OpenStack 企业私有云的若干需求(5):主流硬件支持、云快速交付 和 SLA 保证
  9. VisualStudio代码放在不同文件夹下进行管理,设置包含目录
  10. CTFHub Misc 之 鸡你太美