昨天是周末,在家閑得無(wú)聊,于是去weiphone.com逛了一圈,偶然發(fā)現(xiàn)有人發(fā)了一帖叫《微信 for Mac》, 這勾起了我的好奇心,國(guó)內(nèi)做Mac開(kāi)發(fā)的人確實(shí)很少,對(duì)于那些能夠獨(dú)自開(kāi)發(fā)一些Mac第三方工具的開(kāi)發(fā)者我都表示很敬畏,于是點(diǎn)進(jìn)去看了一個(gè)究竟,如果你 們好奇也可以點(diǎn)進(jìn)去看個(gè)明白,我最終得出的結(jié)論就是:坑爹呢這是!直接用一個(gè)WebView去加載了wx.qq.com這個(gè)網(wǎng)頁(yè)也敢自稱是微信For Mac?對(duì)于這種欺騙用戶的行為我十分不屑,同時(shí)也讓我在思考在微信不提供API的環(huán)境下開(kāi)發(fā)一款原生的微信Mac版本是否可行,最有可能的就是去分析微 信Web版本的通信過(guò)程,然后在程序中模擬這個(gè)流程,在我苦苦研究了一個(gè)下午之后,終于摸透了這個(gè)過(guò)程,并用程序?qū)崿F(xiàn)了大部分功能,下面就詳細(xì)解說(shuō)一下微 信Web版的流程:
1.微信服務(wù)器返回一個(gè)會(huì)話ID
微信Web版本不使用用戶名和密碼登錄,而是采用二維碼登錄,所以服務(wù)器需要首先分配一個(gè)唯一的會(huì)話ID,用來(lái)標(biāo)識(shí)當(dāng)前的一次登錄,通過(guò)請(qǐng)求地址:
https://login.weixin.qq.com /jslogin?appid=wx782c26e4c19acffb&redirect_uri=https%3A%2F %2Fwx.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage&fun=new& amp;lang=zh_CN&_=1377482012272(其中1377482012272這個(gè)值是當(dāng)前距離林威治標(biāo)準(zhǔn)時(shí)間的毫秒)
服務(wù)器會(huì)返回如下的字符串:
window.QRLogin.code = 200; window.QRLogin.uuid = “DeA6idundY9VKn”;
而這個(gè)DeA6idundY9VKn字符串就是微信服務(wù)器返回給我們的ID。
2.通過(guò)會(huì)話ID獲得二維碼
既然微信Web版本是通過(guò)二維碼進(jìn)行登錄,如何獲得這個(gè)隨機(jī)的二維碼呢?答案就是利用剛才獲得的ID去請(qǐng)求服務(wù)器生成的二維碼,通過(guò)上面的ID我們組合得到以下的URL地址:
https://login.weixin.qq.com/qrcode/DeA6idundY9VKn?t=webwx
該請(qǐng)求返回的便是我們需要的二維碼,此時(shí)需要用戶在微信的手機(jī)版本中掃描這個(gè)二維碼(我就搞不明白微信官方是如何想的,登錄Web版本竟然還需要手機(jī)微信去配合登錄,難道沒(méi)有考慮我被迫選擇Web微信就是因?yàn)槭謾C(jī)不在身邊這樣的情形么?)
3.輪詢手機(jī)端是否已經(jīng)掃描二維碼并確認(rèn)在Web端登錄
當(dāng)獲得二維碼之后,就需要用戶去手機(jī)端去掃描二維碼,并獲得用戶的授權(quán),此時(shí)我們并不知道用戶何時(shí)完成這個(gè)操作,所以我們只有輪詢,而輪詢的地址就是:
https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?uuid=DeA6idundY9VKn&tip=1&_=1377482045264(注意UUID和最后時(shí)間這兩個(gè)參數(shù))
如果服務(wù)器返回:
window.code=201;
則說(shuō)明此時(shí)用戶在手機(jī)端已經(jīng)完成掃描,但還沒(méi)有點(diǎn)擊確認(rèn);
如果服務(wù)器返回:
window.redirect_uri=一個(gè)URL地址
則說(shuō)明此時(shí)用戶已經(jīng)在手機(jī)端完成了授權(quán)過(guò)程,保存下這個(gè)URL地址下一步驟中使用。
4.訪問(wèn)登錄地址,獲得uin和sid
通過(guò)訪問(wèn)上一步驟中獲得的URL地址,可以在服務(wù)器返回的Cookies中獲得到wxuin和wxsid這兩個(gè)值,這兩值在后續(xù)的通信過(guò)程中都要使用到這兩個(gè)值,并且Cookies中也需要包括這兩項(xiàng)。
5.初使化微信信息
前面的步驟算是完成了這個(gè)復(fù)雜的登錄過(guò)程,如果我們需要使用微信就需要獲得當(dāng)前用戶的信息、好友列表等,還有一個(gè)關(guān)鍵的就是同步信息(后續(xù)與服務(wù)器輪詢中需要使用同步信息),通過(guò)訪問(wèn)以下的鏈接:
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=1377482058764(r依然是時(shí)間)
訪問(wèn)該鏈接需要使用POST,并且在Body中帶上以下的JSON信息:
{"BaseRequest":
{"Uin":"2545437902","Sid":"QfLp+Z+FePzvOFoG","Skey":"","DeviceID":"e1615250492"}}
這個(gè)JSON串中Uin和Sid分別是上面步驟中獲得的那兩個(gè)Cookie值,DeviceID是一個(gè)本地生成的隨機(jī)字符串(分析了官方的總是e+一串?dāng)?shù)字,所以我們也保持這樣的格式)。
服務(wù)器就會(huì)返回一個(gè)很長(zhǎng)的JSON串,這其中包括:BaseResponse中的值用來(lái)表示請(qǐng)求狀態(tài)碼,ContactList主要用來(lái)表示聯(lián)系人(此列表不全,只包括了類(lèi)似通訊錄助手、文件助手、微信團(tuán)隊(duì)和一些公眾帳號(hào)等,后面會(huì)通過(guò)另一接口去獲得更全面的信息),SyncKey是用戶與服務(wù)器同步的信息,User就是當(dāng)前登錄用戶自己的信息。
6.獲得所有的好友列表
在上一步驟中已經(jīng)獲得了部分好友和公眾帳號(hào),如果需要獲得完整的好友信息,就需要訪問(wèn)以下的鏈接:
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?r=1377482079876(r依然是時(shí)間)
訪問(wèn)該鏈接同樣需要POST方式,但Body為空J(rèn)SON:{},服務(wù)器對(duì)身份的判定是通過(guò)Cookies,所以需要保持之前訪問(wèn)的Cookies不被修改(在Objective-C中會(huì)自動(dòng)保存相關(guān)的Cookies,無(wú)需程序特殊處理),在返回的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=(見(jiàn)以下說(shuō)明)&_=1377482079876
其中的參數(shù)r和_都是time,sid,uin,deviceid與上面步驟的值相對(duì)應(yīng),此處的synkey是上步步驟獲得的同步鍵值,但需要按一定的規(guī)則組合成以下的字符串:
1_124125|2_452346345|3_65476547|1000_5643635
就是將鍵和值用_隔開(kāi),不同的鍵值對(duì)用|隔開(kāi),但記得|需要URL編碼成%7C,通過(guò)訪問(wèn)上面的地址,會(huì)返回如下的字符串:
window.synccheck={retcode:”0”,selector:”0”}
如果retcode中的值不為0,則說(shuō)明與服務(wù)器的通信有問(wèn)題了,但具體問(wèn)題我就無(wú)法預(yù)測(cè)了,selector中的值表示客戶端需要作出的處理,目前已經(jīng)知道當(dāng)為6的時(shí)候表示有消息來(lái)了,就需要去訪問(wèn)另一個(gè)接口獲得新的消息。
8.獲得別人發(fā)來(lái)的消息
當(dāng)一個(gè)步驟中知道有新消息時(shí),就需要去獲取消息內(nèi)容,通過(guò)訪問(wèn)以下的鏈接:
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid=QfLp+Z+FePzvOFoG&r=1377482079876
上面鏈接中的參數(shù)sid對(duì)應(yīng)上面步驟中的值,r為時(shí)間,訪問(wèn)鏈接需要使用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與上面步驟中的值對(duì)應(yīng),SyncKey也是上面步驟中獲得的同步鍵值對(duì),rr為時(shí)間,訪問(wèn)成功之后服務(wù)器會(huì)返回一個(gè)JSON串,其中AddMsgList中是一個(gè)數(shù)組,包含了所有新消息。
9.向用戶發(fā)送消息
用戶主動(dòng)發(fā)送消息,通過(guò)以下的URL地址:
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg?sid=QfLp+Z+FePzvOFoG&r=1377482079876
上面的sid和r參數(shù)不再解釋了,訪問(wèn)該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)的值,與上面的步驟中的值對(duì)應(yīng),Msg是對(duì)消息的描述,包括了發(fā)送人與接收人,消息內(nèi)容,消息的類(lèi)型(1為文本),ClientMsgId和LocalID由本地生成。rr可用當(dāng)前的時(shí)間。
在返回JSON結(jié)果中BaseResponse描述了發(fā)送情況,Ret為0表示發(fā)送成功。
網(wǎng)頁(yè)微信客戶端封包大全
http://www.langyeweb.com/Program/70.html
網(wǎng)頁(yè)版微信功能只有一個(gè):聊天。根據(jù) Copyright (C) 狼夜我這兩天研究發(fā)現(xiàn), 網(wǎng)頁(yè)版微信可以脫離手機(jī)微信,也就是手機(jī)微信退出、手機(jī)關(guān)機(jī),都不影響網(wǎng)頁(yè)端微信的 在線以及聊天,關(guān)于如何使用加好友、朋友圈、搖一搖功能,我有個(gè)思路就是抓手機(jī)封包 @Icenowy 在微博上有抓手機(jī)包的計(jì)劃 然后使用,不過(guò)這個(gè)想法因?yàn)闀r(shí)間問(wèn)題沒(méi)有去實(shí)踐, 希望大家能研究出來(lái)的話在本頁(yè)面留一個(gè)鏈接,十分感謝!
以下是Post/Get的封包大全,如果能看懂這個(gè),基本上你就可以做出來(lái)了。
獲取uuid
https://login.weixin.qq.com/jslogin?appid=wx782c26e4c19acffb&redirect_uri=https%3A%2F%2Fwx.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage&fun=new&lang=zh_CN&_=1388994062250
獲取二維碼
https://login.weixin.qq.com/qrcode/{$uuid}?t=webwx
等待掃描Get
https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?uuid=454d958c7f6243&tip=1&_=1388975894359
https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?uuid=454d958c7f6243&tip=1&_=1388975873359
https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?uuid=454d958c7f6243&tip=1&_=1388975883859
掃描了(但還沒(méi)有確認(rèn))-返回
window.code=201;
未掃描返回空
掃描之后-第一次請(qǐng)求成功
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxstatreport?type=1&r=1388975895453
{"BaseRequest":{"Uin":0,"Sid":0},"Count":1,"List":[{"Type":1,"Text":"/cgi-bin/mmwebwx-bin/login, First Request Success, uuid: 454d958c7f6243"}]}
掃描之后-第二次請(qǐng)求開(kāi)始
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxstatreport?type=1&r=1388975895453
{"BaseRequest":{"Uin":0,"Sid":0},"Count":1,"List":[{"Type":1,"Text":"/cgi-bin/mmwebwx-bin/login, Second Request Start, uuid: 454d958c7f6243"}]}
等待確認(rèn)Get
https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?uuid=454d958c7f6243&tip=0&_=1388975895453
https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?uuid=454d958c7f6243&tip=0&_=1388975900953
https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?uuid=454d958c7f6243&tip=0&_=1388975906453
https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?uuid=454d958c7f6243&tip=0&_=1388975911953
手機(jī)確認(rèn)-返回
window.code=200;
window.redirect_uri="https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=03f725a8039d418ab79c69b6ffbd771b&lang=zh_CN&scan=1388975896";
未確認(rèn)返回空
get 登陸獲取Cookie
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=03f725a8039d418ab79c69b6ffbd771b&lang=zh_CN&scan=1388975896&fun=new
WX2新協(xié)議
https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=b03aa3dfbe8d4130981ddf771137ae7b&lang=zh_CN&scan=1419126125&fun=old
設(shè)置Cookie 返回一個(gè)狀態(tài)
post 第二次請(qǐng)求成功
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxstatreport?type=1&r=1388976086218
{"BaseRequest":{"Uin":0,"Sid":0},"Count":1,"List":[{"Type":1,"Text":"/cgi-bin/mmwebwx-bin/login, Second Request Success, uuid: 454d958c7f6243, time: 190765ms"}]}
post 表示登陸成功-返回重要的數(shù)據(jù)SKey
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=1388976086484
DeviceID 是e + 隨機(jī)數(shù)
http://www.tanhao.me/talk/1466.html
{"BaseRequest":{"Uin":"750366800","Sid":"e75TXbI7TnKUevmI","Skey":"","DeviceID":"e519062714508114"}}
post 應(yīng)該是向服務(wù)器端提供的一次驗(yàn)證-返回SyncKey
http://freezingsky.iteye.com/blog/2055502
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid=e75TXbI7TnKUevmI&r=1388976086734
{"BaseRequest":{"Uin":750366800,"Sid":"e75TXbI7TnKUevmI"},"SyncKey":{"Count":4,"List":[{"Key":1,"Val":620916854},{"Key":2,"Val":620917961},{"Key":3,"Val":620917948},{"Key":1000,"Val":1388967977}]},"rr":1388976086734}
post 可能是獲取當(dāng)前會(huì)話列表
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?r=1388976086734
{}
post 可能是在手機(jī)上顯示的提示信息
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxstatusnotify?r=1388976086750
{"BaseRequest":{"Uin":750366800,"Sid":"e75TXbI7TnKUevmI","Skey":"","DeviceID":"e519062714508114"},"Code":3,"FromUserName":"langyeie","ToUserName":"langyeie","ClientMsgId":"1388976086750"}
get 獲取頭像圖片
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgeticon?seq=1388335457&username=langyeie
get 同理可以獲取其他微信好友的頭像
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgeticon?seq=620917759&username=wxid_xx3mtgeux5511
post 更改什么狀態(tài)?標(biāo)記已讀?
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxbatchgetcontact?type=ex&r=1388976086812
{"BaseRequest":{"Uin":750366800,"Sid":"e75TXbI7TnKUevmI","Skey":"","DeviceID":"e519062714508114"},"Count":10,"List":[{"UserName":"z_zer0v","ChatRoomId":3445229833},{"UserName":"huobao002","ChatRoomId":3445229833},{"UserName":"wxid_jo4qxoep4go411","ChatRoomId":3445229833},{"UserName":"jijunlong123456","ChatRoomId":3445229833},{"UserName":"wxid_toyaj4qwrynb21","ChatRoomId":3445229833},{"UserName":"wxid_6655286553012","ChatRoomId":3445229833},{"UserName":"wxid_rankrke1kkyd12","ChatRoomId":3445229833},{"UserName":"wxid_chcblpm846k022","ChatRoomId":3445229833},{"UserName":"tw297554396","ChatRoomId":3445229833},{"UserName":"wxid_3076050756212","ChatRoomId":3445229833}]}
聊天室頭像
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetheadimg?seq=620917806&username=3445229833chatroom@
get 監(jiān)聽(tīng)會(huì)話
https://webpush.weixin.qq.com/cgi-bin/mmwebwx-bin/synccheck?callback=jQuery18308660551080269895_1388975862078&r=1388976091937&sid=e75TXbI7TnKUevmI&uin=750366800&deviceid=e519062714508114&synckey=1_620916854%7C2_620917963%7C3_620917948%7C11_1388976090%7C1000_1388967977&_=1388976091937
https://webpush.weixin.qq.com/cgi-bin/mmwebwx-bin/synccheck?callback=jQuery18308660551080269895_1388975862078&r=1388976119062&sid=e75TXbI7TnKUevmI&uin=750366800&deviceid=e519062714508114&synckey=1_620916854%7C2_620917963%7C3_620917948%7C11_1388976090%7C1000_1388967977&_=1388976119078
https://webpush.weixin.qq.com/cgi-bin/mmwebwx-bin/synccheck?callback=jQuery18308660551080269895_1388975862078&r=1388976173375&sid=e75TXbI7TnKUevmI&uin=750366800&deviceid=e519062714508114&synckey=1_620916854%7C2_620917963%7C3_620917948%7C11_1388976090%7C1000_1388967977&_=1388976173390
https://webpush.weixin.qq.com/cgi-bin/mmwebwx-bin/synccheck?callback=jQuery18308660551080269895_1388975862078&r=1388976146265&sid=e75TXbI7TnKUevmI&uin=750366800&deviceid=e519062714508114&synckey=1_620916854%7C2_620917963%7C3_620917948%7C11_1388976090%7C1000_1388967977&_=1388976146265
正常返回結(jié)果
window.synccheck={retcode:"0",selector:"0"}
有消息返回結(jié)果
window.synccheck={retcode:"0",selector:"6"}
發(fā)送消息返回結(jié)果
window.synccheck={retcode:"0",selector:"2"}
朋友圈有動(dòng)態(tài)
window.synccheck={retcode:"0",selector:"4"}
獲取消息-post-設(shè)置Cookie
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid=e75TXbI7TnKUevmI&r=1388977398062
{"BaseRequest":{"Uin":750366800,"Sid":"e75TXbI7TnKUevmI"},"SyncKey":{"Count":5,"List":[{"Key":1,"Val":620916854},{"Key":2,"Val":620917978},{"Key":3,"Val":620917975},{"Key":201,"Val":1388977392},{"Key":1000,"Val":1388967977}]},"rr":1388977398062}
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid=e75TXbI7TnKUevmI&r=1388977583250
{"BaseRequest":{"Uin":750366800,"Sid":"e75TXbI7TnKUevmI"},"SyncKey":{"Count":5,"List":[{"Key":1,"Val":620916854},{"Key":2,"Val":620917980},{"Key":3,"Val":620917975},{"Key":201,"Val":1388977400},{"Key":1000,"Val":1388967977}]},"rr":1388977583250}
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid=e75TXbI7TnKUevmI&r=1388977660750
{"BaseRequest":{"Uin":750366800,"Sid":"e75TXbI7TnKUevmI"},"SyncKey":{"Count":5,"List":[{"Key":1,"Val":620916854},{"Key":2,"Val":620917982},{"Key":3,"Val":620917975},{"Key":201,"Val":1388977585},{"Key":1000,"Val":1388967977}]},"rr":1388977660750}
post 發(fā)送消息
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg?sid=e75TXbI7TnKUevmI&r=1388977830140
{"BaseRequest":{"Uin":750366800,"Sid":"e75TXbI7TnKUevmI","Skey":"D6EBA5FA425CAE258F24E75CF51F2E1B4EEA9C5338BE456C","DeviceID":"e519062714508114"},"Msg":{"FromUserName":"langyeie","ToUserName":"pp80000","Type":1,"Content":"55","ClientMsgId":1388977830140,"LocalID":1388977830140}}
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid=e75TXbI7TnKUevmI&r=1388977830390
{"BaseRequest":{"Uin":750366800,"Sid":"e75TXbI7TnKUevmI"},"SyncKey":{"Count":5,"List":[{"Key":1,"Val":620916854},{"Key":2,"Val":620917986},{"Key":3,"Val":620917975},{"Key":201,"Val":1388977776},{"Key":1000,"Val":1388967977}]},"rr":1388977830390}
get 有消息來(lái),響鈴
https://res.wx.qq.com/zh_CN/htmledition/swf/msg17ced3.mp3
獲取消息中的圖片
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetmsgimg?type=slave&MsgID={MsgID值}&skey=%40{skey值}
獲取視頻
/cgi-bin/mmwebwx-bin/webwxgetvideo?type=flv&msgid={MsgID值}&skey={SKey值}
/cgi-bin/mmwebwx-bin/webwxgetvideo?fun=download&msgid={MsgID值}&skey={SKey值}
獲取語(yǔ)音
webwxgetvoice
@import url(http://www.shnenglu.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);