微信原生小程序接入腾讯即时通讯IM

3,302 阅读7分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情

腾讯即时通讯IM

要想在小程序中实现类似QQ、微信一对一或者一对多实时聊天功能,可以在腾讯云提供的即时通讯IM基础上进行开发。官方针对不同的应用,比如Web、小程序、Android、IOS、uni-app、Electron、Unity、UE、Flutter和React Native都提供了相应的IM SDK详细文档和简单Demo,开发人员可以先下载Demo查看实现效果,再在IM SDK配置文档的基础上进行开发环境的配置。
本文就将记录如何从零开始配置原生微信小程序即时通讯IM开发环境,为后续实现聊天功能奠定开发基础。

配置原生小程序IM开发环境

IM配置步骤

  • 首先需要安装好微信开发者工具,可以直接依据小程序文档进行安装。此处不再过多赘述。
  • 登录即时通讯IM控制台,这里需要先注册腾讯云账号,登录成功后,创建新应用并输入应用名称,然后就能够查看该新建应用的状态、业务版本、SDKAppID、创建时间以及到期时间等信息。点击该应用,复制并保存SDKAppID信息以及密钥,后续在小程序中需要使用。如下图

1664774792805.png

1664774948654.png

  • 获取GenerateTestUserSig.js,该文件在TUIKit源码内,可通过如下命令获取:git clone https://github.com/tencentyun/TIMSDK.git,然后单独保存TUIKit/miniprogram/debug/GenerateTestUserSig.js文件,便于后续登录im实时聊天时作为参数传入使用。
  • 更改GenerateTestUserSig.js文件中的SDKAPPID和SECRETKEY为我们上一步骤获取的SDKAppID信息以及密钥

1664775948245.png 该文件主要用于在客户端生成UserSig,前期开发或测试时可以使用,但是如果要上线,更加推荐将UserSig的计算代码集成到服务端并提高获取UserSig的接口。

原生小程序集成IM SDK

该步骤主要是将腾讯云即时通IM SDK集成到小程序项目中。
首先新建一个小程序项目,创建utils文件夹,该文件夹下创建tencentIM文件夹,用于存放IM SDK相关的文件,比如我们将之前获取Usersig的GenerateTestUserSig.js、lib-generate-test-usersig-es.min.js文件就放置于该文件夹下。
安装IM SDK相关插件:通过以下命令安装tim-wx-sdk和tim-upload-plugin,tim-upload-plugin主要用于发送上传图片、文件等。

npm install tim-wx-sdk --save
// 发送图片、文件等消息需要腾讯云 即时通信 IM 上传插件
npm install tim-upload-plugin --save

安装完成后,点击微信开发者工具中:工具-构建npm,开始构建npm,构建完成后代码目录如下图所示:

1664776891936.png 最后在项目中引入IM SDK相关模块并初始化:

import TIM from 'tim-wx-sdk';
import TIMUploadPlugin from 'tim-upload-plugin';
let options = {
  SDKAppID: 0 // 接入时需要将0替换为您的即时通信 IM 应用的 SDKAppID
};
// 创建 SDK 实例,`TIM.create()`方法对于同一个 `SDKAppID` 只会返回同一份实例
let tim = TIM.create(options); // SDK 实例通常用 tim 表示

// 设置 SDK 日志输出级别,详细分级请参见 setLogLevel  https://web.sdk.qcloud.com/im/doc/zh-cn/SDK.html#setLogLevel 接口的说明</a>
tim.setLogLevel(0); // 普通级别,日志量较多,接入时建议使用
// tim.setLogLevel(1); // release 级别,SDK 输出关键信息,生产环境时建议使用

// 注册腾讯云即时通信 IM 上传插件
tim.registerPlugin({'tim-upload-plugin': TIMUploadPlugin});

初始化代码

由于后续许多消息监听与收发等代码都需要在SDK初始化之后进行,所以可以将上述初始化代码封装为单独的一个init_TIM方法:

