腾讯云即时通信IM,拉取群历史消息

  • 需求说明
  • 服务端代码

需求说明

由于腾讯云历史消息存储时长为7天,所以在结束群聊后,需要将群聊消息拉取到本地,方面后续随时查看。

这里调用腾讯云 拉取群历史消息接口,这个接口只提供最多20条最近消息记录,所以需要使用递归不断查询,最终得到所有消息记录。

服务端代码

接口工具类

package com.cxbdapp.hbhtyyBackground.utils;import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;/*** 群组管理相关接口*/
@Slf4j
public class GroupSystemUtils {/*** 拉取群历史全量消息** @param groupId 拉取消息的群 ID* @return 群历史全量消息*/public static JSONObject groupMsgGetSimple(String groupId) {try {JSONObject groupMsgJsonData = groupMsgGetSimplePage(groupId, null);if (groupMsgJsonData == null) {return null;}Integer code = (Integer) groupMsgJsonData.get("ErrorCode");if (code != 0) {return null;}JSONArray rspMsgList = groupMsgJsonData.getJSONArray("RspMsgList");groupMsgRecursive(rspMsgList, groupId);groupMsgJsonData.put("RspMsgList", rspMsgList);return groupMsgJsonData;} catch (Exception e) {log.error("拉取群历史消息异常", e);return null;}}/*** 递归算法,查询所有消息记录** @param rspMsgList 消息记录集合* @param groupId    群ID*/public static void groupMsgRecursive(JSONArray rspMsgList, String groupId) {JSONObject leastMsgSeq = (JSONObject) rspMsgList.get(rspMsgList.size() - 1);Integer msgSeq = leastMsgSeq.getInt("MsgSeq");if (msgSeq > 1) {JSONObject groupMsgJsonData = groupMsgGetSimplePage(groupId, msgSeq - 1);if (groupMsgJsonData == null) {return;}Integer code = (Integer) groupMsgJsonData.get("ErrorCode");if (code != 0) {return;}rspMsgList.addAll(groupMsgJsonData.getJSONArray("RspMsgList"));groupMsgRecursive(rspMsgList, groupId);}}/*** 拉取群历史消息** @param groupId   拉取消息的群 ID* @param reqMsgSeq 请求的消息最大 seq,返回 <=ReqMsgSeq 的消息* @return 群历史消息*/public static JSONObject groupMsgGetSimplePage(String groupId, Integer reqMsgSeq) {try {String userSig = GenerateUserSigUtil.getUserSig(AppletUtils.identifier);String random = GenerateUserSigUtil.get32Random();String url = String.format(AppletUtils.GROUP_MSG_GET_SIMPLE, AppletUtils.SDKAPPID, AppletUtils.identifier, userSig, random);JSONObject requestPackage = new JSONObject();requestPackage.put("GroupId", groupId); //拉取消息的群 IDif (reqMsgSeq != null) {requestPackage.put("ReqMsgSeq", reqMsgSeq); //请求的消息最大 seq,返回 <=ReqMsgSeq 的消息}requestPackage.put("ReqMsgNumber", 20); //需要拉取的消息条数String body = HttpUtil.post(url, requestPackage.toString());log.info("拉取群历史消息应答包体报文:{}", body);if (StrUtil.isEmpty(body)) {return null;}return JSONUtil.parseObj(body);} catch (Exception e) {log.error("拉取群历史消息异常", e);return null;}}}

即时通信IM辅助工具类(腾讯云SDK拷贝的)

package com.cxbdapp.hbhtyyBackground.utils;import android.util.Base64;
import cn.hutool.core.util.StrUtil;
import org.json.JSONException;
import org.json.JSONObject;import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Random;
import java.util.zip.Deflater;/*** Module:   GenerateTestUserSig* <p>* Function: 用于生成测试用的 UserSig,UserSig 是腾讯云为其云服务设计的一种安全保护签名。* 其计算方法是对 SDKAppID、UserID 和 EXPIRETIME 进行加密,加密算法为 HMAC-SHA256。* <p>* Attention: 请不要将如下代码发布到您的线上正式版本的 App 中,原因如下:* <p>* 本文件中的代码虽然能够正确计算出 UserSig,但仅适合快速调通 SDK 的基本功能,不适合线上产品,* 这是因为客户端代码中的 SECRETKEY 很容易被反编译逆向破解,尤其是 Web 端的代码被破解的难度几乎为零。* 一旦您的密钥泄露,攻击者就可以计算出正确的 UserSig 来盗用您的腾讯云流量。* <p>* 正确的做法是将 UserSig 的计算代码和加密密钥放在您的业务服务器上,然后由 App 按需向您的服务器获取实时算出的 UserSig。* 由于破解服务器的成本要高于破解客户端 App,所以服务器计算的方案能够更好地保护您的加密密钥。* <p>* Reference:https://cloud.tencent.com/document/product/269/32688#Server*/
public class GenerateUserSigUtil {/*public static void main(String[] args) {System.out.println(gen32Random());}*/public static String get32Random() {Random rand = new Random();StringBuffer sb = new StringBuffer();for (int i = 1; i <= 32; i++) {int randNum = rand.nextInt(9) + 1;String num = randNum + "";sb = sb.append(num);}String random = String.valueOf(sb);return random;}/*** 计算 UserSig 签名* <p>* 函数内部使用 HMAC-SHA256 非对称加密算法,对 SDKAPPID、userId 和 EXPIRETIME 进行加密。** @note: 请不要将如下代码发布到您的线上正式版本的 App 中,原因如下:* <p>* 本文件中的代码虽然能够正确计算出 UserSig,但仅适合快速调通 SDK 的基本功能,不适合线上产品,* 这是因为客户端代码中的 SECRETKEY 很容易被反编译逆向破解,尤其是 Web 端的代码被破解的难度几乎为零。* 一旦您的密钥泄露,攻击者就可以计算出正确的 UserSig 来盗用您的腾讯云流量。* <p>* 正确的做法是将 UserSig 的计算代码和加密密钥放在您的业务服务器上,然后由 App 按需向您的服务器获取实时算出的 UserSig。* 由于破解服务器的成本要高于破解客户端 App,所以服务器计算的方案能够更好地保护您的加密密钥。* <p>* 文档:https://cloud.tencent.com/document/product/269/32688#Server*/public static String getUserSig(String userId) {return getTlsSignature(AppletUtils.SDKAPPID, userId, AppletUtils.EXPIRETIME, null, AppletUtils.SECRETKEY);}/*** 生成 tls 票据** @param sdkappid      应用的 appid* @param userId        用户 id* @param expire        有效期,单位是秒* @param userbuf       默认填写null* @param priKeyContent 生成 tls 票据使用的私钥内容* @return 如果出错,会返回为空,或者有异常打印,成功返回有效的票据*/private static String getTlsSignature(long sdkappid, String userId, long expire, byte[] userbuf, String priKeyContent) {if (StrUtil.isEmpty(priKeyContent)) {return "";}long currTime = System.currentTimeMillis() / 1000;JSONObject sigDoc = new JSONObject();try {sigDoc.put("TLS.ver", "2.0");sigDoc.put("TLS.identifier", userId);sigDoc.put("TLS.sdkappid", sdkappid);sigDoc.put("TLS.expire", expire);sigDoc.put("TLS.time", currTime);} catch (JSONException e) {e.printStackTrace();}String base64UserBuf = null;if (null != userbuf) {base64UserBuf = Base64.encodeToString(userbuf, Base64.NO_WRAP);try {sigDoc.put("TLS.userbuf", base64UserBuf);} catch (JSONException e) {e.printStackTrace();}}String sig = hmacSha256(sdkappid, userId, currTime, expire, priKeyContent, base64UserBuf);if (sig.length() == 0) {return "";}try {sigDoc.put("TLS.sig", sig);} catch (JSONException e) {e.printStackTrace();}Deflater compressor = new Deflater();compressor.setInput(sigDoc.toString().getBytes(Charset.forName("UTF-8")));compressor.finish();byte[] compressedBytes = new byte[2048];int compressedBytesLength = compressor.deflate(compressedBytes);compressor.end();return new String(base64EncodeUrl(Arrays.copyOfRange(compressedBytes, 0, compressedBytesLength)));}private static String hmacSha256(long sdkappid, String userId, long currTime, long expire, String priKeyContent, String base64Userbuf) {String contentToBeSigned = "TLS.identifier:" + userId + "\n"+ "TLS.sdkappid:" + sdkappid + "\n"+ "TLS.time:" + currTime + "\n"+ "TLS.expire:" + expire + "\n";if (null != base64Userbuf) {contentToBeSigned += "TLS.userbuf:" + base64Userbuf + "\n";}try {byte[] byteKey = priKeyContent.getBytes("UTF-8");Mac hmac = Mac.getInstance("HmacSHA256");SecretKeySpec keySpec = new SecretKeySpec(byteKey, "HmacSHA256");hmac.init(keySpec);byte[] byteSig = hmac.doFinal(contentToBeSigned.getBytes("UTF-8"));return new String(Base64.encode(byteSig, Base64.NO_WRAP));} catch (UnsupportedEncodingException e) {return "";} catch (NoSuchAlgorithmException e) {return "";} catch (InvalidKeyException e) {return "";}}private static byte[] base64EncodeUrl(byte[] input) {byte[] base64 = new String(Base64.encode(input, Base64.NO_WRAP)).getBytes();for (int i = 0; i < base64.length; ++i)switch (base64[i]) {case '+':base64[i] = '*';break;case '/':base64[i] = '-';break;case '=':base64[i] = '_';break;default:break;}return base64;}}

静态变量工具类

package com.cxbdapp.hbhtyyBackground.utils;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;/*** @Author cgp/zxy* @Date 2020/11/02 11:40* @Description 小程序公用静态变量工具类*/
@Component
public class AppletUtils {/*** 拉取群历史消息** @author zxy*/public static final String GROUP_MSG_GET_SIMPLE = "https://console.tim.qq.com/v4/group_open_http_svc/group_msg_get_simple?sdkappid=%s&identifier=%s&usersig=%s&random=%s&contenttype=json";/*** App 管理员帐号** @author zxy*/public static String identifier;@Value("${im.identifier}")public void setIdentifier(String identifier) {this.identifier = identifier;}/*** 腾讯云 SDKAppId,需要替换为您自己账号下的 SDKAppId。* <p>* 进入腾讯云云通信[控制台](https://console.cloud.tencent.com/avc ) 创建应用,即可看到 SDKAppId,* 它是腾讯云用于区分客户的唯一标识。** @author zxy*/public static int SDKAPPID;@Value("${tencent.cloud.sdkAppId}")public void setSDKAPPID(int SDKAPPID) {this.SDKAPPID = SDKAPPID;}/*** 签名过期时间,建议不要设置的过短* <p>* 时间单位:秒* 默认时间:7 x 24 x 60 x 60 = 604800 = 7 天** @author zxy*/public static int EXPIRETIME;@Value("${im.expireTime}")public void setEXPIRETIME(int EXPIRETIME) {this.EXPIRETIME = EXPIRETIME;}/*** 计算签名用的加密密钥,获取步骤如下:* <p>* step1. 进入腾讯云云通信[控制台](https://console.cloud.tencent.com/avc ) ,如果还没有应用就创建一个,* step2. 单击“应用配置”进入基础配置页面,并进一步找到“帐号体系集成”部分。* step3. 点击“查看密钥”按钮,就可以看到计算 UserSig 使用的加密的密钥了,请将其拷贝并复制到如下的变量中* <p>* 注意:该方案仅适用于调试Demo,正式上线前请将 UserSig 计算代码和密钥迁移到您的后台服务器上,以避免加密密钥泄露导致的流量盗用。* 文档:https://cloud.tencent.com/document/product/269/32688#Server** @author zxy*/public static String SECRETKEY;@Value("${im.secretKey}")public void setSECRETKEY(String SECRETKEY) {this.SECRETKEY = SECRETKEY;}
}

配置文件application.properties

spring.profiles.active=dev
#spring.profiles.active=test
#spring.profiles.active=online# App 管理员帐号
im.identifier=administrator
# 签名过期时间,时间单位:秒;7 x 24 x 60 x 60 = 604800 = 7 天
im.expireTime=604800
# 腾讯云 SDKAppId
tencent.cloud.sdkAppId=1234123412
# 计算签名用的加密密钥
im.secretKey=...

pigxCloud微服务项目04——服务端——腾讯云即时通信IM,拉取群历史消息(全量消息、所有群消息)相关推荐

