首先對微擎的工作原理做簡單描述, 微擎使用規則和子產品的機制來處理公衆平台的請求資料并傳回響應的結果. 執行流程描述為: 粉絲使用者與公衆号碼進行對話或互動, 而後公衆平台将粉絲使用者的請求消息(目前包括: 文本, 圖檔, 位置, 連結, 事件. 請參閱消息類型)傳遞給微擎系統, 微擎系統按照消息類型和對應的公衆号所設定的規則清單比對到合适的規則(請參閱消息路由), 規則定義中包括處理此消息所使用的子產品和此子產品處理消息時所需要的其他附加資料(請參閱子產品定義), 而後子產品将會按照請求的消息資料和子產品附加資料進行相關業務處理并傳回處理結果(請參閱響應類型), 微擎系統将處理結果傳回給公衆平台, 而後經公衆平台傳回給粉絲使用者. 微擎的主處理流程實作定義于: engine.php 中, 如有需要請參閱源碼. 消息類型 消息類型指粉絲使用者通過公衆平台與微擎進行互動時所提供的消息資料的類型. 消息類型基于微信公衆平台提供的資料接口, 微擎在其基礎上進行包裝處理, 友善PHP開發者進行業務處理. 儲存消息的基本對象結構定義為: $message => array(
'from' => '', //string: 發送消息方, 代表一個粉絲使用者(使用OpenID表示)
'to' => '', //string: 消息接收方, 對應目前的公衆号(使用OpenID表示)
'time' => '', //int: 消息發送時間, 使用Unix時間戳表示
'type' => '', //string: 消息類型, 用于區分不同類型的消息, 請參閱下文
'msgid' => '' //int: 消息ID, 公衆平台系統用于唯一辨別一條請求消息
); 消息類型同公衆平台官方不同之處在于将event類型拆分開為獨立的消息類型, 避免了重複判斷. 根據消息類型不同, 消息對象結構還存在不同的附加資料, 按照類型定義如下: 文本消息 粉絲使用者向公衆号發送了一條普通文本消息(包括包含表情的消息, 或者純表情消息), 處理文本消息可以實作簡單的文本對話, 結合使用文本上下文(請參閱上下文處理)可以實作調查, 測試等複雜的互動. $message => array(
//....全局資料
'type' => 'text', //string: 代表目前消息為文本消息
'content' => '' //string: 文本消息内容
); 圖檔消息 粉絲使用者向公衆号發送了一張圖檔, 處理圖檔消息可以實作分享使用者圖檔的相關功能 $message => array(
//....全局資料
'type' => 'image', //string: 代表目前消息為圖檔消息
'url' => 'http://same.im/image.jpg' //string: 使用者所發送的圖檔位址
); 地理位置消息 粉絲使用者向公衆号發送了一條地理位置, 處理地理位置消息可以實作lbs相關功能(參閱LBS方案) $message => array(
//....全局資料
'type' => 'location', //string: 代表目前消息為位置消息
'location_x' => '', //float: 代表位置經度
'location_y' => '', //float: 代表位置緯度
'scale' => '', //int: 表示地圖縮放倍數
'label' => '' //float: 表示地點描述
); 連結消息 粉絲使用者向公衆号發送了一條連結消息, 處理連結消息可以實作好友分享等社交功能 $message => array(
//....全局資料
'type' => 'link', //string: 代表目前消息為連結消息
'title' => '', //float: 代表連結标題
'description' => '', //float: 代表連結描述資訊
'scale' => 'url' //int: 表示連結的URL
); 關注消息 粉絲使用者關注目前公衆号後将會獲得此消息, 處理此消息可以實作歡迎資訊和粉絲增長統計 $message => array(
//....全局資料
'type' => 'subscribe' //string: 代表目前消息為關注消息
); 取消關注消息 粉絲使用者取消關注目前公衆号後将會獲得此消息, 處理此消息可以實作粉絲數量增長分析 $message => array(
//....全局資料
'type' => 'unsubscribe' //string: 代表目前消息為取消關注消息
); 菜單點選消息 粉絲使用者點選自定菜單後, 如果菜單設定為消息回複, 那麼将會獲得此消息, 處理此消息能實作自定義菜單的特定回複 $message => array(
//....全局資料
'type' => 'CLICK', //string: 代表目前消息為菜單點選消息
'eventkey' => '' //string: 菜單點選附加的菜單資料資訊
); 消息路由 消息路由是指粉絲使用者經公衆平台發送消息内容至微擎時, 微擎系統查找對應的規則記錄, 并将消息配置設定至合适的子產品處理的過程. 微擎系統按照不同的消息類型, 進行不同的處理. 處理方式如下: 上下文消息路由 微擎支援上下文操作, 通過上下文支援微擎可将使用者對話鎖定至特定的子產品, 如果目前消息是上下文對話的消息, 那麼将會自動路由至上下文鎖定的子產品. (請參閱 上下文處理) ' 文本消息規則比對(重要) 針對文本消息, 微擎使用文本比對來選擇合适的規則和子產品, 規則是指針對特定消息的處理方式. 微擎選擇規則的方式包括: * 關鍵字包含 指粉絲使用者發送的消息内容含有指定的關鍵字就指派到特定規則.
* 内容等價 指粉絲使用者發送的消息内容完全等于指定的内容才指派到特定規則.
* 正規表達式 指粉絲使用者發送的消息類型符合指定正規表達式定義的模式時指派到特定規則.(進階模式, 需要有程式設計經驗) 其他類型消息路由規則 圖檔消息, 位置消息, 連結消息等其他類型請求消息的路由支援正在緊張開發中 子產品定義 上下文處理 微擎現已支援上下文鎖定對話, 可以将粉絲使用者的對話鎖定至特定子產品. 用以實作線上調查, 線上測試等類似的功能. 微擎的上下文操作使用 $_SESSION + DB 來實作.上下文資料儲存在$_SESSION['context']變量中,并與sessions表中資料做一對一的映射,使用者可通過操作sessions表中的資料進行上下文會話的基本管理. 要實作上下文操作主要使用 Processor 裡的内定方法: public inContext; 本次對話是否為上下文響應對話, 如果目前對話是由上下文鎖定而路由到的. 此值為 true, 否則為 false protected function beginContext($expire = 3600); 請在子產品處理程式中調用此函數已開始一個新的上下文對話. 附加的參數 $expire 說明本次會話的失效時間. 例如 $this->beginContext(1800) 就說明啟動一次上下文會話鎖定, 并且本次會話将會于30分鐘後釋放, 如果不固定逾時的話, 請在每次請求時調用 beginContext protected function endContext(); 在子產品處理程式中調用 endContext 來結束一次會話, 并銷毀會話中儲存的所有資料(目前為 $_SESSION) protected function refreshContext($expire = 0); 在子產品處理程式中調用 refreshContext 來重新整理使用者處于上下文的時限.超過時限使用者将會自動退出上文環境. protected function addParamContext($var, $val = ''); 在子產品處理程式中調用 addParamContext 用于增加上下文中的附加資料,此資料将會一直存在于上下文消息中,使用者可通過 $this->context 變量來調用儲存的資料. class BloodTestModuleProcessor extends WeModuleProcessor {
//void: 所有處理程式必須實作虛函數 respond. 用以響應消息
public function respond() {
if(!$this->inContext) {
$reply = '請輸入你的血型(A, B, O, AB), 來分析你今年的運程. ';
$this->beginContext();
// 如果是按照規則觸發到本子產品, 那麼先輸出提示問題語句, 并啟動上下文來鎖定會話, 以保證下次回複依然執行到本子產品
} else {
$btypes = array('a', 'b', 'o', 'ab');
$b = strtolower($this->message['content']);
// 如果目前會話在上下文中, 那麼表示目前回複是使用者回答提示問題的答案.
if(in_array($b, $btypes)) {
switch($b) {
case 'a':
$reply = 'A型血今年.....';
break;
case 'b':
$reply = 'B型血今年.....';
break;
case 'o':
$reply = 'O型血今年.....';
break;
case 'ab':
$reply = 'AB型血今年.....';
break;
}
$this->endContext();
// 如果目前回答符合答案格式, 那麼進行儲存并進行下一個問題. (可以儲存至 SESSION 中)
// 直到最後一個問題回答完成, 輸出測試結果給使用者, 并結束對話鎖定. 以保證使用者其他對話能正常路由.
// 本示例隻有一個問題, 是以不儲存答案, 直接輸出測試結果.
// 如果對話預設的逾時不夠, 那麼可以在每次提出下一個問題的時候重新調用 beginContext 來順延逾時.
} else {
$reply = '請輸入正确的血型(A, B, O, AB). ';
// 回答不符合答案格式, 那麼重新顯示目前問題.
}
}
return $this->respText($reply);
// 傳回至系統
}
private function respText($content) {
$response = array();
$response['FromUserName'] = $this->message['to'];
$response['ToUserName'] = $this->message['from'];
$response['MsgType'] = 'text';
$response['Content'] = htmlspecialchars_decode($content);
return $response;
}
} |