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

《微信公众平台开发:从零基础到ThinkPHP5高性能框架实践》3.3.4 消息交互原理分析

关灯直达底部

下面结合3.3.3节的代码来分析微信公众平台的消息交互原理。下面的代码基于微信公众平台官方示例代码修改完善而成。


 1 <?php 2 /* 3     方倍工作室 http:// www.fangbei.org/ 4     CopyRight 2013 www.doucube.com  All Rights Reserved 5 */ 6  7 define("TOKEN", "weixin"); 8 $wechatObj = new wechatCallbackapiTest; 9 if (isset($_GET['echostr'])) {10     $wechatObj->valid;11 }else{12     $wechatObj->responseMsg;13 }14 15 class wechatCallbackapiTest16 {17     public function valid18     {19         $echoStr = $_GET["echostr"];20         if($this->checkSignature){21             echo $echoStr;22             exit;23         }24     }25 26     private function checkSignature27     {28         $signature = $_GET["signature"];29         $timestamp = $_GET["timestamp"];30         $nonce = $_GET["nonce"];31 32         $token = TOKEN;33         $tmpArr = array($token, $timestamp, $nonce);34         sort($tmpArr);35         $tmpStr = implode( $tmpArr );36         $tmpStr = sha1( $tmpStr );37 38         if( $tmpStr == $signature ){39             return true;40         }else{41             return false;42         }43     }44 45     public function responseMsg46     {47         $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];48 49         if (!empty($postStr)){50             $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_               NOCDATA);51             $fromUsername = $postObj->FromUserName;52             $toUsername = $postObj->ToUserName;53             $keyword = trim($postObj->Content);54             $time = time;55             $textTpl = "<xml>56                         <ToUserName><![CDATA[%s]]></ToUserName>57                         <FromUserName><![CDATA[%s]]></FromUserName>58                         <CreateTime>%s</CreateTime>59                         <MsgType><![CDATA[%s]]></MsgType>60                         <Content><![CDATA[%s]]></Content>61                         <FuncFlag>0</FuncFlag>62                         </xml>";63             if($keyword == "?" || $keyword == "?")64             {65                 $msgType = "text";66                 $content = date("Y-m-d H:i:s",time);67                 $result = sprintf($textTpl, $fromUsername, $toUsername, $time,                    $msgType, $content);68                 echo $result;69             }70         }else{71             echo "";72             exit;73         }74     }75 }76 ?>  

首先看一下代码的结构。

第2~5行是注释部分。

第7行使用define函数定义常量,常量名称为TOKEN,常量的值为weixin,这个值就是在启用开发模式时填写的Token。

第15~75行定义了一个类wechatCallbackapiTest,并在类中定义了3个方法valid、checkSignature和responseMsg。

第8~13行为程序执行语句。第8行实例化了一个类对象。在第9行中,判断是否有GET请求有echostr变量,如果有,则执行valid方法,否则执行responseMsg方法。

下面分析微信消息交互流程。

提交URL和Token申请验证的时候,微信服务器将发送GET请求到填写的URL上,并且带上4个参数(signature、timestamp、nonce、echostr)。GET请求类似如下。


signature=6e35c6f3d3279338781047dbffd09426b9ecdee3&echostr=5979420653038092664&timestamp=1392001400&nonce=1392192345  

上述请求的参数说明如表3-1所示。

表3-1 请求校验参数说明

这个GET请求是包含echostr变量的,所以执行valid方法。在该方法中,又调用了校验签名方法checkSignature。如果签名校验为真,则原样输出变量$echoStr的值。

加密/校验流程如下。

1)将token、timestamp、nonce等3个参数进行字典序排序,见第33~34行。

2)将3个参数字符串拼接成一个字符串进行sha1加密,见第35~36行。

3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信,见第38~42行。

发送问号的时候,微信服务器也会带上前面3个参数(signature、timestamp、nonce)访问开发者设置的URL,同时还会将消息的XML数据包POST到URL上。XML格式类似如下。


<xml>    <ToUserName><![CDATA[gh_ba6050bc0be7]]></ToUserName>    <FromUserName><![CDATA[oDeOAjgSJUX10wvImSRMSwmyQAyA]]></FromUserName>    <CreateTime>1392043637</CreateTime>    <MsgType><![CDATA[text]]></MsgType>    <Content><![CDATA[?]]></Content>    <MsgId>5978781895719912033</MsgId></xml>  

而消息请求不包含echostr变量,所以将执行响应消息方法responseMsg。

响应消息方法首先接收上述原始POST数据,见第47行。

然后它将数据载入对象中,对象名为SimpleXMLElement,LIBXML_NOCDATA表示将CDATA合并为文本节点,代码中第50行实现此功能。

第51~54行取得XML类对象的值,并赋给新的变量,注意发送方变为接收方,接收方变为发送方。

第55~62行构造要回复的XML数据包。

第63行判断发送过来的关键字是不是问号。

第64~65行设置回复的消息类型为text,内容为当前年月日时分秒。

第66~67行封装回复的XML数据包,并且向微信服务器输出。XML格式如下。


<xml>    <ToUserName><![CDATA[oDeOAjgSJUX10wvImSRMSwmyQAyA]]></ToUserName>    <FromUserName><![CDATA[gh_ba6050bc0be7]]></FromUserName>    <CreateTime>1392043638</CreateTime>    <MsgType><![CDATA[text]]></MsgType>    <Content><![CDATA[2014-01-05 11:43:23]]></Content></xml>  

这样用户就会收到回复的消息,效果如图3-26所示。