本文干货充足篇幅较长,建议收藏后阅读避免迷路。文末可获取【自动聊天机器人源码和Demo】。

即时通讯IM概述

如果能开发一款即时聊天App,能和微信消息互通,并且只需少许代码量,应该是件非常兴奋的事情吧。首先,希望快速开发安全稳定的即时聊天App,最好借助(白嫖充足的免费额度)第三方提供的即时聊天SDK。其次,跟微信消息打通,只需借助本文提供的SDK。今天我们学习如何快速实现一款与微信消息互通的聊天App

最终效果如下(可在文末获取源码):

1-【自动聊天】

2-【聊天】

3-【自动回复】

1 技术实现原理

整个技术实现原理如下图所示

2 微信消息劫持

2.1 第三方已有的微信消息劫持工具

本文不会教你从零开发微信消息劫持,而是借助第三方已有的工具:pc-wechat-hook-http-api。相关文档在这里https://www.apifox.cn/apidoc/project-1222856/doc-1012539

需要注意的是,此工具基于3.6.0.18版本微信。下载此版本微信后直接覆盖安装,这样可以保留之前的微信聊天记录。

2.2 如何使用微信消息劫持工具?

首先前往官网下载好压缩包,如果不知道怎么官网怎么下载,可以直接拉到本文文末获取。

