微信Web版通信过程分析

微信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表示发送成功。

版权声明:本文为MagicTyphoon原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/MagicTyphoon/articles/6349322.html