目录
处理 V2TIMListener -> onUserSigExpired 过期回调
getC2CHistoryMessageList 获取单聊历史消息
getGroupHistoryMessageList 获取群组历史消息
insertGroupMessageToLocalStorage 接口说明
V2TimGroupTipsElem.type 群Tips类型
博主wx:yuanlai45_csdn 博主qq:2777137742
后期会创建粉丝群,为同学们提供分享交流平台以及提供官方发送的福利奖品~
PS:重新清理依赖,在拷贝新项目的时候用得上
flutter clean
flutter pub get
1. 服务端API
1.1 生成签名
与腾讯通讯时需要带上 UserSig 签名参数,这个是标识这个用户访问被允许,所以这是必须要做的事情。
签名的方式有两种,一个是客户端签名,这种方式缺点容易被反编译后复制出密钥。
另一种方式是服务端签名,虽然消耗点服务器资源,但是这种比较安全。这是推荐的方式。
本文将会以 nodejs 作为后端,来说明签名过程。毕竟 js 语法大家容易理解。
1.1.1 步骤
第一步:获取签名算法
资料 即时通信 IM 生成 UserSig-服务端 API-文档中心-腾讯云
采用服务端计算 UserSig,可以最大限度地保障计算 UserSig 所用的密钥信息不被泄露。您只需将计算代码部署在您的服务器上,并提供面向 App 的服务端接口,在需要 UserSig 时由您的 App 向业务服务器发起请求获取动态 UserSig。 为了简化实现过程,我们提供了下列语言或平台的 UserSig 计算源码,您可以直接下载并集成到您的服务端。
语言版本 | 关键函数 | 下载链接 |
---|---|---|
Java | HMAC-SHA256 | genSig |
GO | HMAC-SHA256 | GenSig |
PHP | HMAC-SHA256 | genSig |
Nodejs(这个) | HMAC-SHA256 | genSig |
Python | HMAC-SHA256 | gen_sig |
C# | HMAC-SHA256 | GenSig |
C++ | HMAC-SHA256 | gen_sig |
第二步:查看函数输入输出
资料 tls-sig-api-v2-node/TLSSigAPIv2.js at master · tencentyun/tls-sig-api-v2-node · GitHub
初始化签名对象,传入 appid, key 密钥
...
var Api = function (sdkappid, key) {
this.sdkappid = sdkappid;
this.key = key;
};
...
签名函数,传入 userid 用户编号,expire 过期时间秒,userBuf 默认 null 只有在音视频时才用上
Api.prototype.genSig = function (userid, expire, userBuf) {
var currTime = Math.floor(Date.now() / 1000);
var sigDoc = {
'TLS.ver': "2.0",
'TLS.identifier': "" + userid,
'TLS.sdkappid': Number(this.sdkappid),
'TLS.time': Number(currTime),
'TLS.expire': Number(expire)
};
var sig = '';
if (null != userBuf) {
var base64UserBuf = base64encode(userBuf);
sigDoc['TLS.userbuf'] = base64UserBuf;
sig = this._hmacsha256(userid, currTime, expire, base64UserBuf);
} else {
sig = this._hmacsha256(userid, currTime, expire, null);
}
sigDoc['TLS.sig'] = sig;
var compressed = zlib.deflateSync(newBuffer(JSON.stringify(sigDoc))).toString('base64');
return base64url.escape(compressed);
}
第三步:nodejs 实现功能
配置环境变量 env
.env
# tim
tim_server=console.tim.qq.com
tim_appid=1400803542
tim_key=密钥xxxxxxxxxxxxxxxxxx
初始签名对象
// 腾讯 tim
const tim = new TLSSigAPIv2.Api(config.tim_appid, config.tim_key);
fastify.decorate("tim", tim);
生成 UserSig 签名
// tim 签名
const im_sign_expire = 31536000; // 365天
const im_sign = await this.tim.genSig(username, im_sign_expire);
使用 apifox 来测试
调用 /users/me 接口
客户端保存好你的 im_sign 。
1.1.2 验证签名
输入 userid, 签名 sig, 点击开始校验,输出签名信息查看。
果然有效期是 365 天
小结
本节讲了腾讯签名令牌的后端实现方式,业务里面放在了获取用户资料的接口里面,因为我本来就要用 userid 去查询下数据库,这样就一起返回数据了。
如果发现不能登录、提示签名错误的,可以在腾讯后台点击开始校验看下是否签名正确。
apifox接口——可直接在项目设置选择apifix格式导入
{"apifoxProject":"1.0.0","$schema":{"app":"apifox","type":"project","version":"1.2.0"},"info":{"name":"猫哥视频站-课程","description":"","mockRule":{"rules":[],"enableSystemRule":true}},"responseCollection":[],"apiCollection":[{"name":"根目录","parentId":0,"serverId":"","description":"","preProcessors":[{"id":"inheritProcessors","type":"inheritProcessors","data":{}}],"postProcessors":[{"id":"inheritProcessors","type":"inheritProcessors","data":{}}],"inheritPostProcessors":{},"inheritPreProcessors":{},"auth":{},"identityPattern":{"httpApi":{"type":"methodAndPath","bodyType":""}},"items":[{"name":"用户","parentId":0,"serverId":"","description":"","preProcessors":[{"id":"inheritProcessors","type":"inheritProcessors","data":{}}],"postProcessors":[{"id":"inheritProcessors","type":"inheritProcessors","data":{}}],"inheritPostProcessors":{},"inheritPreProcessors":{},"auth":{},"identityPattern":{"httpApi":{"type":"inherit","bodyType":"","fields":[]}},"items":[{"name":"注册","api":{"id":"75406090","method":"post","path":"/users/register","parameters":{"query":[],"path":[]},"auth":{},"commonParameters":{"query":[],"body":[],"cookie":[],"header":[]},"responses":[{"id":"190834219","name":"成功","code":200,"contentType":"json","jsonSchema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"],"x-apifox-orders":["id"]}}],"responseExamples":[{"name":"成功示例 ","data":"{\n \"id\": \"7\"\n}","responseId":190834219,"ordering":1}],"requestBody":{"type":"application/json","parameters":[],"jsonSchema":{"title":"","type":"object","properties":{"username":{"type":"string","mock":{"mock":"ducafecat"},"title":""},"password":{"type":"string","mock":{"mock":"123456"}},"email":{"type":"string","mock":{"mock":"ducafecat@gmail.com"}},"verify_code":{"type":"string"}},"x-apifox-orders":["username","password","email","verify_code"],"required":["username","password","email","verify_code"]}},"description":"","tags":[],"status":"developing","serverId":"","operationId":"","sourceUrl":"","ordering":0,"cases":[{"id":81441640,"type":"http","path":null,"name":"成功","responseId":190834219,"parameters":{},"commonParameters":{"query":[],"body":[],"header":[],"cookie":[]},"requestBody":{"parameters":[],"type":"application/json","data":"{\n \"username\": \"ducafecat\",\n \"password\": \"123456\",\n \"email\": \"ducafecat@gmail.com\"\n}"},"preProcessors":[],"postProcessors":[],"inheritPostProcessors":{},"inheritPreProcessors":{},"auth":{},"advancedSettings":{}}],"mocks":[],"customApiFields":"{}","advancedSettings":{},"mockScript":{},"codeSamples":[],"preProcessors":[],"postProcessors":[],"inheritPostProcessors":{},"inheritPreProcessors":{}}},{"name":"获取 Email 验证码","api":{"id":"75406088","method":"post","path":"/users/verify","parameters":{"query":[],"path":[]},"auth":{},"commonParameters":{"query":[],"body":[],"cookie":[],"header":[]},"responses":[{"id":"190834216","name":"成功","code":200,"contentType":"json","jsonSchema":{"type":"object","properties":{},"x-apifox-orders":[]}}],"responseExamples":[],"requestBody":{"type":"application/json","parameters":[],"jsonSchema":{"title":"","type":"object","properties":{"email":{"type":"string","mock":{"mock":"ducafecat@gmail.com"}},"type":{"type":"string","description":"register, findPassword"}},"x-apifox-orders":["email","type"],"required":["email","type"]}},"description":"","tags":[],"status":"developing","serverId":"","operationId":"","sourceUrl":"","ordering":6,"cases":[],"mocks":[],"customApiFields":"{}","advancedSettings":{},"mockScript":{},"codeSamples":[],"preProcessors":[],"postProcessors":[],"inheritPostProcessors":{},"inheritPreProcessors":{}}},{"name":"找回密码","api":{"id":"75406091","method":"post","path":"/users/findpwd","parameters":{"query":[],"path":[]},"auth":{},"commonParameters":{"query":[],"body":[],"cookie":[],"header":[]},"responses":[{"id":"190834218","name":"成功","code":200,"contentType":"json","jsonSchema":{"type":"object","properties":{},"x-apifox-orders":[]}}],"responseExamples":[],"requestBody":{"type":"application/json","parameters":[],"jsonSchema":{"title":"","type":"object","properties":{"email":{"type":"string","mock":{"mock":"ducafecat@gmail.com"}},"verify_code":{"type":"string","description":"验证码"},"password":{"type":"string","description":"密码"}},"x-apifox-orders":["email","verify_code","password"],"required":["email","verify_code","password"]}},"description":"","tags":[],"status":"developing","serverId":"","operationId":"","sourceUrl":"","ordering":12,"cases":[],"mocks":[],"customApiFields":"{}","advancedSettings":{},"mockScript":{},"codeSamples":[],"preProcessors":[],"postProcessors":[],"inheritPostProcessors":{},"inheritPreProcessors":{}}},{"name":"加密","api":{"id":"75406087","method":"post","path":"/users/encrypt","parameters":{"query":[],"path":[]},"auth":{},"commonParameters":{"query":[],"body":[],"cookie":[],"header":[]},"responses":[{"id":"190834215","name":"成功","code":200,"contentType":"json","jsonSchema":{"type":"object","properties":{},"x-apifox-orders":[]}}],"responseExamples":[],"requestBody":{"type":"application/json","parameters":[],"jsonSchema":{"title":"","type":"object","properties":{"password":{"type":"string","description":"密码"}},"x-apifox-orders":["password"],"required":["password"]}},"description":"","tags":[],"status":"developing","serverId":"","operationId":"","sourceUrl":"","ordering":18,"cases":[],"mocks":[],"customApiFields":"{}","advancedSettings":{},"mockScript":{},"codeSamples":[],"preProcessors":[],"postProcessors":[],"inheritPostProcessors":{},"inheritPreProcessors":{}}},{"name":"登录","api":{"id":"75406089","method":"post","path":"/users/login","parameters":{"query":[],"path":[]},"auth":{},"commonParameters":{"query":[],"body":[],"cookie":[],"header":[]},"responses":[{"id":"190834217","name":"成功","code":200,"contentType":"json","jsonSchema":{"type":"object","properties":{"token":{"type":"string"},"profile":{"type":"object","properties":{"username":{"type":"string"},"email":{"type":"string"},"nick_name":{"type":"string"},"avatar":{"type":"string"},"intro":{"type":"null"},"vip_grade":{"type":"string"},"vip_expire_time":{"type":"null"},"total_times":{"type":"integer"},"last_time":{"type":"string"},"reg_time":{"type":"string"}},"required":["username","email","nick_name","avatar","intro","vip_grade","vip_expire_time","total_times","last_time","reg_time"],"x-apifox-orders":["username","email","nick_name","avatar","intro","vip_grade","vip_expire_time","total_times","last_time","reg_time"]}},"required":["token","profile"],"x-apifox-orders":["token","profile"]}}],"responseExamples":[{"name":"成功示例 ","data":"{\n \"token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiNiIsImlhdCI6MTY2MDM5NzM0NSwiZXhwIjoxNjYxMDAyMTQ1fQ.KYSfIeK2Q-9PgPivIIqfIMWF0owSee6LXqoK7gk83F8\"\n}","responseId":190834217,"ordering":1}],"requestBody":{"type":"application/json","parameters":[],"jsonSchema":{"title":"","type":"object","properties":{"username":{"type":"string","mock":{"mock":"ducafecat@gmail.com"}},"password":{"type":"string","mock":{"mock":"kWrIeYCYAYvd3i5fUpjttlvXJC8ftNwNtIuToK9H6dh5zJdTXTA8ghZf46SWZuQn6DYBBEEzZc6FQghjssW/Kw=="}}},"x-apifox-orders":["username","password"],"required":["username","password"]}},"description":"","tags":[],"status":"developing","serverId":"","operationId":"","sourceUrl":"","ordering":24,"cases":[{"id":81441636,"type":"http","path":null,"name":"成功","responseId":190834217,"parameters":{},"commonParameters":{"query":[],"body":[],"header":[],"cookie":[]},"requestBody":{"parameters":[],"type":"application/json","data":"{\n \"username\": \"ducafecat01\",\n \"password\": \"cpVDcw/rkyPeYMeVJFa5cA7P5yuH8pI1h1U+thEdkI20Dhb5p66reU/HQHtDGZsTVXIMBLKCOtLmCZfG43m5SA==\"\n}"},"preProcessors":[],"postProcessors":[],"inheritPostProcessors":{},"inheritPreProcessors":{},"auth":{},"advancedSettings":{}}],"mocks":[],"customApiFields":"{}","advancedSettings":{"isDefaultUrlEncoding":1},"mockScript":{},"codeSamples":[],"preProcessors":[],"postProcessors":[],"inheritPostProcessors":{},"inheritPreProcessors":{}}},{"name":"Profile","api":{"id":"75406092","method":"get","path":"/users/me","parameters":{"query":[],"path":[]},"auth":{},"commonParameters":{"query":[],"body":[],"cookie":[],"header":[]},"responses":[{"id":"190834220","name":"成功","code":200,"contentType":"json","jsonSchema":{"type":"object","properties":{"id":{"type":"string"},"im_sig":{"type":"string"},"username":{"type":"string"},"email":{"type":"string"},"nick_name":{"type":"string"},"avatar":{"type":"string"},"intro":{"type":"null"},"vip_grade":{"type":"string"},"vip_expire_time":{"type":"string"},"total_times":{"type":"integer"},"last_time":{"type":"string"},"reg_time":{"type":"string"},"attributes":{"type":"object","properties":{"username":{"type":"string"},"email":{"type":"string"},"nick_name":{"type":"string"},"intro":{"type":"null"},"vip_grade":{"type":"string"},"vip_expire_time":{"type":"null"},"total_times":{"type":"integer"},"ip":{"type":"null"},"country":{"type":"null"},"province":{"type":"null"},"city":{"type":"null"},"last_time":{"type":"string"},"reg_time":{"type":"string"}},"required":["username","email","nick_name","intro","vip_grade","vip_expire_time","total_times","ip","country","province","city","last_time","reg_time"],"x-apifox-orders":["username","email","nick_name","intro","vip_grade","vip_expire_time","total_times","ip","country","province","city","last_time","reg_time"]}},"required":["id","im_sig","username","email","nick_name","avatar","intro","vip_grade","vip_expire_time","total_times","last_time","reg_time","attributes"],"x-apifox-orders":["id","attributes","im_sig","username","email","nick_name","avatar","intro","vip_grade","vip_expire_time","total_times","last_time","reg_time"]}}],"responseExamples":[{"name":"成功示例 ","data":"{\n \"id\": \"6\",\n \"attributes\": {\n \"username\": \"ducafecat\",\n \"email\": \"ducafecat@gmail.com\",\n \"nick_name\": \"ducafecat\",\n \"intro\": null,\n \"vip_grade\": \"guest\",\n \"vip_expire_time\": null,\n \"total_times\": 0,\n \"ip\": null,\n \"country\": null,\n \"province\": null,\n \"city\": null,\n \"last_time\": \"2022-08-13T13:28:00.646Z\",\n \"reg_time\": \"2016-07-20T12:00:15.000Z\"\n }\n}","responseId":190834220,"ordering":1}],"requestBody":{"type":"application/json","parameters":[],"jsonSchema":{"title":"","type":"object","properties":{},"x-apifox-orders":[]}},"description":"","tags":[],"status":"developing","serverId":"","operationId":"","sourceUrl":"","ordering":30,"cases":[{"id":81441638,"type":"http","path":null,"name":"成功","responseId":190834220,"parameters":{},"commonParameters":{"query":[],"body":[],"header":[],"cookie":[]},"requestBody":{"parameters":[],"type":"application/json"},"preProcessors":[],"postProcessors":[],"inheritPostProcessors":{},"inheritPreProcessors":{},"auth":{},"advancedSettings":{}}],"mocks":[],"customApiFields":"{}","advancedSettings":{},"mockScript":{},"codeSamples":[],"preProcessors":[],"postProcessors":[],"inheritPostProcessors":{},"inheritPreProcessors":{}}},{"name":"更新 Profile","api":{"id":"75406093","method":"put","path":"/users/me","parameters":{"query":[],"path":[]},"auth":{},"commonParameters":{"query":[],"body":[],"cookie":[],"header":[]},"responses":[{"id":"190834221","name":"成功","code":200,"contentType":"json","jsonSchema":{"type":"object","properties":{"id":{"type":"string"},"attributes":{"type":"object","properties":{"username":{"type":"string"},"email":{"type":"string"},"nick_name":{"type":"string"},"intro":{"type":"null"},"vip_grade":{"type":"string"},"vip_expire_time":{"type":"null"},"total_times":{"type":"integer"},"ip":{"type":"null"},"country":{"type":"null"},"province":{"type":"null"},"city":{"type":"null"},"last_time":{"type":"string"},"reg_time":{"type":"string"}},"required":["username","email","nick_name","intro","vip_grade","vip_expire_time","total_times","ip","country","province","city","last_time","reg_time"],"x-apifox-orders":["username","email","nick_name","intro","vip_grade","vip_expire_time","total_times","ip","country","province","city","last_time","reg_time"]}},"required":["id","attributes"],"x-apifox-orders":["id","attributes"]}}],"responseExamples":[{"name":"成功示例 ","data":"{\n \"id\": \"6\",\n \"attributes\": {\n \"username\": \"ducafecat\",\n \"email\": \"ducafecat@gmail.com\",\n \"nick_name\": \"ducafecat\",\n \"intro\": null,\n \"vip_grade\": \"guest\",\n \"vip_expire_time\": null,\n \"total_times\": 0,\n \"ip\": null,\n \"country\": null,\n \"province\": null,\n \"city\": null,\n \"last_time\": \"2022-08-13T13:28:00.646Z\",\n \"reg_time\": \"2016-07-20T12:00:15.000Z\"\n }\n}","responseId":190834221,"ordering":1}],"requestBody":{"type":"application/json","parameters":[],"jsonSchema":{"title":"","type":"object","properties":{},"x-apifox-orders":[]}},"description":"","tags":[],"status":"developing","serverId":"","operationId":"","sourceUrl":"","ordering":36,"cases":[],"mocks":[],"customApiFields":"{}","advancedSettings":{},"mockScript":{},"codeSamples":[],"preProcessors":[],"postProcessors":[],"inheritPostProcessors":{},"inheritPreProcessors":{}}},{"name":"tim 数据准备","api":{"id":"75406097","method":"post","path":"/users/chatPrepare","parameters":{"query":[],"path":[]},"auth":{},"commonParameters":{"query":[],"body":[],"cookie":[],"header":[]},"responses":[{"id":"190834227","name":"成功","code":200,"contentType":"json","jsonSchema":{"type":"object","properties":{},"x-apifox-orders":[]}}],"responseExamples":[{"name":"成功示例 ","data":"{\n \"id\": \"7\"\n}","responseId":190834227,"ordering":1}],"requestBody":{"type":"application/json","parameters":[],"jsonSchema":{"title":"","type":"object","properties":{"user_ids":{"type":"array","items":{"type":"string"}}},"x-apifox-orders":["user_ids"],"required":["user_ids"]}},"description":"","tags":[],"status":"developing","serverId":"","operationId":"","sourceUrl":"","ordering":60,"cases":[{"id":81441643,"type":"http","path":null,"name":"成功","responseId":0,"parameters":{},"commonParameters":{"query":[],"body":[],"header":[],"cookie":[]},"requestBody":{"parameters":[],"type":"application/json","data":"{\n \"password\": \"123456\"\n}"},"preProcessors":[],"postProcessors":[],"inheritPostProcessors":{},"inheritPreProcessors":{},"auth":{},"advancedSettings":{}}],"mocks":[],"customApiFields":"{}","advancedSettings":{},"mockScript":{},"codeSamples":[],"preProcessors":[],"postProcessors":[],"inheritPostProcessors":{},"inheritPreProcessors":{}}},{"name":"tim 解散聊天群","api":{"id":"75406098","method":"post","path":"/users/chatDeleteGroup","parameters":{"query":[],"path":[]},"auth":{},"commonParameters":{"query":[],"body":[],"cookie":[],"header":[]},"responses":[{"id":"190834226","name":"成功","code":200,"contentType":"json","jsonSchema":{"type":"object","properties":{},"x-apifox-orders":[]}}],"responseExamples":[],"requestBody":{"type":"application/json","parameters":[],"jsonSchema":{"title":"","type":"object","properties":{"userId":{"type":"string"},"groupId":{"type":"string"}},"x-apifox-orders":["userId","groupId"],"required":["userId","groupId"]}},"description":"","tags":[],"status":"developing","serverId":"","operationId":"","sourceUrl":"","ordering":66,"cases":[{"id":81441642,"type":"http","path":null,"name":"成功","responseId":0,"parameters":{},"commonParameters":{"query":[],"body":[],"header":[],"cookie":[]},"requestBody":{"parameters":[],"type":"application/json","data":"{\n \"password\": \"123456\"\n}"},"preProcessors":[],"postProcessors":[],"inheritPostProcessors":{},"inheritPreProcessors":{},"auth":{},"advancedSettings":{}}],"mocks":[],"customApiFields":"{}","advancedSettings":{},"mockScript":{},"codeSamples":[],"preProcessors":[],"postProcessors":[],"inheritPostProcessors":{},"inheritPreProcessors":{}}},{"name":"用户列表","api":{"id":"75406100","method":"post","path":"/users/findList","parameters":{"query":[],"path":[]},"auth":{},"commonParameters":{"query":[],"body":[],"cookie":[],"header":[]},"responses":[{"id":"190834228","name":"成功","code":200,"contentType":"json","jsonSchema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"attributes":{"type":"object","properties":{"username":{"type":"string"},"nick_name":{"type":"string"},"avatar":{"type":"string"}},"required":["username","nick_name","avatar"],"x-apifox-orders":["username","nick_name","avatar"]}},"required":["id","attributes"],"x-apifox-orders":["id","attributes"]}}}],"responseExamples":[{"name":"成功示例","data":"[\n {\n \"id\": \"186\",\n \"attributes\": {\n \"username\": \"bruce-bnu\",\n \"nick_name\": \"bruce-bnu\",\n \"avatar\": \"00258VC3ly1gty0r05zh2j60ut0u0tce02.jpg\"\n }\n },\n {\n \"id\": \"187\",\n \"attributes\": {\n \"username\": \"hbz_la\",\n \"nick_name\": \"hbz_la\",\n \"avatar\": \"00258VC3ly1gty0qy7h06j60hj0hjdhh02.jpg\"\n }\n },\n {\n \"id\": \"188\",\n \"attributes\": {\n \"username\": \"jiezaichan\",\n \"nick_name\": \"jiezaichan\",\n \"avatar\": \"00258VC3ly1gty0qzj6d9j60go0goabi02.jpg\"\n }\n },\n {\n \"id\": \"189\",\n \"attributes\": {\n \"username\": \"tyrSwift\",\n \"nick_name\": \"tyrSwift\",\n \"avatar\": \"71bdf8ebly1gty0qz6q32j20e80e8my9.jpg\"\n }\n },\n {\n \"id\": \"190\",\n \"attributes\": {\n \"username\": \"dy6429829\",\n \"nick_name\": \"dy6429829\",\n \"avatar\": \"00258VC3ly1gty0qxcj1cj609w09w3yy02.jpg\"\n }\n },\n {\n \"id\": \"191\",\n \"attributes\": {\n \"username\": \"leebin17\",\n \"nick_name\": \"leebin17\",\n \"avatar\": \"71bdf8ebly1gty1ti7lruj208c08bgm0.jpg\"\n }\n },\n {\n \"id\": \"192\",\n \"attributes\": {\n \"username\": \"CoderTiany\",\n \"nick_name\": \"CoderTiany\",\n \"avatar\": \"00258VC3ly1gty0qxcj1cj609w09w3yy02.jpg\"\n }\n },\n {\n \"id\": \"193\",\n \"attributes\": {\n \"username\": \"vijayh\",\n \"nick_name\": \"vijayh\",\n \"avatar\": \"71bdf8ebly1gty1th3xlyj20ch0cjmyb.jpg\"\n }\n },\n {\n \"id\": \"194\",\n \"attributes\": {\n \"username\": \"s365790504\",\n \"nick_name\": \"s365790504\",\n \"avatar\": \"00258VC3ly1gty0qwvax1j60gn0gngno02.jpg\"\n }\n },\n {\n \"id\": \"195\",\n \"attributes\": {\n \"username\": \"andy-wangzhenhua\",\n \"nick_name\": \"andy-wangzhenhua\",\n \"avatar\": \"00258VC3ly1gty0qyxpv1j60hj0hjtak02.jpg\"\n }\n },\n {\n \"id\": \"196\",\n \"attributes\": {\n \"username\": \"hasenharrison\",\n \"nick_name\": \"hasenharrison\",\n \"avatar\": \"00258VC3ly1gty1tgwpqvj60cj0cimyi02.jpg\"\n }\n },\n {\n \"id\": \"197\",\n \"attributes\": {\n \"username\": \"chenjiahui1024\",\n \"nick_name\": \"chenjiahui1024\",\n \"avatar\": \"00258VC3ly1gty1tgwpqvj60cj0cimyi02.jpg\"\n }\n },\n {\n \"id\": \"198\",\n \"attributes\": {\n \"username\": \"bjipattorney\",\n \"nick_name\": \"bjipattorney\",\n \"avatar\": \"71bdf8ebly1gty1th3xlyj20ch0cjmyb.jpg\"\n }\n },\n {\n \"id\": \"199\",\n \"attributes\": {\n \"username\": \"ljr13512765863\",\n \"nick_name\": \"ljr13512765863\",\n \"avatar\": \"00258VC3ly1gty0r05zh2j60ut0u0tce02.jpg\"\n }\n },\n {\n \"id\": \"200\",\n \"attributes\": {\n \"username\": \"jqc5656\",\n \"nick_name\": \"jqc5656\",\n \"avatar\": \"71bdf8ebly1gty0r1f5x4j20go0gogna.jpg\"\n }\n },\n {\n \"id\": \"201\",\n \"attributes\": {\n \"username\": \"subaoxiang\",\n \"nick_name\": \"subaoxiang\",\n \"avatar\": \"00258VC3ly1gty0r265hmj60u00u041y02.jpg\"\n }\n },\n {\n \"id\": \"202\",\n \"attributes\": {\n \"username\": \"XrZxHn521\",\n \"nick_name\": \"XrZxHn521\",\n \"avatar\": \"00258VC3ly1gty0qxmdwoj60hs0hs0tw02.jpg\"\n }\n },\n {\n \"id\": \"203\",\n \"attributes\": {\n \"username\": \"_shukNgan\",\n \"nick_name\": \"_shukNgan\",\n \"avatar\": \"00258VC3ly1gty1tgwpqvj60cj0cimyi02.jpg\"\n }\n },\n {\n \"id\": \"204\",\n \"attributes\": {\n \"username\": \"kevin02040\",\n \"nick_name\": \"kevin02040\",\n \"avatar\": \"00258VC3ly1gty1tgwpqvj60cj0cimyi02.jpg\"\n }\n },\n {\n \"id\": \"205\",\n \"attributes\": {\n \"username\": \"XDH2023\",\n \"nick_name\": \"XDH2023\",\n \"avatar\": \"00258VC3ly1gty0qxw06hj60u00u0dkf02.jpg\"\n }\n }\n]","responseId":190834228,"ordering":1}],"requestBody":{"type":"application/json","parameters":[],"jsonSchema":{"title":"","type":"object","properties":{"keyword":{"type":"string"},"page":{"type":"integer"},"pageSize":{"type":"integer"}},"x-apifox-orders":["keyword","page","pageSize"],"required":["keyword","pageSize","page"]}},"description":"","tags":[],"status":"developing","serverId":"","operationId":"","sourceUrl":"","ordering":72,"cases":[{"id":81441645,"type":"http","path":null,"name":"成功","responseId":0,"parameters":{},"commonParameters":{"query":[],"body":[],"header":[],"cookie":[]},"requestBody":{"parameters":[],"type":"application/json","data":"{\n \"password\": \"123456\"\n}"},"preProcessors":[],"postProcessors":[],"inheritPostProcessors":{},"inheritPreProcessors":{},"auth":{},"advancedSettings":{}}],"mocks":[],"customApiFields":"{}","advancedSettings":{"isDefaultUrlEncoding":1},"mockScript":{},"codeSamples":[],"preProcessors":[],"postProcessors":[],"inheritPostProcessors":{},"inheritPreProcessors":{}}}]},{"name":"博客","parentId":0,"serverId":"","description":"","preProcessors":[{"id":"inheritProcessors","type":"inheritProcessors","data":{}}],"postProcessors":[{"id":"inheritProcessors","type":"inheritProcessors","data":{}}],"inheritPostProcessors":{},"inheritPreProcessors":{},"auth":{},"identityPattern":{"httpApi":{"type":"inherit","bodyType":"","fields":[]}},"items":[{"name":"博客列表","api":{"id":"75406111","method":"get","path":"/blog","parameters":{"query":[{"required":false,"description":"页码 1","type":"integer","id":"WQTlENHs9g","example":"1","enable":true,"name":"page"},{"required":false,"description":"分类","type":"string","id":"QxVh259QPd","example":"flutter","enable":true,"name":"category"},{"required":false,"description":"查询词","type":"string","id":"Y8xke36dym","example":"","enable":true,"name":"keyword"},{"required":false,"description":"标签","type":"string","id":"Xg0Pz2Nhna","example":"","enable":true,"name":"tag"}]},"auth":{},"commonParameters":{"query":[],"body":[],"cookie":[],"header":[]},"responses":[{"id":"190834239","name":"成功","code":200,"contentType":"json","jsonSchema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"attributes":{"type":"object","properties":{"uri":{"type":"string"},"title":{"type":"string"},"keyword":{"type":"null"},"description":{"type":"string"},"tags":{"type":"string"},"cover":{"type":"string"},"pv":{"type":"integer"}},"required":["uri","title","keyword","description","tags","cover","pv"],"x-apifox-orders":["uri","title","keyword","description","tags","cover","pv"]}},"x-apifox-orders":["id","attributes"]}}}],"responseExamples":[],"requestBody":{"type":"none","parameters":[]},"description":"","tags":[],"status":"released","serverId":"","operationId":"","sourceUrl":"","ordering":0,"cases":[{"id":81441655,"type":"http","path":null,"name":"成功","responseId":190834239,"parameters":{"query":[{"id":"4WvPGW73gU","relatedId":"WQTlENHs9g","relatedName":"page","value":"1","enable":true,"isDelete":false},{"id":"eRvyxDKKwF","relatedId":"Y8xke36dym","relatedName":"keyword","value":"","enable":true,"isDelete":false},{"id":"mkSYtdT3Zb","relatedId":"QxVh259QPd","relatedName":"category","value":"flutter","enable":true,"isDelete":false},{"id":"TlWyzMx1OY","relatedId":"Xg0Pz2Nhna","relatedName":"tag","value":"","enable":true,"isDelete":false}],"path":[],"cookie":[],"header":[]},"commonParameters":{"query":[],"body":[],"header":[],"cookie":[]},"requestBody":{"parameters":[],"generateMode":"normal"},"preProcessors":[],"postProcessors":[],"inheritPostProcessors":{},"inheritPreProcessors":{},"auth":{},"advancedSettings":{"isDefaultUrlEncoding":1}}],"mocks":[],"customApiFields":"{}","advancedSettings":{"isDefaultUrlEncoding":1},"mockScript":{},"codeSamples":[],"preProcessors":[],"postProcessors":[],"inheritPostProcessors":{},"inheritPreProcessors":{}}},{"name":"博客详情","api":{"id":"75406112","method":"get","path":"/blog/{uri}","parameters":{"query":[],"path":[{"id":"uri#0","name":"uri","required":true,"description":"唯一标识","enable":true,"example":"flutter-autocomplete-debounce"}]},"auth":{},"commonParameters":{"query":[],"body":[],"cookie":[],"header":[]},"responses":[{"id":"190834240","name":"成功","code":200,"contentType":"json","jsonSchema":{"type":"object","properties":{"id":{"type":"string"},"attributes":{"type":"object","properties":{"uri":{"type":"string"},"title":{"type":"string"},"keyword":{"type":"null"},"description":{"type":"string"},"tags":{"type":"string"},"cover":{"type":"string"},"pv":{"type":"integer"},"content":{"type":"string"}},"required":["uri","title","keyword","description","tags","cover","pv","content"],"x-apifox-orders":["uri","title","keyword","description","tags","cover","pv","content"]}},"required":["id","attributes"],"x-apifox-orders":["id","attributes"]}}],"responseExamples":[],"requestBody":{"type":"none","parameters":[]},"description":"","tags":[],"status":"released","serverId":"","operationId":"","sourceUrl":"","ordering":6,"cases":[{"id":81441656,"type":"http","path":null,"name":"成功","responseId":190834240,"parameters":{"query":[],"path":[{"id":"uri#0","name":"uri","relatedId":"uri#0","enable":true,"isDelete":false,"value":"flutter-autocomplete-debounce","relatedName":"uri"}],"cookie":[],"header":[]},"commonParameters":{"query":[],"body":[],"header":[],"cookie":[]},"requestBody":{"parameters":[],"generateMode":"normal"},"preProcessors":[],"postProcessors":[],"inheritPostProcessors":{},"inheritPreProcessors":{},"auth":{},"advancedSettings":{"isDefaultUrlEncoding":1}}],"mocks":[],"customApiFields":"{}","advancedSettings":{"isDefaultUrlEncoding":1},"mockScript":{},"codeSamples":[],"preProcessors":[],"postProcessors":[],"inheritPostProcessors":{},"inheritPreProcessors":{}}},{"name":"博客路径","api":{"id":"75406113","method":"get","path":"/blog/paths","parameters":{"query":[],"path":[]},"auth":{},"commonParameters":{"query":[],"body":[],"cookie":[],"header":[]},"responses":[{"id":"190834241","name":"成功","code":200,"contentType":"json","jsonSchema":{"type":"array","items":{"type":"object","properties":{"params":{"type":"object","properties":{"uri":{"type":"string"}},"required":["uri"],"x-apifox-orders":["uri"]}},"x-apifox-orders":["params"]}}}],"responseExamples":[],"requestBody":{"type":"none","parameters":[]},"description":"","tags":[],"status":"released","serverId":"","operationId":"","sourceUrl":"","ordering":12,"cases":[],"mocks":[],"customApiFields":"{}","advancedSettings":{"isDefaultUrlEncoding":1},"mockScript":{},"codeSamples":[],"preProcessors":[],"postProcessors":[],"inheritPostProcessors":{},"inheritPreProcessors":{}}}]},{"name":"腾讯 tim 接口","parentId":0,"serverId":"","description":"","preProcessors":[{"id":"inheritProcessors","type":"inheritProcessors","data":{}}],"postProcessors":[{"id":"inheritProcessors","type":"inheritProcessors","data":{}}],"inheritPostProcessors":{},"inheritPreProcessors":{},"auth":{},"identityPattern":{"httpApi":{"type":"inherit","bodyType":"","fields":[]}},"items":[{"name":"用户","parentId":15032824,"serverId":"","description":"","preProcessors":[{"id":"inheritProcessors","type":"inheritProcessors","data":{}}],"postProcessors":[{"id":"inheritProcessors","type":"inheritProcessors","data":{}}],"inheritPostProcessors":{},"inheritPreProcessors":{},"auth":{},"identityPattern":{"httpApi":{"type":"inherit","bodyType":"","fields":[]}},"items":[{"name":"导入单个帐号","api":{"id":"75406114","method":"post","path":"https://{
{tim_server}}/v4/im_open_login_svc/account_import","parameters":{"query":[{"id":"VA6fwOfAMc","name":"sdkappid","example":"{
{tim_sdkappid}}","required":false,"description":"","enable":true,"type":"string"},{"id":"7XXQds5SKG","name":"identifier","example":"{
{tim_identifier}}","required":false,"description":"","enable":true,"type":"string"},{"id":"EnzbxrrpU4","name":"usersig","example":"{
{tim_usersig}}","required":false,"description":"","enable":true,"type":"string"},{"id":"349Hx9sGPJ","name":"random","example":"{% mock 'timestamp' %}","required":false,"description":"","enable":true,"type":"string"},{"id":"JAUX2MzawK","name":"contenttype","example":"json","required":false,"description":"","enable":true,"type":"string"}],"path":[]},"auth":{},"commonParameters":{"query":[],"body":[],"cookie":[],"header":[]},"responses":[{"id":"190834242","name":"成功","code":200,"contentType":"json","jsonSchema":{"type":"object","properties":{"ActionStatus":{"type":"string"},"ErrorCode":{"type":"integer"},"ErrorInfo":{"type":"string"}},"required":["ActionStatus","ErrorCode","ErrorInfo"],"x-apifox-orders":["ActionStatus","ErrorCode","ErrorInfo"]}}],"responseExamples":[{"name":"成功示例","data":"{\n \"ActionStatus\": \"OK\",\n \"ErrorCode\": 0,\n \"ErrorInfo\": \"\"\n}","responseId":190834242,"ordering":1}],"requestBody":{"type":"application/json","parameters":[],"jsonSchema":{"type":"object","properties":{"UserID":{"type":"string","mock":{"mock":"ducafecat"}},"Nick":{"type":"string","mock":{"mock":"猫哥"}},"FaceUrl":{"type":"string","mock":{"mock":"https://ducafecat.oss-cn-beijing.aliyuncs.com/ducafecat-video-flutter/avatar/00258VC3ly1gty0qztbhmj60e80e83zk02.jpg"}}},"x-apifox-orders":["UserID","Nick","FaceUrl"],"required":["UserID","Nick","FaceUrl"]},"example":"{\n \"UserID\": \"52\",\n \"Nick\": \"段涛\",\n \"FaceUrl\": \"{
{avatar_url}}\"\n}"},"description":"","tags":[],"status":"developing","serverId":"","operationId":"","sourceUrl":"","ordering":0,"cases":[{"id":81441657,"type":"http","path":null,"name":"成功","responseId":190834242,"parameters":{"query":[{"id":"skMbfmqv1H","relatedId":"VA6fwOfAMc","relatedName":"sdkappid","value":"{
{tim_sdkappid}}","enable":true,"isDelete":false},{"id":"umLImBnSzD","relatedId":"7XXQds5SKG","relatedName":"identifier","value":"{
{tim_identifier}}","enable":true,"isDelete":false},{"id":"1CFsX7WF5o","relatedId":"EnzbxrrpU4","relatedName":"usersig","value":"{
{tim_usersig}}","enable":true,"isDelete":false},{"id":"ihdtVexZx1","relatedId":"349Hx9sGPJ","relatedName":"random","value":"{% mock 'timestamp' %}","enable":true,"isDelete":false},{"id":"yCvm17mpTL","relatedId":"JAUX2MzawK","relatedName":"contenttype","value":"json","enable":true,"isDelete":false}],"path":[],"cookie":[],"header":[]},"commonParameters":{"query":[],"body":[],"header":[],"cookie":[]},"requestBody":{"parameters":[],"data":"{\n \"UserID\": \"ducafecat\",\n \"Nick\": \"猫哥\",\n \"FaceUrl\": \"https://ducafecat.oss-cn-beijing.aliyuncs.com/ducafecat-video-flutter/avatar/00258VC3ly1gty0qztbhmj60e80e83zk02.jpg\"\n}","generateMode":"normal"},"preProcessors":[],"postProcessors":[],"inheritPostProcessors":{},"inheritPreProcessors":{},"auth":{},"advancedSettings":{"isDefaultUrlEncoding":1}}],"mocks":[],"customApiFields":"{}","advancedSettings":{"isDefaultUrlEncoding":1},"mockScript":{},"codeSamples":[],"preProcessors":[],"postProcessors":[],"inheritPostProcessors":{},"inheritPreProcessors":{}}}]},{"name":"群组","parentId":15032824,"serverId":"","description":"","preProcessors":[{"id":"inheritProcessors","type":"inheritProcessors","data":{}}],"postProcessors":[{"id":"inheritProcessors","type":"inheritProcessors","data":{}}],"inheritPostProcessors":{},"inheritPreProcessors":{},"auth":{},"identityPattern":{"httpApi":{"type":"inherit","bodyType":"","fields":[]}},"items":[]}]}]}],"socketCollection":[],"docCollection":[],"schemaCollection":[],"webSocketCollection":[],"apiTestCaseCollection":[{"name":"根目录","children":[{"name":"默认分组","children":[],"items":[]}],"items":[]}],"apiTestSuiteCollection":[],"testCaseReferences":[],"environments":[],"commonScripts":[],"databaseConnections":[],"globalVariables":[{"variables":[{"name":"tim_server","value":"","description":""},{"name":"tim_sdkappid","value":"","description":""},{"name":"tim_identifier","value":"","description":""},{"name":"tim_usersig","value":"","description":""}],"id":"2593114"}],"commonParameters":{"parameters":{"body":[]},"id":436205,"projectId":2593114,"creatorId":563818,"editorId":563818,"createdAt":"2023-04-14T09:51:34.000Z","updatedAt":"2023-04-14T09:51:34.000Z","deletedAt":null},"projectSetting":{"apiStatuses":["developing","testing","released","deprecated"],"servers":[{"id":"default","name":"默认服务"}],"preProcessors":[],"postProcessors":[],"auth":{"type":"bearer","bearer":{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiMjY3IiwiaWF0IjoxNjgxMTEzMTU3LCJleHAiOjE2ODE3MTc5NTd9.QJEEGc8rTOkp9XQc4oldC89qcvwtdkhwd4CT-RNnmVk"}},"initialDisabledMockIds":[],"mockSettings":{},"gateway":[],"advancedSettings":{},"language":"zh-CN","id":"2062407","cloudMock":{"security":"free","enable":false,"tokenKey":"apifoxToken"}}}
1.2 Rest API 调用
腾讯提供了一系列的 api 接口,方便我们维护聊天业务功能,本文会对常见接口做一个介绍。
后面涉及到服务端调用问题不再重复。
用到的接口有用户、聊天群、消息推送。
1.2.1 签名介绍
即时通信 IM REST API 简介-服务端 API-文档中心-腾讯云
REST API 的 URL 格式如下:
其中各个参数的含义以及取值如下(参数名称及其取值均区分大小写):
参数 | 含义 | 取值 |
---|---|---|
https | 请求协议 | 请求协议为 HTTPS,请求方式为 POST |
xxxxxx | 专属域名 | 中国:console.tim.qq.com 新加坡:adminapisgp.im.qcloud.com 首尔: adminapikr.im.qcloud.com 法兰克福:adminapiger.im.qcloud.com 孟买:adminapiind.im.qcloud.com 硅谷:adminapiusa.im.qcloud.com |
ver | 协议版本号 | 固定为v4 |
servicename | 内部服务名,不同的 servicename 对应不同的服务类型 | 示例:v4/im_open_login_svc/account_import ,其中im_open_login_svc 为servicename 更多详情请参见 REST API 接口列表 |
command | 命令字,与 servicename 组合用来标识具体的业务功能 | 示例:v4/im_open_login_svc/account_import ,其中account_import 为command 更多详情请参见 REST API 接口列表 |
sdkappid | App 在即时通信 IM 控制台获取的应用标识 | 在申请接入时获得 |
identifier | 用户名,调用 REST API 时必须为 App 管理员帐号 | 参见 App 管理员 |
usersig | 用户名对应的密码 | 参见 生成 UserSig |
random | 标识当前请求的随机数参数 | 32位无符号整数随机数,取值范围0 - 4294967295 |
contenttype | 请求格式 | 固定值为json |
1.2.2 腾讯接口
生成管理员 administrator 签名
进入后台 辅助工具->UserSig生成&校验
配置到项目的 env 中
# tim
tim_server=console.tim.qq.com tim_appid=1400803542 tim_key=4d461a6e470248ffeeb75484xxxxxsssss7ee5b27126c5a728 tim_admin_sig=eJwtzEELgkAUxxxsssszexVNhkrV9VgTbMthZ3JxXBx8n-n7NjRVNn6-Z9weliDXv
包装一个 post 请求函数
async _post(path, jsonValue) {
// 随机的32位无符号整数
const random = Math.floor(Math.random() * 4294967295)
const url = `https://${config.tim_server}/${path}?sdkappid=${config.tim_appid}&identifier=administrator&usersig=${config.tim_admin_sig}&random=${random}&contenttype=json`
const res = await superagent.post(url).send(jsonValue).set('accept', 'json')
const json = JSON.parse(res.text)
return json
}
查询账号
用于查询自有帐号是否已导入即时通信 IM,支持批量查询。
async queryUser(username) {
const req = {
CheckItem: [
{
UserID: username
}
]
}
const res = await this._post('v4/im_open_login_svc/account_check', req)
if (res.ActionStatus != 'OK') {
throw new Error(res)
}
return res
}