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,然后组装成响应消息回复。