当微信用户向公众号发送消息时,微信服务器会向公众号配置的服务器URL地址发送请求,并将相关内容包装成一定格式的xml发送到这个服务器;响应时,这个服务器只要回复特定格式的xml字符串给微信服务器,微信服务器即可向微信用户的客户端转发这条回复消息.(假设公众号开发模式已开启,以后的教程,如果没有特别说明,都是如此).如下图:
例如,文本消息的xml结构如下:
<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>1348831860</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[this is a test]]></Content> <MsgId>1234567890123456</MsgId> </xml>
各参数说明如下:
其他消息类型的xml结构详见微信公众号官方文档.
微信暂时能转发的消息类型分为:普通消息和事件推送消息.其中普通消息又分为:文本消息,图片消息,语音消息,视频消息,小视频消息,地理位置消息,链接消息;事件推消息又分为:关注/取消关注事件,扫描带参数二维码事件,上报地理位置事件,自定义菜单事件.
下面偿试接收这些所有消息:
<?php //文件名: http://szuzsq.tunnel.qydev.com/weixin/index.php $wechatObj = new wechatCallbackapiTest(); $wechatObj->responseMsg(); class wechatCallbackapiTest { public function responseMsg() { //注:微信官方demo是使用$GLOBALS,而我使用的是file_get_contents的形式,来获取转发过来的xml内容.具体php配置不同,应采用不同的形式,请大家注意下,不然后可能粉丝收不到你的公众号回复的消息. //$str = $GLOBALS["HTTP_RAW_POST_DATA"]; $str = file_get_contents("php://input"); if(!isset($str) || empty($str)) exit(""); libxml_disable_entity_loader(true); $xml = simplexml_load_string($str, 'SimpleXMLElement', LIBXML_NOCDATA); switch($xml->MsgType) { case "text": { $fmt = "<xml>"; $fmt .= "<ToUserName><![CDATA[%s]]></ToUserName>"; $fmt .= "<FromUserName><![CDATA[%s]]></FromUserName>"; $fmt .= "<CreateTime>%s</CreateTime>"; $fmt .= "<MsgType><![CDATA[%s]]></MsgType>"; $fmt .= "<Content><![CDATA[%s]]></Content>"; $fmt .= "</xml>"; $toUserName = $xml->FromUserName; $fromUserName = $xml->ToUserName; $createTime = time(); $msgType = "text"; $content = "接收方:$xml->ToUserName"; $content .= "\n发送方:$xml->FromUserName"; $content .= "\n创建时间:$xml->CreateTime"; $content .= "\n类型:$xml->MsgType"; $content .= "\n内容:$xml->Content"; $content .= "\n消息ID:$xml->MsgId"; $rs = sprintf($fmt, $toUserName, $fromUserName, $createTime, $msgType, $content); echo $rs; break; } case "image": { $fmt = "<xml>"; $fmt .= "<ToUserName><![CDATA[%s]]></ToUserName>"; $fmt .= "<FromUserName><![CDATA[%s]]></FromUserName>"; $fmt .= "<CreateTime>%s</CreateTime>"; $fmt .= "<MsgType><![CDATA[%s]]></MsgType>"; $fmt .= "<Content><![CDATA[%s]]></Content>"; $fmt .= "</xml>"; $toUserName = $xml->FromUserName; $fromUserName = $xml->ToUserName; $createTime = time(); $msgType = "text"; $content = "接收方:$xml->ToUserName"; $content .= "\n发送方:$xml->FromUserName"; $content .= "\n创建时间:$xml->CreateTime"; $content .= "\n类型:$xml->MsgType"; $content .= "\n图片链接:$xml->PicUrl"; $content .= "\n图片ID:$xml->MediaId"; $content .= "\n消息ID:$xml->MsgId"; $rs = sprintf($fmt, $toUserName, $fromUserName, $createTime, $msgType, $content); echo $rs; break; } case "voice": { $fmt = "<xml>"; $fmt .= "<ToUserName><![CDATA[%s]]></ToUserName>"; $fmt .= "<FromUserName><![CDATA[%s]]></FromUserName>"; $fmt .= "<CreateTime>%s</CreateTime>"; $fmt .= "<MsgType><![CDATA[%s]]></MsgType>"; $fmt .= "<Content><![CDATA[%s]]></Content>"; $fmt .= "</xml>"; $toUserName = $xml->FromUserName; $fromUserName = $xml->ToUserName; $createTime = time(); $msgType = "text"; $content = "接收方:$xml->ToUserName"; $content .= "\n发送方:$xml->FromUserName"; $content .= "\n创建时间:$xml->CreateTime"; $content .= "\n类型:$xml->MsgType"; $content .= "\n语音ID:$xml->MediaID"; $content .= "\n语音格式:$xml->Format"; $content .= "\n语音识别结果:$xml->Recognition"; $content .= "\n消息ID:$xml->MsgId"; $rs = sprintf($fmt, $toUserName, $fromUserName, $createTime, $msgType, $content); echo $rs; break; } case "video": { $fmt = "<xml>"; $fmt .= "<ToUserName><![CDATA[%s]]></ToUserName>"; $fmt .= "<FromUserName><![CDATA[%s]]></FromUserName>"; $fmt .= "<CreateTime>%s</CreateTime>"; $fmt .= "<MsgType><![CDATA[%s]]></MsgType>"; $fmt .= "<Content><![CDATA[%s]]></Content>"; $fmt .= "</xml>"; $toUserName = $xml->FromUserName; $fromUserName = $xml->ToUserName; $createTime = time(); $msgType = "text"; $content = "接收方:$xml->ToUserName"; $content .= "\n发送方:$xml->FromUserName"; $content .= "\n创建时间:$xml->CreateTime"; $content .= "\n类型:$xml->MsgType"; $content .= "\n视频ID:$xml->MediaId"; $content .= "\n视频缩略图ID:$xml->ThumbMediaId"; $content .= "\n消息ID:$xml->MsgId"; $rs = sprintf($fmt, $toUserName, $fromUserName, $createTime, $msgType, $content); echo $rs; break; } case "shortvideo": { $fmt = "<xml>"; $fmt .= "<ToUserName><![CDATA[%s]]></ToUserName>"; $fmt .= "<FromUserName><![CDATA[%s]]></FromUserName>"; $fmt .= "<CreateTime>%s</CreateTime>"; $fmt .= "<MsgType><![CDATA[%s]]></MsgType>"; $fmt .= "<Content><![CDATA[%s]]></Content>"; $fmt .= "</xml>"; $toUserName = $xml->FromUserName; $fromUserName = $xml->ToUserName; $createTime = time(); $msgType = "text"; $content = "接收方:$xml->ToUserName"; $content .= "\n发送方:$xml->FromUserName"; $content .= "\n创建时间:$xml->CreateTime"; $content .= "\n类型:$xml->MsgType"; $content .= "\n视频ID:$xml->MediaId"; $content .= "\n视频缩略图ID:$xml->ThumbMediaId"; $content .= "\n消息ID:$xml->MsgId"; $rs = sprintf($fmt, $toUserName, $fromUserName, $createTime, $msgType, $content); echo $rs; break; } case "location": { $fmt = "<xml>"; $fmt .= "<ToUserName><![CDATA[%s]]></ToUserName>"; $fmt .= "<FromUserName><![CDATA[%s]]></FromUserName>"; $fmt .= "<CreateTime>%s</CreateTime>"; $fmt .= "<MsgType><![CDATA[%s]]></MsgType>"; $fmt .= "<Content><![CDATA[%s]]></Content>"; $fmt .= "</xml>"; $toUserName = $xml->FromUserName; $fromUserName = $xml->ToUserName; $createTime = time(); $msgType = "text"; $content = "接收方:$xml->ToUserName"; $content .= "\n发送方:$xml->FromUserName"; $content .= "\n创建时间:$xml->CreateTime"; $content .= "\n类型:$xml->MsgType"; $content .= "\n地理位置维度:$xml->Location_X "; $content .= "\n地理位置经度:$xml->Location_Y "; $content .= "\n地图缩放大小:$xml->Scale"; $content .= "\n地理位置信息:$xml->Label"; $content .= "\n消息ID:$xml->MsgId"; $rs = sprintf($fmt, $toUserName, $fromUserName, $createTime, $msgType, $content); echo $rs; break; } case "link": { $fmt = "<xml>"; $fmt .= "<ToUserName><![CDATA[%s]]></ToUserName>"; $fmt .= "<FromUserName><![CDATA[%s]]></FromUserName>"; $fmt .= "<CreateTime>%s</CreateTime>"; $fmt .= "<MsgType><![CDATA[%s]]></MsgType>"; $fmt .= "<Content><![CDATA[%s]]></Content>"; $fmt .= "</xml>"; $toUserName = $xml->FromUserName; $fromUserName = $xml->ToUserName; $createTime = time(); $msgType = "text"; $content = "接收方:$xml->ToUserName"; $content .= "\n发送方:$xml->FromUserName"; $content .= "\n创建时间:$xml->CreateTime"; $content .= "\n类型:$xml->MsgType"; $content .= "\n消息标题:$xml->Title"; $content .= "\n消息描述:$xml->Description"; $content .= "\n消息链接:$xml->Url"; $content .= "\n消息ID:$xml->MsgId"; $rs = sprintf($fmt, $toUserName, $fromUserName, $createTime, $msgType, $content); echo $rs; break; } case "event": { switch($xml->Event) { case "subscribe": { $fmt = "<xml>"; $fmt .= "<ToUserName><![CDATA[%s]]></ToUserName>"; $fmt .= "<FromUserName><![CDATA[%s]]></FromUserName>"; $fmt .= "<CreateTime>%s</CreateTime>"; $fmt .= "<MsgType><![CDATA[%s]]></MsgType>"; $fmt .= "<Content><![CDATA[%s]]></Content>"; $fmt .= "</xml>"; $toUserName = $xml->FromUserName; $fromUserName = $xml->ToUserName; $createTime = time(); $msgType = "text"; $content = "接收方:$xml->ToUserName"; $content .= "\n发送方:$xml->FromUserName"; $content .= "\n创建时间:$xml->CreateTime"; $content .= "\n类型:$xml->MsgType"; $content .= "\n事件类型:$xml->Event"; //注:只有在用户还未关注公众号但扫描带参数二维码事件时,微信服务器才会带场景值的关注事件. //即:普通关注事件只有Event参数.扫描带参数二维码并关注事件还有EventKey,Ticket参数. $content .= "\n事件KEY值:$xml->EventKey"; $content .= "\n二维码的ticket:$xml->Ticket"; $content .= "\n消息ID:$xml->MsgId"; $rs = sprintf($fmt, $toUserName, $fromUserName, $createTime, $msgType, $content); echo $rs; break; } case "unsubscribe": { $fmt = "<xml>"; $fmt .= "<ToUserName><![CDATA[%s]]></ToUserName>"; $fmt .= "<FromUserName><![CDATA[%s]]></FromUserName>"; $fmt .= "<CreateTime>%s</CreateTime>"; $fmt .= "<MsgType><![CDATA[%s]]></MsgType>"; $fmt .= "<Content><![CDATA[%s]]></Content>"; $fmt .= "</xml>"; $toUserName = $xml->FromUserName; $fromUserName = $xml->ToUserName; $createTime = time(); $msgType = "text"; $content = "接收方:$xml->ToUserName"; $content .= "\n发送方:$xml->FromUserName"; $content .= "\n创建时间:$xml->CreateTime"; $content .= "\n类型:$xml->MsgType"; $content .= "\n事件类型:$xml->Event"; $content .= "\n消息ID:$xml->MsgId"; $rs = sprintf($fmt, $toUserName, $fromUserName, $createTime, $msgType, $content); echo $rs; break; } case "SCAN": { $fmt = "<xml>"; $fmt .= "<ToUserName><![CDATA[%s]]></ToUserName>"; $fmt .= "<FromUserName><![CDATA[%s]]></FromUserName>"; $fmt .= "<CreateTime>%s</CreateTime>"; $fmt .= "<MsgType><![CDATA[%s]]></MsgType>"; $fmt .= "<Content><![CDATA[%s]]></Content>"; $fmt .= "</xml>"; $toUserName = $xml->FromUserName; $fromUserName = $xml->ToUserName; $createTime = time(); $msgType = "text"; $content = "接收方:$xml->ToUserName"; $content .= "\n发送方:$xml->FromUserName"; $content .= "\n创建时间:$xml->CreateTime"; $content .= "\n类型:$xml->MsgType"; $content .= "\n事件类型:$xml->Event"; $content .= "\n事件KEY值:$xml->EventKey"; $content .= "\n二维码的ticket:$xml->Ticket"; $content .= "\n消息ID:$xml->MsgId"; $rs = sprintf($fmt, $toUserName, $fromUserName, $createTime, $msgType, $content); echo $rs; break; } case "LOCATION": { $fmt = "<xml>"; $fmt .= "<ToUserName><![CDATA[%s]]></ToUserName>"; $fmt .= "<FromUserName><![CDATA[%s]]></FromUserName>"; $fmt .= "<CreateTime>%s</CreateTime>"; $fmt .= "<MsgType><![CDATA[%s]]></MsgType>"; $fmt .= "<Content><![CDATA[%s]]></Content>"; $fmt .= "</xml>"; $toUserName = $xml->FromUserName; $fromUserName = $xml->ToUserName; $createTime = time(); $msgType = "text"; $content = "接收方:$xml->ToUserName"; $content .= "\n发送方:$xml->FromUserName"; $content .= "\n创建时间:$xml->CreateTime"; $content .= "\n类型:$xml->MsgType"; $content .= "\n事件类型:$xml->Event"; $content .= "\n地理位置纬度:$xml->Latitude"; $content .= "\n地理位置经度:$xml->Longitude"; $content .= "\n地理位置精度:$xml->Precision"; $content .= "\n消息ID:$xml->MsgId"; $rs = sprintf($fmt, $toUserName, $fromUserName, $createTime, $msgType, $content); echo $rs; break; } case "CLICK": { $fmt = "<xml>"; $fmt .= "<ToUserName><![CDATA[%s]]></ToUserName>"; $fmt .= "<FromUserName><![CDATA[%s]]></FromUserName>"; $fmt .= "<CreateTime>%s</CreateTime>"; $fmt .= "<MsgType><![CDATA[%s]]></MsgType>"; $fmt .= "<Content><![CDATA[%s]]></Content>"; $fmt .= "</xml>"; $toUserName = $xml->FromUserName; $fromUserName = $xml->ToUserName; $createTime = time(); $msgType = "text"; $content = "接收方:$xml->ToUserName"; $content .= "\n发送方:$xml->FromUserName"; $content .= "\n创建时间:$xml->CreateTime"; $content .= "\n类型:$xml->MsgType"; $content .= "\n事件类型:$xml->Event"; $content .= "\n事件KEY值:$xml->EventKey"; $content .= "\n消息ID:$xml->MsgId"; $rs = sprintf($fmt, $toUserName, $fromUserName, $createTime, $msgType, $content); echo $rs; break; } case "VIEW": { $fmt = "<xml>"; $fmt .= "<ToUserName><![CDATA[%s]]></ToUserName>"; $fmt .= "<FromUserName><![CDATA[%s]]></FromUserName>"; $fmt .= "<CreateTime>%s</CreateTime>"; $fmt .= "<MsgType><![CDATA[%s]]></MsgType>"; $fmt .= "<Content><![CDATA[%s]]></Content>"; $fmt .= "</xml>"; $toUserName = $xml->FromUserName; $fromUserName = $xml->ToUserName; $createTime = time(); $msgType = "text"; $content = "接收方:$xml->ToUserName"; $content .= "\n发送方:$xml->FromUserName"; $content .= "\n创建时间:$xml->CreateTime"; $content .= "\n类型:$xml->MsgType"; $content .= "\n事件类型:$xml->Event"; $content .= "\n事件KEY值:$xml->EventKey"; $content .= "\n消息ID:$xml->MsgId"; $rs = sprintf($fmt, $toUserName, $fromUserName, $createTime, $msgType, $content); echo $rs; break; } } break; } } } } ?>
文本消息
图片消息
语音消息
视频消息
小视频消息
地理位置消息
链接消息
关注事件
以下事件暂时没截到效果图.
微信官方文档里说:"其中,某些事件推送在发生后,是允许开发者回复用户的,某些则不允许,详细说明请见本页末尾的微信推送消息与事件说明。".我没找着那个说明.也不知道是否微信服务器不能接收回复,还是微信服务器接收回复后不会向公众号服务器转发.如果有同学知道,也请告诉我.不过我用微信公众平台接口调试工具,似乎都返回成功,代码应该是没问题了的.
取消关注事件
扫描带参数二维码事件
上报地理位置事件
自定义菜单事件--点击菜单拉取消息时的事件推送
自定义菜单事件--点击菜单跳转链接时的事件推送