最近在做个微信机器人,所以研究了网页版的微信协议及相关接口,在这里简单总结一下。
从表面上看,对于网页版微信我们的使用流程是这样的:
很简单,只有四步,但如果细化到内里细节的话,上面这简单四步的背后其实隐藏很多其他的逻辑。比如说网页微信是怎么知道手机已经扫码了?微信服务器是怎么确定用户此时的登录是有效的?网页微信又是怎么知道新消息过来的?关于这些,我们可以看看下面的流程图:
而在这个流程中,主要涉及以下几个接口:
UUID获取接口
登录二维码下载接口
二维码扫描状态查询接口
登录页面跳转接口(获取登录后的关键参数)
登录初始化接口(获取同步密钥SyncKey)
心跳检测接口(查询是否有新消息)
消息拉取接口
消息发送接口
UUID获取接口:
url:https://login.wx.qq.com/jslogin
method:GET
request parameter:
response:window.QRLogin.code = 200; window.QRLogin.uuid = "gdl0dOM6cg==“;
window.QRLogin.code为请求响应结果,200表示成功
window.QRLogin.uuid后面为 uuid,这里的 uuid 是 gdl0dOM6cg==
登录二维码下载接口:
二维码扫描状态查询接口:
url:https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login
method:GET
request parameter:
response:这里的返回值有四种可能
参数校验失败:window.code = 400;
未扫码未登录:window.code = 408;
已扫码未登录:window.code = 201;
已扫码已登录:window.code=200;window.redirect_uri="https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=AyTxRevj7IxauFXHBvH_BVIl@qrticket_0&uuid=IeqFbW6eJQ==&lang=zh_CN&scan=1523256945”;
登录页面跳转接口(获取登录后的关键参数):
url:https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage
method:GET
request parameter:
response:0OKxxxxxxxxx
xxx1
登录初始化接口(获取同步密钥SyncKey):
url:https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=129620808
method:POST
request parameter:JSON格式
{
BaseRequest: {
Uin: 登录关键参数wxuin,
Sid: 登录关键参数wxsid,
Skey: 登录关键参数skey,
DeviceID: 随机数
}
}
response:JSON格式,里面有个SyncKey字段,数据结构是一个List,List 里面的元素 e 是 key-value 的模式,后续心跳请求的时候通过 e1.key_e1.value | e2.key_e2.value 的格式拼装成 synckey
心跳检测接口(查询是否有新消息):
url:https://webpush.wx2.qq.com/cgi-bin/mmwebwx-bin/synccheck
method:GET
request parameter:
response:window.synccheck = { retcode: "0", selector: "0" }
retcode:0( 0 表示请求成功)
selector:
0: 无消息
2: 有新消息
消息拉取接口:
url:https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsync
method:POST
request parameter:有两部分,url拼接 和 POST 都要
URL 拼接:sid 和 skey
POST:
{
BaseRequest: { Uin: xxx, Sid: xxx, Skey: xxx, DeviceID: xxx },
SyncKey: xxx,
rr:
}
response:JSON格式。请求成功时有两个关键字段,SyncKey(新的同步密钥)和 AddMsgList(消息列表)
消息发送接口:
url:https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg
method:POST
request parameter:JSON格式{
BaseRequest: { Uin: xxx, Sid: xxx, Skey: xxx, DeviceID: xxx },
Msg: {
Type: 1 文字消息,
Content: 要发送的消息,
FromUserName: 自己的ID,
ToUserName: 好友的ID,
LocalID: 与clientMsgId相同,
ClientMsgId: 时间戳左移4位随后补上4位随机数
}
}
response:JSON格式
{ "BaseResponse": { "Ret": 0, "ErrMsg": "" }, ... }