C++微信网页协议实现和应用
微信推送报警消息实现
目录
1 前言... 2
1.1 背景... 2
1.2 现有技术对比... 2
2 总体流程... 2
3 微信网页接口解析... 3
3.1 获取用户uuid. 3
3.2 获取二维码图片... 4
3.3 轮询检测用户是否登录... 4
3.4 重定向url登录微信并获取公参... 5
3.5 微信初始化... 5
3.6 获取联系人列表... 11
3.7 批量获取联系人详情... 13
3.8 检测是否有微信消息... 16
3.9 获取最新消息... 17
3.10 通过微信推送报警消息... 22
3.11 上传文件到微信服务器... 24
3.12 发送图片... 27
4 一些状态码code值的说明... 28
4.1 BaseResponse里的Ret 28
4.2 同步消息检查返回值中retcode和selector 28
4.3 返回消息类型... 29
5 实现操作步骤... 30
6 技术制约... 32
7 技术应用推广... 32
1 前言
1.1 背景
微信已经普遍被大家应用,而且手机微信方便快捷,可以随时随地的接受消息。目前项目中有需求通过微信推送报警消息。但是微信没有对外接口,无法实现报警推送。微信的方便快捷没有办法使用。可以通过微信的网页接口来实现微信的登录、获取好友信息、发送微信消息、获取微信消息等;
1.2 现有技术对比
现有的技术主要是通过电脑客户端、或者手机客户端去接收报警,电脑客户端只能在电脑上查看,不够方便快捷。而手机客户端需要开发对应手机系统的app,还要经过复杂的传输协议。开发周期长,实现复杂。而且需要安装特定的app才可以接收报警。报警接收和发送不够方便快捷。而通过微信的网页端口去推送报警,可以实现报警的方便推送,报警可以发到微信用户、微信群、微信公众号。
2 总体流程
微信网页接口的调用流程如图2-1所示,
(1) 首先要获取用户UUID,用标识一个用户;
(2) 然后将UUID作为参数,获取用户登录扫描的二维码,然后等待用户去扫描二维码;
(3) 用户扫描之后,二维码变成用户的头像;轮循去查看用户是否点击登录按钮;
(4) 用户登录之后,会返回一个重定向的URL,作为用户的登录URL;
用URL去登录微信服务器,返回用户的key值、用户id、用户标识id、cookie
(5) 调用初始化的接口,初始化微信主界面,首页用户信息,登录用户自己的用户信息,检测是否有人发消息过来的键值组。每个键值针对不同的消息;
(6) 获取所有好友、微信群、公众号的信息;
(7) 查询服务器是否有微信消息发给登录用户,包括微信通讯消息,好友修改备注消息等。解析消息协议,显示在窗口中;
(8) 指定用户发送微信消息;也可以将报警消息通过微信发送接口进行发送;
图2-1 微信接口调用流程
3 微信网页接口解析
3.1 获取用户uuid
- 说明:用于获取显示二维码以及登录所需的uuid,标识获取二维码和扫码的为同一个用户
- 请求方式:GET
- 地址:https://login.wx.qq.com/jslogin?appid=wx782c26e4c19acffb&fun=new&lang=zh_CN
- get参数:
参数 |
示例值 |
说明 |
appid |
wx782c26e4c19acffb |
固定值 |
fun |
new |
固定值 |
lang |
zh_CN |
表示中文字符集 |
- 返回:
window.QRLogin.code = 200; window.QRLogin.uuid = "wb7R2kx9dA==";
3.2 获取二维码图片
- 说明:展示一张用于登陆的二维码图片,地址里的{uuid}传第一步所获取的uuid
- 请求方式:GET
- 地址:https://login.wx.qq.com/qrcode/{uuid}
- get参数:
参数 |
示例值 |
说明 |
t |
webwx |
固定值 |
- 返回:二维码的二进制流,浏览器打开会直接显示一张二维码图片,客户端需要保存到本地文件,然后用label加载显示;
3.3 轮询检测用户是否登录
- 说明:尝试登录。若此时用户手机已完成扫码并点击登录,则返回一个真正用于登录的url地址。否则接口大概10s后返回未扫码或未登录的状态码
- 请求方式:GET
- 地址:https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login
- get参数:
参数 |
示例值 |
说明 |
tip |
1 |
1:未扫描 0:一扫描 |
uuid |
wb7R2kx9dA== |
第一步所获取的uuid |
- 返回:redirect_uri的值可以直接用于下一步的“登录并获取公参”请求
window.code=200(408为未扫码,201为已扫码但未点击登录,200为成功登录);window.redirect_uri="https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=AfrMMbhsnElmA7xc1R9CWUq-@qrticket_0&uuid=4ZnG7WZ0Cg==&lang=zh_CN&scan=1520738372";
3.4 重定向url登录微信并获取公参
- 说明:访问后可获取一组公参,用于之后访问所有的接口。这也意味着如果这部分数据泄露,代表其他人可以在这段时间内随意操作你的微信(仅限于网页版支持的操作)
- 请求方式:GET
- 地址:https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage
- get参数:直接用上一步返回的redirect_uri中的所有参数即可
- 返回:获取并存储该返回值中的四个参数skey、wxsid、wxuin、pass_ticket,返回cookie保存到本地文件中,下面有接口调用时需要带上这个cookie文件。
返回结果:
<error>
<ret>0</ret>
<message></message>
<skey>@crypt_8b4f09cc_a5871dc10130a48703b9afd5602152e4</skey>
<wxsid>+urBrYI292xoIknf</wxsid>
<wxuin>211722515</wxuin>
<pass_ticket>qg%2BL%2BfjNnoHyqYsL3xj0KoNi5nqchsInPWWSxDwqCJ8%3D</pass_ticket>
<isgrayscale>1</isgrayscale>
</error>
3.5 微信初始化
- 说明:初始化微信首页栏的联系人、公众号等(不是通讯录里的联系人),初始化登录者自己的信息(包括昵称等),初始化同步消息所用的SycnKey
- 请求方式:POST
- 地址:https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit
- get参数:
参数 |
示例值 |
说明 |
pass_ticket |
qg%2BL%2BfjNnoHyqYsL3xj0KoNi5nqchsInPWWSxDwqCJ8%3D |
公参中的值 |
- post参数:(json格式)
{
BaseRequest: {
Uin: 211722515,
Sid: +urBrYI292xoIknf,
Skey: @crypt_8b4f09cc_a5871dc10130a48703b9afd5602152e4,
DeviceID: e545297464380306
上边的DeviceID可以用如下代码生成,每次登录过程中保持一致。String DeviceID = "e" + String.valueOf(new Random().nextLong()).substring(1, 16);
}
}
- 返回:获取并存储该返回值中的四个参数skey、wxsid、wxuin、pass_ticket,以及所返回Cookie中的webwx_data_ticket,webwx_auth_ticket
{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
},
"Count": 11,
"ContactList": [{微信首页的联系人,不是保存在通讯录中的联系人
"Uin": 0,
"UserName": "filehelper",
"NickName": "文件传输助手",
"HeadImgUrl": "/cgi-bin/mmwebwx-bin/webwxgeticon?seq=680769514&username=filehelper&skey=@crypt_8b4f09cc_a5871dc10130a48703b9afd5602152e4",
"ContactFlag": 1,
"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
},
......此处省略剩下的10个联系人信息
],
"SyncKey": { 同步消息时用的syncKey,用于之后轮询消息的接口
"Count": 4,
"List": [{
"Key": 1,
"Val": 700722177
}, {
"Key": 2,
"Val": 700723184
}, {
"Key": 3,
"Val": 700723136
}, {
"Key": 1000,
"Val": 1520723642
}]
},
"User": { 登录者的信息
"Uin": 211722515,
"UserName": "@f4c054c78f40743b095b85409dbdc1b3", 微信随机码,每个联系人和群都有,每次登录由微信端随机分配
"NickName": "测试微信号的昵称",
"HeadImgUrl": "/cgi-bin/mmwebwx-bin/webwxgeticon?seq=1730335888&username=@f4c054c78f40743b095b85409dbdc1b3&skey=@crypt_8b4f09cc_a5871dc10130a48703b9afd5602152e4",
"RemarkName": "",
"PYInitial": "",
"PYQuanPin": "",
"RemarkPYInitial": "",
"RemarkPYQuanPin": "",
"HideInputBarFlag": 0,
"StarFriend": 0,
"Sex": 1,
"Signature": "这里是签名",
"AppAccountFlag": 0,
"VerifyFlag": 0,
"ContactFlag": 0,
"WebWxPluginSwitch": 0,
"HeadImgFlag": 1,
"SnsFlag": 17
},
"ChatSet": "filehelper,weixin,@52d5b97ca1bed2d76b405fba4c4ded6c893bd6b28cc514344dd9a7d8cd766286,@4baf3160e84b9e726efd1a0629d16b01,@@54a4fd2c81875aac779935330b67bf7905793bb66da9c6d4029f18f4927b3c1c,@@9542a551bfcafe1ae83b931d21b318573c8c6e2c67f3eaef189e7e9179cdb2d1,@ac3532106e21aa250cc746055a0c72d5,@d593e5745931641d060cdc9fcda5d996,@34f12e07290f62677137181998bf4c1eb0a9c128f2355562e8cc7967d0f9a044,@@31e445167b2fd23404b672f6f1a4a805fffbd369d6bae8efe959240a6c50cf46,@@c5fa6cb3779e217b5ae3e9b3d53faef09d6cde9615106ebe0a115de38976c7fc,@513fcb83ccc696b9d90206f0e80eb8e341e35e1f464b08446795132d180db040,@@b944058f6fd91b850867bb1f534205e86460b4b3a947f4ca4bd49109e532116f,@@859e98412d1faf03abdf784e97ed66b25c52dccc7ec446d681b2906525262fcd,@257fb1c805c1429ca45a737143d7a7e1302487d9bbb268bf2dd8a564bf814186,filehelper,@@dc3e7f04b1ccead2ecf8c50eaa476d6c71dc3f7396696be0724002e1ee228812,@@d1758feb60b1ff7ad262b8fb05ee9f1c1821722a0376a1431cee351c75cbebc3,@@e49ba13661221be9c9f81fb952391754ee74f98d2457f46364bdb745943b2bfc,@@a5cdd9eb797807cc081bc0e3ab3f101c9dc18d86d527c5defed8e8fd9010ec06,@@dfab3cde2a39ccdf31da803381528f130dae207583a5c088514bf4e1a0af49ab,@@13776e6ea475a8e86a46e4f242917db146664572e910dcca976047cb31e660f4,@@d1999c210e6f9a19d28b4a8fcc391a7b612c9765ff5bd078aaa022e1cc8bbf5c,",
"SKey": "@crypt_8b4f09cc_ce5178b3c156048fff69cdf1fccc31e4",
"ClientVersion": 637927733,
"SystemTime": 1520742050,
"GrayScale": 1,
"InviteStartCount": 40,
"MPSubscribeMsgCount": 1,
"MPSubscribeMsgList": [{
"UserName": "@4baf3160e84b9e726efd1a0629d16b01",
"MPArticleCount": 1,
"MPArticleList": [{
"Title": "不动手就能逛淘宝,这又是什么“黑科技”?英国小哥表示:中文说得溜就是这么方便! | 解码新时代",
"Digest": "张口说话就能逛淘宝,沉溺“黑科技”的英国小哥表示不想回家了!",
"Cover": "http://mmbiz.qpic.cn/mmbiz_jpg/8vd2Hk2TS2Pfibh9ILZKicg5icBlWKHBIVibVM8Vupsg3NsfSnibzptB9XQxArqzFmfOw7nlk6ByTdNvWBoBf4NjVmQ/640?wxtype=jpeg&wxfrom=0",
"Url": "http://mp.weixin.qq.com/s?__biz=MjM5MzI3NTI2MA==&mid=2651224106&idx=1&sn=0a5772013ae7c14dd9ac854f30fad934&chksm=bd6b54398a1cdd2f6f9c1d61c93aa3248968b8b56206a0af85341f510322b21548c975d8ebba&scene=0#rd"
}],
"Time": 1520732033,
"NickName": "中国日报双语新闻"
}],
"ClickReportInterval": 600000
}
3.6 获取联系人列表
- 说明:获取手机通讯录中的所有联系人(包括人、群、公众号等)
- 请求方式:POST
- 地址:https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact
- get参数:
参数 |
示例值 |
说明 |
pass_ticket |
yp5RfCpb%2FsNVex0Uepn1BWXNCYCqTfqe8NOYzan%2B4Y4%3D |
公参中的值 |
skey |
@crypt_8b4f09cc_1b827f84b1535b6be801f00427499050 |
公参中的值 |
- post参数:
{
"BaseRequest": {均是公参中的值
"Uin": 211722515,
"Sid": "+FhlgkGS3wD/GKQw",
"Skey": "@crypt_8b4f09cc_1b827f84b1535b6be801f00427499050",
"DeviceID": "e609547902722302"
}
}
- 返回:所有通讯录中的联系人信息,主要在MemberList中查看
{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
},
"MemberCount": 771,
"MemberList": [{
"Uin": 0,
"UserName": "@9c30c8d81e75a7eff0603cdd5de860b18fe92995845473fc2f0cda6ed76053cb",(微信随机码,潜规则:前面@为联系人,@@为群)
"NickName": "Nandi Wardhana",(联系人的微信昵称)
"HeadImgUrl": "/cgi-bin/mmwebwx-bin/webwxgeticon?seq=620986971&username=@9c30c8d81e75a7eff0603cdd5de860b18fe92995845473fc2f0cda6ed76053cb&skey=@crypt_8b4f09cc_1b827f84b1535b6be801f00427499050",
"ContactFlag": 3,
"MemberCount": 0,(如果是群,该字段表示成员数量)
"MemberList": [],(群成员列表)
"RemarkName": "",(备注名称,如果空则说明没有给他备注)
"HideInputBarFlag": 0,
"Sex": 1,(性别,1为男,2为女)
"Signature": "Stay young naturally...",(签名)
"VerifyFlag": 0,(用来判断是否是公众号或服务号的字段)
"OwnerUin": 0,
"PYInitial": "NANDIWARDHANA",
"PYQuanPin": "NandiWardhana",(名字拼音全拼)
"RemarkPYInitial": "",
"RemarkPYQuanPin": "",
"StarFriend": 0,
"AppAccountFlag": 0,
"Statues": 0,
"AttrStatus": 2359303,
"Province": "Jakarta Raya",(省份)
"City": "",(城市)
"Alias": "",
"SnsFlag": 17,
"UniFriend": 0,
"DisplayName": "",(如果是群内成员,该字段表示群内名称)
"ChatRoomId": 0,
"KeyWord": "",
"EncryChatRoomId": "",(如果是群,该字段表示群的id,不同于微信随机码@@那个)
"IsOwner": 0
},
... 此处省略剩下770个联系人信息
]
}
3.7 批量获取联系人详情
- 说明:批量获取联系人详情,人或群均可。获取群详情主要是获取群内联系人列表。获取人详情主要是获取群内的某个人的详细信息。
- 请求方式:POST
- 地址:https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxbatchgetcontact
- get参数:
参数 |
示例值 |
说明 |
pass_ticket |
yp5RfCpb%2FsNVex0Uepn1BWXNCYCqTfqe8NOYzan%2B4Y4%3D |
公参中的值 |
type |
ex |
我也不知道这是啥意思 |
- post参数:
{
"BaseRequest": {
"Uin": 211722515,
"Sid": "+FhlgkGS3wD/GKQw",
"Skey": "@crypt_8b4f09cc_1b827f84b1535b6be801f00427499050",
"DeviceID": "e862192966399662"
},
"Count": 2,
"List": [{ 这里表示需要获取详情的所有联系人
"UserName": "@@e203c90e07d64242336d573acd4a1db1c01ccb92ca05410444a3003c282c21db",
"EncryChatRoomId": ""
},
{
"UserName": "@ba194a63575be7fd0f4ea4e4547b2942d0dccc7fffc00ef5a6d141f93adb7739",
"EncryChatRoomId": ""
}
]
}
- 返回:
{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
},
"Count": 2,
"ContactList": [{
"Uin": 0,
"UserName": "@ba194a63575be7fd0f4ea4e4547b2942d0dccc7fffc00ef5a6d141f93adb7739",
"NickName": "张三丰",
"HeadImgUrl": "/cgi-bin/mmwebwx-bin/webwxgeticon?seq=680786093&username=@ba194a63575be7fd0f4ea4e4547b2942d0dccc7fffc00ef5a6d141f93adb7739&skey=",
"ContactFlag": 3,
"MemberCount": 0,
"MemberList": [],
"RemarkName": "丰哥",
"HideInputBarFlag": 0,
"Sex": 2,
"Signature": "<span class=\"emoji emoji2600\"></span> 一定会找到<span class=\"emoji emoji1f31b\"></span>",
"VerifyFlag": 0,
"OwnerUin": 0,
"PYInitial": "ZSF",
"PYQuanPin": "zhangsanfeng",
"RemarkPYInitial": "FG",
"RemarkPYQuanPin": "fengge",
"StarFriend": 0,
"AppAccountFlag": 0,
"Statues": 0,
"AttrStatus": 111719,
"Province": "北京",
"City": "平谷",
"Alias": "",
"SnsFlag": 17,
"UniFriend": 0,
"DisplayName": "",
"ChatRoomId": 0,
"KeyWord": "",
"EncryChatRoomId": "0",
"IsOwner": 0
}
...此处省略第二个联系人信息
]
}
3.8 检测是否有微信消息
- 说明:同步消息检查。这里只做检查不做同步,如果检查出有新消息,再掉具体同步的接口。
- 请求方式:GET,需要传入获取到的cookie,否则失败
- 地址:https://webpush2.weixin.qq.com/cgi-bin/mmwebwx-bin/synccheck
- get参数:
参数 |
示例值 |
说明 |
deviceid |
e547171618594402 |
参考5中的生成方式 |
sid |
+FhlgkGS3wD/GKQw |
公参中的值 |
skey |
@crypt_8b4f09cc_1b827f84b1535b6be801f00427499050 |
公参中的值 |
synckey |
1_700722177|2_700724323|3_700724315|1000_1520925834 |
微信初始化后获取的4个key,这些key会随着每次获取最新消息(参见9)后的返回值更新,其目的在于每次同步消息后记录一个当前同步的状态。 |
uin |
211722515 |
公参中的值 |
- 返回:
window.synccheck={retcode:"0",selector:"2"}
retcode
SUCCESS("0", "成功"),
TICKET_ERROR("-14", "ticket错误"),
PARAM_ERROR("1", "传入参数错误"),
NOT_LOGIN_WARN("1100", "未登录提示"),
NOT_LOGIN_CHECK("1101", "未检测到登录"),
COOKIE_INVALID_ERROR("1102", "cookie值无效"),
LOGIN_ENV_ERROR("1203", "当前登录环境异常,为了安全起见请不要在web端进行登录"),
TOO_OFEN("1205", "操作频繁");
selector
NORMAL("0", "正常"),
NEW_MSG("2", "有新消息"),
MOD_CONTACT("4", "有人修改了自己的昵称或你修改了别人的备注"),
ADD_OR_DEL_CONTACT("6", "存在删除或者新增的好友信息"),
ENTER_OR_LEAVE_CHAT("7", "进入或离开聊天界面");
3.9 获取最新消息
- 说明:当同步检查接口显示有新消息时,调用该接口获取具体的新消息。此处的新消息为广义的,包括消息,修改群名,群内成员变化,加好友等。
- 请求方式:POST,需要传入获取到的cookie,否则失败
- 地址:https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync
- get参数:
参数 |
示例值 |
说明 |
sid |
+FhlgkGS3wD/GKQw |
公参中的值 |
skey |
@crypt_8b4f09cc_1b827f84b1535b6be801f00427499050 |
公参中的值 |
uin |
211722515 |
公参中的值 |
- post参数:
{
"BaseRequest": {
"Uin": 211722515,
"Sid": "+FhlgkGS3wD/GKQw",
"Skey": "@crypt_8b4f09cc_1b827f84b1535b6be801f00427499050",
"DeviceID": "e304534670317808"
},
"SyncKey": {
"Count": 4,
"List": [{
"Key": 1,
"Val": 700722177
}, {
"Key": 2,
"Val": 700724323
}, {
"Key": 3,
"Val": 700724315
}, {
"Key": 1000,
"Val": 1520925834
}]
},
"rr": -508959981 String.valueOf(-new Date().getTime() / 1000)
}
- 返回:主要有AddMsgList,ModContactList,DelContactList,新一轮消息同步的检测消息的键值SyncCheckKey ,新一轮获取消息的synckey
{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
},
"AddMsgCount": 1, 新增信息
"AddMsgList": [{
"MsgId": "320984672637990367", 服务端返回的消息id,可用于撤回接口参数。如果是图片,该参数还可以作为调用微信获取图片接口的参数之一。
"FromUserName": "@abf90232027117affa7f0c0df3d1bf20", 发消息的人
"ToUserName": "@abf90232027117affa7f0c0df3d1bf20", 发给谁
"MsgType": 51, 消息类型,1为文字,3为图片...,具体请参照消息类型表
"Content": "",
"Status": 3,
"ImgStatus": 1,
"CreateTime": 1520927383,
"VoiceLength": 0,
"PlayLength": 0,
"FileName": "",
"FileSize": "",
"MediaId": "",
"Url": "",
"AppMsgType": 0,
"StatusNotifyCode": 4,
"ForwardFlag": 0,
"AppInfo": {
"AppID": "",
"Type": 0
},
"HasProductId": 0,
"Ticket": "",
"ImgHeight": 0,
"ImgWidth": 0,
"SubMsgType": 0,
"NewMsgId": 320984672637990367,
"OriContent": "",
"EncryFileName": ""
}],
"ModContactCount": 0, 联系人修改
"ModContactList": [],
"DelContactCount": 0, 联系人删除
"DelContactList": [],
"ModChatRoomMemberCount": 0, 群内成员变动
"ModChatRoomMemberList": [],"ContinueFlag": 0,
"SyncKey": { 新一轮消息更新用这些SyncKey
"Count": 7,
"List": [{
"Key": 1,
"Val": 700722177
}, {
"Key": 2,
"Val": 700724325
}, {
"Key": 3,
"Val": 700724315
}, {
"Key": 11,
"Val": 700724093
}, {
"Key": 201,
"Val": 1520927383
}, {
"Key": 1000,
"Val": 1520925834
}, {
"Key": 1001,
"Val": 1520917874
}]
},
"SKey": "",
"SyncCheckKey": { 新一轮消息检测用这些Key
"Count": 7,
"List": [{
"Key": 1,
"Val": 700722177
}, {
"Key": 2,
"Val": 700724325
}, {
"Key": 3,
"Val": 700724315
}, {
"Key": 11,
"Val": 700724093
}, {
"Key": 201,
"Val": 1520927383
}, {
"Key": 1000,
"Val": 1520925834
}, {
"Key": 1001,
"Val": 1520917874
}]
}
}
3.10 通过微信推送报警消息
- 说明:发送文本消息(包括表情),不能发送图片或文件。
- 请求方式:POST,需要传入获取到的cookie,否则失败
- 地址:https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg
- get参数:
参数 |
示例值 |
说明 |
pass_ticket |
yp5RfCpb%2FsNVex0Uepn1BWXNCYCqTfqe8NOYzan%2B4Y4%3D |
公参中的值 |
- post参数:
{
"BaseRequest": {
"Uin": 211722515,
"Sid": "+FhlgkGS3wD/GKQw",
"Skey": "@crypt_8b4f09cc_1b827f84b1535b6be801f00427499050",
"DeviceID": "e107694022625701"
},
"Msg": {
"Type": 1,
"Content": "呵呵",
"FromUserName": "@abf90232027117affa7f0c0df3d1bf20",
"ToUserName": "filehelper",
"LocalID": "15209344559450477", 时间戳左移4位随后补上4位随机数
"ClientMsgId": "15209344559450477"
"MediaId": "" 如果是图片才传这个值
},
"Scene": 0
}
- 返回:
{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
},
"MsgID": "7615282929538795099", 服务端返回的消息id,可用于撤回等接口的参数
"LocalID": "15209344559450477" 本地的消息id,是你自己发请求时的参数
}
3.11 上传文件到微信服务器
- 说明:发送图片时需要先调用该接口将图片上传至微信服务器,微信会返回一个图片的id,发送消息时携带该id即可发送图片。
- 请求方式:POST(此处的Content-Type应该设置为multipart/form-data; boundary=…------------------41184676334)
- 地址:https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxuploadmedia
- get参数:
参数 |
示例值 |
说明 |
pass_ticket |
yp5RfCpb%2FsNVex0Uepn1BWXNCYCqTfqe8NOYzan%2B4Y4%3D |
公参中的值 |
- post参数:
-----------------------------41184676334
Content-Disposition: form-data; name="id" 此处随意
WU_FILE_0
-----------------------------41184676334
Content-Disposition: form-data; name="name" 图片名称
Desert.jpg
-----------------------------41184676334
Content-Disposition: form-data; name="type" 图片类型
image/jpeg
-----------------------------41184676334
Content-Disposition: form-data; name="lastModifiedDate" 发送时间,该参数可无
Tue Jul 14 2009 13:32:31 GMT+0800
-----------------------------41184676334
Content-Disposition: form-data; name="size" 图片大小
845941
-----------------------------41184676334
Content-Disposition: form-data; name="chunks" 总共分多少批上传
2
-----------------------------41184676334
Content-Disposition: form-data; name="chunk" 当前是第几批
0
-----------------------------41184676334
Content-Disposition: form-data; name="mediatype" 当传图片时,此处写pic
pic
-----------------------------41184676334
Content-Disposition: form-data; name="uploadmediarequest"
{
"UploadType": 2, 固定为2
"BaseRequest": {
"Uin": 211722515,
"Sid": "+FhlgkGS3wD/GKQw",
"Skey": "@crypt_8b4f09cc_1b827f84b1535b6be801f00427499050",
"DeviceID": "e787605163473377"
},
"ClientMediaId": 1520935168955,
"TotalLen": 845941, 文件大小
"StartPos": 0,
"DataLen": 845941, 文件大小
"MediaType": 4, 固定为4,表示图片
"FromUserName": "@abf90232027117affa7f0c0df3d1bf20", 该参数可填可不填
"ToUserName": "filehelper", 该参数可填可不填
"FileMd5": "ba45c8f60456a672e003a875e469d0eb" 该参数随机一个uuid即可
}
-----------------------------41184676334
Content-Disposition: form-data; name="webwx_data_ticket"
gSenocajd7UaXQesCD3smJ5p
-----------------------------41184676334
Content-Disposition: form-data; name="pass_ticket"
yp5RfCpb/sNVex0Uepn1BWXNCYCqTfqe8NOYzan+4Y4=
-----------------------------41184676334
Content-Disposition: form-data; name="filename"; filename="Desert.jpg"
Content-Type: application/octet-stream
此处为该文件的流,前端写成<input type="file">就是这个效果
- 返回:可能分批次上传,最后上传成功时返回如下结果
{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
},
下面的MediaId参数,作为下一步发送图片接口的入参,就可以发送该图片了
"MediaId": "@crypt_14402eb3_bb9eee20e7239fcd3323a0ea5a36cfd5e7fd162b72e03088efa4f63f53219c6f672c6be3ec1865291a70f38bb82bc5bf1d42166996b4a0313abe95454bff0316c19bfd29b71f4f98ccb7d301eed7b74995e35eabfd3f8264a3d684b8e9f08485ad00c3955cdc5b60ac96e67a9ca24bf7a01b9363ae0364f75fa0c9e6235e2dc91aef95b34c71c503deada9898a28ce5bf13d908f7834f7cae427aaba68aff5500125314f73b79f5a63103d430aa162420262e3d1a5e5f110cba0f2ee20017aaf0f127303153dcf63f9e5a56ff8c64f5dfb3f229011374b34fe7a905b0ee055d85b76827e2e68b8947c7b5fcd56c98ede9f012b6160a193762f63842886dca36872727db0c3cd4761af96c56bfdfb0a42630fee9954c764b5cd31f6ff666649b028bb1852366e639e1008cee678d5e587aabbe78014307ae1fbe638e2c0b52115",
"StartPos": 845941,
"CDNThumbImgHeight": 75,
"CDNThumbImgWidth": 100,
"EncryFileName": "Desert.jpg"
}
3.12 发送图片
- 说明:上一步上传文件到微信服务器成功后,调用该发送图片接口。
- 请求方式:POST
- 地址:https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsgimg
- get参数:
参数 |
示例值 |
说明 |
pass_ticket |
yp5RfCpb%2FsNVex0Uepn1BWXNCYCqTfqe8NOYzan%2B4Y4%3D |
公参中的值 |
fun |
async |
- post参数:同发文本消息,只是多一个MediaId
- 返回:同发文本消息
15、获取图片
- 说明:上一步上传文件到微信服务器成功后,调用该发送图片接口。
- 请求方式:GET
- 地址:https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsgimg
- get参数:
参数 |
示例值 |
说明 |
MsgID |
3176600141007621447 |
服务端返回的消息id |
skey |
@crypt_8b4f09cc_1b827f84b1535b6be801f00427499050 |
公参中的值 |
type |
slave |
该参数有则为缩略图,没有则为原图 |
- 携带3个cookie的值:wxuin,wxsid,webwx_data_ticket
- 返回:图片的流
4 一些状态码code值的说明
4.1 BaseResponse里的Ret
SUCCESS("0", "成功"),
TICKET_ERROR("-14", "ticket错误"),
PARAM_ERROR("1", "传入参数错误"),
NOT_LOGIN_WARN("1100", "未登录提示"),
NOT_LOGIN_CHECK("1101", "未检测到登录"),
COOKIE_INVALID_ERROR("1102", "cookie值无效"),
LOGIN_ENV_ERROR("1203", "当前登录环境异常,为了安全起见请不要在web端进行登录"),
TOO_OFEN("1205", "操作频繁");
4.2 同步消息检查返回值中retcode和selector
retcode
SUCCESS("0", "成功"),
TICKET_ERROR("-14", "ticket错误"),
PARAM_ERROR("1", "传入参数错误"),
NOT_LOGIN_WARN("1100", "未登录提示"),
NOT_LOGIN_CHECK("1101", "未检测到登录"),
COOKIE_INVALID_ERROR("1102", "cookie值无效"),
LOGIN_ENV_ERROR("1203", "当前登录环境异常,为了安全起见请不要在web端进行登录"),
TOO_OFEN("1205", "操作频繁");
selector
NORMAL("0", "正常"),
NEW_MSG("2", "有新消息"),
MOD_CONTACT("4", "有人修改了自己的昵称或你修改了别人的备注"),
ADD_OR_DEL_CONTACT("6", "存在删除或者新增的好友信息"),
ENTER_OR_LEAVE_CHAT("7", "进入或离开聊天界面");
4.3 返回消息类型
TEXT(1, "文本消息类型"),
IMAGE(3, "图片消息"),
VOICE(34, "语音消息"),
VIDEO(43, "小视频消息"),
MICRO_VIDEO(62, "短视频消息"),
EMOTI_CON(47, "表情消息"),
MEDIA(49, "多媒体消息"),
VOIP_MSG(50, ""),
VOIP_NOTIFY(52, ""),
VOIP_INVITE(53, ""),
LOCATION(48, ""),
STATUS_NOTIFY(51, "状态通知,自己访问了某一个聊天页面"),
SYS_NOTICE(9999, ""),
POSSIBLE_FRIEND_MSG(40, ""),
VERIFY_MSG(37, "好友请求"),
SHARE_CARD(42, "分享名片"),
SYS(10000, "系统消息"),
RECALLED(10002, "撤回消息");
5 实现操作步骤
(1)开发QT界面,点击重新登录按钮,下载二维码,等待用户扫描;
(2)用手机扫描二维码,登录微信;
登录成功之后,选择要发送的微信用户、文件传输助手、微信群、公众号等。勾选是否推送到微信复选框,表示是否要发送到微信,修改好之后点击保存按钮。默认情况是发给文件传输助手,然后点击测试发送。看是否能够发送成功。心跳发送按钮是每隔一分钟发送一条时间消息,让你知道通讯连接正常,测试用的。没有实际的作用。由于微信的限制,无法自己发给自己,发给文件传输助手、微信群、微信公众号,自己只能显示消息,手机端不会出现屏幕消息提示。所以最好有两个手机账号,一个登陆发送,一个接收消息。因为微信同时只能登录一个网页端或者window的客户端,所以微信登录了之后,不能再去登录网页或者客户端,否则会挤掉登录,导致发送失败。
(3)在手机端查看微信,可以查看到报警推送消息,电脑客户端的报警消息会同步推送到手机指定用户。
(4)如上图所示,为了避免报警消息打扰到用户,当用户不想接收报警消息时,登录发送报警的用户或者接受报警消息的用户,都可以在手机微信上通过反向控制命令:QStockView:Stop(或者QStockView:停止)停止接收报警消息,也可以通过反向控制命令QStockView:Start(或者QStockView:开始)来开始接收报警消息;不区分大小写,中间不能有空格,否则命令无效。发送命令成功之后,会返回一个通知消息。表示命令发送成功。
6 技术制约
由于微信的限制,无法自己发给自己,发给文件传输助手、微信群、微信公众号,自己只能显示消息,手机端不会出现屏幕消息提示。所以最好有两个手机账号,一个登陆发送,一个接收消息。因为微信同时只能登录一个网页端或者window的客户端,所以微信登录了之后,不能再去登录网页或者客户端,否则会挤掉登录,导致发送失败。而且微信发送频率不能太快,否则会导致微信发送频繁而被限制发送,需要等待30-60分钟,才可以继续发送。所以可以使用定时器去发送消息,消息发送频率在1次/秒;
7 技术应用推广
在其他项目现场,如果有需求要推送报警消息到微信,可以复用该方法,去对接微信网页接口,采用微信的方便快捷实现报警推送;
下载地址:
https://www.cnblogs.com/bclshuai/p/11380657.html
百度云盘下载地址:
链接:https://pan.baidu.com/s/1swkQzCIKI3g3ObcebgpIDg
提取码:mc8l
微信公众号获取最新的软件和视频介绍
QStockView
C++微信网页协议实现和应用的更多相关文章
- Java微信公众平台开发(十六)--微信网页授权(OAuth2.0授权)获取用户基本信息
转自:http://www.cuiyongzhi.com/post/78.html 好长时间没有写文章了,主要是最近的工作和生活上的事情比较多而且繁琐,其实到现在我依然还是感觉有些迷茫,最后还是决定静 ...
- 手把手实现微信网页授权和微信支付,附源代码(VUE and thinkPHP)
wechat github 手把手实现微信网页授权和微信支付,附源代码(VUE and thinkPHP) 概述 公众号开发是痛苦的,痛苦在好多问题开发者文档是没有提到的,是需要你猜的. 在开发过程中 ...
- 微信网页授权demo2
1.在微信公众号请求用户网页授权之前,开发者需要先到公众平台官网中的“开发 - 接口权限 - 网页服务 - 网页帐号 - 网页授权获取用户基本信息”的配置选项中,修改授权回调域名.请注意,这里填写的是 ...
- PHP实现微信网页登陆授权开发
这篇文章主要介绍了关于PHP实现微信网页登陆授权开发,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 更多PHP相关知识请关注我的专栏PHPzhuanlan.zhihu.com 微信开 ...
- Spring Security中实现微信网页授权
微信公众号提供了微信支付.微信优惠券.微信H5红包.微信红包封面等等促销工具来帮助我们的应用拉新保活.但是这些福利要想正确地发放到用户的手里就必须拿到用户特定的(微信应用)微信标识openid甚至是用 ...
- 微信网页版APP - 网页微信客户端电脑版体验
微信网页版很早就出来了,解决了很多人上班不能玩手机的问题.微信电脑版-网页微信客户端,直接安装在桌面的微信网页版,免去了开浏览器的麻烦.双击就启动了,和其他的应用程序一样:运行过程中可以隐藏在桌面右下 ...
- 微信网页授权snsapi_base、snsapi_userinfo的问题
微信网页授权SCOPE分为snsapi_base.snsapi_userinfo,前者是用户无感知的静默授权只能拿到openid:而后者需要用户确认,能拿到更多的用户信息. 我有一个系统需要进行网页授 ...
- 以蓝牙开发的视觉解读微信Airsync协议
微信硬件平台使用蓝牙作为近场控制的连接件,并拟定了<微信蓝牙外设协议>.这份协议更像一个标准,用于规范微信和蓝牙外设之间的数据交互场景和接口.但从开发者来看,要完全读懂这份协议,恐怕需要熟 ...
- Protocol buffer序列化及其在微信蓝牙协议中的应用
Protocol buffer是Google出品的一种轻便高效的结构化数据存储格式,可对结构化数据进行序列化,并具有语言无关.平台无关等特点,在通信协议和数据存储等领域已经得到广泛的应用.目前其已经提 ...
随机推荐
- bean的创建(五)第三部分 bean工厂方法参数的解析
准备好一系列参数之后,开始参数类型的转换,方法参数的对应. ConstructorResolver.createArgumentArray private ArgumentsHolder create ...
- DotSpatial安装、类库引用方法
解决VS工具栏添加DotSpatial后,控件不全问题. 注意注意注意:不要使用Nuget安装DotSpatial!!! 我在Nuget上把所有DotSpatial的版本都安装了一遍,都缺少控件,然后 ...
- JAVA对象实例化方式总结
JAVA对象实例化的方法 New对象实例 // 直接new对象实例 Productor productor = new Productor(); 反射机制 Java反射机制是在运行状态中,对于任意一个 ...
- 【Android Studio】提示代码忽略大小写
在 Preference... 中找到如下,设置 Case sensitive completion 为 None 即可,如下图: PS: 该截图是 Intellij IDEA (Android St ...
- Python实现批量处理扫描特定目录
## 简述在渗透测试中遇到相同CMS站点时,搞定一个站点,相当于拿了一个站群的通用漏洞,所以我们首先需要标注站点的CMS类型,根据要求编写如下脚本 ## 要求1.访问特定目录,如:站点特定 /cmsa ...
- oracle的本地远程连接和配置
Oracle数据库的远程连接可以通过多种方式来实现,本文我们主要介绍四种远程连接的方法和注意事项,并通过示例来说明,接下来我们就开始介绍. 第一种情况: 若oracle服务器装在本机上,那就不多说了, ...
- 【Java例题】3.6 计算arcsin(x)的值
6.使用泰勒展开式计算arcsin(x)的值. arcsin(x)=x+x^3/(2*3)+1*3*x^5/(2*4*5)+...+ (2n)!*x^(2n+1)/(2^2n)*(n!)^2*(2n+ ...
- 12、面向对象的思想(OOP)
面向对象与面向过程 1.都是解决问题的思维方式,都是代码的组织的方式: 2.解决简单的问题可以使用面向过程: 3.解决复杂的问题建议使用面向对象,微观处理依旧会使用面向过程. 对象的进化史(数据管理的 ...
- Paxos算法原理
1.从ACID到CAP 我们知道传统集中式系统中实现ACID是很简单的,在分布式环境中,涉及到不同的节点,节点内的ACID可以控制,那么节点间的ACID如何控制呢?构建一个可用性和一致性的分布系统成为 ...
- Vsftp服务器配置文件详解
vsftp软件是我们常见的FTP服务器搭建软件,所有的配置都是基于vsftpd.conf这个配置文件的.vsftpd.conf里面主要包括安全配置,传输,用户还有权限等相关的选项.现在我们讲解下关于V ...