微信網頁版協議分析和實現機器人
- 開啟首頁,分配一個隨機uuid,
- 根據該uuid獲取二維碼圖片。
- 微信客戶端掃描該圖片,在客戶端確認登入。
- 瀏覽器不停的呼叫一個介面,如果返回登入成功,則呼叫登入介面
- 此時可以獲取聯絡人列表,可以傳送訊息。然後不斷呼叫同步介面。
- 如果同步介面有返回,則可以獲取新訊息,然後繼續呼叫同步介面。
Java版實現原始碼:https://github.com/biezhi/wechat-robot
Python實現:https://github.com/Urinx/WeixinBot
C#實現:https://github.com/sherlockchou86/WeChat.NET
QT實現:https://github.com/xiangzhai/qwx
執行流程
+--------------+ +---------------+ +---------------+ | | | | | | | 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):
<error>
<ret>0</ret>
<message>OK</message>
<skey>xxx</skey>
<wxsid>xxx</wxsid>
<wxuin>xxx</wxuin>
<pass_ticket>xxx</pass_ticket>
<isgrayscale>1</isgrayscale>
</error>
在這一步獲取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