微信web协议分析和实现微信机器人(微信网页版 wx2.qq.com)

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

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

执行流程

       +--------------+     +---------------+   +---------------+
       |              |     |               |   |               |
       |   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|
+-------------+

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: zh_CN
_ : 时间戳

返回数据(String):

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

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):

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\";

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):


    0
    OK
    xxx
    xxx
    xxx
    xxx
    1

在这一步获取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):

{
    \"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
}

这一步中获取 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):

{
    \"BaseResponse\": {
        \"Ret\": 0,
        \"ErrMsg\": \"\"
    },
    ...
}

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):

{
    \"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
}

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):

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

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

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):

{
    \'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,
    ...
}

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):

{
    \"BaseResponse\": {
        \"Ret\": 0,
        \"ErrMsg\": \"\"
    },
    ...
}

更多资料:
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