微信公众平台应用开发实践
上QQ阅读APP看书,第一时间看更新

4.5 回复消息

对于每一个POST请求,开发者需要在响应包中返回特定XML结构的响应报文,现在支持回复文本、图片、图文、语音、视频、音乐。需要注意的是,回复图片等多媒体消息需要预先上传多媒体文件到微信服务器。

微信服务器在5秒内收不到响应会断掉链接,并且重新发起请求,最多重试3次。所以我们需要有消息的排重机制,防止对同一消息或事件回复多条响应消息。对于有msgid的消息可以使用msgid排重。事件类型消息则可以使用FromUserName+CreateTime排重。

对于有些耗时较多,无法保证在5秒内应答的请求可以直接回复空串,微信服务器不会对此做任何处理,并且不会发起重试。在这种情况下,可以使用客服消息接口进行异步回复,这个将在后面介绍。

4.5.1 回复文本消息

     <xml>
     <ToUserName><![CDATA[toUser]]></ToUserName>
     <FromUserName><![CDATA[fromUser]]></FromUserName>
     <CreateTime>12345678</CreateTime>
     <MsgType><![CDATA[text]]></MsgType>
     <Content><![CDATA[你好]]></Content>
     </xml>

参数说明如表4-15所示。

表4-15 参数说明

     const REPLY_TYPE_TEXT = 'text';
     /**
          *生成向用户发送的文字信息
          * @param string $content
          * @return string xml字符串
          */
         public function outputText($content)
         {
             $textTpl = '<xml>
                    <ToUserName><![CDATA[%s]]></ToUserName>
                    <FromUserName><![CDATA[%s]]></FromUserName>
                    <CreateTime>%s</CreateTime>
                    <MsgType><![CDATA[%s]]></MsgType>
                    <Content><![CDATA[%s]]></Content>
                </xml>';

$text = sprintf($textTpl, $this->_postData->FromUserName, $this->_postData->ToUserName, time(), self::REPLY_TYPE_TEXT, $content); header('Content-Type: application/xml'); echo $text; }

header函数向客户端发送原始的HTTP报头,因为我们要发送的是XML格式的内容,定义Content-Type为application/xml。

4.5.2 回复图片消息

     <xml>
     <ToUserName><![CDATA[toUser]]></ToUserName>
     <FromUserName><![CDATA[fromUser]]></FromUserName>
     <CreateTime>12345678</CreateTime>
     <MsgType><![CDATA[image]]></MsgType>
     <Image>
     <MediaId><![CDATA[media_id]]></MediaId>
     </Image>
     </xml>

参数说明如表4-16所示。

表4-16 参数说明

     const REPLY_TYPE_IMAGE='image';
     /**
          *生成向用户发送的图片信息
          * @param string $media_id
          * @return string xml字符串
          */
         public function outputImage($media_id)
         {
             $textTpl = '<xml>
                    <ToUserName><![CDATA[%s]]></ToUserName>
                    <FromUserName><![CDATA[%s]]></FromUserName>
                    <CreateTime>%s</CreateTime>
                    <MsgType><![CDATA[%s]]></MsgType>
                    <Image>
                         <MediaId><![CDATA[%s]]></MediaId>
                    </Image>
                </xml>';

$text = sprintf($textTpl, $this->_postData->FromUserName, $this->_postData->ToUserName, time(), self::REPLY_TYPE_IMAGE, $media_id); header('Content-Type: application/xml'); echo $text; }

注意这里的mediaid是笔者上传获取的,而且微信服务器对多媒体只保存3天,所以读者在实验这段代码的时候请自行上传多媒体文件获取mediaid。上传下载多媒体的接口将在后面介绍,如图4-18所示。

图4-18

4.5.3 回复语音消息

     <xml>
     <ToUserName><![CDATA[toUser]]></ToUserName>
     <FromUserName><![CDATA[fromUser]]></FromUserName>
     <CreateTime>12345678</CreateTime>
     <MsgType><![CDATA[voice]]></MsgType>
     <Voice>
     <MediaId><![CDATA[media_id]]></MediaId>
     </Voice>
     </xml>

参数说明如表4-17所示。

