微信Web版通信過程分析


=====================================

本文參考 掘微信Web版通信的全過程

代碼參考 Python網頁微信API    

作者根據以上代碼用.NET重構的版本 

=====================================

 

0.說明

前人已經做了大量工作,作者在此基礎上略加更新修改,適用於微信6.5.4。

1.微信服務器返回一個會話ID(uuid)

微信Web版本不使用用戶名和密碼登錄,而是采用掃描二維碼登錄,所以服務器需要首先分配一個唯一的會話ID,用來標識當前的一次登錄,通過請求地址:

https://login.weixin.qq.com/jslogin?appid=wx782c26e4c19acffb&fun=new&lang=zh_CN&_=1377482012272(其中1377482012272這個值是當前距離林威治標准時間的毫秒);

請求成功服務器會返回如下的字符串:

window.QRLogin.code = 200; window.QRLogin.uuid = "IZrc7nK6TQ=="

200表示正確返回,而這個IZrc7nK6TQ==字符串就是微信服務器返回給我們的ID(uuid)。

2.通過會話ID獲得二維碼

既然微信Web版本是通過二維碼進行登錄,如何獲得這個隨機的二維碼呢?答案就是通過上面的ID我們組合得到以下的URL地址:

https://login.weixin.qq.com/l/IZrc7nK6TQ==

不需做任何HTTP請求,直接將這個URL地址作為文本信息生成二維碼,此時需要用戶在微信的手機版本中掃描這個二維碼。

3.輪詢手機端是否已經掃描二維碼並確認在Web端登錄

當獲得二維碼之后,就需要用戶去手機端去掃描二維碼,並獲得用戶的授權,此時我們並不知道用戶何時完成這個操作,所以我們只有輪詢,而輪詢的地址就是:

https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?uuid=IZrc7nK6TQ==&tip=1&_=1377482045264

注意tip的值是變化的。首次設置tip=1。

如果服務器返回:window.code=201

則說明此時用戶在手機端已經完成掃描,但還沒有點擊確認,再次輪詢時設置tip=0

如果服務器返回:window.code=200

window.redirect_uri="https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=A5ncNUM2NJBYNOpJ49Jd38m2@qrticket_0&uuid=Ia7HTPkEdQ==&lang=zh_CN&scan=1485320697"

則說明此時用戶在手機端確認登錄,保存下window.redirect_uri=這個URL地址,供下一步驟中使用。

如果服務器返回:window.code=408

等待超時,再次輪詢時設置tip=1

4.訪問登錄地址,獲得uin、sid、pass_ticket、skey

通過訪問上一步驟中獲得的URL地址,可以獲取uin、sid、pass_ticket、skey,在后續的通信過程中都要使用到這幾個值。

5.初使化微信信息

前面的步驟算是完成了這個復雜的登錄過程,如果我們需要使用微信就需要獲得當前用戶的信息、好友列表等,還有一個關鍵的就是同步信息(后續與服務器輪詢中需要使用同步信息),通過URL進行HTTP POST:

https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=1486118990309&lang=en_US&pass_ticket=gzP3GEH0awvApwIttyTwxzAvA27%2BwVAp9tQ1osM%2FLL90XWWU5JeIdNLLVjN%2BJ9bq

POST的內容為以下的JSON信息:

{"BaseRequest":{"Uin":"2897899826","Sid":"5Lo1OrZQix+sduZT","Skey":"@crypt_dcaca546_c69b06b40828731a0acb3235758c0ea6","DeviceID":"e9803127325048260"}}

DeviceID是一個本地生成的隨機字符串(e+十六位的一串數字)。

服務器會返回一個很長的JSON串,這其中包括:用戶信息以及同步鍵值,SyncKey是用戶與服務器同步的鍵值,User就是當前登錄用戶自己的信息。

6.獲得所有的好友列表

在上一步驟中已經獲得了部分好友和公眾帳號,如果需要獲得完整的好友信息,就需要訪問以下的鏈接:

