1. 程式人生 > >PHP微信定製開發-訊息的識別和訊息工具類的封裝

PHP微信定製開發-訊息的識別和訊息工具類的封裝

對於訊息管理,伺服器被動回覆訊息是比較重要且需要好好掌握的知識點,在這個模組中我們需要接收到使用者傳送過來的訊息,並識別出訊息型別,最後把識別結果以文字訊息的形式響應給使用者,下面是文件地址

從文件中我們可以看出通過MsgType來判斷訊息型別,通過Content取得傳送過來的訊息(僅文字),為了把訊息響應給使用者方便開發我們需要先寫一個工具類用來處理訊息,因訊息體的格式比較統一,這裡的工具類封裝對於xml選用最簡單的方式,類似simplexml就不適用了,有興趣的自己嘗試

一 訊息工具類的封裝

<?php
namespace  util;


define("TEXTMESSAGE","text");
define("NEWSMESSAGE","news");

/** 訊息工具類
 * @author chenwill2
 *
 */
class MessageUtil{
    
    /** 生成文字訊息字串
     * @param $toUserName
     * @param $fromUserName
     * @param $content
     * @return string
     */
    function textMessageToXml($toUserName,$fromUserName,$content="你傳送的是文字訊息"){
        $textTpl = "<xml>
                        <ToUserName><![CDATA[%s]]></ToUserName>
                        <FromUserName><![CDATA[%s]]></FromUserName>
                        <CreateTime>%s</CreateTime>
                        <MsgType><![CDATA[%s]]></MsgType>
                        <Content><![CDATA[%s]]></Content>
                        <FuncFlag>0</FuncFlag>
                        </xml>";
        $resultStr=sprintf($textTpl,$toUserName,$fromUserName,time(),TEXTMESSAGE,$content);
       
        return $resultStr;
    }
    
    /** 生成圖文訊息字串
     * @param $toUserName
     * @param $fromUserName
     * @param $article
     * @return string
     */
    function articleMessageToXml($toUserName,$fromUserName,$article){
        $childArticle="";
        foreach ($article as $item){
            $child="<item>
                        <Title><![CDATA[%s]]></Title> 
                        <Description><![CDATA[%s]]></Description>
                        <PicUrl><![CDATA[%s]]></PicUrl>
                        <Url><![CDATA[%s]]></Url>
                     </item>";
            $childInfo=sprintf($child,$item["title"],$item["description"],$item["picurl"],$item["url"]);
            $childArticle.=$childInfo;
        }
        
        $textTpl = "<xml>
                       <ToUserName><![CDATA[%s]]></ToUserName>
                       <FromUserName><![CDATA[%s]]></FromUserName>
                       <CreateTime>%s</CreateTime>
                       <MsgType><![CDATA[%s]]></MsgType>
                       <ArticleCount>%s</ArticleCount>
                       <Articles>
                          $childArticle
                        </Articles>
                      </xml>";
                          
        $resultStr=sprintf($textTpl,$toUserName,$fromUserName,time(),NEWSMESSAGE,count($article));
      
        return $resultStr;
    }
   
}

?>

這裡只封裝了2種比較常用的訊息分別是文字訊息、圖文訊息;其他的如有需要可以自己編寫,反正封裝方式都差不多

二  訊息型別識別並回復型別結果給使用者

<?php
namespace handler;

include_once __DIR__.DIRECTORY_SEPARATOR."util".DIRECTORY_SEPARATOR."MessageUtil.php";


define("TOKEN", "weixinCourse");

// 1 判斷請求方法,get請求一般為訊息驗證,post為其他訊息互動
// 2 驗證signature是否正確(訊息來自微信伺服器)
$handler = new \handler\WeixinHandler();

$reqMethod = strtolower($_SERVER["REQUEST_METHOD"]);
if ("get" == $reqMethod && !empty($_GET["echostr"])) {
    if ($handler->isValid()) {
        $echostr = $_GET["echostr"];
        echo $echostr;
        exit();
    }
} else {
    //判斷訊息型別,返回"你傳送的是xxx訊息"
    $handler->responseMessage();
}

class WeixinHandler
{

    function checkSignature()
    {
        $timestamp = $_GET["timestamp"];
        $nonce = $_GET["nonce"];

        $tmpArr = array(
            TOKEN,
            $timestamp,
            $nonce
        );
        sort($tmpArr, SORT_STRING);
        $tmpStr = implode($tmpArr);
        $tmpStr = sha1($tmpStr);

        if ($tmpStr) {
            return $tmpStr;
        } else {
            return "";
        }
    }

    function isValid()
    {
        $signature = $_GET["signature"];
        if ($signature == $this->checkSignature()) {
            return true;
        } else {
            return false;
        }
    }
    function responseMessage(){
        $msgUtil = new \util\MessageUtil();
        $defaultMsgType="text";
        //從請求資料獲取FromUserName和ToUserName以及訊息型別
        $postStr = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : file_get_contents("php://input");
        
        if(!empty($postStr)){
            $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
            //傳送方賬號(openId)
            $fromUsername = $postObj->FromUserName;
            //開發者微訊號
            $toUsername = $postObj->ToUserName;
            //訊息型別
            $MsgType = strtolower($postObj->MsgType);
            //訊息內容
            $keyword = trim($postObj->Content);
          
            
            $msgUtil = new \util\MessageUtil();
            $typeResult="";
            $resultStr="";
           
            if("text"==$MsgType){
               $typeResult="你傳送的是文字訊息";
            }else if("image"==$MsgType){
                $typeResult="你傳送的是圖片訊息";
            }else if("voice"==$MsgType){
                $typeResult="你傳送的是語音訊息";
            }else if("video"==$MsgType){
                $typeResult="你傳送的是視訊訊息";
            }else if("shortvideo"==$MsgType){
                $typeResult="你傳送的是短視訊訊息";
            }else if("location"==$MsgType){
                $typeResult="你傳送的是地理位置訊息";
            }else if("link"==$MsgType){
                $typeResult="你傳送的是連結訊息";
            }else if("event"==$MsgType){
                //事件推送處理
                $typeResult="事件推送訊息";
            }else{
                $typeResult="你傳送的是其他型別的訊息";
            }
            
            if("text"==$defaultMsgType){
                $resultStr=$msgUtil->textMessageToXml($fromUsername, $toUsername,$typeResult);
            }
           
            echo $resultStr;
           
        }else{
           echo "";
           exit;
       }
    
    }
}

?>

需要注意的是如果使用名稱空間,new一個類的時候要注意帶上名稱空間,否則會出現錯誤

到此為止微信就能正常響應訊息給使用者了,對於事件推送這裡沒有做詳細區分,後面會針對這塊分享幾篇部落格給大家,下次分享的內容是 微信選單介面和微信根據城市呼叫百度API查天氣預報的小例子