2
0
mirror of https://gitee.com/hotlcc/wechat4j.git synced 2025-06-07 11:04:07 +08:00
wechat4j/doc/web-weixin-api.md
2018-09-14 16:21:39 +08:00

1124 lines
31 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Web微信API文档
## 1、登录
Web微信登录页面是[https://wx.qq.com](https://wx.qq.com),以下内容以此页开始。
### 1.1、获取登录uuid
进入Web微信登录页面后在开发者工具中查看网络请求情况可以发现在二维码图片加载之前浏览器发送了一次 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&_=1532078129220
```
该请求用于获取登录uuid分析发现有如下URL参数
|参数名|示例值|描述|
|---|---|---|
|appid|wx782c26e4c19acffb|这个值不变表示来自Web版微信|
|redirect_uri|https%3A%2F%2Fwx2.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage|跳转页面;非必须值;|
|fun|new|固定值;|
|lang|zh_CN|语言zh_CN表示中文|
|_|1532078129220|13位时间戳|
然后服务器返回数据:
```
window.QRLogin.code = 200; window.QRLogin.uuid = "wcXrINkB9Q==";
```
- window.QRLogin.code的值为200时表示成功为其它值均表示失败。
- window.QRLogin.uuid的值为获取到的uuid每次刷新会获取到不同的uuid实际上uuid是服务端用来标识每一次登录的。
### 1.2、获取二维码
接着会发现如下 GET 请求:
```
https://login.weixin.qq.com/qrcode/wcXrINkB9Q==
```
该url为二维码图片的链接url尾部的字符串即是上面获取到的uuid。
### 1.3、等待确认登录
在获取二维码的请求之后,会发现如下 GET 请求:
```
https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=wcXrINkB9Q==&tip=0&r=1223005686&_=1532080293141
```
这是等待扫描登录并获取跳转url的请求。如果没有及时扫描二维码一定时间后该请求会重复出现表示浏览器在轮询请求。
URL参数分析
|数名|示例值|描述|
|---|---|---|
|loginicon|true|固定值;|
|uid|wcXrINkB9Q==|同前面的uuid|
|tip|0或1|0表示等待用户扫码确认1表示等待用户直接确认用于push登陆时|
|r|1223005686|10位随机数|
|_|1532080293141|13位时间戳|
如果没有及时扫描二维码,服务器返回数据:
```
window.code=408;
```
- 表示没有轮询到认证信息,此时需要再次发送该请求。
如果一直没有扫描二维码,服务器返回数据:
```
window.code=400;
```
- 表示该次登录uuid失效即二维码失效此时会停止轮询需要重新获取uuid才能继续。
及时扫码认证之后,在点击确认登录之前,服务器返回数据:
```
window.code=201;
```
- 表示微信APP端已经扫码但还没有点击确认。
及时扫码并点击确认之后,服务器返回:
```
window.code=200;
window.redirect_uri="https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=A51bGY49nxxxxxxx1wNPC3@qrticket_0&uuid=wcXrINkB9Q==&lang=zh_CN&scan=1532083897";
```
- window.code的值为200表示APP端认证成功。
- window.redirect_uri为需要跳转的url。
### 1.4、获取登录认证码
微信APP端认证后会产生的新的 GET 请求:
```
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=A51bGY49nxxxxxxx1wNPC3@qrticket_0&uuid=wcXrINkB9Q==&lang=zh_CN&scan=1532083897&fun=new&version=v2
```
我们发现该请求即是上一步认证成功之后得到的redirect_uri再拼上&fun=new&version=v2。
该请求发送之后其它web或pc端登录的微信会被踢下线。
URL参数分析
|数名|示例值|描述|
|---|---|---|
|ticket|A51bGY49nxxxxxxx1wNPC3@qrticket_0|保存不变即可;|
|uuid|wcXrINkB9Q==|同前面的uuid|
|lang|zh_CN|语言zh_CN表示中文|
|scan|1532083897|用户扫描的时间戳;|
|fun|new|固定值;|
|version|v2|固定值;|
服务器返回数据:
```XML
<error>
   <ret>0</ret>
   <message></message>
   <skey>@crypt_jkde99da_b4xxxxxxxxxxxxxxx76d9yualp</skey>
   <wxsid>8rwxxxxxxxxxHq2P</wxsid>
   <wxuin>26xxx7</wxuin>
   <pass_ticket>AFsdZ7eHxxxxxxxxxxxxxxxxfr1vjHPn=</pass_ticket>
   <isgrayscale>1</isgrayscale>
</error>
```
***(为了个人隐私,以上返回数据有打码)***
- ret表示请求返回状态0表示成功。
- skey、wxsid和wxuin都是具体微信用户的信息不会变化在后续的通讯中需要用到。
- pass_ticket在初始化页面时需要用到。
### 1.5、退出登录
如果点击退出,我们会发现先后出现如下两个 POST 请求:
```
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxlogout?redirect=1&type=0&skey=%40crypt_jkde99da_b4xxxxxxxxxxxxxxx76d9yualp
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxlogout?redirect=1&type=1&skey=%40crypt_jkde99da_b4xxxxxxxxxxxxxxx76d9yualp
```
这两个请求唯一的区别就是type的值先是0再是1。
URL参数分析
|数名|示例值|描述|
|---|---|---|
|redirect|1|固定值;|
|type|0或1|0或1固定值|
|skey|%40crypt_jkde99da_b4xxxxxxxxxxxxxxx76d9yualp|登录时获取的需要urlencode。|
FORM表单参数分析
|参数名|示例值|描述|
|---|---|---|
|sid||登录时获取的;|
|uin||登录时获取的;|
服务器返回数据:
- 该请求会导致页面跳转,没有返回数据。
### 1.6、push登录
点击退出后页面会出现点击直接登录的页面点击登录之后会发现产生一个叫webwxpushloginurl的 GET 请求:
```
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxpushloginurl?uin=26xxx7
```
该请求是不扫码获取uuid的方式仅用在手动退出登录之后uuid获取之后还是继续1.3的等待确认。
URL参数分析
|数名|示例值|描述|
|---|---|---|
|uin|26xxx7|同前面获取的uin|
服务器返回数据:
```JavaScript
{
"ret": "0",
"msg": "all ok",
"uuid": "A_1_xxxw=="
}
```
- ret为0表示成功为1表示uin错误等失败。
- uuid为新的uuid。经过反复“退出-push登录-退出-push登录”测试发现全程uin保持不变uuid会变化。
## 2、数据同步
### 2.1、页面初始化
上面已经拿到了用户认证码,接着需要登录并初始化页面。
初始化页面就是向服务端请求常用的联系人等信息,如下 POST 请求:
```
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=1219172280&lang=zh_CN&pass_ticket=AFsdZ7eHxxxxxxxxxxxxxxxxfr1vjHPn=
```
URL参数分析
|数名|示例值|描述|
|---|---|---|
|r|1219172280|10位随机数|
|lang|zh_CN|语言zh_CN表示中文|
|pass_ticket|AFsdZ7eHxxxxxxxxxxxxxxxxfr1vjHPn=|上一步获取到的;|
POST的数据JSON
```JavaScript
{
"BaseRequest": {
"DeviceID": "e659xxxxxxxx3006",
"Sid": "8rwxxxxxxxxxHq2P",
"Skey": "@crypt_jkde99da_b4xxxxxxxxxxxxxxx76d9yualp",
"Uin": "26xxx7"
}
}
```
POST参数分析
|数名|示例值|描述|
|---|---|---|
|BaseRequest.DeviceID|e659xxxxxxxx3006|设备IDe拼上15位随机串|
|BaseRequest.Sid|rwxxxxxxxxxHq2P|上一步获取到的wxsid|
|BaseRequest.Skey|crypt_jkde99da_b4xxxxxxxxxxxxxxx76d9yualp|上一步获取到的skey|
|BaseRequest.Uin|6xxx7|上一步获取到的wxuin|
服务器返回数据:
```JavaScript
{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
},
"Count": 11,
"ContactList": [{
"Uin": 0,
"UserName": "filehelper",
"NickName": "...",
"HeadImgUrl": "...",
"ContactFlag": 5,
"MemberCount": 0,
"MemberList": [],
"RemarkName": "",
"HideInputBarFlag": 0,
"Sex": 0,
"Signature": "",
"VerifyFlag": 0,
"OwnerUin": 0,
"PYInitial": "WJCSZS",
"PYQuanPin": "wenjianchuanshuzhushou",
"RemarkPYInitial": "",
"RemarkPYQuanPin": "",
"StarFriend": 0,
"AppAccountFlag": 0,
"Statues": 0,
"AttrStatus": 0,
"Province": "",
"City": "",
"Alias": "",
"SnsFlag": 0,
"UniFriend": 0,
"DisplayName": "",
"ChatRoomId": 0,
"KeyWord": "fil",
"EncryChatRoomId": "",
"IsOwner": 0
}],
"SyncKey": {
"Count": 4,
"List": [{
"Key": 1,
"Val": 704152857
}, {
"Key": 2,
"Val": 704152894
}, {
"Key": 3,
"Val": 704152870
}, {
"Key": 1000,
"Val": 1532075042
}]
},
"User": {
...
},
"ChatSet": "...",
"SKey": "@crypt_jkde99da_b4xxxxxxxxxxxxxxx76d9yualp",
"ClientVersion": 3697797,
"SystemTime": 1132000000,
"GrayScale": 1,
"InviteStartCount": 40,
"MPSubscribeMsgCount": 0,
"MPSubscribeMsgList": [],
"ClickReportInterval": 600000
}
```
- BaseResponse.Ret表示请求返回状态0表示成功。
- ContactList为最近联系人列表。联系人的UserName以一个@开头为好友,两个@为群组
- MPSubscribeMsg为公众号订阅消息。
- User是当前登录账户信息。
### 2.2、开启消息状态通知
接着需要开启消息状态通知。我们可以看到如下 POST 请求:
```
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxstatusnotify?lang=zh_CN&pass_ticket=AFsdZ7eHxxxxxxxxxxxxxxxxfr1vjHPn=
```
URL参数分析
|数名|示例值|描述|
|---|---|---|
|lang|zh_CN|语言zh_CN表示中文|
|pass_ticket|AFsdZ7eHxxxxxxxxxxxxxxxxfr1vjHPn=|同前面;|
POST的数据JSON
```JavaScript
{
"BaseRequest": {
"DeviceID": "e81xxxxxxxxx7686",
"Sid": "8rwxxxxxxxxxHq2P",
"Skey": "@crypt_jkde99da_b4xxxxxxxxxxxxxxx76d9yualp",
"Uin": "26xxx7"
},
"ClientMsgId": 1532xxxxx3374,
"Code": 3,
"FromUserName": "@56a0a9xxxxxxxxxxxxx54w0dxxxxbfab",
"ToUserName": "@56a0a9xxxxxxxxxxxxx54w0dxxxxbfab"
}
```
POST参数分析
|参数名|示例值|描述|
|---|---|---|
|BaseRequestB|{<br> "DeviceID":"e81xxxxxxxxx7686",<br> "Sid":"8rwxxxxxxxxxHq2P",<br> "Skey":"@crypt_jkde99da_b4xxxxxxxxxxxxxxx76d9yualp",<br> "Uin":"26xxx7"<br>}|每一次POST请求都会发送BaseRequest其中DeviceID是字母e拼上15位随机字符串其余三个都是前面获取到的认证信息。|
|ClientMsgId|1532xxxxx3374|13位时间戳|
|Code|3|固定值;|
|FromUserName|@56a0a9xxxxxxxxxxxxx54w0dxxxxbfab|页面加载时获取到的User.UserName|
|ToUserName|@56a0a9xxxxxxxxxxxxx54w0dxxxxbfab|同FromUserName|
服务器返回数据:
```javascript
{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
},
"MsgID": "2271xxxxxxxxxxxxx44"
}
```
- BaseResponse.Ret表示请求返回状态0表示成功。
### 2.3、服务端状态同步
继续观察,我们没间隔一定的时间,浏览器会想服务器发送一个重复的 GET 请求:
```
https://webpush.wx.qq.com/cgi-bin/mmwebwx-bin/synccheck?r=1532145313248&skey=%40crypt_jkde99da_b4xxxxxxxxxxxxxxx76d9yualp&sid=8rwxxxxxxxxxHq2P&uin=26xxx7&deviceid=e35077xxxx772148&synckey=1_704152857%7C2_704152996%7C3_704152955%7C1000_1532127722&_=1532145290777
```
该请求是轮询向服务器获取最新在线、消息等状态的。
URL参数分析
|数名|示例值|描述|
|---|---|---|
|r|1532145313248|13位时间戳|
|skey|%40crypt_jkde99da_b4xxxxxxxxxxxxxxx76d9yualp|同前面需要urlencode|
|sid|8rwxxxxxxxxxHq2P|同前面;|
|uin|26xxx7 同前面;|
|deviceid|e35077xxxx772148|设备IDe拼上15位随机串|
|synckey|1_704152857%7C2_704152996%7C3_704152955%7C1000_1532127722|由初始化登录页面信息返回串中Sync的list列表组成需要urlencode|
|_|1532145290777|13位时间戳|
服务器返回数据:
```
window.synccheck={retcode:"0",selector:"2"}
```
返回数据分析:
|名称|示例值|描述|
|---|---|---|
|retcode|0|表示当前在线状态。<br>0正常<br>1100失败/登出微信<br>1101从其它设备登录微信|
|selector|2|表示消息状态。<br>0正常<br>2有新消息<br>4目前发现修改了联系人备注会出现<br>7手机操作了微信|
## 3、联系人管理
### 3.1、获取全部联系人列表
接着可以看到获取全部联系人列表的 GET 请求:
```
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?lang=zh_CN&pass_ticket=AFsdZ7eHxxxxxxxxxxxxxxxxfr1vjHPn%253D&r=1532190636970&seq=0&skey=@crypt_jkde99da_b4xxxxxxxxxxxxxxx76d9yualp
```
URL参数分析
|参数名|示例值|描述|
|---|---|---|
|lang|zh_CN|语言;|
|pass_ticket|AFsdZ7eHxxxxxxxxxxxxxxxxfr1vjHPn%253D|同前面获取到的;|
|r|1532190636970|13位时间戳|
|seq|0|固定值;|
|skey|@crypt_jkde99da_b4xxxxxxxxxxxxxxx76d9yualp|同前面获取到的;|
服务器返回数据:
```javascript
{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
},
"MemberCount": 1,
"MemberList": [{
"Uin": 0,
"UserName": "weixin",
"NickName": "微信团队",
"HeadImgUrl": "/cgi-bin/mmwebwx-bin/webwxgeticon?seq=1&username=weixin&skey=@crypt_4fb399da_91a345e0be9deca5d61b183fc36a3a93",
"ContactFlag": 1,
"MemberCount": 0,
"MemberList": [],
"RemarkName": "",
"HideInputBarFlag": 0,
"Sex": 0,
"Signature": "微信团队官方帕啷",
"VerifyFlag": 56,
"OwnerUin": 0,
"PYInitial": "WXTD",
"PYQuanPin": "weixintuandui",
"RemarkPYInitial": "",
"RemarkPYQuanPin": "",
"StarFriend": 0,
"AppAccountFlag": 0,
"Statues": 0,
"AttrStatus": 4,
"Province": "",
"City": "",
"Alias": "",
"SnsFlag": 0,
"UniFriend": 0,
"DisplayName": "",
"ChatRoomId": 0,
"KeyWord": "wei",
"EncryChatRoomId": "",
"IsOwner": 0
}],
"Seq": 0
}
```
- BaseResponse.Ret为0表示请求成功。
- MemberCount表示联系人总数。
- MemberList表示联系人列表。这个列表中同时包含好友、群组、公众号。好友和公众号是通过ContactFlag来区分的1是好友2是群组3是公众号。
- User内部字段介绍
```javascript
"Uin": 0,
"UserName": 用户名称一个"@"为好友两个"@"为群组
"NickName": 昵称
"HeadImgUrl":头像图片链接地址
"ContactFlag": 1-好友 2-群组 3-公众号
"MemberCount": 成员数量只有在群组信息中才有效,
"MemberList": 成员列表,
"RemarkName": 备注名称
"HideInputBarFlag": 0,
"Sex": 性别0-未设置公众号保密1-2-
"Signature": 公众号的功能介绍 or 好友的个性签名
"VerifyFlag": 0,
"OwnerUin": 0,
"PYInitial": 用户名拼音缩写
"PYQuanPin": 用户名拼音全拼
"RemarkPYInitial":备注拼音缩写
"RemarkPYQuanPin": 备注拼音全拼
"StarFriend": 是否为星标朋友  0-  1-
"AppAccountFlag": 0,
"Statues": 0,
"AttrStatus": 119911,
"Province":
"City":
"Alias":
"SnsFlag": 17,
"UniFriend": 0,
"DisplayName": "",
"ChatRoomId": 0,
"KeyWord":
"EncryChatRoomId": ""
```
### 3.2、批量获取指定用户信息
然后可以看到批量获取指定联系人信息的 POST 请求:
```
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxbatchgetcontact?type=ex&r=1532246093335&lang=zh_CN&pass_ticket=AFsdZ7eHxxxxxxxxxxxxxxxxfr1vjHPn%253D
```
该请求用于批量获取好友信息,或者批量获取群聊中的成员信息。
URL参数分析
|参数名|示例值|描述|
|---|---|---|
|type|ex|不知道什么意思;|
|r|1532246093335|13位时间戳|
|lang|zh_CN|语言;|
|pass_ticket|AFsdZ7eHxxxxxxxxxxxxxxxxfr1vjHPn%253D|前面获取到的;|
POST的数据JSON
```javascript
{
"BaseRequest": {
"DeviceID": "e81xxxxxxxxx7686",
"Sid": "8rwxxxxxxxxxHq2P",
"Skey": "@crypt_jkde99da_b4xxxxxxxxxxxxxxx76d9yualp",
"Uin": "26xxx7"
},
"Count": 2,
"List": [
{
"EncryChatRoomId": "",
"UserName": "@@76feaa87c63576aaxxxxxxxxeaaa7030c60a09d33"
},
{
"ChatRoomId": "",
"UserName": "@@55664b9ab69bbe5e6aaxxxxxxxxx778c17e11e9dab09c9a1"
}
]
}
```
POST参数分析
|参数名|示例值|描述|
|---|---|---|
|BaseRequest||基本请求参数,同前面;|
|Count||要进行批量查询的用户数;|
|List||批量指定要查询的UserName的列表如果要获取好友信息EncryChatRoomId或ChatRoomId为空UserName为好友的UserName如果要获取群聊成员的信息EncryChatRoomId或ChatRoomId为群聊的UserNameUserName为成员的UserName。|
服务器返回数据:
```javascript
{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
},
"Count": 2,
"ContactList": [{
"Uin": 0,
"UserName": "@@76feaa87c635763438059aaeaaa7030c60a09d33",
"NickName": "一啣ç<span class=\"emoji emoji1f525\"></span>¾¤)",
"HeadImgUrl": "/cgi-bin/mmwebwx-bin/webwxgetheadimg?seq=704138898&username=@@76feaa87c635763438059aaeaaa7030c60a09d33&skey=",
"ContactFlag": 3,
"MemberCount": 80,
"MemberList": [{
"Uin": 0,
"UserName": "@3a13860046f9f5cac66faba26f2bd0537f535",
"NickName": "龎",
"AttrStatus": 2147437,
"PYInitial": "",
"PYQuanPin": "",
"RemarkPYInitial": "",
"RemarkPYQuanPin": "",
"MemberStatus": 0,
"DisplayName": "",
"KeyWord": ""
}, ...],
"RemarkName": "",
"HideInputBarFlag": 0,
"Sex": 0,
"Signature": "",
"VerifyFlag": 0,
"OwnerUin": 0,
"PYInitial": "",
"PYQuanPin": "",
"RemarkPYInitial": "",
"RemarkPYQuanPin": "",
"StarFriend": 0,
"AppAccountFlag": 0,
"Statues": 0,
"AttrStatus": 0,
"Province": "",
"City": "",
"Alias": "",
"SnsFlag": 0,
"UniFriend": 0,
"DisplayName": "",
"ChatRoomId": 0,
"KeyWord": "",
"EncryChatRoomId": "@5fd8877457351e3a697",
"IsOwner": 0
}, {
"Uin": 0,
"UserName": "@f7dee38d1c3626c0e421c1f66deac0906559ac",
"NickName": "尕娅",
"HeadImgUrl": "/cgi-bin/mmwebwx-bin/webwxgeticon?seq=686458815&username=@f7dee38d1c3626c0e421c1f66deac0906559ac&skey=",
"ContactFlag": 259,
"MemberCount": 0,
"MemberList": [],
"RemarkName": "啢潧",
"HideInputBarFlag": 0,
"Sex": 2,
"Signature": "ä½ è<span class=\"emoji emoji1f48b\"></span>",
"VerifyFlag": 0,
"OwnerUin": 0,
"PYInitial": "XY",
"PYQuanPin": "",
"RemarkPYInitial": "",
"RemarkPYQuanPin": "",
"StarFriend": 0,
"AppAccountFlag": 0,
"Statues": 0,
"AttrStatus": 1047,
"Province": "å京",
"City": "",
"Alias": "",
"SnsFlag": 49,
"UniFriend": 0,
"DisplayName": "",
"ChatRoomId": 0,
"KeyWord": "",
"EncryChatRoomId": "0",
"IsOwner": 0
}]
}
```
- ContactList即是获取到的指定的联系人信息。
### 3.3、修改联系人备注
当我们修改联系人备注的时候,会发现浏览器发送了如下 POST 请求:
```
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxoplog
```
POST的数据JSON
```javascript
{
"BaseRequest": {
"DeviceID": "e81xxxxxxxxx7686",
"Sid": "8rwxxxxxxxxxHq2P",
"Skey": "@crypt_jkde99da_b4xxxxxxxxxxxxxxx76d9yualp",
"Uin": "26xxx7"
},
"CmdId": 2,
"RemarkName": "新的备注名",
"UserName": "@07a2e8b4a1f98eb78a7xxxxxxxxxxxx5b7bc4908376xxx05917b"
}
```
POST参数分析
|参数名|示例值|描述|
|---|---|---|
|BaseRequest||基本请求参数,同其它;|
|CmdId|2|固定值;有可能还有其它值来表示不同类型操作。|
|RemarkName||新的备注名;|
|UserName||要修改的联系人的UserName|
服务器返回数据:
```javascript
{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
}
}
```
- BaseResponse.Ret表示操作成功。
## 4、收发消息
### 4.1、从服务端拉取新消息
我们发现2.4中的轮询请求每一次返回的数据中selector为2或者6时都会发生如下的 POST 请求来从服务端获取新消息:
```
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid=8rwxxxxxxxxxHq2P&skey=@crypt_jkde99da_b4xxxxxxxxxxxxxxx76d9yualp&pass_ticket=AFsdZ7eHxxxxxxxxxxxxxxxxfr1vjHPn%253D
```
URL参数分析
|参数名|示例值|描述|
|---|---|---|
|sid|8rwxxxxxxxxxHq2P|同前面获取的;|
|skey|@crypt_jkde99da_b4xxxxxxxxxxxxxxx76d9yualp|同前面获取的;|
|pass_ticket|AFsdZ7eHxxxxxxxxxxxxxxxxfr1vjHPn%253D|同前面获取的;|
POST的数据JSON
```javascript
{
"BaseRequest": {
"DeviceID": "e2089xxxxx902803",
"Sid": "8rwxxxxxxxxxHq2P",
"Skey": "@crypt_jkde99da_b4xxxxxxxxxxxxxxx76d9yualp",
"Uin": 26xxx7
},
"SyncKey": {
"Count": 4,
"List": [{
"Key": 1,
"Val": 704153081
},
{
"Key": 2,
"Val": 704153167
},
{
"Key": 3,
"Val": 704153152
},
{
"Key": 1000,
"Val": 1532180042
}
]
},
"rr": 1112687259
}
```
POST参数分析
|参数名|示例值|描述|
|---|---|---|
|BaseRequest|{<br>"DeviceID": "e81xxxxxxxxx7686",<br> "Sid": "8rwxxxxxxxxxHq2P",<br> "Skey": "@crypt_jkde99da_b4xxxxxxxxxxxxxxx76d9yualp",<br> "Uin": "26xxx7"<br>}|每一次POST请求都会发送<br>BaseRequest其中DeviceID是字母e拼上15位随机字符串其余三个都是前面获取到的认证信息。|
|SyncKey|{<br> "Count": ...,<br> "List": [...]<br>}|前一次获取到的SyncKey首次是初始化数据时获取的zhiy之后都是通过本请求更新|
服务端返回数据:
```javascript
{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
},
"AddMsgCount": 1,
"AddMsgList": [{
"MsgId": "462399962004142457",
"FromUserName": "@56a0a9xxxxxxxxxxxxx54w0dxxxxbfab",
"ToUserName": "@56a0a9xxxxxxxxxxxxx54w0dxxxxbfab",
"MsgType": 51,
"Content": "",
"Status": 3,
"ImgStatus": 1,
"CreateTime": 1532190642,
"VoiceLength": 0,
"PlayLength": 0,
"FileName": "",
"FileSize": "",
"MediaId": "",
"Url": "",
"AppMsgType": 0,
"StatusNotifyCode": 4,
"StatusNotifyUserName": "...",
"RecommendInfo": {
"UserName": "",
"NickName": "",
"QQNum": 0,
"Province": "",
"City": "",
"Content": "",
"Signature": "",
"Alias": "",
"Scene": 0,
"VerifyFlag": 0,
"AttrStatus": 0,
"Sex": 0,
"Ticket": "",
"OpCode": 0
},
"ForwardFlag": 0,
"AppInfo": {
"AppID": "",
"Type": 0
},
"HasProductId": 0,
"Ticket": "",
"ImgHeight": 0,
"ImgWidth": 0,
"SubMsgType": 0,
"NewMsgId": 462399962004142457,
"OriContent": "",
"EncryFileName": ""
}],
"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": 704153081
}, {
"Key": 2,
"Val": 704153169
}, {
"Key": 3,
"Val": 704153152
}, {
"Key": 11,
"Val": 704152941
}, {
"Key": 201,
"Val": 1532190642
}, {
"Key": 1000,
"Val": 1532190561
}, {
"Key": 1001,
"Val": 1532180114
}]
},
"SKey": "",
"SyncCheckKey": {
"Count": 7,
"List": [{
"Key": 1,
"Val": 704153081
}, {
"Key": 2,
"Val": 704153169
}, {
"Key": 3,
"Val": 704153152
}, {
"Key": 11,
"Val": 704152941
}, {
"Key": 201,
"Val": 1532190642
}, {
"Key": 1000,
"Val": 1532190561
}, {
"Key": 1001,
"Val": 1532180114
}]
}
}
```
- AddMsgCount为新消息数目。
- AddMsgList为新消息列表。
- MsgType说明
- 1文本消息
- 3图片消息
- 34语音消息
- 37VERIFYMSG验证消息
- 40POSSIBLEFRIEND_MSG可能的朋友的消息
- 42共享名片
- 43视频通话消息
- 47动画表情
- 48位置消息
- 49分享链接
- 50VOIPMSGVoIP消息
- 51微信初始化消息
- 52VOIPNOTIFYVoIP通知
- 53VOIPINVITEVoIP邀请
- 62小视频
- 9999SYSNOTICE系统通知
- 10000系统消息
- 10002撤回消息
- SyncKey会暂存起来作为下一次请求的参数。
### 4.2、发送消息
打开一个聊天界面,向好友发送一条消息,会发现产生如下 POST 请求:
```
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg?pass_ticket=AFsdZ7eHxxxxxxxxxxxxxxxxfr1vjHPn%253D
```
URL参数分析
|参数名|示例值|描述|
|---|---|---|
|pass_ticket|AFsdZ7eHxxxxxxxxxxxxxxxxfr1vjHPn%253D|同前面获取的;|
POST的数据JSON
```javascript
{
"BaseRequest": {
"DeviceID": "e57xxxxxxx94xx27",
"Sid": "8rwxxxxxxxxxHq2P",
"Skey": "@crypt_jkde99da_b4xxxxxxxxxxxxxxx76d9yualp",
"Uin": "26xxx7"
},
"Msg": {
"ClientMsgId": "15321964202620841",
"Content": "这里是消息内容",
"FromUserName": "@da9d7631177b3c54492954010eb7",
"LocalID": "15321964202620841",
"ToUserName": "@d946a2006c12e85deda45c26b8cd42dbd3f03fa67be",
"Type": 1
},
"Scene": 0
}
```
POST参数分析
|Key|示例值|描述|
|---|---|---|
|BaseRequest||同上;|
|Msg.ClientMsgId||同LocalID|
|Msg.Content||消息内容消息为媒体时该值为媒体ID。|
|Msg.FromUserName||发送用户;|
|Msg.LocalID||13位时间戳+4位随机数|
|Msg.ToUserName||接收用户;|
|Msg.Type|1|消息类型同3.1中接收的消息类型;|
|Scene|0|固定值;|
服务端返回数据:
```javascript
{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
},
"MsgID": "7650884298732299102",
"LocalID": "15321964202620841"
}
```
- LocalID是发送时指定的LocalID。
- MsgID是服务端的消息ID。
### 4.3、上传媒体到服务器
如果我们发送一个图片、文件等媒体类消息,会看到在发送消息请求前有如下 POST 请求:
```
https://file.wx.qq.com/cgi-bin/mmwebwx-bin/webwxuploadmedia?f=json
```
若文件较小则只会产生一个该请求若文件较大则会产生多个该请求。多个请求表示以分片的方式发送文件数据分片大小约为524288。
FORM表单参数分析
|参数名|示例值|描述|
|---|---|---|
|~~id~~|WU_FILE_0|页面文件组件ID非必须|
|~~name~~|bd00c8eed5c2cd522e69f38317b46903.jpg|文件名;非必须;|
|~~type~~|image/jpeg|文件的MimeType非必须|
|~~lastModifieDate~~||文件最后修改时间;非必须;|
|~~size~~|99785|文件大小;非必须;|
|chunks|3|文件分片数量;文件较大需要分片时必须;|
|chunk|0|文件分片序号从0开始文件较大需要分片时必须|
|mediatype|pic|文件类型图片为pic其它文件为doc非必须|
|uploadmediarequest||JSON字符串必须|
|webwx_data_ticket||cookie中的数据必须|
|pass_ticket||登录时获取的;必须;|
|filename||文件二进制数据;必须;|
uploadmediarequest结构示例
```json
{
"UploadType": 2,
"BaseRequest": {
"Uin": 1245,
"Sid": "zxaODbK4ed",
"Skey": "@crypt_4f399da_3c7a87e93b7872bce",
"DeviceID": "e69688819413"
},
"ClientMediaId": 153686311,
"TotalLen": 87508,
"StartPos": 0,
"DataLen": 87508,
"MediaType": 4,
"FromUserName": "@6feb88ee01067121479f686",
"ToUserName": "@6feb88ee0106f67121479f686",
"FileMd5": "717d1dbb9833c7cdbdd09ac"
}
```
服务端返回数据:
```json
{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
},
"MediaId": "@crypt_17ab5.................39bd9cfa9ab",
"StartPos": 99785,
"CDNThumbImgHeight": 56,
"CDNThumbImgWidth": 100,
"EncryFileName": "bd00c8e.....38317b46903.jpg"
}
```
上传成功后返回数据中会有MediaId如果是分片上传的则最后一个请求会返回MediaId。
### 4.4、发送图片消息
发送图片后紧接着4.3的是如下POST请求
```
https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsgimg?fun=async&f=json&lang=zh_CN&pass_ticket=xFAjPcq0eXh.......TYHHdHgVL52eHo%253D
```
URL参数分析
|数名|示例值|描述|
|---|---|---|
|pass_ticket|xFAjPcq0eXh.......TYHHdHgVL52eHo%253D|同前面获取的;|
POST的数据JSON
```json
{
"BaseRequest": {
"Uin": 16...245,
"Sid": "KvCP..../TNqh8",
"Skey": "@crypt_4fb399da......9f1b3d997c4b5eef82",
"DeviceID": "e2825...3652448"
},
"Msg": {
"Type": 3,
"MediaId": "@crypt_17ab5.................39bd9cfa9ab",
"Content": "",
"FromUserName": "@3641f45.......69bed57642",
"ToUserName": "@3641f454....9bed57642",
"LocalID": "153691....0527",
"ClientMsgId": "1536....390527"
},
"Scene": 0
}
```
POST参数分析
|Key|示例值|描述|
|---|---|---|
|BaseRequest||同上;|
|Msg.ClientMsgId||同LocalID|
|Msg.Content||消息内容消息为媒体时该值为媒体ID。|
|Msg.FromUserName||发送用户;|
|Msg.LocalID||13位时间戳+4位随机数|
|Msg.ToUserName||接收用户;|
|Msg.Type|3|消息类型同3.1中接收的消息类型;|
|Msg.MediaId||4.3接口中返回的MediaId|
|Scene|0|固定值;|
服务端返回数据:
```json
{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
},
"MsgID": "28832......8291836",
"LocalID": "1536.....54390527"
}
```
Web微信发送图片需要先调4.3的接口将媒体文件上传到服务器然后再调4.4的接口发送图片的相关信息。