相比于最常用的短信和邮件的通知方式,微信有着无可比拟的优势:快速、免费,特别适合用在报警通知类应用上。 但是微信并没有提供现成的api接口来给好友发送信息,公众平台也只能被动回复。那么如何才能主动发信息呢?答案就在微信网页版。 仔细观察微信网页
相比于最常用的短信和邮件的通知方式,微信有着无可比拟的优势:快速、免费,特别适合用在报警通知类应用上。
但是微信并没有提供现成的api接口来给好友发送信息,公众平台也只能被动回复。那么如何才能主动发信息呢?答案就在微信网页版。
仔细观察微信网页版和服务器请求的记录,发现完全就是以oauth授权方式运行,完全不用考虑cookie。据此,分析请求记录,就能模拟网页版登录微信,从而实现主动向用户发送消息的功能。
以下是用到的请求:
1. 获取uuid,从返回的数据中,找到uuid
https://login.weixin.qq.com/jslogin?appid=wx782c26e4c19acffb&redirect_uri=https%3A%2F%2Fwx.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage&fun=new&lang=zh_CN
2. 获取二维码图片,然后使用微信扫描
https://login.weixin.qq.com/qrcode/$this->uuid?t=webwx
3. 获取令牌,轮询,直到从返回的数据中找到window.redirect_uri=xxxx的代码,xxx就是令牌url
https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?uuid=$this->uuid&tip=1
4. 访问令牌url,获取sid。从返回的头信息中,分析出Uin,sid和uuid,保存起来
xxxxxx
5. 初始化微信,从返回的数据中读取UserName
1
2
3
4
5
6
7
8
9
|
$data
= array (
"BaseRequest" => array (
"DeviceID"
=> 'e538770852445779' ,
"Sid"
=> $this ->sid,
"Skey"
=> "" ,
"Uin"
=> $this ->Uin,
)
);
$this ->post_contents( 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit' ,
$this ->encode( $data ));
|
6. 获取Skey
1
|
$this ->post_contents( 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid='
. urlencode( $this ->sid),
'{"BaseRequest":{"Uin":' . $this ->Uin. ',"Sid":"' . $this ->sid. '"},"SyncKey":{"Count":0,"List":[]}}' );
|
7. 发送消息,POST方式,
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
$data
= array (
"BaseRequest"
=> array (
"Uin" =>
$this ->Uin,
"Sid" =>
$this ->sid,
"Skey" =>
$this ->Skey,
"DeviceID" =>
$this ->DeviceID,
),
"Msg"
=> array (
"FromUserName"
=> $this ->FromUserName,
"ToUserName"
=> $name ,
"Type"
=> 1,
"Content"
=> $content ,
"ClientMsgId"
=> $this ->ClientMsgId,
"LocalID"
=> $this ->ClientMsgId,
),
);
$str
= $this ->encode( $data );
son_decode( $this ->post_contents( 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg?sid='
. urlencode( $this ->sid)
. '&r='
. $this ->ClientMsgId,
$str ),
true);
|
发送消息的经典过程为:
- 初始化对象,设置Uin,sid,uuid
- 更新Skey
- 发送信息
但是微信网页版长时间不登录会失效,所以还需要写个任务去ping
1
2
|
$data
= '{"BaseRequest":{"Uin":' . $this ->Uin. ',"Sid":"' . $this ->sid. '"},"SyncKey":{"Count":0,"List":[]}}' ;
$ret
= json_decode( $this ->post_contents( 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid='
. urlencode( $this ->sid),
$data ,
30), true);
|
微信的数据都是以json格式传输的,但是他这个json比较特殊,还需要用特别的函数来实现
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
protected
function
encode( $data ){
if (! is_array ( $data )){
return
$this ->encode_str( $data );
}
$ds
= array ();
foreach ( $data
as
$k
=> $v ){
$ds
[] = "\"$k\":"
. $this ->encode( $v );
}
return
'{'
. join( ',' ,
$ds )
. '}' ;
}
protected
function
encode_str( $str ){
if (preg_match( '|^\d+$|' ,
$str )){
return
$str ;
}
return
'"'
. str_replace ( '"' ,
'\"' ,
i
|