簡述網頁版微信掃碼登陸的過程

個人小站html

網頁版微信掃碼登陸流程

1. 請求頁面

先打開https://wx.qq.com/顯示出頁面,這時候會加載一堆的html,js等資源。web

2. 獲取會話UUID

微信Web版本不使用用戶名和密碼登陸,而是採用掃描二維碼登陸,因此服務器須要首先分配一個惟一的會話ID,用來標識當前的一次登陸。json

使用get方法,經過請求地址:https://login.weixin.qq.com/j...數組

其中,時間戳這個值是當前距離林威治標準時間的毫秒。瀏覽器

get成功,則返回:window.QRLogin.code = 200; window.QRLogin.uuid = "AAAAAAAA"
其中的AAAAAAAA就是咱們須要的uuid服務器

web端微信登陸

3. 獲取登陸二維碼

訪問網址:https://login.weixin.qq.com/q...
這裏的XXXXXXX就是咱們剛纔獲取的uuid,這個網址直接顯示的就是二維碼,該二維碼是有有效期的,有效期時長由微信服務端決定。微信

4. 查詢是否掃描二維碼登陸

顯示了二維碼之後,用戶必須用手機微信掃描這個二維碼才能登陸。(微信爲啥要這麼設計?很奇怪的思惟。。。我用電腦不少狀況不就是由於手機沒在旁邊嗎。。。)app

使用get方法,查詢地址:https://login.weixin.qq.com/c...ide

這裏的AAAAAAAA是咱們剛纔獲取的uuid,時間戳同上。tip在第一次獲取時應爲1,其餘次時爲0.測試

若是服務器返回:

window.code=201,
window.userAvatar = base64:img/bbb

web端微信登陸

則說明此時用戶在手機端已經完成掃描,並在網頁端顯示掃描人的頭像。但尚未點擊登陸,繼續使用上面的地址查詢。

點擊登陸後,若是服務器返回:

window.code=200;
window.redirect_uri="https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=AZBAkjuOKc-2GAHcRBsKNuOt@qrticket_0&uuid=YbHBoVi8_w==&lang=zh_CN&scan=1504160545";

web端微信登陸

則說明此時用戶在手機端已經確認登陸,window.redirect_uri=後面的這個網址(暫稱爲BB)要記下來,接着要訪問這個地址。

若是服務器返回:window.code=408,則說明等待超時,繼續使用上面的地址查詢。

web端微信登陸

5. 訪問登陸地址BB,得到uin、sid、pass_ticket、skey

用get方法,訪問在上一步驟得到訪問地址BB,並在參數後面加上:&fun=new,會返回一個xml格式的文本,相似這樣:

<error>
    <ret>0</ret>
    <message></message>
    <skey>@crypt_d6549c5a_37242e82c0913b75e5d3ad5ef2c7bdba</skey>
    <wxsid>n/5yTn844+kHkU66</wxsid>
    <wxuin>2799942121</wxuin>
    <pass_ticket>JOkd35AoEoi8MVx34qKT6xJVeaS8tT7mo8BFdGlKRfDGRCWKkKLW9DsrA%2BEJ34WM</pass_ticket>
    <isgrayscale>1</isgrayscale>
    </error>

web端微信登陸

  • skey是獲取聯繫人信息的關鍵信息(好比獲取好友(包括訂閱的公衆號)頭像信息),標識當前人的身份。仍是檢查web端微信心跳的標識。發消息時也會使用。

  • pass_ticket是在受權成功後進行初始化和收發消息使用的。

  • wxsid在收發消息會子啊url後或請求體中使用。

  • wxuin在發消息時使用

web端微信登陸

把這裏的wxuin,wxsid,skey,pass_ticket都記下來,這是重要數據。

該結果中包含的信息就是用來在接下來的請求中校驗用戶用的。

到這裏已經代表當前用戶已經掃碼登陸成功了,並且能夠看到只是經過ticket方式確認web端登陸成功,而不通過用戶名密碼方式的登陸,其實我的感受就是移動端微信掃碼給web端發送了一個受權而已。

