腾讯云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
}
腾讯云微信小程序一站式解决方案源码,里面包括了群聊的实现,信道状态枚举,断线重连最多尝试 5 次,每次重连前,等待时间的增量值,等确认微信小程序全面支持 ES6 就不用那么麻烦了。   这里包括了消息发送和接收,gi8p有信道处理事件等,里面还有比较多的子函数,比如注册消息处理函数、派发事件,通知所有处理函数进行处理、信道连接控制、获取 WebSocket 连接地址,获取地址成功后,开始进行 WebSocket 连接、   心跳、断开与重连处理、微信登录,获取 code 和 encryptData、进行服务器登录,以获得登录会话。信道事件处理机制    // 信道事件包括:    // connect - 连接已建立    // close - 连接被关闭(包括主动关闭和被动关闭)    // reconnecting - 开始重连    // reconnect - 重连成功    // error - 发生错误,其中包括连接失败、重连失败、解包失败等等    // [message] - 信道服务器发送过来的其它事件类型,如果事件类型和上面内置的事件类型冲突,将在事件类型前面添加前缀 `@`   腾讯云小程序一站式解决方案,Ping-Pong 心跳检测超时控制,这个值有两个作用:    * 1. 表示收到服务器的 Pong 相应之后,过多久再发下一次 Ping    * 2. 如果 Ping 发送之后,超过这个时间还没收到 Pong,断开与服务器的连接    * 该值将在与信道服务器建立连接后被更新
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值