映月读书网 > 微信公众平台开发:从零基础到ThinkPHP5高性能框架实践 > 4.4 案例实践 >

4.4 案例实践

4.4.1 微信基础消息SDK

基础消息的SDK将前面章节的各种接收消息类型进行了处理,另外对被动发送消息类型进行了定义。其代码如下。


  1 <?php
  2 /*
  3     方倍工作室 http:// www.fangbei.org/
  4     CopyRight 2016 All Rights Reserved
  5 */
  6 header('Content-type:text');
  7 
  8 define("TOKEN", "weixin");
  9 $wechatObj = new wechatCallbackapiTest;
 10 if (!isset($_GET['echostr'])) {
 11     $wechatObj->responseMsg;
 12 }else{
 13     $wechatObj->valid;
 14 }
 15 
 16 class wechatCallbackapiTest
 17 {
 18     // 验证签名
 19     public function valid
 20     {
 21         $echoStr = $_GET["echostr"];
 22         $signature = $_GET["signature"];
 23         $timestamp = $_GET["timestamp"];
 24         $nonce = $_GET["nonce"];
 25         $token = TOKEN;
 26         $tmpArr = array($token, $timestamp, $nonce);
 27         sort($tmpArr, SORT_STRING);
 28         $tmpStr = implode($tmpArr);
 29         $tmpStr = sha1($tmpStr);
 30         if($tmpStr == $signature){
 31             echo $echoStr;
 32             exit;
 33         }
 34     }
 35 
 36     // 响应消息
 37     public function responseMsg
 38     {
 39         $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
 40         if (!empty($postStr)){
 41             $this->logger("R \r\n".$postStr);
 42             $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_
                NOCDATA);
 43             $RX_TYPE = trim($postObj->MsgType);
 44             
 45             // 消息类型分离
 46             switch ($RX_TYPE)
 47             {
 48                 case "event":                // 事件
 49                     $result = $this->receiveEvent($postObj);
 50                     break;
 51                 case "text":                // 文本
 52                     $result = $this->receiveText($postObj);
 53                     break;
 54                 case "image":                // 图片
 55                     $result = $this->receiveImage($postObj);
 56                     break;
 57                 case "location":        // 位置
 58                     $result = $this->receiveLocation($postObj);
 59                     break;
 60                 case "voice":                // 语音
 61                     $result = $this->receiveVoice($postObj);
 62                     break;
 63                 case "video":                // 视频
 64                 case "shortvideo":
 65                     $result = $this->receiveVideo($postObj);
 66                     break;
 67                 case "link":                // 链接
 68                     $result = $this->receiveLink($postObj);
 69                     break;
 70                 default:
 71                     $result = "unknown msg type: ".$RX_TYPE;
 72                     break;
 73             }
 74             $this->logger("T \r\n".$result);
 75             echo $result;
 76         }else {
 77             echo "";
 78             exit;
 79         }
 80     }
 81 
 82     // 接收事件消息
 83     private function receiveEvent($object)
 84     {
 85         $content = "";
 86         switch ($object->Event)
 87         {
 88             case "subscribe":
 89                 $content = "欢迎关注方倍工作室 \n请回复以下关键字:文本 表情 单图文 多
        图文 音乐\n请按住说话 或 点击 + 再分别发送以下内容:语音 图片 小视频 我的收藏 位置";
 90                 break;
 91             case "unsubscribe":
 92                 $content = "取消关注";
 93                 break;
 94             default:
 95                 $content = "receive a new event: ".$object->Event;
 96                 break;
 97         }
 98 
 99         if(is_array($content)){
100             $result = $this->transmitNews($object, $content);
101         }else{
102             $result = $this->transmitText($object, $content);
103         }
104         return $result;
105     }
106 
107     // 接收文本消息
108     private function receiveText($object)
109     {
110         $keyword = trim($object->Content);
111 
112         if (strstr($keyword, "文本")){                // 回复文本
113             $content = "这是个文本消息";
114         }else if (strstr($keyword, "表情")){
115             $content = "微笑:/::)\n乒乓:/:oo\n中国:".$this->bytes_to_emoji(0x
        1F1E8).$this->bytes_to_emoji(0x1F1F3)."\n仙人掌:".$this->bytes_to_emoji(0x1F335);
116         }else if (strstr($keyword, "单图文")){        // 回复图文消息
117             $content = array;
118             $content = array("Title"=>"单图文标题",  "Description"=>"单图文内
        容", "PicUrl"=>"http:// discuz.comli.com/weixin/weather/icon/cartoon.jpg", 
        "Url" =>"http:// m.cnblogs.com/?u=txw1958");
119         }else if (strstr($keyword, "图文") || strstr($keyword, "多图文")){
120             $content = array;
121             $content = array("Title"=>"多图文1标题", "Description"=>"", "Pic
        Url"=>"http:// discuz.comli.com/weixin/weather/icon/cartoon.jpg", "Url" =>
        "http:// m.cnblogs.com/?u=txw1958");
122             $content = array("Title"=>"多图文2标题", "Description"=>"", "Pic
        Url"=>"http:// d.hiphotos.bdimg.com/wisegame/pic/item/f3529822720e0cf3ac9f
        1ada0846f21fbe09aaa3.jpg", "Url" =>"http:// m.cnblogs.com/?u=txw1958");
123             $content = array("Title"=>"多图文3标题", "Description"=>"", "Pic
        Url"=>"http:// g.hiphotos.bdimg.com/wisegame/pic/item/18cb0a46f21fbe09
        0d338acc6a600c338644adfd.jpg", "Url" =>"http:// m.cnblogs.com/?u=txw1958");
124         }else if (strstr($keyword, "音乐")){                // 回复音乐消息
125             $content = array;
126             $content = array("Title"=>"最炫民族风", "Description"=>"歌手:凤凰传
        奇", "MusicUrl"=>"http:// mascot-music.stor.sinaapp.com/zxmzf.mp3", "HQMu
        sicUrl"=>"http:// mascot-music.stor.sinaapp.com/zxmzf.mp3"); 
127         }else{
128             $content = date("Y-m-d H:i:s",time)."\nOpenID:".$object->FromUser
        Name."\n技术支持 方倍工作室";
129         }
130 
131         if(is_array($content)){
132             if (isset($content[0])){
133                 $result = $this->transmitNews($object, $content);
134             }else if (isset($content['MusicUrl'])){
135                 $result = $this->transmitMusic($object, $content);
136             }
137         }else{
138             $result = $this->transmitText($object, $content);
139         }
140         return $result;
141     }
142 
143     // 接收图片消息
144     private function receiveImage($object)
145     {
146         $content = array("MediaId"=>$object->MediaId);
147         $result = $this->transmitImage($object, $content);
148         return $result;
149     }
150 
151     // 接收位置消息
152     private function receiveLocation($object)
153     {
154         $content = "你发送的是位置,经度为:".$object->Location_Y.";纬度为:".$ob
        ject->Location_X.";缩放级别为:".$object->Scale.";位置为:".$object->Label;
155         $result = $this->transmitText($object, $content);
156         return $result;
157     }
158 
159     // 接收语音消息
160     private function receiveVoice($object)
161     {
162         if (isset($object->Recognition) && !empty($object->Recognition)){
163             $content = "你刚才说的是:".$object->Recognition;
164             $result = $this->transmitText($object, $content);
165         }else{
166             $content = array("MediaId"=>$object->MediaId);
167             $result = $this->transmitVoice($object, $content);
168         }
169         return $result;
170     }
171 
172     // 接收视频消息
173     private function receiveVideo($object)
174     {
175         $content = array("MediaId"=>$object->MediaId, "ThumbMediaId"=>$object->
            ThumbMediaId, "Title"=>"", "Description"=>"");
176         $result = $this->transmitVideo($object, $content);
177         return $result;
178     }
179 
180     // 接收链接消息
181     private function receiveLink($object)
182     {
183         $content = "你发送的是链接,标题为:".$object->Title.";内容为:".$object->
            Description.";链接地址为:".$object->Url;
184         $result = $this->transmitText($object, $content);
185         return $result;
186     }
187     
188     // 回复文本消息
189     private function transmitText($object, $content)
190     {
191         if (!isset($content) || empty($content)){
192             return "";
193         }
194 
195         $xmlTpl = "<xml>
196                    <ToUserName><![CDATA[%s]]></ToUserName>
197                    <FromUserName><![CDATA[%s]]></FromUserName>
198                    <CreateTime>%s</CreateTime>
199                    <MsgType><![CDATA[text]]></MsgType>
200                    <Content><![CDATA[%s]]></Content>
201                    </xml>";
202         $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, 
        time, $content);
203 
204         return $result;
205     }
206 
207     // 回复图文消息
208     private function transmitNews($object, $newsArray)
209     {
210         if(!is_array($newsArray)){
211             return "";
212         }
213         $itemTpl = "<item>
214                     <Title><![CDATA[%s]]></Title>
215                     <Description><![CDATA[%s]]></Description>
216                     <PicUrl><![CDATA[%s]]></PicUrl>
217                     <Url><![CDATA[%s]]></Url>
218                     </item>";
219             
220         $item_str = "";
221         foreach ($newsArray as $item){
222             $item_str .= sprintf($itemTpl, $item['Title'], $item['Description'], 
                $item['PicUrl'], $item['Url']);
223         }
224         $xmlTpl = "<xml>
225                    <ToUserName><![CDATA[%s]]></ToUserName>
226                    <FromUserName><![CDATA[%s]]></FromUserName>
227                    <CreateTime>%s</CreateTime>
228                    <MsgType><![CDATA[news]]></MsgType>
229                    <ArticleCount>%s</ArticleCount>
230                    <Articles>
231                    $item_str    </Articles>
232                    </xml>";
233 
234         $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, 
        time, count($newsArray));
235         return $result;
236     }
237 
238     // 回复音乐消息
239     private function transmitMusic($object, $musicArray)
240     {
241         if(!is_array($musicArray)){
242             return "";
243         }
244         $itemTpl = "<Music>
245                     <Title><![CDATA[%s]]></Title>
246                     <Description><![CDATA[%s]]></Description>
247                     <MusicUrl><![CDATA[%s]]></MusicUrl>
248                     <HQMusicUrl><![CDATA[%s]]></HQMusicUrl>
249                     </Music>";
250 
251         $item_str = sprintf($itemTpl, $musicArray['Title'], $musicArray['Des
        cription'], $musicArray['MusicUrl'], $musicArray['HQMusicUrl']);
252 
253         $xmlTpl = "<xml>
254                    <ToUserName><![CDATA[%s]]></ToUserName>
255                    <FromUserName><![CDATA[%s]]></FromUserName>
256                    <CreateTime>%s</CreateTime>
257                    <MsgType><![CDATA[music]]></MsgType>
258                    $item_str
259                    </xml>";
260 
261         $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, 
        time);
262         return $result;
263     }
264 
265     // 回复图片消息
266     private function transmitImage($object, $imageArray)
267     {
268         $itemTpl = "<Image>
269                     <MediaId><![CDATA[%s]]></MediaId>
270                     </Image>";
271 
272         $item_str = sprintf($itemTpl, $imageArray['MediaId']);
273 
274         $xmlTpl = "<xml>
275                    <ToUserName><![CDATA[%s]]></ToUserName>
276                    <FromUserName><![CDATA[%s]]></FromUserName>
277                    <CreateTime>%s</CreateTime>
278                    <MsgType><![CDATA[image]]></MsgType>
279                    $item_str
280                    </xml>";
281 
282         $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, 
        time);
283         return $result;
284     }
285 
286     // 回复语音消息
287     private function transmitVoice($object, $voiceArray)
288     {
289         $itemTpl = "<Voice>
290                     <MediaId><![CDATA[%s]]></MediaId>
291                     </Voice>";
292 
293         $item_str = sprintf($itemTpl, $voiceArray['MediaId']);
294         $xmlTpl = "<xml>
295                    <ToUserName><![CDATA[%s]]></ToUserName>
296                    <FromUserName><![CDATA[%s]]></FromUserName>
297                    <CreateTime>%s</CreateTime>
298                    <MsgType><![CDATA[voice]]></MsgType>
299                    $item_str
300                    </xml>";
301 
302         $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, 
        time);
303         return $result;
304     }
305 
306     // 回复视频消息
307     private function transmitVideo($object, $videoArray)
308     {
309         $itemTpl = "<Video>
310                     <MediaId><![CDATA[%s]]></MediaId>
311                     <ThumbMediaId><![CDATA[%s]]></ThumbMediaId>
312                     <Title><![CDATA[%s]]></Title>
313                     <Description><![CDATA[%s]]></Description>
314                     </Video>";
315 
316         $item_str = sprintf($itemTpl, $videoArray['MediaId'], $videoArray['Thu
        mbMediaId'], $videoArray['Title'], $videoArray['Description']);
317 
318         $xmlTpl = "<xml>
319                    <ToUserName><![CDATA[%s]]></ToUserName>
320                    <FromUserName><![CDATA[%s]]></FromUserName>
321                    <CreateTime>%s</CreateTime>
322                    <MsgType><![CDATA[video]]></MsgType>
323                    $item_str
324                    </xml>";
325 
326         $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, 
        time);
327         return $result;
328     }
329 
330     // 日志记录
331     private function logger($log_content)
332     {
333         if(isset($_SERVER['HTTP_APPNAME'])){   // SAE
334             sae_set_display_errors(false);
335             sae_debug($log_content);
336             sae_set_display_errors(true);
337         }else if($_SERVER['REMOTE_ADDR'] != "127.0.0.1"){ // LOCAL
338             $max_size = 1000000;
339             $log_filename = "log.xml";
340             if(file_exists($log_filename) and (abs(filesize($log_filename)) > $max_
                size)){unlink($log_filename);}
341             file_put_contents($log_filename, date('Y-m-d H:i:s')." ".$log_content.|
                "\r\n", FILE_APPEND);
342         }
343     }
344 }
345 ?>
 

在responseMsg方法中,先提取消息类型$postObj->MsgType,从而实现各种消息类型的分离。在类wechatCallbackapiTest中,为每种消息类型定义了接收方法。在每个方法中,返回消息的主要特征值,组成文本信息作为内容回复。

在接收到文本指令回复文本、图文(包括单图文和多图文)、音乐3种消息时,是使用直接构造相应消息类型实现的,而图片、语音、视频3种消息需要MediaId参数,在这里直接使用用户发送过来的消息中的MediaId,然后组装成响应消息回复。