function init_TIM() { //初始化im实时聊天
  if (app.globalData.isInit) {
    //这里设置了一个全局变量isInit来标记是否已登录,避免重复创建im实例
    return false
  }
  let options = {
    SDKAppID: xxxxxx // 接入时需要将0替换为您的即时通信 IM 应用的 SDKAppID
  };

  // 创建 SDK 实例,`TIM.create()`方法对于同一个 `SDKAppID` 只会返回同一份实例
  tim = TIM.create(options); // SDK 实例通常用 tim 表示
  // 设置 SDK 日志输出级别,详细分级请参见 setLogLevel 接口的说明
  tim.setLogLevel(0); // 普通级别,日志量较多,接入时建议使用
  // tim.setLogLevel(1); // release 级别,SDK 输出关键信息,生产环境时建议使用
  // 注册腾讯云即时通信IM上传插件
  tim.registerPlugin({
    'tim-upload-plugin': TIMUploadPlugin
  });

  // 监听事件,例如:
  tim.on(TIM.EVENT.SDK_READY, function (event) {
    console.log('SDK_READY');
    // 收到离线消息和会话列表同步完毕通知,接入侧可以调用 sendMessage 等需要鉴权的接口
    // event.name - TIM.EVENT.SDK_READY
  });

  tim.on(TIM.EVENT.MESSAGE_RECEIVED, function (event) {
    console.log('收到消息');
    console.log(event.data);
 
    // // event.name - TIM.EVENT.MESSAGE_RECEIVED
    // // event.data - 存储 Message 对象的数组 - [Message]
  });

  tim.on(TIM.EVENT.MESSAGE_REVOKED, function (event) {
    // 收到消息被撤回的通知
    // event.name - TIM.EVENT.MESSAGE_REVOKED
    // event.data - 存储 Message 对象的数组 - [Message] - 每个 Message 对象的 isRevoked 属性值为 true
    console.log('消息被撤回');
    console.log(event.data);
  });

  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]

    // 更新当前所有会话列表
    console.log('发送了消息');
    console.log('更新当前所有会话列表');
    console.log(event.data);
  });

  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

    console.log('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起支持)。 

    console.log('KICKED_OUT');
  });

  tim.on(TIM.EVENT.NET_STATE_CHANGE, function (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 会自动同步消息  
  });
  tim.on(TIM.EVENT.FRIEND_APPLICATION_LIST_UPDATED, function (event) {
    console.log('需对方验证通过');
    console.log(event);
    // friendApplicationList - 好友申请列表 - [FriendApplication]
    // unreadCount - 好友申请的未读数
    const {
      friendApplicationList,
      unreadCount
    } = event.data;
  });
  tim.on(TIM.EVENT.FRIEND_LIST_UPDATED, function (event) {
    console.log('无需对方验证通过,自动添加通过');
    console.log(event);
  });
  tim.on(TIM.EVENT.FRIEND_LIST_UPDATED, function (event) {
    console.log('好友列表更新');
    console.log(event.data);
    getFriendGroupList_TIM();
  });
  app.globalData.isInit = true; //完成im实例创建后设置标志为true
}

如果要使用到关系链,即添加好友、好友关系等功能,则需要使用tim-wx-friendship.js,该文件在tim-wx-sdk文件夹下:

// import TIM from 'tim-wx-sdk'; //  无需关系链使用
//需要关系链则引入tim-wx-friendship.js
import TIM from '../../miniprogram_npm/tim-wx-sdk/tim-wx-friendship.js';

为了便于管理,可以在tencentIM文件夹下新建一个tim_func文件,该文件中引入SDK相关模块、定义上述初始化init_TIM函数、定义各种方法,这样能够方便的在SDK的各个监听函数中调用相关方法。如下所示:

1664777801956.png

注意点

  • 需要注意的是,由于小程序不存在类似Vue一样的事件监听机制或观察者订阅者的Api,所以需要单独新建一个Event类,去实现类似触发emit、监听on等方法。代码如下:
class Event {
  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) {
    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)
      }
    }
  }
}
export default Event