web版微信协议分析

执行流程

web版微信协议分析_第1张图片

1.打开页面后,向服务器发送一个get请求,服务器会返回一个uuid

2.凭借这个uuid就可以获得用于登录的二维码

3.在获取到二维码和用户扫描二维码并确认登录之间,客户端会每隔一段时间向服务器发送一个get请求来查看这个二维码是否被扫描。如果二维码被扫描,返回window.code=201;,否则返回window.code=408;。如果这个二维码长时间没有被扫描,那么这个二维码就会失效。另外,如果二维码被扫描了,但是用户一直没有在手机上点确定登录,那么一段时间后,服务器也会返回window.code=408;。一旦用户点了确定登录,那么服务器就会返回window.code=200;

4.登录后,客户端会向服务器请求到cookiepass_ticket这类东西用来标识用户。

5.客户端就凭借着上面这些东西向服务器请求用户信息和联系人列表。

6.接着,客户端开启状态通知,每隔一段时间就向服务器发送请求,以此来确定客户端当前状态,比如是否有新的消息或者用户已经登出了微信。

具体分析

获得uuid

API 获取uuid
url =xxx”>https://login.wx.qq.com/jslogin?appid=wx782c26e4c19acffb&redirect_uri=https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage&fun=new&lang=zh_CN&=xxx
method get
说明 _:时间戳

响应:

window.QRLogin.code = 200; window.QRLogin.uuid = "xxx";

获得二维码

API 获得二维码
url https://login.weixin.qq.com/qrcode/uuid
method get
说明 uuid即为上面获得的uuid

检查二维码扫描状态

API 检查二维码扫描状态
url =xxx”>https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=xxx&tip=1&r=xxx&=xxx
method get
说明 _r好像都是时间戳,不过不发r好像也没关系

响应:

//二维码未被扫描或者二维码被扫描但用户长时间未点击确认登录时
window.code=408;

//二维码被扫描时
window.code=201;window.userAvatar = 'xxx';

//用户点击确认登录时
window.code=200;
window.redirect_uri="xxx";

登录获取cookie

API 登录获取cookie
url https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=xxx&uuid=xxx&lang=zh_CN&scan=xxx&fun=new&version=v2&lang=zh_CN
method get
说明 ticket scanwindow.redirect_uri="xxx";里面

响应:

<error>
    <ret>0ret>
    <message>OKmessage>
    <skey>xxxskey>
    <wxsid>xxxwxsid>
    <wxuin>xxxwxuin>
    <pass_ticket>xxxpass_ticket>
    <isgrayscale>1isgrayscale>
error>

初始化

API 初始化
url https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=xxx&pass_ticket=xxx
method post
params {"BaseRequest":{"Uin":"xxx","Sid":"xxx","Skey":"xxx","DeviceID":"xxx"}}
请求头 Content-Type application/json;charset=utf-8
说明 DeviceID是e后面跟着一个15字节的随机数,例:e159973572418266

响应:

{
    "BaseResponse": {
        "Ret": 0,
        "ErrMsg": ""
    },
    "Count": 11,
    "ContactList": [...],
    "SyncKey": {
        "Count": 4,
        "List": [
            {
                "Key": 1,
                "Val": 635705559
            },
            ...
        ]
    },
    "User": {
        "Uin": xxx,
        "UserName": xxx,
        "NickName": xxx,
        "HeadImgUrl": xxx,
        "RemarkName": "",
        "PYInitial": "",
        "PYQuanPin": "",
        "RemarkPYInitial": "",
        "RemarkPYQuanPin": "",
        "HideInputBarFlag": 0,
        "StarFriend": 0,
        "Sex": 1,
        "Signature": "Apt-get install B",
        "AppAccountFlag": 0,
        "VerifyFlag": 0,
        "ContactFlag": 0,
        "WebWxPluginSwitch": 0,
        "HeadImgFlag": 1,
        "SnsFlag": 17
    },
    "ChatSet": xxx,
    "SKey": xxx,
    "ClientVersion": 369297683,
    "SystemTime": 1453124908,
    "GrayScale": 1,
    "InviteStartCount": 40,
    "MPSubscribeMsgCount": 2,
    "MPSubscribeMsgList": [...],
    "ClickReportInterval": 600000
}

开启状态通知

API 开启状态通知
url https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxstatusnotify?pass_ticket=xxx
method post
请求头 Content-Type:application/json;charset=utf-8

params:

{
  "BaseRequest": 
  {
    "Uin": "xxx",
    "Sid": "xxx",
    "Skey": "xxx",
    "DeviceID": "xxx"
  },
  "ClientMsgId": "时间戳",
  "Code": 3,
  "FromUserName": "自己的ID",
  "ToUserName": "自己的ID"
}

响应:

