# WebWechat
网页微信PHP登录的实现
依赖扩展
---
* curl
* pcntl 或者 pthreads
* gd
# 微信网页版协议分析
## 微信网页版协议分析(1)-登录
最近研究了微信网页版的实现原理,接下来会通过一系列的文章来总结这次研究的结果,最终会通过PHP代码实现一个简单的微信机器人程序。
### 1.获取uuid(get)
https://login.wx.qq.com/jslogin?appid=wx782c26e4c19acffb&redirect_uri=https%3A%2F%2Fwx.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage&fun=new&lang=zh_CN&_=1476606163580
#### 参数:
```
appid:固定为wx782c26e4c19acffb
redirect_rui:https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage经过url编码
fun:固定值new
lang:语言类型,中国zh_CN
_:当前的unix时间戳
```
#### 返回数据格式:
```
window.QRLogin.code = 200; window.QRLogin.uuid = "gf5Gk61zEA==";
window.QRLogin.uuid的值就是我们需要的uuid
```
### 2.获取二维码(get)
```
https://login.weixin.qq.com/qrcode/gf5Gk61zEA==
固定格式:https://login.weixin.qq.com/qrcode/ 拼接上第一步的带的uuid
```
#### 二维码中实际内容如下地址:
```
https://login.weixin.qq.com/l/gf5Gk61zEA==
即:https://login.weixin.qq.com/l/ 加上那个uuid
```
### 3.等待登录扫描(get轮询):
https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=gf5Gk61zEA==&tip=0&r=862560455&_=1476606163582
#### 参数:
```
loginicon:true
uuid:第一步得到的uuid
tip:0
r:862560455 非必须参数
_:同上为unix时间戳
```
#### 返回数据格式:
```
window.code=408;//登录超时code为408
window.code=201;window.userAvatar = 'data:img/jpg;base64';//扫描成功 201,userAvatar为用户头像
window.code=200;//确认登录code 200, 还有下面的redirect_uri的获取cookie的连接
window.redirect_uri="https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=AYfheMIH6tt9EmcZ0DxCKF4a@qrticket_0&uuid=YeGrrvqmHQ==&lang=zh_CN&scan=1476606728";
```
### 4.登录后获取cookie信息(get):
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=AYfheMIH6tt9EmcZ0DxCKF4a@qrticket_0&uuid=YeGrrvqmHQ==&lang=zh_CN&scan=1476606728&fun=new&version=v2&lang=zh_CN
此连接是上一步确认登录后获取的连接。
#### 返回数据格式(xml,还有登录后设置的cookie数据):
```xml
<error>
<ret>0</ret>
<message></message>
<skey>@crypt_14ae1b12_b73ba2673448154847d7007a2de3c53b</skey>
<wxsid>jSsRlGGPyY7U8det</wxsid>
<wxuin>566148615</wxuin>
<pass_ticket>kUY4PSgKNy4eOlWI%2FwIBMVULe3KHPVyvDqw1%2B4DVVu9McVvE2d5fL7LFOfa4iYnk</pass_ticket>
<isgrayscale>1</isgrayscale>
</error>
xml中skey、wxsid、wxuin、pass_ticket重要参数,
要在接来的请求中使用,需要记下来,还有返回的cookie信息,在接下来的请求中,都要去携带上才可以。
```
## 微信网页版协议分析(2)-获取信息
### 1.微信初始化请求(post):
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=862039733&lang=zh_CN&pass_ticket=kUY4PSgKNy4eOlWI%252FwIBMVULe3KHPVyvDqw1%252B4DVVu9McVvE2d5fL7LFOfa4iYnk
这个请求会获取联系人信息、公众号信息、自己的账号信息
#### 请求头:
Content-Type:application/json;charset=UTF-8
#### 提交数据(json):
```
{
"BaseRequest": {
"Uin": "566148615",
"Sid": "jSsRlGGPyY7U8det",
"Skey": "@crypt_14ae1b12_b73ba2673448154847d7007a2de3c53b",
"DeviceID": "e119795675188164"
}
}
Uin、Sid、Skey 登录后获取的xml中的数据
DeviceID 是e + 随机数
```
#### 返回数据(json,用户的好友信息):
```
{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
},
"Count": 11,
"ContactList": [...], //联系人信息、公众号信息、群
"SyncKey": {
"Count": 4,
"List": [
{
"Key": 1,
"Val": 635705559
},
... //同步key值,下次请求时要写到上
]
},
"User": {
"Uin": xxx,
"UserName": xxx,
"NickName": xxx,
"HeadImgUrl": xxx,
"RemarkName": "",
"PYInitial": "",
"PYQuanPin": "",
"RemarkPYInitial": "",
"RemarkPYQuanPin": "",
"HideInputBarFlag": 0,
"StarFriend": 0,
"Sex": 1,
"Signature": "Apt-get install B",
"AppAccountFlag": 0,
"VerifyFlag": 0,
"ContactFlag": 0,
"WebWxPluginSwitch": 0,
"HeadImgFlag": 1,
"SnsFlag": 17
},
"ChatSet": "xxx",
"SKey": "@crypt_14ae1b12_b73ba2673448154847d7007a2de3c53b",
"ClientVersion": 369302288,
"SystemTime": 1476608977,
"GrayScale": 1,
"InviteStartCount": 40,
"MPSubscribeMsgCount": 7,
"ClickReportInterval": 600000
}
```
### 2.webwxstatusnotify通知消息已读(post):
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxstatusnotify?pass_ticket=ZDJfLCa0EAKrLn2CdD7MDl%252B54GwlW0IEiwYOsm6II%252F8W57y0pF1F8fqS%252B5z4INU5
客户端读取消息后要发起请求,告诉服务器消息已经读取,从而通知手机客户端
#### 参数
```
pass_ticket 登录请求返回的xml中的值
```
#### 请求头:
Content-Type:application/json;charset=UTF-8
#### 提交数据(json):
```
{
"BaseRequest": {
"Uin": 566148615,
"Sid": "EKjoZCMRIvrY7NIP",
"Skey": "@crypt_14ae1b12_f59314a579c67b15f838d09feb79c17f",
"DeviceID": "e098855372553243"
},
"Code": 3,
"FromUserName": 自己ID,
"ToUserName": 自己ID,
"ClientMsgId": 时间戳
}
```
#### 返回数据(json):
```
{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
},
"MsgID": "1525762281689643050"
}
```
### 3.获取联系人信息列表(get):
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?pass_ticket=ZDJfLCa0EAKrLn2CdD7MDl%252B54GwlW0IEiwYOsm6II%252F8W57y0pF1F8fqS%252B5z4INU5&r=1476608979549&seq=0&skey=@crypt_14ae1b12_f59314a579c67b15f838d09feb79c17f
#### 参数
```
pass_ticket 登录请求中返回xml中获取
seq=0 固定值即可
skey 初始化请求中获取
```
#### 返回数据(json):
```
{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
},
"MemberCount": 637,
"MemberList": [
{
"Uin": 0,
"UserName": xxx,
"NickName": "LbbNiu",
"HeadImgUrl": xxx,
"ContactFlag": 3,
"MemberCount": 0,
"MemberList": [],
"RemarkName": "",
"HideInputBarFlag": 0,
"Sex": 0,
"Signature": "IT全才-LbbNiu",
"VerifyFlag": 8,
"OwnerUin": 0,
"PYInitial": "LbbNiu",
"PYQuanPin": "LbbNiu",
"RemarkPYInitial": "",
"RemarkPYQuanPin": "",
"StarFriend": 0,
"AppAccountFlag": 0,
"Statues": 0,
"AttrStatus": 0,
"Province": "",
"City": "",
"Alias": "Urinxs",
"SnsFlag": 0,
"UniFriend": 0,
"DisplayName": "",
"ChatRoomId": 0,
"KeyWord": "gh_",
"EncryChatRoomId": ""
}
....//联系人列表
],
"Seq": 0
}
```
### 4.webwxbatchgetcontact获取聊天会话列表信息(post):
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxbatchgetcontact?type=ex&r=1476608979648&pass_ticket=ZDJfLCa0EAKrLn2CdD7MDl%252B54GwlW0IEiwYOsm6II%252F8W57y0pF1F8fqS%252B5z4INU5
#### 参数
```
type=ex 固定值即可
r 当前时间戳
pass_ticket 登录请求中返回xml中获取
```
#### 请求头:
Content-Type:application/json;charset=UTF-8
#### 提交数据(json):
```
{
"BaseRequest": {
"Uin": 566148615,
"Sid": "EKjoZCMRIvrY7NIP",
"Skey": "@crypt_14ae1b12_f59314a579c67b15f838d09feb79c17f",
"DeviceID": "e316575061818116"
},
"Count": 7,
"List": [
{
"UserName": "@@e2da072e5beda58413f788fd2978b6f9fbde2ba337a71f02e1458958fcdb8371", //去要获取的群UserName
"ChatRoomId": ""
}…
]
}
```
#### 返回数据(json):
```
{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
},
"Count": 7,
"ContactList": [
]
}
```
### 5.同步刷新(get轮询):
https://webpush.wx.qq.com/cgi-bin/mmwebwx-bin/synccheck?r=1476611147442&skey=%40crypt_14a