6. 微信初始化

這個是很重要的一步,我在這個步驟折騰了好久。。。

要使用POST方法,訪問地址:https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=-918790895&pass_ticket=JOkd35AoEoi8MVx34qKT6xJVeaS8tT7mo8BFdGlKRfDGRCWKkKLW9DsrA%252BEJ34WM

其中,時間戳不用解釋,pass_ticket是咱們在上面獲取的一長串字符。

POST的內容是個json串,{"BaseRequest":{"Uin":"XXXXXXXX","Sid":"XXXXXXXX","Skey":XXXXXXXXXXXXX","DeviceID":"e123456789012345"}}

uin、sid、skey分別對應上面步驟4獲取的字符串,DeviceID是e後面跟着一個15字節的隨機數。

web端微信登陸

程序裏面要注意使用UTF8編碼方式。
POST成功,則服務器返回一個很長的JSON串,格式是這樣:

{
    "BaseResponse":{
        "Ret":0,
        "ErrMsg":""
    },
    "Count":11,
    "ContactList":[
        {//公衆號或文件助手信息
            "Uin":0,
            "UserName":"filehelper",
            "NickName":"æ–‡ä»¶ä¼ è¾「助手",
            "HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=660589401&username=filehelper&skey=@crypt_d6549c5a_37242e82c0913b75e5d3ad5ef2c7bdba",
            "ContactFlag":1,
            "MemberCount":0,
            "MemberList":[],
            "RemarkName":"",
            "HideInputBarFlag":0,
            "Sex":0,
            "Signature":"",
            "VerifyFlag":0,
            "OwnerUin":0,
            "PYInitial":"WJCSZS",
            "PYQuanPin":"wenjianchuanshuzhushou",
            "RemarkPYInitial":"",
            "RemarkPYQuanPin":"",
            "StarFriend":0,
            "AppAccountFlag":0,
            "Statues":0,
            "AttrStatus":0,
            "Province":"",
            "City":"",
            "Alias":"",
            "SnsFlag":0,
            "UniFriend":0,
            "DisplayName":"",
            "ChatRoomId":0,
            "KeyWord":"fil",
            "EncryChatRoomId":"",
            "IsOwner":0
        },
        {
            "Uin":0,
            "UserName":"@@ed82e31e61783c765723eb8574831ae0be272bbb6b02f7280e442b0d274e8cb9",
            "NickName":"诗酒趁年华",
            "HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgetheadimg?seq=660624044&username=@@ed82e31e61783c765723eb8574831ae0be272bbb6b02f7280e442b0d274e8cb9&skey=@crypt_d6549c5a_37242e82c0913b75e5d3ad5ef2c7bdba",
            "ContactFlag":2051,
            "MemberCount":13,
            "MemberList":[//用戶信息
                {
                    "Uin":0,
                    "UserName":"@4dae6aa0756bd9899b68d0b2e60f109d",
                    "NickName":"",
                    "AttrStatus":0,
                    "PYInitial":"",
                    "PYQuanPin":"",
                    "RemarkPYInitial":"",
                    "RemarkPYQuanPin":"",
                    "MemberStatus":0,
                    "DisplayName":"",
                    "KeyWord":"cha"
                }
            ],
            "RemarkName":"",
            "HideInputBarFlag":0,
            "Sex":0,
            "Signature":"",
            "VerifyFlag":0,
            "OwnerUin":0,
            "PYInitial":"",
            "PYQuanPin":"",
            "RemarkPYInitial":"",
            "RemarkPYQuanPin":"",
            "StarFriend":0,
            "AppAccountFlag":0,
            "Statues":1,
            "AttrStatus":0,
            "Province":"",
            "City":"",
            "Alias":"",
            "SnsFlag":0,
            "UniFriend":0,
            "DisplayName":"",
            "ChatRoomId":0,
            "KeyWord":"",
            "EncryChatRoomId":"",
            "IsOwner":0
        }
    ],
    "SyncKey":{
        "Count":4,
        "List":[
            {
                "Key":1,
                "Val":660633313
            },
            {
                "Key":2,
                "Val":660633314
            },
            {
                "Key":3,
                "Val":660633176
            },
            {
                "Key":1000,
                "Val":1504141382
            }
        ]
    },
    "User":{//當前用戶信息
        "Uin":2799942121,
        "UserName":"@cee283ef70f5473680a467d23da14918888aa5771f1b08c7410b2ca3d685dd6a",
        "NickName":"followtry",
        "HeadImgUrl":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=842975299&username=@cee283ef70f5473680a467d23da14918888aa5771f1b08c7410b2ca3d685dd6a&skey=@crypt_d6549c5a_37242e82c0913b75e5d3ad5ef2c7bdba",
        "RemarkName":"",
        "PYInitial":"",
        "PYQuanPin":"",
        "RemarkPYInitial":"",
        "RemarkPYQuanPin":"",
        "HideInputBarFlag":0,
        "StarFriend":0,
        "Sex":1,
        "Signature":"",
        "AppAccountFlag":0,
        "VerifyFlag":0,
        "ContactFlag":0,
        "WebWxPluginSwitch":0,
        "HeadImgFlag":1,
        "SnsFlag":17
    },
    "ChatSet":"filehelper,weixin,@@ed82e31e61783c765723eb8574831ae0be272bbb6b02f7280e442b0d274e8cb9,",
    "SKey":"@crypt_d6549c5a_37242e82c0913b75e5d3ad5ef2c7bdba",//個人skey,也就是我的標識
    "ClientVersion":637865269,
    "SystemTime":1504157627,
    "GrayScale":1,
    "InviteStartCount":40,
    "MPSubscribeMsgCount":22,
    "MPSubscribeMsgList":[//訂閱信息列表
        {
            "UserName":"@d532ab26f3404fdc3a95bc7a7d3ae368",
            "MPArticleCount":4,//拉取四篇文章
            "MPArticleList":[//文章列表信息
                {
                    "Title":"Ubuntu Linux",
                    "Cover":"http://mmbiz.qpic.cn/mmbiz_jpg/W9DqKgFsc6icYW9UsESlGZ2r3SEOjIwqeToauxczCXYPLW63YtYmCcK2mxTaRjH7XibemZZOcVXknLFsPnhSLyeg/640?wxtype=jpeg&wxfrom=0",
                    "Url":"http://mp.weixin.qq.com/s?__biz=MjM5NjQ4MjYwMQ==&mid=2664609333&idx=1&sn=9eec4c182757edc5d2e98b2dfa5752b1&chksm=bdce8d738ab904653e64f18e23a8ffe8634fc1547edc05e2dad547de69894d5df572cc4f2b12&scene=0#rd"
                }
            ],
            "Time":1504153992,
            "NickName":"Linux中国"
        }
    ],
    "ClickReportInterval":600000
}

web端微信登陸

web端微信登陸

拿到該結果後,瀏覽器會渲染最近聯繫人,各個訂閱的公衆號的最近幾篇文章。

7. 獲取好友列表

使用POST方法,訪問:https://wx2.qq.com/cgi-bin/mm...

POST的內容爲空。成功則以JSON格式返回全部聯繫人的信息。格式相似:

{
    "BaseResponse": {
        "Ret": 0,
        "ErrMsg": ""
    },
    "MemberCount": 21,
    "MemberList": [
        {
            "Uin": 0,
            "UserName": xxx,
            "NickName": "Urinx",
            "HeadImgUrl": xxx,
            "ContactFlag": 3,
            "MemberCount": 0,
            "MemberList": [],
            "RemarkName": "",
            "HideInputBarFlag": 0,
            "Sex": 0,
            "Signature": "xxxx",
            "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
}
其中,MemberCount表示總共有多少聯繫人,裏面的內容都比較清晰。

8. 開啓微信狀態通知

用POST方法,訪問:https://wx.qq.com/cgi-bin/mmw...

POST的內容是JSON串,格式:

{

BaseRequest: { Uin: xxx, Sid: xxx, Skey: xxx, DeviceID: xxx }, 
 Code: 3, 
 FromUserName: 本身ID, 
 ToUserName: 本身ID, 
 ClientMsgId: 時間戳

}

web端微信登陸

9. 心跳包,與服務器同步並獲取狀態

以上步驟完成之後,就能夠進入收發微信的循環了,能夠用線程方式發送心跳包。

使用get方法,設置超時爲60秒,訪問:https://webpush.wx2.qq.com/cg...

其餘幾個參數不用解釋,這裏的synckey須要說一下,前面的步驟獲取的json串中有多個key信息,須要把這些信息拼起來,key_val,中間用|分割,相似這樣:

1_652651920|2_652651939|3_652651904|1000_0
服務器返回:window.synccheck={retcode:」0」,selector:」0」}

retcode爲0表示成功,selector爲2和6表示有新信息。4表示公衆號新信息。

web端微信登陸

10. 接收新信息

檢測到有新的消息之後,用POST方法,訪問:https://wx2.qq.com/cgi-bin/mm...

web端微信登陸

web端微信登陸

POST的內容:

{
   "BaseResponse":{
       "Ret":0,
       "ErrMsg":""
   },
   "AddMsgCount":0,
   "AddMsgList":[

   ],
   "ModContactCount":0,
   "ModContactList":[

   ],
   "DelContactCount":0,
   "DelContactList":[

   ],
   "ModChatRoomMemberCount":0,
   "ModChatRoomMemberList":[

   ],
   "Profile":{
       "BitFlag":0,
       "UserName":{
           "Buff":""
       },
       "NickName":{
           "Buff":""
       },
       "BindUin":0,
       "BindEmail":{
           "Buff":""
       },
       "BindMobile":{
           "Buff":""
       },
       "Status":0,
       "Sex":0,
       "PersonalCard":0,
       "Alias":"",
       "HeadImgUpdateFlag":0,
       "HeadImgUrl":"",
       "Signature":""
   },
   "ContinueFlag":0,
   "SyncKey":{
       "Count":7,
       "List":[
           {
               "Key":1,
               "Val":660633324
           }
       ]
   },
   "SKey":"",
   "SyncCheckKey":{
       "Count":7,
       "List":[
           {
               "Key":1,
               "Val":660633324
           }
       ]
   }
}

注意這裏的SyncKey格式,參考前面的說明。

請求成功以後服務器會返回一個JSON串,其中AddMsgCount表示有多少信息,AddMsgList中是一個數組,包含了全部新消息,裏面的MsgType表示信息類型,Content就是信息內容。
注意again,返回的信息中,會有新的synckey,要更新這個內容,下次獲取信息訪問要用這個新的key。

11. 發送信息

這個比較簡單,用POST方法,訪問:https://wx2.qq.com/cgi-bin/mm...

POST的仍是json格式,相似這樣:

{
   "Msg":{
       "Type":1,
       "Content":"測試信息",
       "FromUserName":"XXXXXX",
       "ToUserName":"XXXXXX",
       "LocalID":"時間戳",
       "ClientMsgId":"時間戳"
   },
   "BaseRequest":{
       "Uin":"XXXXXX",
       "Sid":"XXXXXX",
       "Skey":"XXXXXX",
       "DeviceID":"XXXXXX"
   }
}

這裏的Content是信息內容,LocalID和ClientMsgId都用當前時間戳。

web端微信登陸

以上就是基本的web端微信受權登陸以及收發消息的過程了,我的看法,有理解有誤差的地方還期待您的批評指正。

參考文章
微信網頁web版通訊協議分析 實現微信登陸發送接收消息

相關文章
相關標籤/搜索