微信公眾平臺萬能程式碼詳解-php語言(二)
阿新 • • 發佈:2019-01-31
1.基礎知識在上一篇地址有講解和圖片,內容大致包括微信開發者模式後臺配置、微信公眾開發者文件程式碼詳解。
2.本篇將粘貼出包括所有型別在內的訊息處理辦法,在開發者模式下用程式碼完成所有編輯模式的基礎內容。
3.本篇程式碼是最基礎的微信公眾平臺功能,大家要掌握如何套用。
===============================================萬能的閹割線================================================================
<?php /* 李凡的實驗 */ define("TOKEN", "weixin"); //定義常量"TOKEN"為weixin,這裡的weixin和上圖Token值一致。 $wechatObj = new wechatCallbackapiTest(); //將wechatCallbackapiTest類例項化,物件名為wechatObj。 /* 開發者文件——驗證訊息真實性:http://mp.weixin.qq.com/wiki/4/2ccadaef44fe1e4b0322355c2312bfa8.html 在開發者首次提交驗證申請時,微信伺服器將傳送GET請求到填寫的URL上,並且帶上四個引數(signature、timestamp、nonce、echostr),開發者通過對簽名(即signature)的效驗,來判斷此條訊息的真實性。此後,每次開發者接收使用者訊息的時候,微信也都會帶上前面三個引數(signature、timestamp、nonce)訪問開發者設定的URL,開發者依然通過對簽名的效驗判斷此條訊息的真實性。校驗方式與首次提交驗證申請一致。 */ if (!isset($_GET['echostr'])) { //從微信伺服器(你的公眾號)獲取隨機字元$echostr;isset()判斷引數是否設定,引數存在且有值為true $wechatObj->responseMsg(); //若沒有echostr,表示已經通過驗證,直接呼叫responseMsg()方法 }else{ $wechatObj->valid(); //若存在echostr,表示第一次提交驗證申請,呼叫驗證方法valid(),判斷微信伺服器(你的公眾號)與網站伺服器的是否連通。 } class wechatCallbackapiTest { //驗證訊息 public function valid() { $echoStr = $_GET["echostr"]; //微信伺服器傳送來的字串,驗證通過,將該字串原樣輸出,表示驗證成功! if($this->checkSignature()){ //呼叫checkSignature()方法檢查簽名(Signature)是否一致 echo $echoStr; exit; } } //檢查簽名 //官網可下載程式碼——http://mp.weixin.qq.com/wiki/4/2ccadaef44fe1e4b0322355c2312bfa8.html private function checkSignature() { $signature = $_GET["signature"]; //從微信伺服器(你的公眾號)獲取簽名 $timestamp = $_GET["timestamp"]; //從微信伺服器獲取時間戳 $nonce = $_GET["nonce"]; //從微信伺服器獲取隨機數 $token = TOKEN; //將自己核心程式碼中定義的Token賦值到這裡 $tmpArr = array($token, $timestamp, $nonce); //建立陣列變數——token+timestamp+nonce sort($tmpArr, SORT_STRING); //對$tmpArr陣列中的 引數 排序;SORT_STRING:把值作為字串來處理。 $tmpStr = implode($tmpArr); //把陣列中的 引數 組合為一個字串——$tmpStr=$token+$timestamp+$nonce $tmpStr = sha1($tmpStr); //對字串$tmpStr進行sha1加密。沒有問題的話它會和 $signature 一致 if($tmpStr == $signature){ //驗證Token一致,通過驗證,返回true return true; }else{ return false; } } //================================================請求校驗結束,相應訊息一步曲開始======================================================== //響應訊息 public function responseMsg() { $postStr = $GLOBALS["HTTP_RAW_POST_DATA"]; //獲取微信端傳送的訊息;因為訊息是XML資料格式,使用$_POST無法解析,故使用此方法獲取 if (!empty($postStr)){ //不是空內容,即有訊息傳送過來的話,就... $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA); /*將$postStr變數進行解析並將 解析後所有資料 賦予 新物件$postObj。 simplexml_load_string():PHP中解析XML的函式; 第一個引數:要解析的XML字串; 第二個引數:規定新物件所屬類——SimpleXMLElement; 第三個引數:將CDATA設定為文字節點,CDATA標籤中的文字XML不解析。*/ $RX_TYPE = trim($postObj->MsgType); //從$postObj物件獲取訊息型別 MsgType。包括文字、圖片、語音、視訊、位置、連結 + 事件 switch ($RX_TYPE) //根據不同的訊息型別,進行不同的處理 { case "event": $result = $this->receiveEvent($postObj); //訊息型別屬於事件(event),呼叫 接收到事件 方法,將包含所有資料的$postObj傳參傳過去 break; case "text": $result = $this->receiveText($postObj); //使用者傳送的是 文字,呼叫 接收到文字 方法 break; case "image": $result = $this->receiveImage($postObj); //使用者傳送的是 圖片,呼叫 接收到圖片 方法 break; case "location": $result = $this->receiveLocation($postObj); //使用者傳送的是 地理位置,呼叫 接收到地理位置 方法 break; case "voice": $result = $this->receiveVoice($postObj); //使用者傳送的是 音訊,呼叫 接收到音訊 方法 break; case "video": $result = $this->receiveVideo($postObj); //使用者傳送的是 視訊,呼叫 接收到視訊 方法 break; case "link": $result = $this->receiveLink($postObj); //使用者傳送的是 連結,呼叫 接收到連結 方法 break; default: $result = "unknown msg type: ".$RX_TYPE; //未知訊息型別 break; } echo $result; //輸出回覆訊息,即 傳送微信。 }else { echo ""; exit; } } //===================================================響應訊息二部曲開始,核心程式碼的核心=================================================== //接收事件型別訊息——關注;取消關注;掃描帶引數二維碼;上報地理位置;自定義選單;點選選單拉取訊息;點選選單跳轉連結 private function receiveEvent($object) //這裡的$object來自$postObj————包含解析了微信訊息 的物件 { $content = ""; //為文字變數賦初值 switch ($object->Event) //獲取事件型別 { case "subscribe": //1.關注事件 $content = "歡迎關注柯南大學人民武裝學院官方微信公眾號,學院微訊號正處於開發者試驗階段,歡迎提出寶貴意見! ";//關注後回覆給使用者的訊息 $content .= (!empty($object->EventKey))?("\n來自二維碼場景 ".str_replace("qrscene_","",$object->EventKey)):""; /*第二個content:高階功能,未關注公眾號時使用者掃描 帶引數二維碼 回覆內容 break; case "unsubscribe": $content = "取消關注"; //2.取消關注事件,可以不寫content break; case "SCAN": $content = "掃描場景 ".$object->EventKey; //使用者已關注公眾號,掃描 帶引數二維碼 回覆內容。 break; case "CLICK": // 自定義選單事件之拉取訊息回覆 switch ($object->EventKey) //點選選單拉取訊息,EventKey為 click型別 選單按鈕的key值 { case "jianjie": $content = array(); $content[] = array("Title"=>"學院簡介","Description"=>"河南大學人民武裝學院,是河南省軍區與河南大學聯合創辦,我省唯一的人民武裝類高等院校。", "PicUrl"=>"http://henurenwu.duapp.com/images/xueyuan.jpg", "Url" =>"http://henurenwu.duapp.com/about/jianjie.html"); break; //點選"jianjie"click按鈕,設定推送 圖文訊息 case "gonggao": $content = "最新通告:\n\n恭喜我校本年度有38名同學考取研究生!\n\n更多公告請點選:\n\nhttp://henurenwu.duapp.com/gonggao/xueyuan_gonggao.html"; break; //這裡超連結會點選跳轉 case "zhaopin": $content = "點選檢視最新招聘資訊\n\nhttp://henurenwu.duapp.com/zhaopin/2015-2-14.html"; break; case "yijianfankui": $content = "請用‘@+您的意見’的形式將你的意見傳送到公眾號:"; break; case "game2048": $content = "點選將跳轉到Game Box,盡情玩耍吧!(遊戲過程不消耗流量)<a href='http://henurenwu.duapp.com/GameBox/GameBox.html'>點選進入Game Box</a>"; break; //加入超連結符號後文字會添上超連結 default: $content = "點選選單:".$object->EventKey; //沒有設定key和超連結的 空白按鈕,點選後回覆訊息 break; } break; case "LOCATION": //地理位置事件——對公眾號傳送位置 $content = "上傳位置:緯度 ".$object->Latitude.";經度 ".$object->Longitude; //回覆地理位置 break; case "VIEW": $content = "跳轉連結 ".$object->EventKey; //自定義選單之跳轉連結事件——如果設定了連結就不會回覆這句話 break; default: $content = "receive a new event: ".$object->Event; //出現新的事件型別回覆訊息,目前還沒出現 break; } if(is_array($content)){ //判斷$content是否為陣列型別——回覆資訊為圖文、音樂型別$content會是陣列格式,正好區分 if (isset($content[0]['PicUrl'])){ //圖文訊息,[0]['PicUrl']:第一條訊息的PicUrl列;[1]['PicUrl']表示第二條訊息的PicUrl列 $result = $this->transmitNews($object, $content);//呼叫 傳輸圖文 方法,將包含訊息的$postObj,回覆訊息$content進行傳參 }else if (isset($content['MusicUrl'])){ //isset():引數存在且非空時為true $result = $this->transmitMusic($object, $content);//呼叫 傳輸音樂 方法 } }else{ $result = $this->transmitText($object, $content); //呼叫 傳輸文字 方法 } return $result; //返回結果 } //接收文字訊息 private function receiveText($object) { switch ($object->Content) // 關鍵字回覆 { case "文字": //使用者傳送內容是“文字” $content = "這是個文字訊息"; //回覆訊息 break; case "圖文": case "單圖文": //使用者傳送內容為“單圖文” $content = array(); //圖文訊息需先建立陣列 $content[] = array("Title"=>"單圖文標題", "Description"=>"單圖文內容", "PicUrl"=>"http://discuz.comli.com/weixin/weather/icon/cartoon.jpg", "Url" =>"http://m.cnblogs.com/?u=txw1958"); //單圖文,只寫一個$content,裡面的內容是根據 文字訊息XML資料格式 編寫 break; case "多圖文": $content = array(); $content[] = array("Title"=>"多圖文1標題", "Description"=>"", "PicUrl"=>"http://discuz.comli.com/weixin/weather/icon/cartoon.jpg", "Url" =>"http://m.cnblogs.com/?u=txw1958"); $content[] = array("Title"=>"多圖文2標題", "Description"=>"", "PicUrl"=>"http://d.hiphotos.bdimg.com/wisegame/pic/item/f3529822720e0cf3ac9f1ada0846f21fbe09aaa3.jpg", "Url" =>"http://m.cnblogs.com/?u=txw1958"); $content[] = array("Title"=>"多圖文3標題", "Description"=>"", "PicUrl"=>"http://g.hiphotos.bdimg.com/wisegame/pic/item/18cb0a46f21fbe090d338acc6a600c338644adfd.jpg", "Url" =>"http://m.cnblogs.com/?u=txw1958"); break; //多圖文,最多10條 case "音樂": $content = array("Title"=>"最炫民族風", "Description"=>"歌手:鳳凰傳奇", "MusicUrl"=>"http://121.199.4.61/music/zxmzf.mp3", "HQMusicUrl"=>"http://121.199.4.61/music/zxmzf.mp3"); //音樂,和單圖文結構相近,陣列內容根據 音樂訊息XML資料格式 編寫 break; case "@": //傳送訊息包含@符號 $content = "感謝您的反饋,讓我們一同建設美好的校園!";//回覆文字訊息 break; default: //傳送文字內容不在上述內容,預設回覆以下訊息 $content = "請回復其它關鍵詞/從選單獲取資訊\n\n".date("Y-m-d H:i:s",time())."\n河南大學人民武裝學院"; break; } if(is_array($content)){ if (isset($content[0]['PicUrl'])){ $result = $this->transmitNews($object, $content); }else if (isset($content['MusicUrl'])){ $result = $this->transmitMusic($object, $content); } }else{ $result = $this->transmitText($object, $content); } return $result; } //接收圖片訊息 private function receiveImage($object) { $content = array("MediaId"=>$object->MediaId); //使用者向公眾號傳送圖片訊息,提取媒體ID。所有的$content都供傳參到XML資料中使用 $result = $this->transmitImage($object, $content); //呼叫 傳輸圖片 方法 return $result; } //接收位置訊息 private function receiveLocation($object) { $content = "你傳送的是位置,緯度為:".$object->Location_X.";經度為:".$object->Location_Y.";縮放級別為:".$object->Scale.";位置為:".$object->Label; //從$object物件(=$postObj物件)獲取位置引數 $result = $this->transmitText($object, $content); //呼叫 傳輸文字 方法 return $result; } //接收語音訊息 private function receiveVoice($object) { if (isset($object->Recognition) && !empty($object->Recognition)){ //使用者傳送的語音訊息,能夠識別且識別結果非空(公眾號需開通語音識別功能) $content = "你剛才說的是:".$object->Recognition; //回覆文字,將識別結果回覆給使用者 $result = $this->transmitText($object, $content); //呼叫 回覆文字 方法 }else{ $content = array("MediaId"=>$object->MediaId); //建立陣列,內容"MediaId",資料來源:語音訊息的MediaId $result = $this->transmitVoice($object, $content); //呼叫 傳輸語音 方法 } return $result; } //接收視訊訊息 private function receiveVideo($object) { $content = array("MediaId"=>$object->MediaId, "ThumbMediaId"=>$object->ThumbMediaId, "Title"=>"", "Description"=>""); $result = $this->transmitVideo($object, $content); return $result; } //接收連結訊息 private function receiveLink($object) { $content = "你傳送的是連結,標題為:".$object->Title.";內容為:".$object->Description.";連結地址為:".$object->Url; $result = $this->transmitText($object, $content); return $result; } //====================================================修改程式碼三部曲,官方文件上臺======================================================== //回覆文字訊息 private function transmitText($object, $content) //以下XML資料格式由微信規定,不可更改 { $textTpl = "<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[%s]]></Content> </xml>"; $result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time(), $content); <pre name="code" class="php">/*將xml格式中的資料分別賦值; sprintf()為變參函式:第一個引數$textTpl表示對它改變引數; 第二個引數叫$fromUsername(它存的是使用者的OpenID),因為資料傳輸方向掉頭了——原來是使用者給伺服器傳送訊息,ToUserName表示伺服器;現在伺服器要傳送資料給使用者(OpenID),ToUserName表示使用者; 第三個引數和第二個引數道理一樣; 第四個引數$time:訊息建立時間; 第五個引數:訊息型別,這裡表示文字; 第六個引數:訊息內容:伺服器向用戶傳送的訊息 */ return $result; }
//回覆圖片訊息 private function transmitImage($object, $imageArray) { $itemTpl = "<Image> <MediaId><![CDATA[%s]]></MediaId> //其它資料型別都有獨有的部分,獨有的部分從前面傳參得到 </Image>"; $item_str = sprintf($itemTpl, $imageArray['MediaId']); $textTpl = "<xml> <ToUserName><![CDATA[%s]]></ToUserName> //當然也有通用的部分 <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[image]]></MsgType> $item_str //將獨有的部分放置在合適的位置,不能破壞微信文件規定的格式。以下類同 </xml>"; $result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time()); return $result; } //回覆語音訊息 private function transmitVoice($object, $voiceArray) { $itemTpl = "<Voice> <MediaId><![CDATA[%s]]></MediaId> </Voice>"; $item_str = sprintf($itemTpl, $voiceArray['MediaId']); $textTpl = "<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[voice]]></MsgType> $item_str </xml>"; $result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time()); return $result; } //回覆視訊訊息 private function transmitVideo($object, $videoArray) { $itemTpl = "<Video> <MediaId><![CDATA[%s]]></MediaId> <ThumbMediaId><![CDATA[%s]]></ThumbMediaId> <Title><![CDATA[%s]]></Title> <Description><![CDATA[%s]]></Description> </Video>"; $item_str = sprintf($itemTpl, $videoArray['MediaId'], $videoArray['ThumbMediaId'], $videoArray['Title'], $videoArray['Description']); $textTpl = "<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[video]]></MsgType> $item_str </xml>"; $result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time()); return $result; } //回覆圖文訊息 private function transmitNews($object, $newsArray) { if(!is_array($newsArray)){ return; } $itemTpl = " <item> <Title><![CDATA[%s]]></Title> <Description><![CDATA[%s]]></Description> <PicUrl><![CDATA[%s]]></PicUrl> <Url><![CDATA[%s]]></Url> </item> "; $item_str = ""; foreach ($newsArray as $item){ $item_str .= sprintf($itemTpl, $item['Title'], $item['Description'], $item['PicUrl'], $item['Url']); } $newsTpl = "<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[news]]></MsgType> <Content><![CDATA[]]></Content> <ArticleCount>%s</ArticleCount> <Articles> $item_str</Articles> </xml>"; $result = sprintf($newsTpl, $object->FromUserName, $object->ToUserName, time(), count($newsArray)); return $result; } //回覆音樂訊息 private function transmitMusic($object, $musicArray) { $itemTpl = "<Music> <Title><![CDATA[%s]]></Title> <Description><![CDATA[%s]]></Description> <MusicUrl><![CDATA[%s]]></MusicUrl> <HQMusicUrl><![CDATA[%s]]></HQMusicUrl> </Music>"; $item_str = sprintf($itemTpl, $musicArray['Title'], $musicArray['Description'], $musicArray['MusicUrl'], $musicArray['HQMusicUrl']); $textTpl = "<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[music]]></MsgType> $item_str </xml>"; $result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time()); return $result; }
===================================================結尾小結===============================================================
總結一下,整體來看基礎的訊息處理程式碼都在這裡了,用圖片對整體再進行了解一下
我用註釋的方式進行講解,對大家查閱程式碼造成一定不便請大家諒解。
有問題或願意共同進行微信公眾平臺開發研究的夥伴請聯絡郵箱:[email protected],歡迎!
因為之前反覆修改,導致內容錯亂,2015年2月25日00:46:47重新修改。