内容提要
本文介绍如何使用ZEGO ZIM SDK在微信小程序中实现单聊:先在控制台开通ZIM服务、配置服务器域名并规划分包,由服务端用ServerSecret签发Token;集成时封装单例并在登录前注册事件监听;登录后待会话同步完成再查询列表;发送文本消息支持乐观UI与重发,接收消息需去重,历史消息用游标分页,图片、语音等文件按type区分发送;群聊只需将conversationType改为2。
延伸解读
接入前必须手动开通 ZIM 服务
文章特别提醒,ZIM 服务在 ZEGO 控制台并非默认开通,需要进入「项目管理 → 即时通讯」手动开启。如果跳过这一步,后续调用 create 和 login 都会失败。此外,ServerSecret 必须仅保存在服务端,用于签发 Token,绝不能写入小程序代码,否则存在严重安全风险。
事件监听必须在登录前注册
SDK 登录后会立即回调连接状态、会话同步等通知,如果监听注册晚于 login,这些初始状态就会丢失。文章建议在封装单例后、调用登录前完成事件注册,并明确五个核心回调的分工:连接状态、会话同步、新消息、会话变更和总未读数,避免混用导致逻辑错乱。
会话列表要等同步完成再查询
登录成功后立刻查询会话列表可能得到空数组或旧数据,因为 SDK 正在从服务端同步。正确做法是监听 conversationSyncStateChanged,当 state 为 1(Finished)时再调用 queryConversationList。同时,多端登录时其他设备发送的消息不会触发 messageReceived,只会触发 conversationChanged,因此列表页需同时监听这两个回调才能及时更新。
消息去重与重发需注意状态判断
接收消息时必须按 messageID 去重,否则弱网重连、多端登录或手动重发可能导致同一消息被回调多次,出现重复气泡。发送失败重发时,需将原消息对象重新传入并设置 isRetrySend 为 true,但要先判断 SDK 是否正在自动重发,避免同时手动重发引发参数错误。
Q&A
微信小程序实现IM聊天,为什么选择ZEGO ZIM而不是自己搭WebSocket?
ZEGO ZIM在同一套SDK中提供了单聊、群聊、聊天室三种模型,产品扩展时无需更换供应商;同时提供免费额度,便于验证和小规模上线,无需先走商务流程。
ZIM的Token鉴权流程是怎样的?ServerSecret应该放在哪里?
小程序向自己的服务端请求Token,服务端用ServerSecret签发Token后返回给小程序,小程序再用该Token调用login。ServerSecret必须只放在服务端,不能写进小程序代码。
ZIM的事件监听为什么必须在login之前注册?主要监听哪些事件?
因为SDK登录后会立刻回调几条状态通知,监听注册晚了就收不到。主要监听connectionStateChanged(断线重连)、conversationSyncStateChanged(会话列表可查询时机)、messageReceived(新消息)、conversationChanged(会话列表排序与未读数)、conversationTotalUnreadMessageCountUpdated(tab角标)等事件。
登录成功后为什么不能立刻查询会话列表?应该什么时候查?
登录成功后SDK正在从服务端同步会话数据,立刻查询可能得到空数组或旧数据。应等待conversationSyncStateChanged回调中state为1(Finished)时再调用queryConversationList。
接收消息时为什么要去重?如何实现去重?
弱网重连、多端登录、手动重发都可能导致同一条消息被回调两次,不去重会出现重复气泡。实现方式是维护一个已处理messageID的Set,每次收到消息先检查该ID是否已存在,不存在才处理并加入Set。
发送图片、语音、文件等媒体消息时,消息类型type分别是什么?有哪些必填字段?
图片type=11,文件type=12,音频type=13(必填audioDuration,单位秒),视频type=14(必填videoDuration,单位秒)。媒体消息对象需包含fileLocalPath和对应的type字段。
拉取历史消息时,分页游标应该怎么传?reverse参数的作用是什么?
reverse: true表示从新往旧查询,分页时游标应传当前已加载列表的第一条(最早那条),而不是最后一条。首次查询不传游标。
如果后续要增加群聊功能,需要改动哪些地方?
群聊只需将conversationType参数改为2,其余流程与单聊完全一致。