微信網(wǎng)頁版登陸原理
-
請求微信服務(wù)器返回一個會話ID
微信Web版本不使用用戶名和密碼登錄,而是采用二維碼登錄,所以服務(wù)器需要首先分配一個唯一的會話ID瓣履,用來標識當前的一次登錄剃斧,通過請求地址:
服務(wù)器會返回如下的字符串:
window.QRLogin.code = 200; window.QRLogin.uuid = "AdrEiQJo7Q==";
而這個AdrEiQJo7Q==字符串就是微信服務(wù)器返回給我們的ID。
-
通過會話ID獲得二維碼
利用剛才獲得的ID去請求服務(wù)器生成的二維碼,通過上面的ID我們組合得到以下的URL地址:
https://login.weixin.qq.com/qrcode/AdrEiQJo7Q==
該請求返回的便是我們需要的二維碼,此時需要用戶在微信的手機版本中掃描這個二維碼即可登陸(長按識別二維碼都不行神僵,必須是掃描) 輪詢手機端是否已經(jīng)掃描二維碼并確認在Web端登錄
當獲得二維碼之后腿宰,就需要用戶去手機端去掃描二維碼呕诉,并獲得用戶的授權(quán),此時我們并不知道用戶何時完成這個操作吃度,所以我們只有輪詢甩挫,而輪詢的地址就是:
https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?uuid=DeA6idundY9VKn&tip=1&_=1377482045264(注意UUID和最后時間這兩個參數(shù))
- 如果服務(wù)器返回:
window.code=201; window.userAvatar = ''
則說明此時用戶在手機端已經(jīng)完成掃描,但還沒有點擊確認椿每; - 如果服務(wù)器返回:
window.code=408;
則說明此時用戶在手機端?還未掃描伊者; - 如果服務(wù)器返回:
window.code=201;window.redirect_uri=一個URL地址
則說明此時用戶已經(jīng)在手機端完成了授權(quán)過程,保存下這個URL地址下一步 驟中使用.
- 訪問登錄地址间护,獲得uin和sid
通過訪問上一步驟中獲得的URL地址亦渗,
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=AVGnnO4cQDp0D-oRRdFpPdKk@qrticket_0&uuid=Qa5hIYJlPg==&lang=zh_CN&scan=1487128220
可以在服務(wù)器返回的Cookies中獲得到wxuin和wxsid這兩個值,
<?xml version="1.0" encoding="utf-8"?>
<error>
<ret>0</ret>
<message/>
<skey>@crypt_6c791e4d_d2cc04dcc3df812824b41abd98616a44</skey>
<wxsid>BqaMHRqFxeQvdOWD</wxsid>
<wxuin>31213e21</wxuin>
<pass_ticket>fVJ6%2FwoyREZ%2BDIeadCjR%2Fz%2BvAh4keU3A3AvI29NzSaXOdBcxxekwJ51O9S05Q6MG</pass_ticket>
<isgrayscale>1</isgrayscale>
</error>
這兩值在后續(xù)的通信過程中都要使用到這兩個值汁尺,并且Cookies中也需要包括這兩項法精。
- 初使化微信信息
前面的步驟算是完成了這個復(fù)雜的登錄過程,如果我們需要使用微信就需要獲得當前用戶的信息痴突、好友列表等亿虽,還有一個關(guān)鍵的就是同步信息(后續(xù)與服務(wù)器輪詢中需要使用同步信息),通過訪問以下的鏈接:
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=1377482058764(r依然是時間)
訪問該鏈接需要使用POST苞也,并且在Body中帶上以下的JSON信息:
{"BaseRequest":
{"Uin":"2545437902","Sid":"QfLp+Z+FePzvOFoG","Skey":"","DeviceID":"e1615250492"}}
這個JSON串中Uin和Sid分別是上面步驟中獲得的那兩個Cookie值,DeviceID是一個本地生成的隨機字符串(分析了官方的總是e+一串數(shù)字粘秆,所以我們也保持這樣的格式)如迟。
服務(wù)器就會返回一個很長的JSON串,這其中包括:BaseResponse中的值用來表示請求狀態(tài)碼攻走,ContactList主要用來表示聯(lián)系人(此列表不全殷勘,只包括了類似通訊錄助手、文件助手昔搂、微信團隊和一些公眾帳號等玲销,后面會通過另一接口去獲得更全面的信息),SyncKey是用戶與服務(wù)器同步的信息摘符,User就是當前登錄用戶自己的信息贤斜。
6.獲得所有的好友列表
在上一步驟中已經(jīng)獲得了部分好友和公眾帳號,如果需要獲得完整的好友信息逛裤,就需要訪問以下的鏈接:
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?r=1377482079876(r依然是時間)
訪問該鏈接同樣需要POST方式瘩绒,但Body為空JSON:{},服務(wù)器對身份的判定是通過Cookies带族,所以需要保持之前訪問的Cookies不被修改(在Objective-C中會自動保存相關(guān)的Cookies锁荔,無需程序特殊處理),在返回的JSON串中蝙砌,MemberList中就包含了所有的好友信息阳堕。
7.保持與服務(wù)器的信息同步
與服務(wù)器保持同步需要在客戶端做輪詢跋理,該輪詢的URL如下:
https://webpush.weixin.qq.com/cgi-bin/mmwebwx-bin/synccheck?callback=jQuery18309326978388708085_1377482079946&r=1377482079876& sid=QfLp+Z+FePzvOFoG&uin=2545437902&deviceid=e1615250492&synckey=(見以下說明)&_=1377482079876
其中的參數(shù)r和_都是time,sid恬总,uin前普,deviceid與上面步驟的值相對應(yīng),此處的synkey是上步步驟獲得的同步鍵值越驻,但需要按一定的規(guī)則組合成以下的字符串:
1_124125|2_452346345|3_65476547|1000_5643635
就是將鍵和值用_隔開汁政,不同的鍵值對用|隔開,但記得|需要URL編碼成%7C缀旁,通過訪問上面的地址记劈,會返回如下的字符串:
window.synccheck={retcode:”0”,selector:”0”}
如果retcode中的值不為0,則說明與服務(wù)器的通信有問題了并巍,但具體問題我就無法預(yù)測了目木,selector中的值表示客戶端需要作出的處理,目前已經(jīng)知道當為6的時候表示有消息來了懊渡,就需要去訪問另一個接口獲得新的消息刽射。
8.獲得別人發(fā)來的消息
當一個步驟中知道有新消息時,就需要去獲取消息內(nèi)容剃执,通過訪問以下的鏈接:
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid=QfLp+Z+FePzvOFoG&r=1377482079876
上面鏈接中的參數(shù)sid對應(yīng)上面步驟中的值誓禁,r為時間,訪問鏈接需要使用POST方式肾档,Body中包括JSON串摹恰,該JSON串格式如下:
{"BaseRequest" : {"Uin":2545437902,"Sid":"QfLp+Z+FePzvOFoG"},
"SyncKey" : {"Count":4,"List":[{"Key":1,"Val":620310295},{"Key":2,"Val":620310303},{"Key":3,"Val":620310285},{"Key":1000,"Val":1377479086}]},
"rr" :1377482079876};
以下的信息中BaseRequest中包括的Uin與Sid與上面步驟中的值對應(yīng),SyncKey也是上面步驟中獲得的同步鍵值對怒见,rr為時間俗慈,訪問成功之后服務(wù)器會返回一個JSON串,其中AddMsgList中是一個數(shù)組遣耍,包含了所有新消息闺阱。
9.向用戶發(fā)送消息
用戶主動發(fā)送消息,通過以下的URL地址:
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg?sid=QfLp+Z+FePzvOFoG&r=1377482079876
上面的sid和r參數(shù)不再解釋了舵变,訪問該URL采用POST方式酣溃,在Body中的JSON串形如以下的格式:
{
"BaseRequest":{
"DeviceID" : "e441551176",
"Sid" : "S8wNi91Zry3024eg",
"Skey" : "F820928BBA5D8ECA23448F076D2E8A915E1349E9FB4F4332",
"Uin" : "2545437902"
},
"Msg" : {
"ClientMsgId" : 1377504862158,
"Content" : "hello",
"FromUserName" : "wxid_2rrz8g8ezuox22",
"LocalID" : 1377504862158,
"ToUserName" : "wxid_j4nu420ojhsr21",
"Type" : 1
},
"rr" = 1377504864463
}
其中BaseRequest都是授權(quán)相關(guān)的值,與上面的步驟中的值對應(yīng)纪隙,Msg是對消息的描述救拉,包括了發(fā)送人與接收人,消息內(nèi)容瘫拣,消息的類型(1為文本)亿絮,ClientMsgId和LocalID由本地生成。rr可用當前的時間。
在返回JSON結(jié)果中BaseResponse描述了發(fā)送情況派昧,Ret為0表示發(fā)送成功黔姜。