表4-17 参数说明

    const REPLY_TYPE_VOICE = 'voice';
    /**
         *生成向用户发送的语音信息
         * @param string $content
         * @return string xml字符串
         */
        public function outputVoice($media_id)
        {
            $textTpl = '<xml>
                    <ToUserName><![CDATA[%s]]></ToUserName>
                    <FromUserName><![CDATA[%s]]></FromUserName>
                    <CreateTime>%s</CreateTime>
                    <MsgType><![CDATA[%s]]></MsgType>
                    <Voice>
                         <MediaId><![CDATA[%s]]></MediaId>
                    </Voice>
                </xml>';

$text = sprintf($textTpl, $this->_postData->FromUserName, $this->_postData->ToUserName, time(), self::REPLY_TYPE_VOICE, $media_id); header('Content-Type: application/xml'); echo $text; }

运行结果如图4-19所示。

图4-19

4.5.4 回复视频消息

     <xml>
     <ToUserName><![CDATA[toUser]]></ToUserName>
     <FromUserName><![CDATA[fromUser]]></FromUserName>
     <CreateTime>12345678</CreateTime>
     <MsgType><![CDATA[video]]></MsgType>
     <Video>
     <MediaId><![CDATA[media_id]]></MediaId>
     <Title><![CDATA[title]]></Title>
     <Description><![CDATA[description]]></Description>
     </Video>
     </xml>

参数说明如表4-18所示。

表4-18 参数说明

     const REPLY_TYPE_VIDEO = 'video';
     /**
          *生成向用户发送的视频信息
          * @param string $content
          * @return string xml字符串
          */
         public function outputVideo($videopost)
         {
             $textTpl = '<xml>
                     <ToUserName><![CDATA[%s]]></ToUserName>
                     <FromUserName><![CDATA[%s]]></FromUserName>
                     <CreateTime>%s</CreateTime>
                     <MsgType><![CDATA[%s]]></MsgType>
                     <Video>
                         <MediaId><![CDATA[%s]]></MediaId>
                         <Title><![CDATA[%s]]></Title>
                         <Description><![CDATA[%s]]></Description>
                     </Video>
                 </xml>';

$text = sprintf($textTpl, $this->_postData->FromUserName, $this->_postData->ToUserName, time(), self::REPLY_TYPE_VIDEO, $videopost['media_id'], $videopost['title'], $videopost['description']); header('Content-Type: application/xml'); echo $text; } private function testVideo() { $video = array( 'media_id' => 'Dx09rTLDC3nZKTSmfWMHXKxNxb01oTbgqn3yHtLPgTUmDJxSSamGW7uqNGRZp3of', 'title' => '独墅湖', 'description' => '生活在独墅湖' ); $this->outputVideo($video); }

运行结果如图4-20所示。

图4-20

4.5.5 回复音乐消息

     <xml>
     <ToUserName><![CDATA[toUser]]></ToUserName>
     <FromUserName><![CDATA[fromUser]]></FromUserName>
     <CreateTime>12345678</CreateTime>
     <MsgType><![CDATA[music]]></MsgType>
     <Music>
     <Title><![CDATA[TITLE]]></Title>
     <Description><![CDATA[DESCRIPTION]]></Description>
     <MusicUrl><![CDATA[MUSIC_Url]]></MusicUrl>
     <HQMusicUrl><![CDATA[HQ_MUSIC_Url]]></HQMusicUrl>
     <ThumbMediaId><![CDATA[media_id]]></ThumbMediaId>
     </Music>
     </xml>

参数说明如表4-19所示。

