以前写过出来一个软件,但是因为微信的尿性啊,有些重,其他省份使用不了,懒得再改了。所以一直没有发布,今天来仔细分析一波微信网页版的协议。有需求的可以写一下工具。

先放一下我写的成品图。

如何实现微信登录网站(微信网页版登陆协议详细分析)(1)

微信网页版的协议无外乎和QQ网页版协议差不多,但也有不同之处。QQ的网页协议暂不分析,以前曾经在论坛发布的源码前几天好像失效了,有人想叫我再找找问题,我找出来问题,到时候再修改吧。

如何实现微信登录网站(微信网页版登陆协议详细分析)(2)

协议分析开始。

先说一下URL参数,appid不用管。直接带入。redirect_uri返回URL不用管,直接带入。标红的这个字符串,也不用管,就是一个随机数。

GET提交方式之后返回内容:

window.QRLogin.code = 200; window.QRLogin.uuid = "4ZOQ8OfKLQ==";

“4ZOQ8OfKLQ==” 此处必须记下来,因为这个是扫码的二维码必须携带的参数,方便下个包的调用。

扫码

  • [GET]https://login.weixin.qq.com/qrcode/4ZOQ8OfKLQ==

标红的地址,为第一个包所得到的参数。

直接进行了提交,然后这个二维码就出现了。

如何实现微信登录网站(微信网页版登陆协议详细分析)(3)

二维码出现之后,那么接下来的操作就是判断扫码状态。

  • [GET]https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=AdHVfxierg==&tip=0&r=1870135597&_=1544318065401

循环响应此包,uuid为第一次发包所得到的UUID。

进行扫码,如果判断扫码成功,登陆成功,那么返回内容:

window.code=200;window.redirect_uri="https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=AdSsiKmYz2u_XBWSMkWskH7y@qrticket_0&uuid=AcLnMRh9GQ==&lang=zh_CN&scan=1544318120";

出现window.redirect_uri 返回的URL,就代表明面上已经登陆成功了,但是你的登陆信息还没有得到。

获得关键信息

  • [GET]https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=AdSsiKmYz2u_XBWSMkWskH7y@qrticket_0&uuid=AcLnMRh9GQ==&lang=zh_CN&scan=1544318120

此处请求第三个包所返回的地址,就是登陆成功的地址。在这个地方,得到请求头中的set-cookie和返回中的内容信息才算是真正的登陆成功。

先来看一下返回中的信息:

如何实现微信登录网站(微信网页版登陆协议详细分析)(4)

得到的是一个xml格式的消息,其中<skey><wxsid><wxuin><pass_ticket>保存并记录下来,以便后续包调用。

再来看一下cookie中的消息。

如何实现微信登录网站(微信网页版登陆协议详细分析)(5)

其中比较重要的是webwx_data_ticket=、webwx_auth_ticket=记录下来,以便后续包名发包时带入。

记录下来这些信息之后才算是真正的登陆成功,可以进行一些操作了。

  • [POST]https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=1869988690&pass_ticket=xcWifD9MMB3vKNTM2PBiGWCZhYMhFryW5UK%2BORQTxJwr0spIVaJScdE6W%2BxS59zc

参数中pass_ticket为上一个包所得到的内容,

cookie无需带入。

但是发送的消息如下。

{"BaseRequest":{"Uin":"2402936223","Sid":"mJM MFX2RoB0og8h","Skey":"@crypt_239b7b7c_03d892405af9080758a6a0e1354abbf9","DeviceID":"e387877040871158"}}

Uin为上一个包得到的wxuin

Sid为上一个包得到的wxsid

Skey为上一个包得到的skey

DeviceID为e 15位的随机数。

响应为自己当前登陆的签名,以及昵称,还有最新聊天的用户,以及微信关注的消息。内容太多就不发了。

但是返回的json数据节点【data.SyncKey.List[0].Key】里面的内容必须记录下来,如果没有这些Key值,消息会发送不出去。标红的0值为递增。

记录Key值

  • [GET]https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?lang=zh_CN&pass_ticket=pass_ticket&r=1540953981074&seq=0&skey=sKey

URL中带入pass_ticket、Skey参数,刚才发的包里面已经得到了。至于r就是一个随机数。

返回关注的微信公众号、以前所有的好友json数据。

到了这个阶段就是开始了重头戏,因为要循环判断消息,确定是否有新的消息,而带入的请求这个key值是必不可少的。

发送Key值

  • [GET]https://webpush.wx.qq.com/cgi-bin/mmwebwx-bin/synccheck?r=1540974131329&skey=" & sKey & "&sid=" & sid & "&uin=" & wxuin & "&deviceid=e" & 随机数 & "&synckey=1_KEY1|2_KEY2|3_KEY3|1000_KEY1000&_=1541036165840

这个是初始请求,初始请求需要带入Key值,这个Key值的得到是上上一个包所得到的内容。

Cookie需带入wxuin=、wxsid=、webwx_data_ticket=

在这里需记住,这个是第一次发Key值,如果有新消息的话会自动获取并自动生成一个Key值。

返回的消息:

如何实现微信登录网站(微信网页版登陆协议详细分析)(6)

