微信web协议分析(微信网页版 wx2.qq.com)

1.打开首页,分配一个随机uuid, 2.根据该uuid获取二维码图片。 3.微信客户端扫描该图片,在客户端确认登录。 4.浏览器不停的调用一个接口,如果返回登录成功,则调用登录接口 5.此时可以获取联系人列表,可以发送消息。然后不断调用同步接口。 6.如果同步接口有返回,则可以获取新消息,然后继续调用同步接口。

源码地址:https://github.com/biezhi/wechat-robot

执行流程

WebWechat API

1. 获取UUID(参考方法 getUUID)

API 获取 UUID
url https://login.weixin.qq.com/jslogin
method GET
data URL Encode
params appid : wx782c26e4c19acffb fun : new lang: zhCN **** : 时间戳

返回数据(String):

2. 显示二维码(参考方法 showQrCode)

API 显示二维码
url https://login.weixin.qq.com/qrcode/{uuid}
method POST
params t : webwx
_ : 时间戳

3. 等待登录(参考方法 waitForLogin)这里是微信确认登录

API 二维码扫描登录
url https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login
method GET
params tip : 1:未扫描 0:已扫描 uuid : 获取到的uuid _ : 时间戳

返回数据(String):

4. 登录获取Cookie(参考方法 login)

API webwxnewloginpage
url https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage
method GET
params ticket : xxx uuid : xxx lang : zh_CN scan : xxx fun : new

返回数据(XML):

在这一步获取xml中的 skey, wxsid, wxuin, pass_ticket

5. 微信初始化(参考方法 wxInit)

API webwxinit
url https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxinit
method POST
data JSON
header Content-Type: application/json; charset=UTF-8
params { BaseRequest: { Uin: xxx, Sid: xxx, Skey: xxx, DeviceID: xxx, } }

返回数据(JSON):

这一步中获取 SyncKey, User 后面的消息监听用。

6. 开启微信状态通知(参考方法 wxStatusNotify)

API webwxstatusnotify
url https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxstatusnotify
method POST
data JSON
header Content-Type: application/json; charset=UTF-8
params { BaseRequest: { Uin: xxx, Sid: xxx, Skey: xxx, DeviceID: xxx }, Code: 3, FromUserName: 自己的ID, ToUserName: 自己的ID, ClientMsgId: 时间戳 }

返回数据(JSON):

7. 获取联系人列表(参考方法 getContact)

API webwxgetcontact
url https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact
method POST
data JSON
header ContentType: application/json; charset=UTF-8
params { BaseRequest: { Uin: xxx, Sid: xxx, Skey: xxx, DeviceID: xxx, } }

返回数据(JSON):

8.消息检查(参考方法 syncCheck)

API synccheck
url https://webpush2.weixin.qq.com/cgi-bin/mmwebwx-bin/synccheck
method GET
data JSON
header ContentType: application/json; charset=UTF-8
params { BaseRequest: { Uin: xxx, Sid: xxx, Skey: xxx, DeviceID: xxx, } }

返回数据(String):

9. 获取最新消息(参考方法 webwxsync)

API webwxsync
url https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid=xxx&skey=xxx&pass_ticket=xxx
method POST
data JSON
header ContentType: application/json; charset=UTF-8
params { BaseRequest: { Uin: xxx, Sid: xxx, Skey: xxx, DeviceID: xxx }, SyncKey: xxx, rr: 时间戳取反 }

返回数据(JSON):

10. 发送消息(参考方法 webwxsendmsg)

API webwxsendmsg
url https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg?pass_ticket=xxx
method POST
data JSON
header ContentType: 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位随机数 } }

返回数据(JSON):

更多资料: https://github.com/xiangzhai/qwx https://github.com/Urinx/WeixinBot http://www.07net01.com/2016/01/1201188.html http://www.cnblogs.com/xiaozhi_5638/p/4923811.html

       +--------------+     +---------------+   +---------------+
       |              |     |               |   |               |
       |   Get UUID   |     |  Get Contact  |   | Status Notify |
       |              |     |               |   |               |
       +-------+------+     +-------^-------+   +-------^-------+
               |                    |                   |
               |                    +-------+  +--------+
               |                            |  |
       +-------v------+               +-----+--+------+      +--------------+
       |              |               |               |      |              |
       |  Get QRCode  |               |  Weixin Init  +------>  Sync Check  <----+
       |              |               |               |      |              |    |
       +-------+------+               +-------^-------+      +-------+------+    |
               |                              |                      |           |
               |                              |                      +-----------+
               |                              |                      |
       +-------v------+               +-------+--------+     +-------v-------+
       |              | Confirm Login |                |     |               |
+------>    Login     +---------------> New Login Page |     |  Weixin Sync  |
|      |              |               |                |     |               |
|      +------+-------+               +----------------+     +---------------+
|             |
|QRCode Scaned|
+-------------+
window.QRLogin.code = 200; window.QRLogin.uuid = "xxx"
window.code=xxx;

xxx:
    408 登陆超时
    201 扫描成功
    200 确认登录

当返回200时,还会有
window.redirect_uri="https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=xxx&uuid=xxx&lang=xxx&scan=xxx";

    0
    OK
    xxx
    xxx
    xxx
    xxx
    1
{
    "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
}
{
    "BaseResponse": {
        "Ret": 0,
        "ErrMsg": ""
    },
    ...
}
{
    "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": "我是二蛋",
            "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
}
window.synccheck={retcode:"xxx",selector:"xxx"}

retcode:
    0 正常
    1100 失败/登出微信
selector:
    0 正常
    2 新的消息
    7 进入/离开聊天界面
{
    'BaseResponse': {'ErrMsg': '', 'Ret': 0},
    'SyncKey': {
        'Count': 7,
        'List': [
            {'Val': 636214192, 'Key': 1},
            ...
        ]
    },
    'ContinueFlag': 0,
    'AddMsgCount': 1,
    'AddMsgList': [
        {
            'FromUserName': '',
            'PlayLength': 0,
            'RecommendInfo': {...},
            'Content': "",
            'StatusNotifyUserName': '',
            'StatusNotifyCode': 5,
            'Status': 3,
            'VoiceLength': 0,
            'ToUserName': '',
            'ForwardFlag': 0,
            'AppMsgType': 0,
            'AppInfo': {'Type': 0, 'AppID': ''},
            'Url': '',
            'ImgStatus': 1,
            'MsgType': 51,
            'ImgHeight': 0,
            'MediaId': '',
            'FileName': '',
            'FileSize': '',
            ...
        },
        ...
    ],
    'ModChatRoomMemberCount': 0,
    'ModContactList': [],
    'DelContactList': [],
    'ModChatRoomMemberList': [],
    'DelContactCount': 0,
    ...
}
{
    "BaseResponse": {
        "Ret": 0,
        "ErrMsg": ""
    },
    ...
}