先说需求!有很多人是在做微商的,要是你把你的产品发到朋友圈,你所发的内容是有可能被掩盖掉的!就是我们再使用手机版微信APP的时候,群发是有一定人数限制的(这些都是废话和铺垫),这个时候就想到是不是可以用Java模拟web微Xin,写个程序(后来知道,居然大家管这个东西叫机器人),然后发送消息,就可以解决了。
作为程序猿的利器,chrome和fiddler,说做就做(其实是对web微信协议的自己分析)。
1.获取二维码:这肯定是最开始需要的
web版地址是这个 https://wx.qq.com/,打开这个地址,F12一下,
这里我们看到加载了一大堆的js和图片,我们关心的只要是标红的三个就好了
1.1 获取UUID换取二维码
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&_=1497430023830
这个方法是第一步,jslogin 这是个get的请求方法,这个我们可以看他所需要的请求参数有4个
我开始做的时候,不管怎么通过F12查看有返回appid的方法都没有找到,后来我试了其他的微信号,发现这个appid都一样,所以告诉大家,这个appid是固定的!至于149开头的那个参数就很好猜了,就是时间戳,其他参数同样固定。
这个请求发返回结果是这样的
window.QRLogin.code = 200; window.QRLogin.uuid = "QY6pTM6Avw==";
我们再来对照F12下面的看下,
是不是发现了,这两个的值是一样的!jslogin返回的uuid,就是我们置换二维码的参数,刷新下页面,我们再看
1.2获取二维码
https://login.weixin.qq.com/qrcode/4aJWOM4Jpw==
这个方法同样是get请求,没有参数
这时候我们就可以在响应看到我们的二维码了,
这个时候是response是没值的,但是我们可以通过preview预显示看到二维码,这是因为这个响应结果是以流的形式返回的,我们只需要将流生成响应的图片就好了。
1.3长轮询判断手机端
https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=AaSwnCS2UQ==&tip=0&r=1512572422&_=1497430963219
请求方式是get
请求参数是
参数解释,其中loginicon、tip是固定参数,uuid是jslogin返回的值,和换取二维码参数一样;_是时间戳;r这个参数,网上很多人说取反,我自己用Java代码亲测是不对的,没有使用js测试,因为js不是太熟悉,我可以明确告诉你们r=_/760,就是时间戳/760,就是参数r。
返回结果是 window.code=408;
我们看到这个方法一直在做长轮询,25秒左右一次,返回结果就是window.code=408;这个是一直发送的请求,是告诉你,服务器没有收到你的扫码或者扫码之后的登录确定;当然,这个扫码和确定登录时需要手机端配合的。
1.4长轮询判断手机端获取头像
https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=QbQnDRrWjg==&tip=0&r=1511576646&_=1497431985392
再看这个请求,长轮询一直进行,参数和上面一样,当我们用手机扫码之后这时候再看返回结果
window.code=201;window.userAvatar = 'data:img/jpg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/2wBDAAMCAgMCAgM..........'
code=201 然后后面紧跟的是个base64,这个大家肯定熟悉了,这个就是你自己微信的头像,这样我们就可以拿到自己的微信头像,这时候大家要知道的是返回code是201,
1.5长轮询判断手机端
https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=QbQnDRrWjg==&tip=0&r=1511570443&_=1497431985393
还在继续这个请求,我用自己的手机扫码之后,然后手机锁屏,这时候,我没有点击手机上的确认登录,我们看到
这个请求还在一直继续,然后返回的结果还是408,我们接着往下做。
1.6长轮询判断手机端确认登录
https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=QbQnDRrWjg==&tip=0&r=1511545371&_=1497431985394
继续这个请求,和上面几个方法一样,也是get请求,参数都和1.3一样。我这时候在手机端点击确认登录网页版
这个时候我们看到有新的返回,code是200了,然后还有个redirect_uri 重定向地址返回给我们,这个是个很重要的地址,也很符合mp文档的规范,使用ticket作为下次的请求,这个地址我们先不拆开,直接作为下次使用的参数
1.7初始化页面得到关键参数
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=.....&uuid=QbQnDRrWjg==&lang=zh_CN&scan=1497432010&fun=new&version=v2&lang=zh_CN
我这边把ticket去掉用....代替,地址就是1.6返回的URI再在后面拼接fun、version、lang构成,
这个请求同样是get请求,
请求参数可以直接在地址后面拼接就好
返回参数;
对这个请求是整个web微信中至关重要的一步,我做的时候就是这一步没有认真,返回参数如下
这里的返回skey,pass_ticket,wxsid,wxuin这些参数都会在后面的请求中使用到;在这里先漏讲2个重要的地方;后面大家有使用发现问题的时候可以直接问我,这2个点非常非常重要。可能有些人也能悟的出来
1.8 微信数据初始化
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=1511600827&lang=zh_CN&pass_ticket=...
这里的pass_ticket我同样使用...代替;
请求方式为 post
请求参数
再看返回结果:
这儿是返回你最近联系的人的信息,其中User是你自己的个人信息,其中nickname是昵称的意思,我们暂时先知道这么多,user其中的username是自己在微信中发消息所使用的得名字,我们需要把这个解析出来;
1.9开启微信接收消息通知状态
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxstatusnotify?lang=zh_CN&pass_ticket=...
请求方式post
请求参数
返回参数
{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
}
,
"MsgID": "..."
}
这个是正确的返回参数,其中MsgID是下面所需要用到的;这里的请求也需要用到上面漏讲的重要2点的内容。
2.0获取联系人
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?lang=zh_CN&pass_ticket=...&seq=0&skey=...
这一步使我们要获取我们发送消息的先决条件,***(在这还有个获取最近联系人的方法
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxbatchgetcontact?type=ex&r=1497432043736&lang=zh_CN&pass_ticket=...
只需要pass_ticket就可以,请求方式post,这是网上很多人所说的获取联系人,这个我不推荐,和我们的出发点很远,也不好用
)***
请求方式get
请求参数直接拼接就好
返回数据预览
2.1置换图片mediaId
https://file.wx.qq.com/cgi-bin/mmwebwx-bin/webwxuploadmedia?f=json
这里我们先说置换图片mediaId,网上大部分人都没有把这个说清楚,当时我去请教别人的时候,别人是要收我钱才肯告诉我的;
请求方式post
请求参数 使用fiddler拦截抓包这样就很清晰了吧
这样够清晰了,这个就是一个form带文件的表单提交,其中各个对应的参数我们需要自己构建,最终是以json的形式发送,其中
uploadmediarequest这个参数较为特殊,我一样使用...代替重要参数
{"UploadType":2,"BaseRequest":{"Uin":408216280,"Sid":"...","Skey":"...","DeviceID":"..."},"ClientMediaId":1497435635161,"TotalLen":318889,"StartPos":0,"DataLen":318889,"MediaType":4,"FromUserName":"...","ToUserName":"filehelper","FileMd5":"12dc0221652975df9723aae462794d77"}
相信大家看的懂,稍微解释一下,UploadType是上传的文件类型2,ClientMediaId时间戳,FromUserName自己的账号,ToUserName发送对象的账号,FileMd5这个也是我请教别人的点,他居然告诉我写死,我自己研究了下,可以明确告诉大家,那家伙瞎说,这个就是文件的MD5,MediaType也是固定的4,剩下的参数应该不是难度了,至于抓包出现的有个参数前面没有出现,我暂时也不解释;
返回参数
{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
}
,
"MediaId": "...",
"StartPos": 318889,
"CDNThumbImgHeight": 56,
"CDNThumbImgWidth": 100
}
其中的mediaId就是我们发送图片时所需要的参数
2.2发送图片消息
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsgimg?fun=async&f=json&lang=zh_CN&pass_ticket=...
请求方式post
请求参数
返回参数
{
"BaseResponse": {
"Ret": 0,
"ErrMsg": ""
}
,
"MsgID": "...",
"LocalID": "..."
}
当ret为0的时候这样我们就发送成功,这边我们以发送图片为例,暂时发送文字消息还有其他的消息就很简单了!
2.3心跳包
https://webpush.wx.qq.com/cgi-bin/mmwebwx-bin/synccheck?r=1497436739199&skey=...&uin=408216280&deviceid=...&synckey=...
心跳包
请求方式get
每个25秒做一次请求
返回参数
window.synccheck={retcode:"0",selector:"0"}
这边就不对其做深入讲解,网上有着总结好的内容!