在微信用户和公众号产生交互的过程中,用户的某些操作会使得微信服务器通过事件推送的形式->通知到开发者在开发者中心处设置的服务器地址,从而[开发者]可以获取到该信息。其中,某些事件推送在发生后,是允许开发者回复用户的,某些则不允许,详细内容如下:
- 关注/取消关注事件
- 扫描带参数二维码事件
- 上报地理位置事件
- 自定义菜单事件
- 点击菜单拉取消息时的事件推送
- 点击菜单跳转链接时的事件推送
一、关注/取消关注事件
- 用户在关注与取消关注公众号时,微信会把这个事件推送到开发者填写的URL。方便开发者给用户下发欢迎消息或者做帐号的解绑。为保护用户数据隐私,开发者收到用户取消关注事件时需要删除该用户的所有信息。
- 微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次。
- 关于重试的消息排重,推荐使用FromUserName + CreateTime 排重。
- 假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试。
<xml>
<ToUserName>
< ![CDATA[toUser] ]>
</ToUserName>
<FromUserName>
< ![CDATA[FromUser] ]>
</FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType>
< ![CDATA[event] ]>
</MsgType>
<Event>
< ![CDATA[subscribe] ]>
</Event>
</xml>
二、扫描带参数二维码事件
用户扫描带场景值二维码时,可能推送以下两种事件:
如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事件推送给开发者。
如果用户已经关注公众号,则微信会将带场景值扫描事件推送给开发者。
1、用户未关注时,进行关注后的事件推送
<xml>
<ToUserName>
< ![CDATA[toUser] ]>
</ToUserName>
<FromUserName>
< ![CDATA[FromUser] ]>
</FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType>
< ![CDATA[event] ]>
</MsgType>
<Event>
< ![CDATA[subscribe] ]>
</Event>
<EventKey>
< ![CDATA[qrscene_123123] ]>
</EventKey>
<Ticket>
< ![CDATA[TICKET] ]>
</Ticket>
</xml>
2、 用户已关注时的事件推送
<xml>
<ToUserName>
< ![CDATA[toUser] ]>
</ToUserName>
<FromUserName>
< ![CDATA[FromUser] ]>
</FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType>
< ![CDATA[event] ]>
</MsgType>
<Event>
< ![CDATA[SCAN] ]>
</Event>
<EventKey>
< ![CDATA[SCENE_VALUE] ]>
</EventKey>
<Ticket>
< ![CDATA[TICKET] ]>
</Ticket>
</xml>
三、上报地理位置事件
用户同意上报地理位置后,每次进入公众号会话时,都会在进入时上报地理位置,
或在进入会话后每5秒上报一次地理位置,公众号可以在公众平台网站中修改以上设置。
上报地理位置时,微信会将上报地理位置事件推送到开发者填写的URL。
<xml>
<ToUserName>
< ![CDATA[toUser] ]>
</ToUserName>
<FromUserName>
< ![CDATA[fromUser] ]>
</FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType>
< ![CDATA[event] ]>
</MsgType>
<Event>
< ![CDATA[LOCATION] ]>
</Event>
<Latitude>23.137466</Latitude>
<Longitude>113.352425</Longitude>
<Precision>119.385040</Precision>
</xml>
四、自定义菜单事件
- 用户点击自定义菜单后,微信会把点击事件推送给开发者,
- 请注意,点击菜单弹出子菜单,不会产生上报。
- 点击菜单拉取消息时的事件推送
点击菜单拉取消息时的事件推送
<xml>
<ToUserName>
< ![CDATA[toUser] ]>
</ToUserName>
<FromUserName>
< ![CDATA[FromUser] ]>
</FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType>
< ![CDATA[event] ]>
</MsgType>
<Event>
< ![CDATA[CLICK] ]>
</Event>
<EventKey>
< ![CDATA[EVENTKEY] ]>
</EventKey>
</xml>
点击菜单跳转链接时的事件推送
<xml>
<ToUserName>
< ![CDATA[toUser] ]>
</ToUserName>
<FromUserName>
< ![CDATA[FromUser] ]>
</FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType>
< ![CDATA[event] ]>
</MsgType>
<Event>
< ![CDATA[VIEW] ]>
</Event>
<EventKey>
< ![CDATA[www.qq.com] ]>
</EventKey>
</xml>
案例《 关注/取消关注事件》如图所示
案例《 关注/取消关注事件》代码如下
<?php
//
// 关注/取消关注事件消息
// 微信公众账号关注与取消关注事件消息
//
define("TOKEN", "weixin");
$wechatObj = new wechatCallbackapiTest();
if (!isset($_GET['echostr'])) {
$wechatObj->responseMsg();
}else{
$wechatObj->valid();
}
class wechatCallbackapiTest
{
public function valid()
{
$echoStr = $_GET["echostr"];
if($this->checkSignature()){
echo $echoStr;
exit;
}
}
private function checkSignature()
{
$signature = $_GET["signature"];
$timestamp = $_GET["timestamp"];
$nonce = $_GET["nonce"];
$token = TOKEN;
$tmpArr = array($token, $timestamp, $nonce);
sort($tmpArr);
$tmpStr = implode($tmpArr);
$tmpStr = sha1($tmpStr);
if($tmpStr == $signature){
return true;
}else{
return false;
}
}
public function responseMsg()
{
$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
if (!empty($postStr)){
$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
$RX_TYPE = trim($postObj->MsgType);
switch ($RX_TYPE)
{
case "event":
$result = $this->receiveEvent($postObj);
break;
}
echo $result;
}else {
echo "";
exit;
}
}
private function receiveEvent($object)
{
$content = "";
switch ($object->Event)
{
case "subscribe": //关注事件
$content = "欢迎关注德强1012";
break;
case "unsubscribe": //取消关注事件
$content = "";
break;
}
$result = $this->transmitText($object, $content);
return $result;
}
private function transmitText($object, $content)
{
$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[%s]]></Content>
</xml>";
$result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time(), $content);
return $result;
}
}
?>