1 <?php
2 /*
3 方倍工作室
4 http://www.cnblogs.com/txw1958/
5 CopyRight 2014 All Rights Reserved
6 */
7
8 define("TOKEN", "weixin");
9
10 $wechatObj = new wechatCallbackapiTest();
11 if (!isset($_GET['echostr'])) {
12 $wechatObj->responseMsg();
13 }else{
14 $wechatObj->valid();
15 }
16
17 class wechatCallbackapiTest
18 {
19 //验证签名
20 public function valid()
21 {
22 $echoStr = $_GET["echostr"];
23 $signature = $_GET["signature"];
24 $timestamp = $_GET["timestamp"];
25 $nonce = $_GET["nonce"];
26 $token = TOKEN;
27 $tmpArr = array($token, $timestamp, $nonce);
28 sort($tmpArr);
29 $tmpStr = implode($tmpArr);
30 $tmpStr = sha1($tmpStr);
31 if($tmpStr == $signature){
32 echo $echoStr;
33 exit;
34 }
35 }
36
37 //响应消息
38 public function responseMsg()
39 {
40 $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
41 if (!empty($postStr)){
42 $this->logger("R ".$postStr);
43 $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
44 $RX_TYPE = trim($postObj->MsgType);
45
46 //消息类型分离
47 switch ($RX_TYPE)
48 {
49 case "event":
50 $result = $this->receiveEvent($postObj);
51 break;
52 case "text":
53 $result = $this->receiveText($postObj);
54 break;
55 case "image":
56 $result = $this->receiveImage($postObj);
57 break;
58 case "location":
59 $result = $this->receiveLocation($postObj);
60 break;
61 case "voice":
62 $result = $this->receiveVoice($postObj);
63 break;
64 case "video":
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 ".$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 = "欢迎关注方倍工作室 ";
90 $content .= (!empty($object->EventKey))?("\n来自二维码场景 ".str_replace("qrscene_","",$object->EventKey)):"";
91 break;
92 case "unsubscribe":
93 $content = "取消关注";
94 break;
95 case "SCAN":
96 $content = "扫描场景 ".$object->EventKey;
97 break;
98 case "CLICK":
99 switch ($object->EventKey)
100 {
101 case "COMPANY":
102 $content = array();
103 $content[] = array("Title"=>"多图文1标题", "Description"=>"", "PicUrl"=>"http://discuz.comli.com/weixin/weather/icon/cartoon.jpg", "Url" =>"http://m.cnblogs.com/?u=txw1958");
104 break;
105 default:
106 $content = "点击菜单:".$object->EventKey;
107 break;
108 }
109 break;
110 case "LOCATION":
111 $content = "上传位置:纬度 ".$object->Latitude.";经度 ".$object->Longitude;
112 break;
113 case "VIEW":
114 $content = "跳转链接 ".$object->EventKey;
115 break;
116 case "MASSSENDJOBFINISH":
117 $content = "消息ID:".$object->MsgID.",结果:".$object->Status.",粉丝数:".$object->TotalCount.",过滤:".$object->FilterCount.",发送成功:".$object->SentCount.",发送失败:".$object->ErrorCount;
118 break;
119 default:
120 $content = "receive a new event: ".$object->Event;
121 break;
122 }
123 if(is_array($content)){
124 if (isset($content[0])){
125 $result = $this->transmitNews($object, $content);
126 }else if (isset($content['MusicUrl'])){
127 $result = $this->transmitMusic($object, $content);
128 }
129 }else{
130 $result = $this->transmitText($object, $content);
131 }
132
133 return $result;
134 }
135
136 //接收文本消息
137 private function receiveText($object)
138 {
139 $keyword = trim($object->Content);
140 //多客服人工回复模式
141 if (strstr($keyword, "您好") || strstr($keyword, "你好") || strstr($keyword, "在吗")){
142 $result = $this->transmitService($object);
143 }
144 //自动回复模式
145 else{
146 if (strstr($keyword, "文本")){
147 $content = "这是个文本消息";
148 }else if (strstr($keyword, "单图文")){
149 $content = array();
150 $content[] = array("Title"=>"单图文标题", "Description"=>"单图文内容", "PicUrl"=>"http://discuz.comli.com/weixin/weather/icon/cartoon.jpg", "Url" =>"http://m.cnblogs.com/?u=txw1958");
151 }else if (strstr($keyword, "图文") || strstr($keyword, "多图文")){
152 $content = array();
153 $content[] = array("Title"=>"多图文1标题", "Description"=>"", "PicUrl"=>"http://discuz.comli.com/weixin/weather/icon/cartoon.jpg", "Url" =>"http://m.cnblogs.com/?u=txw1958");
154 $content[] = array("Title"=>"多图文2标题", "Description"=>"", "PicUrl"=>"http://d.hiphotos.bdimg.com/wisegame/pic/item/f3529822720e0cf3ac9f1ada0846f21fbe09aaa3.jpg", "Url" =>"http://m.cnblogs.com/?u=txw1958");
155 $content[] = array("Title"=>"多图文3标题", "Description"=>"", "PicUrl"=>"http://g.hiphotos.bdimg.com/wisegame/pic/item/18cb0a46f21fbe090d338acc6a600c338644adfd.jpg", "Url" =>"http://m.cnblogs.com/?u=txw1958");
156 }else if (strstr($keyword, "音乐")){
157 $content = array();
158 $content = array("Title"=>"最炫民族风", "Description"=>"歌手:凤凰传奇", "MusicUrl"=>"http://121.199.4.61/music/zxmzf.mp3", "HQMusicUrl"=>"http://121.199.4.61/music/zxmzf.mp3");
159 }else{
160 $content = date("Y-m-d H:i:s",time())."\n技术支持 方倍工作室";
161 }
162
163 if(is_array($content)){
164 if (isset($content[0]['PicUrl'])){
165 $result = $this->transmitNews($object, $content);
166 }else if (isset($content['MusicUrl'])){
167 $result = $this->transmitMusic($object, $content);
168 }
169 }else{
170 $result = $this->transmitText($object, $content);
171 }
172 }
173
174 return $result;
175 }
176
177 //接收图片消息
178 private function receiveImage($object)
179 {
180 $content = array("MediaId"=>$object->MediaId);
181 $result = $this->transmitImage($object, $content);
182 return $result;
183 }
184
185 //接收位置消息
186 private function receiveLocation($object)
187 {
188 $content = "你发送的是位置,纬度为:".$object->Location_X.";经度为:".$object->Location_Y.";缩放级别为:".$object->Scale.";位置为:".$object->Label;
189 $result = $this->transmitText($object, $content);
190 return $result;
191 }
192
193 //接收语音消息
194 private function receiveVoice($object)
195 {
196 if (isset($object->Recognition) && !empty($object->Recognition)){
197 $content = "你刚才说的是:".$object->Recognition;
198 $result = $this->transmitText($object, $content);
199 }else{
200 $content = array("MediaId"=>$object->MediaId);
201 $result = $this->transmitVoice($object, $content);
202 }
203
204 return $result;
205 }
206
207 //接收视频消息
208 private function receiveVideo($object)
209 {
210 $content = array("MediaId"=>$object->MediaId, "ThumbMediaId"=>$object->ThumbMediaId, "Title"=>"", "Description"=>"");
211 $result = $this->transmitVideo($object, $content);
212 return $result;
213 }
214
215 //接收链接消息
216 private function receiveLink($object)
217 {
218 $content = "你发送的是链接,标题为:".$object->Title.";内容为:".$object->Description.";链接地址为:".$object->Url;
219 $result = $this->transmitText($object, $content);
220 return $result;
221 }
222
223 //回复文本消息
224 private function transmitText($object, $content)
225 {
226 $xmlTpl = "<xml>
227 <ToUserName><![CDATA[%s]]></ToUserName>
228 <FromUserName><![CDATA[%s]]></FromUserName>
229 <CreateTime>%s</CreateTime>
230 <MsgType><![CDATA[text]]></MsgType>
231 <Content><![CDATA[%s]]></Content>
232 </xml>";
233 $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, time(), $content);
234 return $result;
235 }
236
237 //回复图片消息
238 private function transmitImage($object, $imageArray)
239 {
240 $itemTpl = "<Image>
241 <MediaId><![CDATA[%s]]></MediaId>
242 </Image>";
243
244 $item_str = sprintf($itemTpl, $imageArray['MediaId']);
245
246 $xmlTpl = "<xml>
247 <ToUserName><![CDATA[%s]]></ToUserName>
248 <FromUserName><![CDATA[%s]]></FromUserName>
249 <CreateTime>%s</CreateTime>
250 <MsgType><![CDATA[image]]></MsgType>
251 $item_str
252 </xml>";
253
254 $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, time());
255 return $result;
256 }
257
258 //回复语音消息
259 private function transmitVoice($object, $voiceArray)
260 {
261 $itemTpl = "<Voice>
262 <MediaId><![CDATA[%s]]></MediaId>
263 </Voice>";
264
265 $item_str = sprintf($itemTpl, $voiceArray['MediaId']);
266
267 $xmlTpl = "<xml>
268 <ToUserName><![CDATA[%s]]></ToUserName>
269 <FromUserName><![CDATA[%s]]></FromUserName>
270 <CreateTime>%s</CreateTime>
271 <MsgType><![CDATA[voice]]></MsgType>
272 $item_str
273 </xml>";
274
275 $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, time());
276 return $result;
277 }
278
279 //回复视频消息
280 private function transmitVideo($object, $videoArray)
281 {
282 $itemTpl = "<Video>
283 <MediaId><![CDATA[%s]]></MediaId>
284 <ThumbMediaId><![CDATA[%s]]></ThumbMediaId>
285 <Title><![CDATA[%s]]></Title>
286 <Description><![CDATA[%s]]></Description>
287 </Video>";
288
289 $item_str = sprintf($itemTpl, $videoArray['MediaId'], $videoArray['ThumbMediaId'], $videoArray['Title'], $videoArray['Description']);
290
291 $xmlTpl = "<xml>
292 <ToUserName><![CDATA[%s]]></ToUserName>
293 <FromUserName><![CDATA[%s]]></FromUserName>
294 <CreateTime>%s</CreateTime>
295 <MsgType><![CDATA[video]]></MsgType>
296 $item_str
297 </xml>";
298
299 $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, time());
300 return $result;
301 }
302
303 //回复图文消息
304 private function transmitNews($object, $newsArray)
305 {
306 if(!is_array($newsArray)){
307 return;
308 }
309 $itemTpl = " <item>
310 <Title><![CDATA[%s]]></Title>
311 <Description><![CDATA[%s]]></Description>
312 <PicUrl><![CDATA[%s]]></PicUrl>
313 <Url><![CDATA[%s]]></Url>
314 </item>
315 ";
316 $item_str = "";
317 foreach ($newsArray as $item){
318 $item_str .= sprintf($itemTpl, $item['Title'], $item['Description'], $item['PicUrl'], $item['Url']);
319 }
320 $xmlTpl = "<xml>
321 <ToUserName><![CDATA[%s]]></ToUserName>
322 <FromUserName><![CDATA[%s]]></FromUserName>
323 <CreateTime>%s</CreateTime>
324 <MsgType><![CDATA[news]]></MsgType>
325 <ArticleCount>%s</ArticleCount>
326 <Articles>
327 $item_str</Articles>
328 </xml>";
329
330 $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, time(), count($newsArray));
331 return $result;
332 }
333
334 //回复音乐消息
335 private function transmitMusic($object, $musicArray)
336 {
337 $itemTpl = "<Music>
338 <Title><![CDATA[%s]]></Title>
339 <Description><![CDATA[%s]]></Description>
340 <MusicUrl><![CDATA[%s]]></MusicUrl>
341 <HQMusicUrl><![CDATA[%s]]></HQMusicUrl>
342 </Music>";
343
344 $item_str = sprintf($itemTpl, $musicArray['Title'], $musicArray['Description'], $musicArray['MusicUrl'], $musicArray['HQMusicUrl']);
345
346 $xmlTpl = "<xml>
347 <ToUserName><![CDATA[%s]]></ToUserName>
348 <FromUserName><![CDATA[%s]]></FromUserName>
349 <CreateTime>%s</CreateTime>
350 <MsgType><![CDATA[music]]></MsgType>
351 $item_str
352 </xml>";
353
354 $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, time());
355 return $result;
356 }
357
358 //回复多客服消息
359 private function transmitService($object)
360 {
361 $xmlTpl = "<xml>
362 <ToUserName><![CDATA[%s]]></ToUserName>
363 <FromUserName><![CDATA[%s]]></FromUserName>
364 <CreateTime>%s</CreateTime>
365 <MsgType><![CDATA[transfer_customer_service]]></MsgType>
366 </xml>";
367 $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, time());
368 return $result;
369 }
370
371 //日志记录
372 private function logger($log_content)
373 {
374 if(isset($_SERVER['HTTP_APPNAME'])){ //SAE
375 sae_set_display_errors(false);
376 sae_debug($log_content);
377 sae_set_display_errors(true);
378 }else if($_SERVER['REMOTE_ADDR'] != "127.0.0.1"){ //LOCAL
379 $max_size = 10000;
380 $log_filename = "log.xml";
381 if(file_exists($log_filename) and (abs(filesize($log_filename)) > $max_size)){unlink($log_filename);}
382 file_put_contents($log_filename, date('H:i:s')." ".$log_content."\r\n", FILE_APPEND);
383 }
384 }
385 }
386 ?>