selector为2,有新的消息,那么接下来请求最新消息,就是得到新的消息。

返回Key值

  • [POST]https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid=sid&skey=skey&lang=zh_CN&pass_ticket=pass_ticket

URL中的参数sid为wxsid、skey为skey、pass_ticket为pass_ticket,前面发包已经得到了。

发送

{""BaseRequest"":{""Uin"":" & wxuin & ",""Sid"":""" & wxsid & """,""Skey"":""" & sKey & """,""DeviceID"":""e" & 随机数 & """},""SyncKey"":{""Count"":个数,""List"":[{""Key"":1,""Val"":" & Key1 & "},{""Key"":2,""Val"":" & Key2 & "},{""Key"":3,""Val"":" & Key3 & "},{""Key"":1000,""Val"":" & Key1000 & "}]},""rr"":914483736}

这次的请求有些繁琐,但是也能看得清,这些数据在这之前都已经获得成功了,在这里就不多说了。

uin就是得到的wxuin

Sid就是得到的wxsid

sKey就是得到的skey

DeviceID就是e 15位的随机数。

count就是下面的key有几个key,但是这个时候是不固定的。我就曾经吃过这个地方的亏。

key值就是咱们之前得到的key值。

返回的包如下:

[JavaScript] 纯文本查看 复制代码

?

001

002

003

004

005

006

007

008

009

010

011

012

013

014

015

016

017

018

019

020

021

022

023

024

025

026

027

028

029

030

031

032

033

034

035

036

037

038

039

040

041

042

043

044

045

046

047

048

049

050

051

052

053

054

055

056

057

058

059

060

061

062

063

064

065

066

067

068

069

070

071

072

073

074

075

076

077

078

079

080

081

082

083

084

085

086

087

088

089

090

091

092

093

094

095

096

097

098

099

100

101

102

103

104

105

106

107

108

109

110

111

{

"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": 682044882

}

,{

"Key": 2,

"Val": 682045004

}

,{

"Key": 3,

"Val": 682044823

}

,{

"Key": 11,

"Val": 682043346

}

,{

"Key": 201,

"Val": 1544320212

}

,{

"Key": 1000,

"Val": 1544310122

}

,{

"Key": 1001,

"Val": 1544310196

}

]

}

,

"SKey": "",

"SyncCheckKey": {

"Count": 7,

"List": [{

"Key": 1,

"Val": 682044882

}

,{

"Key": 2,

"Val": 682045004

}

,{

"Key": 3,

"Val": 682044823

}

,{

"Key": 11,

"Val": 682043346

}

,{

"Key": 201,

"Val": 1544320212

}

,{

"Key": 1000,

"Val": 1544310122

}

,{

"Key": 1001,

"Val": 1544310196

}

]

}

}

将最后的7个key值给记录下来。再次循环POST就能进行接收消息的操作了。

获得联系人

  • [GET]https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?lang=zh_CN&pass_ticket=pass_ticket&r=1540953981074&seq=0&skey=skey

pass_ticket、skey为得到的内容

cookie带入wxuin=、wxsid=,即可返回所有的好友信息。

返回的JSON数据中MemberList[0].UserName 为对方的用户名码,这个必须每一个都得记录下来,不然到时候发送消息的时候确定不了对方是谁。0为递增。

发送消息

  • [POST]https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg?lang=zh_CN&pass_ticket=76%2F1QjLCPhAUFSojEqCbC5ib0I2Qvt1P6zf%2BE4Gr%2Fqma5Oh937hpTG7rYrrkGZtF

{"BaseRequest":{"Uin":Uin,"Sid":Sid,"Skey":Skey,"DeviceID":DeviceID},"Msg":{"Type":1,"Content":"消息内容","FromUserName":"@0ffa505f57e50f9c3f741d8d06b1dbeb5bba0de6feaaf6897eca14a81618dd95","ToUserName":"@2e7ee0f35577deaa1f43edcebe145f37","LocalID":15 随机数,"ClientMsgId":15 随机数},"Scene":0}

uin就是得到的wxuin

Sid就是得到的wxsid

sKey就是得到的skey

DeviceID就是e 15位的随机数。

FromUserName为自己的wx用户名码

ToUserName为对方的wx用户名码

LocalID:15 15位的随机数

ClientMsgId:15 15位的随机数

返回:

[HTML] 纯文本查看 复制代码

?

1

2

3

4

5

6

7

8

9

{

"BaseResponse": {

"Ret": 0,

"ErrMsg": ""

}

,

"MsgID": "9097829072507170245",

"LocalID": "15443223305630897"

}

ret返回为0就算是消息发送成功了。

另外FromUserName、ToUserName在获得好友的时候会有这个记录。

如何实现微信登录网站(微信网页版登陆协议详细分析)(7)

最后再说一下如何检测好友,对方不收到消息呢,向好友发送时发送以下特殊字符,对方不会收到你的任何消息,但是如果对方将你删除或者拉黑将会显示对方已把你删除(拉黑)

但是因为是一个特殊字符,如果要向对方发送的话还需要进行转码操作。

Url转码:

[HTML] 纯文本查看 复制代码

?

1

发送的时候解码发送即可。】

,