表4-19 参数说明

    const REPLY_TYPE_MUSIC='music';
    /**
         *生成向用户发送的音乐信息
         * @param type $musicpost
         * @return type
         * @throws Exception
         */
        public function outputMusic($musicpost){
            $textTpl = '<xml>
                <ToUserName><![CDATA[%s]]></ToUserName>
                <FromUserName><![CDATA[%s]]></FromUserName>
                <CreateTime>%s</CreateTime>
                <MsgType><![CDATA[%s]]></MsgType>
                <Music>%s</Music>
            </xml>';

$musicTpl = ' <Title><![CDATA[%s]]></Title> <Description><![CDATA[%s]]></Description> <MusicUrl><![CDATA[%s]]></MusicUrl> <HQMusicUrl><![CDATA[%s]]></HQMusicUrl> '; $music = ''; if (is_array($musicpost)){ $music .= sprintf($musicTpl, $musicpost['title'], $musicpost['description'], $musicpost['musicurl'], $musicpost['hdmusicurl']); }else{ throw new Exception('$posts数据结构错误'); }
$text = sprintf($textTpl, $this->_postData->FromUserName, $this->_postData->ToUserName, time(), self::REPLY_TYPE_MUSIC, $music); header('Content-Type: application/xml'); echo $text; } private function testMusic() { $music = array( 'title' => '在春天里', 'description' => '在春天里-汪峰', 'musicurl' => 'http://7xnmen.com1.z0.glb.clouddn.com/musicinspring.wma', 'hdmusicurl' => 'http://7xnmen.com1.z0.glb.clouddn.com/musicinspring.mp3' ); $this->outputMusic($music); }

运行结果如图4-21所示。

图4-21

4.5.6 回复图文消息

     <xml>
     <ToUserName><![CDATA[toUser]]></ToUserName>
     <FromUserName><![CDATA[fromUser]]></FromUserName>
     <CreateTime>12345678</CreateTime>
     <MsgType><![CDATA[news]]></MsgType>
     <ArticleCount>2</ArticleCount>
     <Articles>
     <item>
     <Title><![CDATA[title1]]></Title>
     <Description><![CDATA[description1]]></Description>
     <PicUrl><![CDATA[picurl]]></PicUrl>
     <Url><![CDATA[url]]></Url>
     </item>
     <item>
     <Title><![CDATA[title]]></Title>
     <Description><![CDATA[description]]></Description>
     <PicUrl><![CDATA[picurl]]></PicUrl>
     <Url><![CDATA[url]]></Url>
     </item>
     </Articles>
     </xml>

参数说明如表4-20所示。

表4-20 参数说明

     const REPLY_TYPE_NEWS = 'news';
     /**
          *生成向用户发送的图文信息
          * @param arrry $posts文章数组,每一个元素是一个文章数组,索引跟微信官方接口说明一致
          * @return string xml字符串
          */
         public function outputNews($posts = array())
         {
             $textTpl = '<xml>
                  <ToUserName><![CDATA[%s]]></ToUserName>
                  <FromUserName><![CDATA[%s]]></FromUserName>
                  <CreateTime>%s</CreateTime>
                  <MsgType><![CDATA[%s]]></MsgType>
                  <ArticleCount>%d</ArticleCount>
                  <Articles>%s</Articles>
              </xml>';

$itemTpl = '<item> <Title><![CDATA[%s]]></Title> <Discription><![CDATA[%s]]></Discription> <PicUrl><![CDATA[%s]]></PicUrl> <Url><![CDATA[%s]]></Url> </item>';
$items = ''; foreach ((array)$posts as $p) { if (is_array($p)) $items .= sprintf($itemTpl, $p['title'], $p['discription'], $p['picurl'], $p['url']); else throw new Exception('$posts数据结构错误'); }
$text = sprintf($textTpl, $this->_postData->FromUserName, $this->_postData->ToUserName, time(), self::REPLY_TYPE_NEWS, count($posts), $items); header('Content-Type: application/xml'); echo $text; }
private function testNews() { $posts = array( array( 'title' => '世界因你而不同', 'discription' => '最大化你的影响力,这就是你一生的意义。', 'picurl' => 'http://www.hers.cn/uploadfile/2011/1006/20111006022157183.jpg', 'url' => 'http://mp.weixin.qq.com/mp/appmsg/show?__biz=MjM5MDE4Njg2MQ== &appmsgid=10000072&itemidx=1&sign=bea6deb75836dbe1249dcf394e8f3c21#wechat_redirect', ), array( 'title' => '平横', 'discription' => '心要多静才能保持如此的平衡', 'picurl' => 'http://news.shangdu.com/304/2009/08/20/images/501_20090820_911.jpg', 'url' => 'http://mp.weixin.qq.com/mp/appmsg/show?__biz=MjM5MDE4Njg2MQ== &appmsgid=10000066&itemidx=1#wechat_redirect', ) ); // outputNews用来返回图文信息 $xml = $this->outputNews($posts); }

运行结果如图4-22所示。

图4-22