瞭解一波網頁端微信是如何登陸的

前言

工做之餘忽然對微信的網頁版的協議通訊感興趣能夠搞一波瞭解下。畢竟網頁版容易抓,靠一個瀏覽器的開發者工具的Network就開始抓包解析了。
這是我2019年03月寫的文檔。由於微信的協議可能隨時存在變更,如下內容能夠參考一波。本人爬蟲的方法很簡單,就是盡一切方法模仿被爬蟲者的行爲。
該文檔目前只寫到獲取最新消息。先記錄一波。有空更新javascript

項目地址: 楠尼瑪大帝 / wxWebR(Java版)

流程步驟

(這裏只說到成功登陸到微信並獲取最新消息,由於只是模仿到這裏,其餘的所有都已經清清楚楚只是看你調不調用而已了。該拿到的參數都有了)java

  1. 去獲取一個uuid,能夠根據這個uuid獲取一張二維碼登陸的圖片
  2. 微信客戶端掃描該二維碼,在客戶端確認登陸。
  3. 瀏覽器不停的調用一個接口,若是返回登陸成功,則調用登陸接口
  4. 循環遍歷一個檢查是否有新消息的接口。
  5. 若是新消息的接口返回有新消息的狀態碼去獲取消息接口。(完)

WebWechat API

(這裏也只說到成功登陸到微信並獲取最新消息。其餘能夠自行去抓包或者參考其餘文檔好比碼雲參考->python版(老版本)python

第一步獲取UUID(參考方法 getUUID)

API 獲取 UUID
url https://login.wx.qq.com/jslogin
method POST
data URL Encode(text/javascript)
params appid: 應用ID 參考:wx782c26e4c19acffb
redirect_uri 轉發地址 參考:https://wx.qq.com/cgi-bin/mmw...
fun: 應用類型 參考:new
lang: 語言 參考:zh_CN
_: 時間戳 參考:當前時間毫秒級13位數的時間戳

返回數據(String):git

window.QRLogin.code = 200; window.QRLogin.uuid = "xxx"
注:目前看來參數除了 _ 當前時間毫秒級13位數的時間戳 其餘都是固定的值。在微信給的js裏面 index_ad43596.js裏搜索API_jsLogin能夠獲得這些參數。並且大部分不理解參數均可以從這個js文件獲得答案。
輸入圖片說明

顯示二維碼就不浪費時間直接就是拿第一步拿到的uuid拼接就是二維碼地址:https://login.weixin.qq.com/q...{uuid}web

第二步等待掃碼登陸即微信確認登陸

API 獲取二維碼掃描登陸狀態
url https://login.wx.qq.com/cgi-b...
method GET(text/javascript)
params tip :這個東西根據瀏覽器走的話就是第一次爲1,後面都是爲0,網上說是掃碼狀態
loginicon 參考:true
uuid : 獲取到的uuid
_ : 當前時間毫秒級13位數的時間戳

返回數據(String):json

window.code=xxx;

xxx:
    【未掃碼的話】 -> window.code=408; 
    【手機掃碼可是未登陸】 -> window.code = 201; 
    【手機取消登陸】 -> window.code=400; 
    【手機受權登陸】 -> window.code=200;
當返回200時:
wechatLoginStatus:window.code=200; window.redirect_uri=
"https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=XXX&uuid=XXX&lang=XXX&scan=XXX"; 
當返回201時能夠獲取掃碼用戶頭像的base64數據哦(好像沒啥用)
注: 像這種成功的話獲得這種參數本身必定存起來,下一步確定要用即ticketlanguuidscan

第三步掃描成功去獲取你的登陸憑據

API 獲取登陸憑據
url https://wx2.qq.com/cgi-bin/mm...
method GET(text/plain;charset=utf-8)
params ticket : ticket
uuid : uuid
lang : lang
scan : scan
fun : 參考:new
version 參考:v2

返回數據(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>

核心數據點: skey, wxsid, wxuin, pass_ticket服務器

注: 切記,第三步會返回cookie,存下來,這裏這個接口會獲得cookie的。 cookie哪裏用到我會說明的。

第四步微信初始化

API 微信初始化
url https://wx2.qq.com/cgi-bin/mm...lang&pass_ticket=pass_ticket
method POST
data JSON(application/json; charset=UTF-8)
header Content-Type: application/json; charset=UTF-8
params {
     BaseRequest: {
         Uin: wxuin,
         Sid: wxsid,
         Skey: skey,
         DeviceID: xxx,
     }
}
注: r這個參數是經過js的一個 ~new Date 這是一個相似二進制反轉的一個,可自行百度或者打開控制檯輸出一下就知道了。

DeviceID這個參數是一個簡單js拼接出來的參數 "e"+(Math.random().toFixed(15)).substring(2, 17)

返回數據(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 後面的消息監聽用。cookie

第五步消息檢查是否有新消息(這裏要帶上cookie)

API synccheck
url https://webpush.wx2.qq.com/cg...skey&sid=wxsid&uin=wxuin&deviceid=xxx&synckey=Synckey&_=xxx
method POST
data JSON(text/javascript)
header ContentType: application/json; charset=UTF-8
params

返回數據(String):

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

retcode:
    0 正常
    1100 失敗/登出微信
    1101 在其餘地方登陸了微信
        1102 無憑據或者憑據已失效
selector:
    0 正常
    2 新的消息
    7 進入/離開聊天界面
注: deviceid 和上面的 DeviceID這個參數是同樣的:一個簡單js拼接出來的參數 "e"+(Math.random().toFixed(15)).substring(2, 17)
咱們叫他 時間戳取反
_是一個當前時間毫秒級13位數的時間戳

第六步獲取最新消息(要帶上Cookie)

API webwxsync
url https://wx2.qq.com/cgi-bin/mm...wxsid&skey=Skey
method POST
data JSON(text/plain)
header ContentType: application/json; charset=UTF-8
params {
     BaseRequest: { Uin: User下的Uin, Sid: wxsid, Skey: skey, DeviceID: DeviceID},
     SyncKey: syncKey,
     rr: 時間戳取反
}

返回數據(JSON):

{
    'BaseResponse': {'ErrMsg': '', 'Ret': 0},
    'SyncKey': {
        'Count': 不肯定個數,
        '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,
    ...
}
注 這一塊比較要特別注意,獲得消息後發現返回的信息也是有 SyncKey 這個要更新一波直接拿下來替換本身的舊的,否則第五步檢查消息是會出現問題就是刷的特別快,並且消息是不正確的。由於真正成功訪問的到是微信的請求不會當即返回,一個請求會跑的比較久至少幾十秒,由於防止瘋狂遍歷,不用擔憂由於一旦有數據返回微信服務器會馬上返回數據給你進入下一階段的循環。這一步也是比較坑的就是 SyncKey要記得更新就好了。還有一個很騷的點就是 _這個參數雖然是毫秒級的13位時間戳,可是在微信第一次獲取後他不會再去new了,就是一直+1+1;

致謝

本項目受到如下項目的啓發:

相關文章
相關標籤/搜索