文/劉歡 盧蓓蓉 陳穎
自從2012年8月華中科技大學(xué)推出首個(gè)國內(nèi)高校官方微信后,越來越多的高校已陸續(xù)開通了微信公共賬號(hào)。其中,除部分高校開發(fā)了專門的微信平臺(tái)系統(tǒng)外,大部分高校都還停留在使用“關(guān)鍵詞自動(dòng)回復(fù)”的簡(jiǎn)單交互層面,即在微信提供的管理后臺(tái)中設(shè)置多種關(guān)鍵詞及其對(duì)應(yīng)的回復(fù)內(nèi)容,一旦用戶輸入了某個(gè)關(guān)鍵詞,則返回其對(duì)應(yīng)的預(yù)設(shè)內(nèi)容。關(guān)鍵詞自動(dòng)回復(fù)能夠?qū)崿F(xiàn)一些初級(jí)的匹配功能,但無法實(shí)時(shí)查詢和返回高校各個(gè)業(yè)務(wù)系統(tǒng)中的數(shù)據(jù)信息,也無法實(shí)現(xiàn)上下文交互,更無法深入使用微信公共平臺(tái)提供的各種自定義功能。
本文梳理了當(dāng)前高校微信公共平臺(tái)的各種功能,以華東師范大學(xué)現(xiàn)有信息化應(yīng)用系統(tǒng)作為數(shù)據(jù)基礎(chǔ),通過使用CodeIgniter敏捷開源框架開發(fā)富有交互性的微信公共平臺(tái),分析和闡述了平臺(tái)關(guān)鍵功能實(shí)現(xiàn)過程中存在的問題,并提出相應(yīng)的技術(shù)解決方案。
微信公共平臺(tái)的通訊路線可簡(jiǎn)單歸納為“用戶-微信服務(wù)器-平臺(tái)服務(wù)器-微信服務(wù)器-用戶”,我們可以將每一次通訊視為一次交互過程,如圖1所示。用戶是交互過程的發(fā)起人,通過在微信程序中向公共賬號(hào)發(fā)送消息來啟動(dòng)交互。微信服務(wù)器是交互的信息中轉(zhuǎn)站,消息被直接發(fā)送至微信服務(wù)器,服務(wù)器再根據(jù)該公共賬號(hào)所設(shè)置的模式類型來確定消息的處理方式。當(dāng)該賬號(hào)為簡(jiǎn)單的編輯模式時(shí),微信將通過諸如關(guān)鍵詞回復(fù)等功能對(duì)消息進(jìn)行匹配,直接將匹配結(jié)果返回給用戶。而當(dāng)賬號(hào)設(shè)置為開發(fā)模式時(shí),微信服務(wù)器將把用戶發(fā)送的消息以XML數(shù)據(jù)的形式發(fā)送至公共賬號(hào)預(yù)設(shè)的接口,即平臺(tái)服務(wù)器。平臺(tái)服務(wù)器是交互的信息處理方,其核心是由公共賬號(hào)管理者自主搭建的Web應(yīng)用程序。平臺(tái)服務(wù)器在接收到來自微信服務(wù)器的數(shù)據(jù)后,根據(jù)數(shù)據(jù)中包含的消息類型和關(guān)鍵詞內(nèi)容準(zhǔn)備相應(yīng)的回調(diào)格式和信息,并按照微信規(guī)定的消息格式返回響應(yīng)數(shù)據(jù)。微信服務(wù)器在收到該響應(yīng)數(shù)據(jù)后,再將其中的內(nèi)容信息以規(guī)定的格式發(fā)送給用戶,完成整個(gè)交互過程。微信公共平臺(tái)開發(fā)的主要任務(wù)即搭建其中的平臺(tái)服務(wù)器,創(chuàng)建Web應(yīng)用程序來處理所有的信息請(qǐng)求任務(wù),向微信服務(wù)器返回相應(yīng)的數(shù)據(jù)內(nèi)容。
微信公共平臺(tái)的接口主要包含三大類。一類是接收用戶消息接口,其中包含文本信息、圖片信息、地理位置信息、鏈接信息等類型,平臺(tái)服務(wù)器通過這些接口從微信服務(wù)器推送的數(shù)據(jù)中獲取相應(yīng)內(nèi)容。另一類是回復(fù)用戶消息接口,其中包含文本信息、圖文信息和音樂信息等類型,平臺(tái)服務(wù)器將根據(jù)回復(fù)消息的格式,選擇相應(yīng)的接口向微信服務(wù)器回調(diào)數(shù)據(jù)。第三類為事件推送接口,包含了用戶的關(guān)注和取消關(guān)注兩類事件接口,用于平臺(tái)服務(wù)器向新近關(guān)注用戶發(fā)送歡迎消息。
基于微信公共平臺(tái)簡(jiǎn)潔的運(yùn)行機(jī)制,我們選擇了輕量化的CodeIgniter框架來作為平臺(tái)的開發(fā)工具。CodeIgniter框架的優(yōu)點(diǎn)是架構(gòu)簡(jiǎn)單、配置靈活,擁有出色的運(yùn)行性能,且其運(yùn)營成本低、開發(fā)周期短,特別適合于高校自主開發(fā)微信平臺(tái)。
1. 設(shè)計(jì)模式
CodeIgniter框架是基于“模型-視圖-控制器”的MVC模式的,我們?cè)谖⑿殴财脚_(tái)開發(fā)中也遵循了這一設(shè)計(jì)模式,以實(shí)現(xiàn)邏輯和表現(xiàn)層面的分離。其中,模型(Model)代表了數(shù)據(jù)結(jié)構(gòu),在本平臺(tái)中主要表現(xiàn)為一個(gè)模型類,實(shí)現(xiàn)平臺(tái)數(shù)據(jù)的讀取、插入、更新、刪除等功能。視圖(View)代表了展示給用戶的信息,即平臺(tái)中展示給用戶的各種網(wǎng)頁,包含了用戶授權(quán)的相關(guān)頁面模板??刂破?(Controller) 是模型、視圖和其他資源之間的中介,在本平臺(tái)中主要用于調(diào)度各種數(shù)據(jù),創(chuàng)建消息處理流程。由于微信平臺(tái)不需要過多向用戶展示網(wǎng)頁,其數(shù)據(jù)也基本來自其他信息化系統(tǒng)的接口,因此本框架中的模型和視圖類型都較為簡(jiǎn)單。平臺(tái)的核心在于控制器,其主要功能都由控制器完成,其中包括消息的接收、判斷、處理和回調(diào)等。
圖1 微信公共平臺(tái)通訊機(jī)制
智能終端的一代。
此外,平臺(tái)將一些核心的功能類和常用函數(shù)抽離出來,分別創(chuàng)建對(duì)應(yīng)的裝載類(Libraries)和輔助函數(shù)類(Helpers),在運(yùn)用時(shí)按需加載,以簡(jiǎn)化控制器中的功能代碼,提高系統(tǒng)運(yùn)行效率。在裝載類中包含了網(wǎng)頁HTML標(biāo)簽內(nèi)容的采集、正則解析,以及模板解析等復(fù)雜的功能類庫。在輔助函數(shù)中則包含了各種單獨(dú)的函數(shù),包括各種數(shù)據(jù)接口的連接、時(shí)間日期處理、敏感詞過濾、單位換算等。
2. 數(shù)據(jù)庫設(shè)計(jì)
平臺(tái)采用MySQL數(shù)據(jù)庫。該庫中主要的數(shù)據(jù)有三種,分別是用戶(User)、規(guī) 則(Rule) 和 消 息(Message)。User表中儲(chǔ)存了每個(gè)微信用戶的用戶號(hào)(OpenId),以及上一次操作的狀態(tài)記錄、學(xué)號(hào)和工號(hào)信息等,用于實(shí)現(xiàn)用戶的上下文交互,使用各種校內(nèi)信息系統(tǒng)的授權(quán)功能。Message表中儲(chǔ)存了用戶向微信公共賬號(hào)發(fā)送的所有消息,是平臺(tái)消息的歷史存檔。Rule表中包含了管理員預(yù)設(shè)的消息響應(yīng)規(guī)則,是平臺(tái)消息處理流程的具體依據(jù)。
除以上三種數(shù)據(jù)外,數(shù)據(jù)庫中還包含了實(shí)現(xiàn)各種平臺(tái)功能所需的配置數(shù)據(jù)。如為“背單詞”功能創(chuàng)建Dictionary表,以儲(chǔ)存四六級(jí)單詞數(shù)據(jù);為“自動(dòng)聊天”功能創(chuàng)建Talk表,以儲(chǔ)存各種對(duì)話規(guī)則;為“自習(xí)教室查詢”功能創(chuàng)建Classroom表,以儲(chǔ)存常用的自習(xí)教室列表等。
3.?dāng)?shù)據(jù)的獲取
平臺(tái)有四種獲取數(shù)據(jù)的方式。第一種方式是從平臺(tái)數(shù)據(jù)庫中直接獲取數(shù)據(jù),包括前文所述的單詞、對(duì)話規(guī)則、自習(xí)教室列表等。第二種方式是從已有的校園信息系統(tǒng)接口中獲取數(shù)據(jù),如獲取校園卡余額、拾卡記錄、課程表、學(xué)期日歷、校園新聞、通知公告、講座報(bào)告等。第三種方式是從各種社會(huì)網(wǎng)站接口中獲取數(shù)據(jù),比如從中國天氣網(wǎng)獲取天氣預(yù)報(bào)數(shù)據(jù),從PM25.in獲取空氣質(zhì)量數(shù)據(jù)等。第四種方式是對(duì)網(wǎng)頁進(jìn)行HTML采集,經(jīng)過正則解析,獲取特定標(biāo)簽中的內(nèi)容,如通過教師個(gè)人主頁系統(tǒng)查詢教師的個(gè)人信息、根據(jù)關(guān)鍵字獲取某研究方向?qū)?yīng)的教師列表、查詢圖書信息等。
在以上四種數(shù)據(jù)獲取方式中,第一種方式通過CodeIgniter框架的模型類進(jìn)行實(shí)現(xiàn),第二、三種方式通過輔助函數(shù)類實(shí)現(xiàn),第四種方式通過裝載類實(shí)現(xiàn)。數(shù)據(jù)交互格式主要為XML和JSON兩種,其中JSON在精簡(jiǎn)數(shù)據(jù)流量方面優(yōu)于XML,有助于縮短平臺(tái)的響應(yīng)延時(shí)。
4. 消息處理流程
在CodeIgniter框架的主控制器中定義了微信平臺(tái)的消息處理流程,如圖2所示。首先,在控制器中加載必要的裝載類和輔助函數(shù),獲取來自微信服務(wù)器的推送數(shù)據(jù),并解析數(shù)據(jù)中的用戶微信號(hào)、消息類型和消息內(nèi)容,將其記錄到Message表。然后,從User表中查詢是否存在當(dāng)前的用戶微信號(hào)記錄,如果不存在則表示當(dāng)前用戶為新關(guān)注用戶,將其OpenId信息寫入U(xiǎn)ser表,并從Rule表中獲取歡迎信息,作為返回給微信服務(wù)器的數(shù)據(jù)內(nèi)容。
當(dāng)存在用戶微信號(hào)記錄時(shí),系統(tǒng)提取該OpenId對(duì)應(yīng)的歷史操作記錄,更新本次交互的信息記錄,并進(jìn)入按規(guī)則匹配的消息處理階段。根據(jù)用戶之前的操作記錄,結(jié)合Rule表中的響應(yīng)規(guī)則,系統(tǒng)將判斷本次交互是否屬于上下文對(duì)話。系統(tǒng)中的上下文對(duì)話包括校車查詢、教師查詢、自動(dòng)聊天、背單詞等,每當(dāng)用戶輸入相應(yīng)的關(guān)鍵字后,下一次對(duì)話即進(jìn)入相應(yīng)的情景模式。如此前用戶曾輸入過“校車”,則表示當(dāng)前為校車查詢情景模式,若本次輸入的消息內(nèi)容為“1”或“線路1”,則上下文對(duì)話有效,將從Rule表中獲取第一種校車線路作為返回內(nèi)容。如果當(dāng)前輸入的關(guān)鍵字不在情景模式規(guī)定的對(duì)話規(guī)則之內(nèi),則退出該情景模式,進(jìn)入非上下文對(duì)話的規(guī)則匹配階段。平臺(tái)中每一條規(guī)則都對(duì)應(yīng)了多個(gè)關(guān)鍵字,如輸入“新聞”、“校園新聞”、“要聞”等詞語都將獲取門戶網(wǎng)站系統(tǒng)中的新聞列表,輸入“撿卡”、“拾卡”、“丟卡”等詞語都將調(diào)用校園卡的拾卡記錄查詢接口等。在一些規(guī)則中我們采用了寬松的匹配模式,如當(dāng)用戶輸入的消息中含有“看病”、“生病”、“醫(yī)院”等字樣時(shí),均返回校園就診的相關(guān)信息,這樣,用戶不管是輸入“我想看病”,還是“我生病了,怎么辦?”這樣難以精確預(yù)測(cè)的描述語時(shí),都能匹配到相應(yīng)的響應(yīng)結(jié)果。
在遍歷了Rule表中的所有規(guī)則后,如果關(guān)鍵字仍然沒有匹配結(jié)果,則進(jìn)入網(wǎng)站匹配階段,即通過網(wǎng)站群數(shù)據(jù)接口,搜索所有校園網(wǎng)站中包含該關(guān)鍵字的信息條目。華東師范大學(xué)網(wǎng)站群中目前運(yùn)行了包括門戶網(wǎng)站、二級(jí)院系部門網(wǎng)站在內(nèi)的近100個(gè)校園站點(diǎn),全面涵蓋了校內(nèi)的新聞、公告、教學(xué)、科研等信息。通過這一階段的匹配,能夠?qū)崿F(xiàn)強(qiáng)大的校內(nèi)信息聚合功能。如用戶輸入“校友返校”,在Rule表沒有對(duì)應(yīng)匹配規(guī)則的前提下,平臺(tái)將從網(wǎng)站群數(shù)據(jù)接口中獲取所有含有該關(guān)鍵字的信息,其中包含了校級(jí)層面和學(xué)院層面的各種校友返校信息。
當(dāng)網(wǎng)站匹配階段仍然沒有符合的匹配結(jié)果時(shí),系統(tǒng)將隨機(jī)返回給用戶一些使用建議,如提供平臺(tái)的使用幫助,詢問用戶是否需要背單詞,是否需要進(jìn)入聊天模式等。系統(tǒng)還將隨機(jī)向用戶發(fā)送一些簡(jiǎn)單的調(diào)查問題,如詢問用戶是否是校友,所在部門是哪個(gè)等,以此逐步完善用戶數(shù)據(jù)信息,為后續(xù)的平臺(tái)功能開發(fā)打下基礎(chǔ)。
通過以上的消息處理,系統(tǒng)已經(jīng)準(zhǔn)備好了返回給用戶的信息。最后,系統(tǒng)按照信息的類型準(zhǔn)備相應(yīng)的XML結(jié)構(gòu),并向微信服務(wù)器返回響應(yīng)數(shù)據(jù)包,完成整個(gè)交互過程。其中,大部分情況下信息以文本類型打包,即在微信中直接返回一段文字對(duì)話。在處理新聞列表、講座列表、教師名錄列表等多條信息時(shí),需要使用圖文模板的XML結(jié)構(gòu),以便在用戶微信界面中以列表形式顯示這些信息。在少數(shù)情況下,系統(tǒng)會(huì)返回音頻信息,此時(shí)需要使用音樂模板返回響應(yīng)數(shù)據(jù)包。
5. 安全性
微信公共平臺(tái)由于帶有官方賬號(hào)的權(quán)威效應(yīng),且直接面向用戶交互,其服務(wù)的穩(wěn)定性、數(shù)據(jù)的安全性不可忽視。在CodeIgniter框架中包含了一些重要的內(nèi)部安全特性,如嚴(yán)格限制URI中的字符,系統(tǒng)初始化期間注銷所有全局變量,在生產(chǎn)環(huán)境中禁用PHP錯(cuò)誤報(bào)告等,以降低系統(tǒng)被惡意數(shù)據(jù)入侵的風(fēng)險(xiǎn)。同時(shí),我們也在平臺(tái)中使用了CodeIgniter框架的XSS過濾器對(duì)數(shù)據(jù)進(jìn)行過濾,降低跨站腳本攻擊的風(fēng)險(xiǎn);使用框架的表單驗(yàn)證類以驗(yàn)證、過濾和預(yù)處理數(shù)據(jù),并在插入數(shù)據(jù)庫之前轉(zhuǎn)移所有數(shù)據(jù)。
此外,在站點(diǎn)配置階段,我們將CodeIgniter框架中system和application兩個(gè)重要的腳本文件夾放在網(wǎng)站根目錄以外的本地路徑下,使瀏覽器無法直接訪問這些文件,同時(shí)在主目錄中使用絕對(duì)路徑來引用這些腳本文件,以增強(qiáng)系統(tǒng)的安全性。
1. 用戶授權(quán)
在微信公共平臺(tái)中存在校園卡余額查詢、校園卡掛失等功能,需要與現(xiàn)有的校園信息系統(tǒng)進(jìn)行數(shù)據(jù)對(duì)接,對(duì)接前提是該用戶已獲得公共數(shù)據(jù)庫賬號(hào)授權(quán)。在進(jìn)行授權(quán)操作時(shí),如果要求用戶通過微信對(duì)話來輸入賬號(hào)和密碼,則該授權(quán)信息將以明文的方式暴露在微信消息記錄中,導(dǎo)致嚴(yán)重的安全問題。
針對(duì)這一授權(quán)問題,平臺(tái)的解決方式是將用戶的OpenId進(jìn)行SHA加密并儲(chǔ)存在User表中,當(dāng)用戶選擇在微信平臺(tái)中綁定自己的公共數(shù)據(jù)庫賬號(hào)時(shí),系統(tǒng)返回給用戶一個(gè)帶有SHA加密字符串的URI地址,用戶可以通過微信應(yīng)用中的內(nèi)置瀏覽器訪問該頁面。該頁面創(chuàng)建于平臺(tái)服務(wù)器中,并且整合了校園的CAS登錄驗(yàn)證服務(wù)。用戶驗(yàn)證成功后,系統(tǒng)將更新帶有該SHA加密字符串的用戶記錄,標(biāo)記授權(quán)狀態(tài)。此后凡是平臺(tái)中涉及到與校園信息系統(tǒng)相關(guān)的任何操作,都可以通過User表中的授權(quán)狀態(tài)進(jìn)行判斷和處理,從而實(shí)現(xiàn)微信賬號(hào)與公共數(shù)據(jù)庫賬號(hào)的安全綁定。
2. 系統(tǒng)響應(yīng)速度
圖2 平臺(tái)消息處理流程
微信要求平臺(tái)服務(wù)器在收到微信服務(wù)器POST的數(shù)據(jù)后,必須在5秒鐘之內(nèi)返回響應(yīng)包,否則將不會(huì)返回給用戶任何信息。從前文可以明顯看出,平臺(tái)應(yīng)用程序中包含了大量的流程判斷,其中一些流程需要調(diào)用外部接口,或者通過頁面采集來獲取相關(guān)內(nèi)容,這些環(huán)節(jié)的響應(yīng)時(shí)間有可能過長,從而影響到整個(gè)平臺(tái)在規(guī)定的時(shí)間內(nèi)返回響應(yīng)包。
該問題的解決分為兩個(gè)方面,一方面是通過優(yōu)化CodeIgniter框架中的加載項(xiàng)、優(yōu)化系統(tǒng)代碼來實(shí)現(xiàn)平臺(tái)本身的響應(yīng)加速;另一方面是制定服務(wù)器策略,定時(shí)采集某些外部接口中的數(shù)據(jù),將其儲(chǔ)存于系統(tǒng)自身的數(shù)據(jù)庫中。如在微信平臺(tái)實(shí)際運(yùn)行中,用戶查詢空氣質(zhì)量時(shí)常常無法得到回應(yīng),查找原因后發(fā)現(xiàn)問題在于提供數(shù)據(jù)的相關(guān)網(wǎng)站響應(yīng)較慢,導(dǎo)致整體響應(yīng)時(shí)長超過了5秒鐘。針對(duì)該情況,系統(tǒng)修改為每隔1小時(shí)定期采集該網(wǎng)站中的實(shí)時(shí)空氣質(zhì)量數(shù)據(jù),通過平臺(tái)數(shù)據(jù)庫直接向用戶返回?cái)?shù)據(jù),有效解決了該問題。
3. 自動(dòng)聊天功能
為了增加微信平臺(tái)的交互趣味性,我們?cè)谄脚_(tái)中添加了自動(dòng)聊天功能,實(shí)現(xiàn)簡(jiǎn)單的互動(dòng)對(duì)話。目前網(wǎng)絡(luò)上有一些流行的聊天接口,如小i機(jī)器人、小黃雞等,但其中往往含有一些不良的聊天內(nèi)容,不適宜用作高校官方賬號(hào)的聊天接口。為此平臺(tái)中編寫了一種學(xué)習(xí)模式,用戶可以通過輸入問題和回答來使系統(tǒng)學(xué)習(xí)該問答,如輸入“你好”,回答“你也好”等。由于問答的經(jīng)驗(yàn)都來自于用戶,因此同一個(gè)問題對(duì)應(yīng)的回答是不盡相同的,系統(tǒng)將從回答中進(jìn)行隨機(jī)抽取。用戶輸入越多的回答,在對(duì)話中出現(xiàn)的概率越大。
此外,不排除存在用戶在學(xué)習(xí)模式中惡意輸入不良內(nèi)容的可能性。為此平臺(tái)使用了關(guān)鍵詞過濾及不良內(nèi)容舉報(bào)機(jī)制,凡是用戶在聊天模式下發(fā)現(xiàn)違規(guī)內(nèi)容,都可以直接回復(fù)關(guān)鍵詞舉報(bào)該內(nèi)容。
通過自動(dòng)聊天功能,校園用戶可以共享許多有價(jià)值的經(jīng)驗(yàn),如“哪個(gè)自修教室最安靜”、“食堂哪個(gè)供餐點(diǎn)的飯菜味道不錯(cuò)”等,使微信公共賬號(hào)從“一對(duì)一”的交流模式變?yōu)椤岸鄬?duì)多”交流。
4. 結(jié)果網(wǎng)頁顯示
在查詢新聞、講座、通知等信息時(shí),平臺(tái)返回的列表中包含了信息的標(biāo)題、簡(jiǎn)介和鏈接,用戶通過打開該鏈接來閱讀信息的全文。由于閱讀的環(huán)境為微信的內(nèi)置瀏覽器,普通的網(wǎng)頁在該環(huán)境下需要手動(dòng)放大才能看清文字,并且需要上下左右不斷移動(dòng)頁面來瀏覽內(nèi)容信息,用戶體驗(yàn)較差,也較為耗費(fèi)網(wǎng)絡(luò)流量。
針對(duì)該問題,華東師范大學(xué)網(wǎng)站群部署了一套公用移動(dòng)化模板,使用響應(yīng)式設(shè)計(jì)的方法,為網(wǎng)站群中每個(gè)站點(diǎn)的每個(gè)頁面生成了一份面向移動(dòng)設(shè)備優(yōu)化的頁面,在微信公共平臺(tái)中返回的所有頁面都采用該模板對(duì)應(yīng)的頁面地址。這樣無論在微信中瀏覽校級(jí)新聞、公告,還是來自任何院系網(wǎng)站的網(wǎng)頁內(nèi)容,用戶都能夠獲得最佳的使用體驗(yàn)。
華東師范大學(xué)微信公共平臺(tái)已于2013年5月正式開通,至今關(guān)注人數(shù)已超過5000人。微信平臺(tái)實(shí)現(xiàn)了校園信息化系統(tǒng)與社會(huì)化媒體的有機(jī)結(jié)合,方便了師生使用各種校內(nèi)服務(wù)資源,拓展了學(xué)校信息宣傳工作在新媒體領(lǐng)域的影響力。在下一階段,我們將著眼于微信公共平臺(tái)與高校教學(xué)資源的結(jié)合,使其能夠進(jìn)一步服務(wù)于學(xué)校的教學(xué)和科研工作。