{
    "BaseResponse": {
        "Ret": 0,
        "ErrMsg": ""
    },
    "MsgID":xxx
}

获取联系人信息

API 获取联系人信息
url https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?pass_ticket=xxx&r=xxx&seq=0&skey=xxx
method get

响应:

{
    "BaseResponse": {
        "Ret": 0,
        "ErrMsg": ""
    },
    "MemberCount": 334,
    "MemberList": [
        {
            "Uin": 0,
            "UserName": xxx,
            "NickName": "Urinx",
            "HeadImgUrl": xxx,
            "ContactFlag": 3,
            "MemberCount": 0,
            "MemberList": [],
            "RemarkName": "",
            "HideInputBarFlag": 0,
            "Sex": 0,
            "Signature": "xxx",
            "VerifyFlag": 8,
            "OwnerUin": 0,
            "PYInitial": "URINX",
            "PYQuanPin": "Urinx",
            "RemarkPYInitial": "",
            "RemarkPYQuanPin": "",
            "StarFriend": 0,
            "AppAccountFlag": 0,
            "Statues": 0,
            "AttrStatus": 0,
            "Province": "",
            "City": "",
            "Alias": "Urinxs",
            "SnsFlag": 0,
            "UniFriend": 0,
            "DisplayName": "",
            "ChatRoomId": 0,
            "KeyWord": "gh_",
            "EncryChatRoomId": ""
        },
        ...
    ],
    "Seq": 0
}
API 获取联系人信息
url https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxbatchgetcontact?type=ex&r=xxx0&pass_ticket=xxx
method post
请求头 Content-Type:application/json;charset=utf-8
说明 UserName是要查询具体信息的用户名,EncryChatRoomId是该用户所属的群用户名。

params:

  {
    "BaseRequest": {
    "Uin": "xxx",
    "Sid": "xxx",
    "Skey": "xxx",
    "DeviceID": "xxx"
    },
    "Count":xx,
    "List":{
      0:{
        "EncryChatRoomId":
        "UserName":"xxx"
      },
      ...
    }
  }

这两种方法的区别在于webwxbatchgetcontact返回的数据中会有群成员信息

心跳检查

API 心跳检查
url =xxx”>https://webpush.wx.qq.com/cgi-bin/mmwebwx-bin/synccheck?r=xxx&skey=xxx&sid=xxx&deviceid=xxx&synckey=xxx&=xxx
method get

要把初始化中得到的SyncKey整理成key_val|key_val这种格式,例如:1_694411380|2_694413141|3_694412799|1000_1526698782

响应(String):

window.synccheck={retcode:"xxx",selector:"xxx"}

retcode:
    0 正常
    1100 失败/登出微信
selector:
    0 正常
    2 新的消息
    7 进入/离开聊天界面

获取最新消息

API 获取最新消息
url https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid=xxx&skey=xxx&lang=zh_CN&pass_ticket=xxx
method post
请求头 Content-Type:application/json;charset=utf-8
说明 rr:时间戳取反。

params:

{
    "BaseRequest": {
    "Uin": "xxx",
    "Sid": "xxx",
    "Skey": "xxx",
    "DeviceID": "xxx"
    },
    "rr":xx,
    "SyncKey":{
      "Count":xx,
      "List":{
        0:{
          "Key":xx
          "Val":xx
        },
        ...
      }
    }
  }

响应:

BaseResponse
AddMsgCount:新增消息数
AddMsgList:新增消息列表
ModContactCount: 变更联系人数目
ModContactList: 变更联系人列表
SyncKey:新的synckey列表

当webwxsync发送完后会发送一个syncheck请求向服务器表示webwxsync响应已经收到了,这时syncheck用的synckey是发送webwxsync时收到的。若synccheck返回为window.synccheck={retcode:"0",selector:"0"},则继续发出相同请求。若返回不为以上返回值,继续POST请求webwxsync。

发送消息

API 发送消息
url https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg?lang=zh_CN&pass_ticket=xxx
method post
请求头 Content-Type:application/json;charset=utf-8

params:

{
  "BaseRequest": {
    "Uin": "xxx",
    "Sid": "xxx",
    "Skey": "xxx",
    "DeviceID": "xxx"
  },
  "Msg":{
    "Type": 1 文字消息, 
    "Content": 要发送的消息, 
    "FromUserName": 自己的ID, 
    "ToUserName": 好友的ID, 
    "LocalID": 与clientMsgId相同, 
    "ClientMsgId": 时间戳左移4位随后补上4位随机数 
  },
  "Scene": 0
}

响应:

{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
}
,
"MsgID": "xxx",
"LocalID": "xxx"
}

参考文章/项目

  • 微信web协议分析和实现微信机器人

  • Web 微信与基于Node的微信机器人实现

  • wechat-api

你可能感兴趣的:(微信,http)