首页 » 微信公众平台开发:从零基础到ThinkPHP5高性能框架实践 » 微信公众平台开发:从零基础到ThinkPHP5高性能框架实践全文在线阅读

《微信公众平台开发:从零基础到ThinkPHP5高性能框架实践》25.4.1 微信消息接口实现

关灯直达底部

微信消息接口的目录为application/weixin/controller/Index.php。它是微信的开发者接口,用于收发用户发送给公众号的消息并自动回复。

微信消息接口的实现代码如下。


  1 <?php  2 namespace app/weixin/controller;  3 use think/Controller;  4 use think/Db;  5   6 define("TOKEN", "fangbei");  7 class Index extends Controller  8 {  9     public function index{ 10         if (!isset($_GET['echostr'])) { 11             $this->responseMsg; 12         }else{ 13             $this->valid; 14         } 15     } 16      17     // 验证签名 18     public function valid 19     { 20         $echoStr = $_GET["echostr"]; 21         $signature = $_GET["signature"]; 22         $timestamp = $_GET["timestamp"]; 23         $nonce = $_GET["nonce"]; 24         $token = TOKEN; 25         $tmpArr = array($token, $timestamp, $nonce); 26         sort($tmpArr); 27         $tmpStr = implode($tmpArr); 28         $tmpStr = sha1($tmpStr); 29         if($tmpStr == $signature){ 30             echo $echoStr; 31             exit; 32         } 33     } 34      35     // 响应 36     public function responseMsg 37     { 38         $postStr = $GLOBALS["HTTP_RAW_POST_DATA"]; 39         if (!empty($postStr)){ 40             $this->logger("R ".$postStr); 41             $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_             NOCDATA); 42             $RX_TYPE = trim($postObj->MsgType); 43  44             if (($postObj->MsgType == "event") && ($postObj->Event == "subscribe" ||                 $postObj->Event == "unsubscribe" || $postObj->Event == "TEMPLATE-                SENDJOBFINISH")){ 45                 // 过滤关注和取消关注事件 46             }else{ 47                 // 更新互动记录 48                 Db::name('user')->where('openid',strval($postObj->FromUserName))->                        setField('heartbeat', time); 49             } 50             // 消息类型分离 51             switch ($RX_TYPE) 52             { 53                 case "event": 54                     $result = $this->receiveEvent($postObj); 55                     break; 56                 case "text": 57                     $result = $this->receiveText($postObj); 58                     break; 59                 default: 60                     $result = "unknown msg type: ".$RX_TYPE; 61                     break; 62             } 63             $this->logger("T ".$result); 64             echo $result; 65         }else { 66             echo ""; 67             exit; 68         } 69     } 70      71      72     // 接收事件消息 73     private function receiveEvent($object) 74     { 75         $weixin = new /weixin/Wxapi; 76         $openid = strval($object->FromUserName); 77         $content = ""; 78  79         switch ($object->Event) 80         { 81             case "subscribe": 82                 $info = $weixin->get_user_info($openid); 83                 $municipalities = array("北京", "上海", "天津", "重庆", "香港",                     "澳门"); 84                 $sexes = array("", "男", "女"); 85                 $data = array; 86                 $data['openid'] = $openid; 87                 $data['nickname'] = str_replace("'", "", $info['nickname']); 88                 $data['sex'] = $sexes[$info['sex']]; 89                 $data['country'] = $info['country']; 90                 $data['province'] = $info['province']; 91                 $data['city'] = (in_array($info['province'], $municipalities))                    ?$info['province'] : $info['city']; 92                 $data['scene'] = (isset($object->EventKey) && (stripos(strval                    ($object->EventKey),"qrscene_")))?str_replace("qrscene_","",$object                     ->EventKey):"0"; 93  94                 $data['headimgurl'] = $info['headimgurl']; 95                 $data['subscribe'] = $info['subscribe_time']; 96                 $data['heartbeat'] = time; 97                 $data['remark'] = $info['remark']; 98                 $data['score'] = 1; 99                 $data['tagid'] = $info['tagid_list'];100                 Db::name('user')->insert($data);101                 $content = "欢迎关注,".$info['nickname'];102                 break;103             case "unsubscribe":104                 db('user')->where('openid',$openid)->delete;105                 break;106             case "CLICK":107                 switch ($object->EventKey)108                 {109                     default:110                         $content = "点击菜单:".$object->EventKey;111                         break;112                 }113                 break;114             default:115                 $content = "";116                 break;117         }118         if(is_array($content)){119             $result = $this->transmitNews($object, $content);120         }else{121             $result = $this->transmitText($object, $content);122         }123 124         return $result;125     }126 127     // 接收文本消息128     private function receiveText($object)129     {130         $keyword = trim($object->Content);131         $openid = strval($object->FromUserName);132         $content = "";133 134         if (strstr($keyword, "文本")){135             $content = "这是个文本消息/n".$openid;136         }else{137             $content = date("Y-m-d H:i:s",time)."/n".$openid."技术支持 方倍工作室";138         }139 140         if(is_array($content)){141             $result = $this->transmitNews($object, $content);142         }else{143             $result = $this->transmitText($object, $content);144         }145         return $result;146     }147 148     // 回复文本消息149     private function transmitText($object, $content)150     {151         if (!isset($content) || empty($content)){152             return "";153         }154         $xmlTpl = "<xml>155 <ToUserName><![CDATA[%s]]></ToUserName>156 <FromUserName><![CDATA[%s]]></FromUserName>157 <CreateTime>%s</CreateTime>158 <MsgType><![CDATA[text]]></MsgType>159 <Content><![CDATA[%s]]></Content>160 </xml>";161         $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, time,               $content);162         return $result;163     }164 165     // 回复图文消息166     private function transmitNews($object, $newsArray)167     {168         if(!is_array($newsArray)){169             return "";170         }171         $itemTpl = "    <item>172                    <Title><![CDATA[%s]]></Title>173                    <Description><![CDATA[%s]]></Description>174                    <PicUrl><![CDATA[%s]]></PicUrl>175                    <Url><![CDATA[%s]]></Url>176                    </item>177                    ";178         $item_str = "";179         foreach ($newsArray as $item){180             $item_str .= sprintf($itemTpl, $item['Title'], $item['Description'],                             $item['PicUrl'], $item['Url']);181         }182         $xmlTpl = "<xml>183                   <ToUserName><![CDATA[%s]]></ToUserName>184                   <FromUserName><![CDATA[%s]]></FromUserName>185                   <CreateTime>%s</CreateTime>186                   <MsgType><![CDATA[news]]></MsgType>187                   <ArticleCount>%s</ArticleCount>188                   <Articles>189                   $item_str</Articles>190                   </xml>";191 192         $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName,                      time, count($newsArray));193         return $result;194     }195 196     // 日志记录197     private function logger($log_content)198     {199         if(isset($_SERVER['HTTP_APPNAME'])){                        // SAE200             sae_set_display_errors(false);201             sae_debug($log_content);202             sae_set_display_errors(true);203         }else if($_SERVER['REMOTE_ADDR'] != "127.0.0.2"){        // LOCAL204             $max_size = 1000000;205             $log_filename = "log.xml";206             if(file_exists($log_filename) and (abs(filesize($log_filename)) > $max_size))                {unlink($log_filename);}207             file_put_contents($log_filename, date('H:i:s')." ".$log_content."/        r/n", FILE_APPEND);208         }209     }210 } 

上述接口方法中,实现了微信的Token验证,事件、菜单和文本消息的接收,以及文本、图文消息的回复。

根据上述接口,配置微信开发者接口时,其接口为http://www.doucube.com/weixin/index/index,可以简化为http://www.doucube.com/weixin,Token则为fangbei。设置成功后的效果如图25-5所示。

图25-5 开发者接口配置成功