HPSocket4C.dll文件复制到微信目录下(例如E:\Tencent\WeChat\[3.6.0.18]

2.2.1 注入dll

点击Daen注入器.exe文件:

其中:

  1. 文件目录是指微信安装路径,参考上图。
  2. DLL路径指的是DaenWxHook.dll文件的完整路径。
  3. 进程参数直接使用默认即可。其中图中8089指本地用于接收微信实时消息的http server端口。8055指的是dll开启的http server端口,发送消息时只需往这个端口post数据即可。

点击注入并启动,登录微信即可。这里已完成微信消息的劫持,下一步我们尝试发送微信消息验证。

2.2.2 发送微信消息

发送消息方式为往指定端口post http请求即可,具体端口值为上面注入dll工具中指定的8055,如果用nodejs实现,post请求体如下所示:

function post(data, callback) {
var options = {
hostname: '127.0.0.1',
port: 8055,
path: '/DaenWxHook/client/',
method: 'POST',
headers: {
'User-Agent': 'apifox/1.0.0 (https://www.apifox.cn)',
'Content-Type': 'application/json'
}
};
var req = http.request(options, function (res) {
var body = "";
res.setEncoding('utf8');
res.on('data', function (chunk) {
body += chunk;
});
res.on('end', function () {
var json = JSON.parse(body);
callback(json);
});
});
req.on('error', function (e) {
console.log('problem with request: ' + e.message);
});
req.write(JSON.stringify(data));
req.end();
}

其中dataJSON类型,其数据结构具体形式可以参考官方文档或者直接看本文提供的代码。

2.2.3 接收微信消息

接收微信消息也非常方便,只需开启一个http server,并将端口与dll注入时一致,例如2.2.1中指定了8089nodejs示例代码如下:

app.post('/wechat/', function (req, res) {
var data = req.body;
var type = data['type'];
if (type == 'D0003') {
data = data['data']
var msg = data['msg']
var fromType = data['fromType'] // 1私聊, 2群聊, 3公众号
var from_wxid = data['fromWxid']
var isRcv = data['msgSource']==0 //0别人发,1自己发
if (fromType == 2) {
onRcvWXRoomMsg && onRcvWXRoomMsg(msg, from_wxid, isRcv)
} else if (fromType == 3) {
onGHZMsg && onGHZMsg(msg, from_wxid, isRcv);
} else if (fromType == 1) {
onRcvWXP2PMsg && onRcvWXP2PMsg(msg, from_wxid, isRcv);
}
}
res.send('');
});
app.listen(8089, function () {
console.log('正在监听微信消息');
});

3 第三方IM SDK接入

到此,我们实现了收发微信消息,接下来我们需要将这些消息实时转发到自己的app上。如果自己去从0开发一个即时通讯App系统工作量巨大。

我们依然可以借助第三方平台,网上第三方IM平台很多,大家可以随便选一个自己熟悉的平台。这里我选择我比较熟悉的即构IM平台

即构 IM SDK支持所有主流平台,包括flutter和uniapp两大跨平台框架,加速产品上线。在消息安全审核方面,他们采用主流第三方安全厂商的服务,需要的审核功能基本都能够支持。

不仅支持基础的单聊/群聊功能,还支持消息高并发量的房间聊天,官网数据显示:单房间人数支持到百万以上,适合对房间人数要求高的场景使用。另外还有很新颖的呼叫邀请功能,满足即时通讯的需求。

当然了,对于个人开发者而言,有充足的白嫖额度才是最重要的。一方面,即构IM提供的免费额度足够个人开发者用了。另一方面,未来如果有创业计划,快速接入即构IM上线产品也是非常方便

可以先从即构控制台注册添加应用, 获取AppId和ServerSecret, 如下所示。

更多关于即构即时通讯IM SDK的使用介绍文档,可以参考这里

3.1 中转微信收发消息

由于我们针对的是windows版的微信收发消息做劫持,因此必须在windows端也接入即构IM,通过即构IM将数据转发到App上。 而目前即构IMwindows上只有C++版本SDK,开发效率较低。为了更快速构建我们的服务,笔者将即构IMwebSDK做了Nodejs运行环境兼容,读者可以直接通过文末获取。

关于即构SDK的使用我这边不做过多介绍,读者只需关注一点:这是个第三方IM平台,我们利用它做微信消息中转,使得我们在开发App的时候可以实时获取微信消息。 这里贴一下关键代码:

function initZego(onError, onRcvMsg, clientUId = 'C123456', serverUId = 'S123456') {
___clientUID = clientUId;
var token = newToken(serverUId);
var startTimestamp = new Date().getTime();
function _onError(zim, err) {
onError(err);
}
function onRcvP2PMsg(zim, msgObj) {
var msgList = msgObj.messageList;
var fromConversationID = msgObj.fromConversationID;
msgList.forEach(function (msg) {
if (msg.timestamp - startTimestamp >= 0) { //过滤掉离线消息
console.log(msg)
onRcvMsg(msg, fromConversationID);
}
})
}
function onTokenWillExpire(zim, second) {
token = newToken(userId);
zim.renewToken(token);
}
var zim = createZIM(_onError, onRcvP2PMsg, onTokenWillExpire);
login(zim, serverUId, token, function (succ, data) {
if (succ) {
console.log("登录成功!")
} else {
console.log("登录失败!", data)
}
})
return zim;
}

需要注意的是,创建ZIM(即构IM)引擎时,需要提供AppId,必须去从即构控制台添加应用后自动获取。

4 APP开发

App主要包含3个模块:聊天、联系人、个人设置(包括聊天机器人、自动回复等内容)。App需要集成好即构IMSDK,这里不展开细聊,相信官网比我讲的更好。

4.1 聊天

聊天包括收发微信消息,但所有的消息都封装成即构IM的消息。我们对每个消息定义一个消息类型,用于识别。即构IM中接收到来自windows端发来的消息如下:

  private void onRcvMsg(ArrayList<ZIMMessage> messageList, String fromUserID) {
if (lsArr == null) return;
for (ZIMMessage zimMessage : messageList) {
if (zimMessage instanceof ZIMTextMessage) {
ZIMTextMessage zimTextMessage = (ZIMTextMessage) zimMessage;
if (zimMessage.getTimestamp() < this.startTime)
continue;
String uid = zimTextMessage.getSenderUserID();
if (!toUserId.equals(uid)) continue;
String json = zimTextMessage.message;
Msg msg = Msg.parseMsg(json);
for (MsgCenterListener l : lsArr) l.onRcvMsg(msg);
}
}
}

定义微信消息数据如下:

public class P2PMsg extends Msg {
@SerializedName("w")
public String wxid;
@SerializedName("tm")
public long time;
@SerializedName("m")
public String msg;
@SerializedName("r")
public boolean isRcv;
@Expose(serialize = false, deserialize = false)
public String remark;
public P2PMsg(String wxid, long time, String msg) {
this.type = Msg.TYPE_P2P_MSG;
this.wxid = wxid;
this.time = time;
this.msg = msg;
}
}

App端和windows端都使用P2PMsg定义的json格式数据,通过isRcv自动用于判断此消息是接收到的消息还是发送出去的消息。

对于windows端,收到了P2PMsg消息后,就根据里面指定的微信ID号做消息转发。对于App端,根据微信IDisRecv字段判断当前消息时跟谁聊以及是接收到的还是发送出去的。

4.2 联系人

联系人获取方式相对比较简单,在windows端获取到联系人列表后,直接发给App端。但是需要注意的是,由于联系人量级可能非常大,如果一次性传输可能因为消息体过大导致消息中转失败。因此我们分批发送联系人信息:

function sendFriendListZego(msg) {
var pno = msg.pno;
var psize = 10
var max_pno = Math.ceil(WXFriendsList.length * 1.0 / psize);
var friendsList = [];
var json = "";
if (pno < 0) {
json = {
t: TYPE_FRIEND_LIST,
fl: [],
tt: WXFriendsList.length,
p: pno
};
sendSettings();
} else {
if (pno < max_pno - 1)
friendsList = WXFriendsList.slice(pno * psize, (pno + 1) * psize);
else
friendsList = WXFriendsList.slice(pno * psize, WXFriendsList.length);
json = {
t: TYPE_FRIEND_LIST,
fl: friendsList,
tt: max_pno,
p: pno
};
}
sendZegoMsg(JSON.stringify(json))
}

4.3 聊天机器人与自动回复

聊天机器人

聊天机器人我们同样站在巨人肩膀上,使用青云客提供的api,实现自动对话。为了代码简洁性,我们用python示例,读者也可以翻到文末获取nodejs版本源码:

def talk_with_robot(msg, robot_name=None):
url = 'http://api.qingyunke.com/api.php?key=free&appid=0&msg={}'.format(urllib.parse.quote(msg))
html = requests.get(url)
rt = html.json()["content"]
rt = rt.replace("{br}","\n")
if robot_name is not None:
rt = rt.replace("菲菲", robot_name)
return rt

自动回复与定时发送

自动回复和定时发送属于规则性的定义了,只需将app端的配置发送给windows端,由windows端根据具体的配置执行相关操作。如自动回复,每次收到消息就回复固定内容。定时发送通过设置定时器执行发送任务。

5 源码及相关资源

  1. 【2209自动聊天机器人版微信安装包】关注公众号:ZEGO即构开发者社区,回复2209
  2. 【Daen注入器相关dll文件】 关注公众号:ZEGO即构开发者社区,回复:daen
  3. 【android客户端源码】 关注公众号:ZEGO即构开发者社区,回复:WXIM
  4. 【windows端消息中转源码】 关注公众号:ZEGO即构开发者社区,回复:WINZEGO

高仿微信|基于Windows微信实现一个IM即时通讯App的更多相关文章

  1. 高仿“点触验证码”做的一个静态Html例子

    先上源码: <html> <head> <title>TouClick - Designed By MrChu</title> <meta htt ...

  2. 高仿Readhub小程序 微信小程序项目【原】

    # News #### 项目介绍微信小程序项目涉及功能 https://gitee.com/richard1015/News https://github.com/richard1015/News 高 ...

  3. 黑科技!仅需 3 行代码,就能将 Gitter 集成到个人网站中,实现一个 IM 即时通讯聊天室功能?

    欢迎关注个人微信公众号: 小哈学Java, 文末分享阿里 P8 高级架构师吐血总结的 <Java 核心知识整理&面试.pdf>资源链接!! 个人网站: https://www.ex ...

  4. [iOS]从零开始开发一个即时通讯APP

    前言 这是我的毕业设计.刚开始确定这个课题的时候是因为以前有稍微研究过一些XMPP协议,在这个基础上做起来应该不难.然后开始选技术的时候还有半年,我想为什么不从更底层做起呢!那就不用XMPP,当时接触 ...

  5. 基于Facebook开源框架SocketRocket的即时通讯

    SocketRocket 介绍: SocketRock 是 Facebook 开源的框架,基于 WebSocket 客户端类库,适用于 iOS.Mac OS.tv OS.GitHub 传送门:http ...

  6. 基于环信SDK的IM即时通讯填坑之路(vue)

    公司最近使用第三方环信SDK的进行通信聊天,基本已完成.记录下填坑之路 1.可以通过以下方式引用 WebSDK 1.安装 npm install easemob-websdk --save 2. 先 ...

  7. 基于XMPP利用openfire简单的即时通讯

    功能的实现结果:能够使自己编写客户端与spark客户端信息通讯,将接受到的信息更新到textview上. 1.下载openfire并安装.设置域名,添加用户 2.下载安装spark客户端 3.jar包 ...

  8. 高仿腾讯QQ即时通讯IM项目

    前言:其实这个项目早就开发完成了,在本人的github上,本来没打算写成博客的形式,因为一个项目要写出来要花很久,但是最近看到很多 人在我的github上download后随意发布到网上,本来上传到g ...

  9. 微信小程序使用GoEasy实现websocket实时通讯

    不需要下载安装,便可以在微信好友.微信群之间快速的转发,用户只需要扫码或者在微信里点击,就可以立即运行,有着近似APP的用户体验,使得微信小程序成为全民热爱的好东西~ 同时因为微信小程序使用的是Jav ...

  10. 基于vuecli3构建一个快速开发h5 APP的模板

    基于vuecli3构建的一个快速开发h5 APP的模板,集成了高德地图.mint-ui,以及antv-f2可视化框架 vue-cli3安装 查看vue cli版本 vue --version 要求no ...

随机推荐

  1. node学习01

    1.前言 Node.js 是一个开源和跨平台的 JavaScript 运行时环境 Node.js 在浏览器之外运行 V8 JavaScript 引擎(Google Chrome 的内核). 这使得 N ...

  2. 9V,12V输入充3.7V单节锂电池电路和芯片

    锂电池充电管理电路中,普遍常用使用最多的的如PW4054这种的线性降压充电管理芯片,特点就是外围极简洁,但是只能支持USB口的输入5V了.当然也有稍微高点的PW4065,输入电压范围是4.7V-8V的 ...

  3. 关于如何在C#中调用C++的DLL,以及如何在C++中调用C#的DLL

    一.关于如何在C#中调用C++的DLL,以及如何在C++中调用C#的DLL 注:clr指公共语言运行库 CLR是一门非常恶搞的语言,就好像是在C++里面写C#的文件一样,也就是一种所谓的"托 ...

  4. mysql数据库(字段约束条件)

    什么是字段约束 字段约束就是将字段的内容定一个规则,我们要按照规则办事 约束 描述 关键字 非空约束 限制该字段的数据不能为null not null 唯一约束 保证该字段的所有数据都是唯一.不重复的 ...

  5. Mattermost 笔记

    目录 部署 配置 客户端 桌面程序 Android 使用 扩展 Jenkins Hubot 机器人 Jira GitHub Mattermost 是一个开源.可私有化部署的在线通讯平台,可以和Gith ...

  6. cs231n__3. LostFunction

    CS231n 3.1 Lost Function 我们上次提到,要如何选择最优的W呢? 这就是要选择几种损失函数了. 我们要找到一种可行的方法来选择最优的W 先看简单的3个样本的例子 正式定义损失函数 ...

  7. 前端程序员学python(爬虫向)(一文修到筑基期) (本文不含知识诅咒)

    我踏马来辣 还有一件事: 本教程配合c语言中文网 python爬虫 教程 食用 本教程不适用于未成年人 一定要刷牙 本教程不存在知识诅咒 学完本教程即可进入筑基期 js 基础和本教程学习效率成正比 不 ...

  8. 可视化—AntV G6 高亮相邻节点的两种方式

    目录 内置的高亮节点 自定义高亮 自定义高亮时保持原始颜色 总结 案例完整代码 通过官方文档,可知高亮相邻节点分为两种方法,文档描述并不是很清楚,对刚接触这个库的小白并不是很友好,慢慢总结慢慢来吧 内 ...

  9. Spark详解(06) - SparkSQL

    Spark详解(06) - SparkSQL Spark SQL概述 什么是Spark SQL Spark SQL是Spark用于结构化数据(Structured Data)处理的Spark模块. ( ...

  10. 01-Tcl基本知识

    1 Tcl基本知识 1.1 Tcl是什么? Tcl全称是Tool Command Language,是一种基于字符串的命令语言. Tcl是一种解释性语言,类似于其他脚本语言一样,直接对每条语句顺次解释 ...