https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?pass_ticket=gzP3GEH0awvApwIttyTwxzAvA27%2BwVAp9tQ1osM%2FLL90XWWU5JeIdNLLVjN%2BJ9bq&skey=@crypt_dcaca546_c69b06b40828731a0acb3235758c0ea6&r=1486119544662

保持之前訪問的Cookies不被修改,在返回的JSON串中,MemberList中就包含了所有的好友信息。

7.保持與服務器的信息同步

與服務器保持同步需要在客戶端做輪詢,該輪詢的URL如下:

https://webpush.wx2.qq.com/cgi-bin/mmwebwx-bin/synccheck?sid=5Lo1OrZQix+sduZT&uin=2897899826&synckey=1_652651920%7C2_652651939%7C3_652651904%7C1000_0&r=1486119893602&skey=@crypt_dcaca546_c69b06b40828731a0acb3235758c0ea6&deviceid=e9803127325048260&_=1486119893618

其中的參數r和_都是time,sid,uin,skey,deviceid與上面步驟的值相對應,此處的synkey是第五步獲得的同步鍵值,但需要按一定的規則組合成以下的字符串:

1_652653204|2_652653674|3_652653544|1000_0

就是將鍵和值用_隔開,不同的鍵值對用|隔開,但記得|需要URL編碼成%7C,通過訪問上面的地址,會返回如下的字符串:

window.synccheck={retcode:”0”,selector:”2”}

如果retcode中的值不為0,則說明與服務器的通信有問題了。selector中的值表示客戶端需要作出的處理,當為2的時候表示有消息來了,就需要去訪問另一個接口獲得新的消息。

8.獲得別人發來的消息

當一個步驟中知道有新消息時,就需要去獲取消息內容,通過訪問以下的鏈接:

https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid=5Lo1OrZQix+sduZT&lang=zh_CN&skey=@crypt_dcaca546_c69b06b40828731a0acb3235758c0ea6&pass_ticket=gzP3GEH0awvApwIttyTwxzAvA27%2BwVAp9tQ1osM%2FLL90XWWU5JeIdNLLVjN%2BJ9bq

上面鏈接中的參數sid對應上面步驟中的值,r為時間,訪問鏈接需要使用POST方式,Body中包括JSON串,該JSON串格式如下:

{"BaseRequest" : {"DeviceID":"e9803127325048260","Sid":"5Lo1OrZQix+sduZT", "Skey":"@crypt_dcaca546_c69b06b40828731a0acb3235758c0ea6", "Uin":"2897899826"},"SyncKey" : {"Count":4,"List":[{"Key":1,"Val":652653204},{"Key":2,"Val":652653674},{"Key":3,"Val":652653544},{"Key":1000,"Val":0}]},"rr" :1486120093943}

請求成功之后服務器會返回一個JSON串,其中AddMsgList中是一個數組,包含了所有新消息。 

9.向用戶發送消息

用戶主動發送消息,通過以下的URL地址:
https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg?pass_ticket=gzP3GEH0awvApwIttyTwxzAvA27%2BwVAp9tQ1osM%2FLL90XWWU5JeIdNLLVjN%2BJ9bq
訪問該URL采用POST方式,在Body中的JSON串形如以下的格式:

{"Msg":{"Type":1,"Content":"hello world","FromUserName":"@fddaafca276a134rsdf234367fdfsdf6748a0843e6099de91","ToUserName":"@fdda235sfsabd67fas79f55c8a0843eas91","LocalID":"14851203867025441","ClientMsgId":"14851203867025441"},"BaseRequest":{"Uin":"2897899826","Sid":"5Lo1OrZQix+sduZT","Skey":"@crypt_dcaca546_c69b06b40828731a0acb3235758c0ea6","DeviceID":"e9803127325048260"}}

其中BaseRequest都是授權相關的值,與上面的步驟中的值對應,Msg是對消息的描述,包括了發送人與接收人,消息內容,消息的類型,ClientMsgId和LocalID由本地生成。rr可用當前的時間。 

在返回JSON結果中BaseResponse描述了發送情況,Ret為0表示發送成功。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM