腾讯云sdk集成微信小程序开发
开发文档以及说明
1.前言
需求:实现两端微信小程序上进行实时沟通,并对聊天记录进行存储,展现会话列表
2.官方文档
https://cloud.tencent.com/document/product/269/68376 【集成ui说明】
https://cloud.tencent.com/document/product/269/37413#npm-.E9.9B.86.E6.88.90.EF.BC.88.E6.8E.A8.E8.8D.90.EF.BC.89 【集成sdk说明】
https://web.sdk.qcloud.com/im/doc/zh-cn/SDK.html 【说明文档】
开发流程
1.准备工作
首先是要注册腾讯云并创建应用,拿到APPID和秘钥【步骤4注册腾讯云】
https://cloud.tencent.com/document/product/269/68376
2.安装依赖
// IM 小程序 SDK
// 从v2.11.2起,SDK 支持了 WebSocket,推荐接入;v2.10.2及以下版本,使用 HTTP
npm install tim-wx-sdk --save
// 发送图片、文件等消息需要腾讯云 即时通信 IM 上传插件
npm install tim-upload-plugin --save
【微信小程序安装依赖后–构建npm】
3.开发
a app.js初始化
// app.js
/**
* 引入初始化im实时聊天
*/
import {
init_TIM,
} from './utils/TIMInit'
import Event from './utils/event'
const log = require('./utils/log')
App({
onLaunch() {
//腾讯IM初始化
init_TIM()
//挂载发布订阅至wx对象上
wx.event = new Event();
wx.getSystemInfo({
success(res) {
console.log('当前用户基础库版本', res.SDKVersion)
}
})
},
globalData: {
currentConversation: null ,// 消息列表 当前选中的聊天的人
}
})
b 封装工具类
event.js
项目中需要一些时间监听,所以需要在utils里面添加一个event类,然后在app.js上面绑定到wx全局对象上。
class Event {
/**
* on 方法把订阅者所想要订阅的事件及相应的回调函数记录在 Event 对象的 _cbs 属性中
*/
on(event, fn) {
if (typeof fn != "function") {
console.error('fn must be a function')
return
}
this._cbs = this._cbs || {};
(this._cbs[event] = this._cbs[event] || []).push(fn)
}
/**
* emit 方法接受一个事件名称参数,在 Event 对象的 _cbs 属性中取出对应的数组,并逐个执行里面的回调函数
*/
emit(event) {
this._cbs = this._cbs || {}
var callbacks = this._cbs[event], args
if (callbacks) {
callbacks = callbacks.slice(0)
args = [].slice.call(arguments, 1)
for (var i = 0, len = callbacks.length; i < len; i++) {
callbacks[i].apply(null, args)
}
}
}
/**
* off 方法接受事件名称和当初注册的回调函数作参数,在 Event 对象的 _cbs 属性中删除对应的回调函数。
*/
off(event, fn) {
this._cbs = this._cbs || {}
// all
if (!arguments.length) {
this._cbs = {}
return
}
var callbacks = this._cbs[event]
if (!callbacks) return
// remove all handlers
if (arguments.length === 1) {
delete this._cbs[event]
return
}
// remove specific handler
var cb
for (var i = 0, len = callbacks.length; i < len; i++) {
cb = callbacks[i]
if (cb === fn || cb.fn === fn) {
callbacks.splice(i, 1)
break
}
}
return
}
}
export default Event
log.js
微信小程序(或类似平台)的实时日志管理模块。它定义了一个模块,该模块提供了几个方法来处理日志,包括info、warn、error以及设置和添加过滤消息的setFilterMsg和addFilterMsg。
var log = wx.getRealtimeLogManager ? wx.getRealtimeLogManager() : null
module.exports = {
info() {
if (!log) return
log.info.apply(log, arguments)
},
warn() {
if (!log) return
log.warn.apply(log, arguments)
},
error() {
if (!log) return
log.error.apply(log, arguments)
},
setFilterMsg(msg) { // 从基础库2.7.3开始支持
if (!log || !log.setFilterMsg) return
if (typeof msg !== 'string') return
log.setFilterMsg(msg)
},
addFilterMsg(msg) { // 从基础库2.8.1开始支持
if (!log || !log.addFilterMsg) return
if (typeof msg !== 'string') return
log.addFilterMsg(msg)
}
}
TIMinit.js
初始化tim并设置监听
const app = getApp()
import TIM from 'tim-wx-sdk'
import {
genTestUserSig
} from './GenerateTestUserSig'
let tim = '';
function init_TIM() { //初始化im实时聊天
let options = {
SDKAppID: 0 // 接入时需要将0替换为您的即时通信 IM 应用的 SDKAppID
};
let that = this
// 创建 SDK 实例,`TIM.create()`方法对于同一个 `SDKAppID` 只会返回同一份实例
tim = TIM.create(options); // SDK 实例通常用 tim 表示
// 设置 SDK 日志输出级别,详细分级请参见 setLogLevel 接口的说明
tim.setLogLevel(0); // 普通级别,日志量较多,接入时建议使用
// tim.setLogLevel(1); // release 级别,SDK 输出关键信息,生产环境时建议使用
// 注册 COS SDK 插件 此处暂时隐藏有需求要传图片,文件等的请放开进行配置,记住头部引入
// tim.registerPlugin({'cos-wx-sdk': COS})
// 监听事件,例如:
tim.on(TIM.EVENT.SDK_READY, function (event) {
// 收到离线消息和会话列表同步完毕通知,接入侧可以调用 sendMessage 等需要鉴权的接口
// event.name - TIM.EVENT.SDK_READY
console.log('SDK_READY')
wx.event.emit('sdkReady', '')
});
tim.on(TIM.EVENT.MESSAGE_RECEIVED, (event) => {
// 收到推送的单聊、群聊、群提示、群系统通知的新消息,可通过遍历 event.data 获取消息列表数据并渲染到页面
// event.name - TIM.EVENT.MESSAGE_RECEIVED
// event.data - 存储 Message 对象的数组 - [Message]
console.log('收到消息');
console.log(event)
wx.event.emit('renderMsg', event.data)
});
tim.on(TIM.EVENT.MESSAGE_REVOKED, function (event) {
// 收到消息被撤回的通知
// event.name - TIM.EVENT.MESSAGE_REVOKED
// event.data - 存储 Message 对象的数组 - [Message] - 每个 Message 对象的 isRevoked 属性值为 true
});
tim.on(TIM.EVENT.MESSAGE_READ_BY_PEER, function (event) {
// SDK 收到对端已读消息的通知,即已读回执。使用前需要将 SDK 版本升级至 v2.7.0 或以上。仅支持单聊会话。
// event.name - TIM.EVENT.MESSAGE_READ_BY_PEER
// event.data - event.data - 存储 Message 对象的数组 - [Message] - 每个 Message 对象的 isPeerRead 属性值为 true
});
tim.on(TIM.EVENT.CONVERSATION_LIST_UPDATED, function (event) {
// 收到会话列表更新通知,可通过遍历 event.data 获取会话列表数据并渲染到页面
// event.name - TIM.EVENT.CONVERSATION_LIST_UPDATED
// event.data - 存储 Conversation 对象的数组 - [Conversation]
});
tim.on(TIM.EVENT.GROUP_LIST_UPDATED, function (event) {
// 收到群组列表更新通知,可通过遍历 event.data 获取群组列表数据并渲染到页面
// event.name - TIM.EVENT.GROUP_LIST_UPDATED
// event.data - 存储 Group 对象的数组 - [Group]
});
tim.on(TIM.EVENT.PROFILE_UPDATED, function (event) {
// 收到自己或好友的资料变更通知
// event.name - TIM.EVENT.PROFILE_UPDATED
// event.data - 存储 Profile 对象的数组 - [Profile]
});
tim.on(TIM.EVENT.BLACKLIST_UPDATED, function (event) {
// 收到黑名单列表更新通知
// event.name - TIM.EVENT.BLACKLIST_UPDATED
// event.data - 存储 userID 的数组 - [userID]
});
tim.on(TIM.EVENT.ERROR, function (event) {
// 收到 SDK 发生错误通知,可以获取错误码和错误信息
// event.name - TIM.EVENT.ERROR
// event.data.code - 错误码
// event.data.message - 错误信息
});
tim.on(TIM.EVENT.SDK_NOT_READY, function (event) {
// 收到 SDK 进入 not ready 状态通知,此时 SDK 无法正常工作
// event.name - TIM.EVENT.SDK_NOT_READY
});
tim.on(TIM.EVENT.KICKED_OUT, function (event) {
// 收到被踢下线通知
// event.name - TIM.EVENT.KICKED_OUT
// event.data.type - 被踢下线的原因,例如:
// - TIM.TYPES.KICKED_OUT_MULT_ACCOUNT 多实例登录被踢
// - TIM.TYPES.KICKED_OUT_MULT_DEVICE 多终端登录被踢
// - TIM.TYPES.KICKED_OUT_USERSIG_EXPIRED 签名过期被踢 (v2.4.0起支持)。
});
tim.on(TIM.EVENT.NET_STATE_CHANGE, function (event) {
console.log('网络状态发生改变')
console.log(event)
// 网络状态发生改变(v2.5.0 起支持)。
// event.name - TIM.EVENT.NET_STATE_CHANGE
// event.data.state 当前网络状态,枚举值及说明如下:
// \- TIM.TYPES.NET_STATE_CONNECTED - 已接入网络
// \- TIM.TYPES.NET_STATE_CONNECTING - 连接中。很可能遇到网络抖动,SDK 在重试。接入侧可根据此状态提示“当前网络不稳定”或“连接中”
// \- TIM.TYPES.NET_STATE_DISCONNECTED - 未接入网络。接入侧可根据此状态提示“当前网络不可用”。SDK 仍会继续重试,若用户网络恢复,SDK 会自动同步消息
});
// app.globalData_TIM.isInit = true; //完成im实例创建后设置标志为true
}
function login_TIM(userID) { //登录im实时聊天
let promise = tim.login({
userID: userID,
userSig: genTestUserSig(userID).userSig
});
promise.then(function (imResponse) {
console.log('<==========登录成功=========>')
console.log(imResponse.data); // 登录成功
if (imResponse.data.repeatLogin === true) {
// 标识账号已登录,本次登录操作为重复登录。v2.5.1 起支持
console.log('当前重复登录')
console.log(imResponse.data.errorInfo);
}
}).catch(function (imError) {
console.warn('login error:', imError); // 登录失败的相关信息
});
}
// 发送消息
function sendMessage_TIM(sendTo, msg) {
//这里是文字消息的发送,有需求可以增加个type参数控制发送方式,文字/图片/音视频/文件 调用不同的tim接口
console.log(sendTo)
let message = tim.createTextMessage({
to: sendTo,
conversationType: TIM.TYPES.CONV_C2C,
payload: {
text: msg
}
});
let promise = tim.sendMessage(message);
return new Promise(resolve => {
promise.then(function (imResponse) {
// 发送成功
console.log('<==========发送成功=========>')
console.log(imResponse);
const {code} = imResponse
resolve(imResponse.data.message)
// resolve(code)
}).catch(function (imError) {
// 发送失败
console.log('<==========发送失败=========>')
console.warn('sendMessage error:', imError);
})
})
}
function logout_TIM() {
console.log('<==========登出操作=========>')
let promise = tim.logout();
promise.then(function (imResponse) {
console.log('登出成功:',imResponse.data); // 登出成功
}).catch(function (imError) {
console.warn('logout error:', imError);
});
}
function getMessageList_TIM(userId) {
wx.showLoading({
title: '加载中...'
});
console.log('<==========拉取消息=========>')
let promise = tim.getMessageList({
conversationID: `C2C${userId}`,
count: 15
});
return new Promise((resolve, reject) => {
promise.then((imResponse) => {
console.log('<==========拉取消息:成功=========>')
const messageList = imResponse.data.messageList; // 消息列表。
const nextReqMessageID = imResponse.data.nextReqMessageID; // 用于续拉,分页续拉时需传入该字段。
const isCompleted = imResponse.data.isCompleted; // 表示是否已经拉完所有消息。
wx.hideLoading({
complete: (res) => {},
})
resolve(imResponse)
}).catch(imError => {
wx.hideLoading({
complete: (res) => {},
})
reject(imError)
})
})
}
// 获取回话列表
function getConversationList_TIM() {
let promise = tim.getConversationList();
return new Promise((resolve, reject) => {
promise.then(function (imResponse) {
const conversationList = imResponse.data.conversationList; // 会话列表,用该列表覆盖原有的会话列表
resolve(conversationList)
}).catch(function (imError) {
console.warn('getConversationList error:', imError); // 获取会话列表失败的相关信息
reject(imError)
});
})
}
// 微信登录之后 更新个人资料
function updateMyProfile(options) {
let promise = tim.updateMyProfile(options)
return new Promise((resolve, reject) => {
promise.then(function (imResponse) {
console.log('更新资料成功:',imResponse.data); // 更新资料成功
resolve(imResponse.data)
}).catch(function (imError) {
reject(imError)
console.warn('updateMyProfile error:', imError); // 更新资料失败的相关信息
});
})
}
// 获取个人资料
function getUserProfile(userId){
let promise = tim.getUserProfile({
userIDList: [`${userId}`] // 请注意:即使只拉取一个用户的资料,也需要用数组类型,例如:userIDList: ['user1']
});
return new Promise((resolve, reject) => {
promise.then(function (imResponse) {
console.log('获取资料成功:',imResponse.data); // 更新资料成功
resolve(imResponse.data)
}).catch(function (imError) {
reject(imError)
console.warn('updateMyProfile error:', imError); // 更新资料失败的相关信息
});
})
}
//导出初始化,登录,消息发送接口供外部使用
module.exports = {
init_TIM,
login_TIM,
logout_TIM,
updateMyProfile,
getUserProfile,
sendMessage_TIM,
getMessageList_TIM,
getConversationList_TIM
}
GenerateTestUserSig.js
用于生成测试用的 UserSig,UserSig 是腾讯云为其云服务设计的一种安全保护签名。
/*eslint-disable*/
import LibGenerateTestUserSig from './lib-generate-test-usersig-es.min.js'
const _SDKAPPID = 0;
const _SECRETKEY = '0';
/*
* Module: GenerateTestUserSig
*
* Function: 用于生成测试用的 UserSig,UserSig 是腾讯云为其云服务设计的一种安全保护签名。
* 其计算方法是对 SDKAppID、UserID 和 EXPIRETIME 进行加密,加密算法为 HMAC-SHA256。
*
* Attention: 请不要将如下代码发布到您的线上正式版本的 App 中,原因如下:
*
* 本文件中的代码虽然能够正确计算出 UserSig,但仅适合快速调通 SDK 的基本功能,不适合线上产品,
* 这是因为客户端代码中的 SECRETKEY 很容易被反编译逆向破解,尤其是 Web 端的代码被破解的难度几乎为零。
* 一旦您的密钥泄露,攻击者就可以计算出正确的 UserSig 来盗用您的腾讯云流量。
*
* 正确的做法是将 UserSig 的计算代码和加密密钥放在您的业务服务器上,然后由 App 按需向您的服务器获取实时算出的 UserSig。
* 由于破解服务器的成本要高于破解客户端 App,所以服务器计算的方案能够更好地保护您的加密密钥。
*
* Reference:https://cloud.tencent.com/document/product/647/17275#Server
*/
function genTestUserSig(userID) {
/**
* 腾讯云 SDKAppId,需要替换为您自己账号下的 SDKAppId。
*
* 进入腾讯云实时音视频[控制台](https://console.cloud.tencent.com/rav ) 创建应用,即可看到 SDKAppId,
* 它是腾讯云用于区分客户的唯一标识。
*/
var SDKAPPID = _SDKAPPID;
/**
* 签名过期时间,建议不要设置的过短
* <p>
* 时间单位:秒
* 默认时间:7 x 24 x 60 x 60 = 604800 = 7 天
*/
var EXPIRETIME = 604800;
/**
* 计算签名用的加密密钥,获取步骤如下:
*
* step1. 进入腾讯云实时音视频[控制台](https://console.cloud.tencent.com/rav ),如果还没有应用就创建一个,
* step2. 单击“应用配置”进入基础配置页面,并进一步找到“帐号体系集成”部分。
* step3. 点击“查看密钥”按钮,就可以看到计算 UserSig 使用的加密的密钥了,请将其拷贝并复制到如下的变量中
*
* 注意:该方案仅适用于调试Demo,正式上线前请将 UserSig 计算代码和密钥迁移到您的后台服务器上,以避免加密密钥泄露导致的流量盗用。
* 文档:https://cloud.tencent.com/document/product/647/17275#Server
*/
var SECRETKEY = _SECRETKEY;
var generator = new LibGenerateTestUserSig(SDKAPPID, SECRETKEY, EXPIRETIME);
var userSig = generator.genTestUserSig(userID);
return {
sdkappid: SDKAPPID,
userSig: userSig
};
}
export {
_SDKAPPID as SDKAPPID,
genTestUserSig
}