  1. 在线登录注册功能(android客户端+javaweb服务端+腾讯云服务器+腾讯云数据库)

    在线登录注册功能(android客户端+javaweb服务端+腾讯云服务器+腾讯云数据库) 完整的项目已上传github仓库,链接在文章最下面 注:笔者在安卓客户端部分写了kotlin语言和java语 ...

  2. 胖葵酒店管理系统(android客户端+javaweb服务端+腾讯云服务器+腾讯云数据库)

    胖葵酒店管理系统app 完整项目已上传github,链接在文章下面 先看效果图: 登录: 主页面(点击右上角图标进入个人中心页面): 经理模块(客房管理模块和员工管理模块与经理管理模块类似,员工管理模 ...

  3. vue项目打包部署到腾讯云全过程

    文章目录 1.打包本地vue项目 2.购买云服务器 3.使用xshell 4.在xshell里安装宝塔 5.宝塔操作 6.成功访问 关于前端部署研究了挺久的,一开始毫无头绪也走了很多弯路,看了许多视频 ...

  4. c++后台开发项目_5900万!腾讯云中标安徽宿州wecity智慧园区EPC项目(含智慧路灯)...

    注:复制关键字☞宿州智慧园区☜发送至公众号后台可获取详细的招标文件及中标信息 中标情况 1.项目名称:宿州市高新双创智能谷wecity智慧园区EPC项目,项目编号:SZCG2019455 2.成交金额 ...

  5. 云服务器部署web项目 超详细步骤 腾讯云 阿里云

    购买阿里云服务器ECS,选择CentOS 7.6操作系统 外界用户访问云服务器中实例的示意图 重置实例的密码 设置安全组规则 创建安全组和安全组规则 为安全组添加实例 使用XShell和XFTP连接到 ...

  6. 腾讯云服务器怎么搭建ssm项目,SSM 项目如何上传图片到腾讯云COS?

    -------------------- 个人博客上已经同步更新了文章,有目录索引,阅读起来比较方便,欢迎大家移步个人博客上读阅~ 个人博客地址:[http://zwd596257180.gitee. ...

  7. 【新知实验室 - TRTC 实践】音视频互动 Demo、即时通信 IM 服务搭建

    一.TRTC 初识 TRTC 是什么 TRTC(Tencent RTC)腾讯实时音视频,源自于 QQ 音视频团队,是基于 QQ 音视频多年来的音视频技术积累,位于腾讯云的 RTC 云服务.TRTC 支 ...

  8. 【6】使用dockerfile打包/运行微服务项目,并上传到私服harbor

    使用dockerfile打包/运行微服务项目,并上传到私服harbor 关键词 dockerfile自定义demodocker 镜像 把自定义镜像上传到私服harbor 一.环境准备 主机地址 部署 ...

  9. SpringCloud微服务项目实战 - 6.延迟任务

    我没有失约,我与春风共至,我与夏蝉共鸣,我与秋叶共舞,我与凛冬共至,唯独你背道而行! 系列文章目录 项目搭建 App登录及网关 App文章 自媒体平台(博主后台) 内容审核(自动) 延迟任务 - 精准 ...

  10. 日调度5万亿次,腾讯云微服务架构体系TSF深度解读

    http://www.infoq.com/cn/news/2018/02/deep-interpretation-TSF-cloud-mi 写在前面 当前,传统企业的IT系统以单体架构为主,在面对互联 ...

最新文章

  1. 如何在SQL SELECT中执行IF…THEN?
  2. Linux/centos环境下maven安装与配置
  3. NYOJ 289 苹果
  4. C++学习笔记(草稿版)
  5. ipad鼠标圆圈变成箭头_下一代 macOS 或将支持 Mac「投屏」到 iPad
  6. 这也许是你不曾留意过的 Mybatis 细节 1
  7. SpringAOP之@EnableAspectJAutoProxy如何实现自动代理?
  8. Struts 2教程
  9. 2020年浙江大学金融考研经验分享
  10. Windows 使用学习
  11. 浅谈专科程序员的出路
  12. 【附源码】计算机毕业设计java学科竞赛赛场安排系统设计与实现
  13. 百度网址安全中心拦截解除的办法分享
  14. 安装VM、CentOS和网络配置
  15. 电信增值短信平台模块清单(sp用)
  16. 7 netsnmp安装window_NET SNMP|NET-SNMP windows版下载 v5.6.1.1 32位版 - 121下载站
  17. 【detectron】对输入样本如何产生anchor
  18. linux串口驱动安装 RPM,Devart数据库工具【教程】:在Linux(DEB / RPM)上安装和配置ODBC驱动程序...
  19. FPGA驱动24C04实现读写操作,提供工程源码和技术支持
  20. TYVJ 1248 丛林探险 解题报告

热门文章

  1. vue中使用阿里字体图标库
  2. AutoCAD块属性提取
  3. 谷歌学术高级搜索技巧
  4. 企业微信一天最多可以加多少人? 企业微信加好友功能会被限制吗?
  5. npoi Excel图表制作
  6. Python模块和包的导入
  7. 理论+故事,开启你的量化阅读之旅
  8. html文件svchost,解决html文件的DropFileName = svchost.exe木马
  9. 用logisim实现串行的全加器
  10. 一次简单的宾馆路由器后台破解