- 微信公眾平臺(tái)應(yīng)用開發(fā)實(shí)踐
- 閆小坤 周濤
- 2141字
- 2019-01-04 05:28:05
4.3 接收消息
接收的消息是微信服務(wù)器發(fā)送給公共賬號(hào)的消息。在第3章中我們已經(jīng)介紹了微信服務(wù)器的數(shù)據(jù)交互方式,當(dāng)訂閱用戶給微信公眾號(hào)發(fā)送消息時(shí),微信服務(wù)器會(huì)將消息封裝成XML數(shù)據(jù),以POST方式發(fā)送到我們配置的URL上。根據(jù)消息類型的不同,XML數(shù)據(jù)的格式也有所不同,下面我們將詳細(xì)介紹每種消息格式。
4.3.1 文本消息
文本消息是最常使用的交互方式,發(fā)送的所有文字(包括URL)都是文本消息。文本消息的結(jié)構(gòu)如下:
<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>1348831860</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[this is a test]]></Content> <MsgId>1234567890123456</MsgId> </xml>
參數(shù)說明如表4-4所示。
表4-4 參數(shù)說明

表格中的部分參數(shù)詳細(xì)解釋如下:
- ToUserName 微信公共賬號(hào)的原始ID,在公共賬號(hào)的賬號(hào)信息里能看到,類似gh_******的格式,這個(gè)字段對公共賬號(hào)的開發(fā)者而言沒什么用途。
- FromUserName 消息發(fā)送者的OpenID,類似于og17nt6kNCcqq25b77C8L2zEJXdQ的格式。對于同一個(gè)公共賬號(hào),訂閱用戶的OpenID是固定不變的,而對于不同的公共賬號(hào),用戶的OpenID是不同的。
- CreateTime 消息創(chuàng)建的時(shí)間,是一個(gè)整型數(shù)字,表示從1970年1月1日0時(shí)0分0秒到現(xiàn)在經(jīng)過的秒數(shù)。
- MsgType 消息類型?,F(xiàn)在微信服務(wù)器提供6種類型的消息,即文本消息(text)、圖片消息(image)、語音消息(voice)、視頻消息(video)、地理位置消息(location)、鏈接消息(link)。
下面給出具體的代碼。因?yàn)槲⑿欧?wù)器是以POST的方式發(fā)送數(shù)據(jù)的,所以首先解析POST請求,提取出數(shù)據(jù),代碼如下:
/** *解析接收到的post數(shù)據(jù) * @return SimpleXMLElement */ public function parsePostRequestData() { $rawData = $GLOBALS['HTTP_RAW_POST_DATA']; $data = simplexml_load_string($rawData, 'SimpleXMLElement', LIBXML_NOCDATA); if ($data !== false) $this->_postData = $data;
return $data; }
$GLOBALS['HTTP_RAW_POST_DATA']從$GLOBALS全局變量中獲取POST數(shù)據(jù),這時(shí)得到的數(shù)據(jù)是無類型的,通過simplexml_load_string函數(shù)解析成xml對象,就能供后續(xù)使用了。
isTextMsg用于判斷消息的類型是否為文本消息:
const MSG_TYPE_TEXT = 'text'; /** *判斷是否是文字信息 * @return boolean */ public function isTextMsg() { return $this->_postData->MsgType == self::MSG_TYPE_TEXT; } //發(fā)送消息 $this->text("你發(fā)送的是文本消息,消息內(nèi)容是:".$data->Content);
text函數(shù)用來發(fā)送文本消息,這個(gè)將在后面介紹,如圖4-3所示。

圖4-3
4.3.2 圖片消息
圖片消息是多媒體消息,微信在收到這類消息時(shí)會(huì)將圖片存在微信服務(wù)器端,生成圖片的URL和媒體ID,圖片URL是可以公共訪問的,而公共賬號(hào)可以通過媒體ID獲取圖片文件。
<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>1348831860</CreateTime> <MsgType><![CDATA[image]]></MsgType> <PicUrl><![CDATA[this is a url]]></PicUrl> <MediaId><![CDATA[media_id]]></MediaId> <MsgId>1234567890123456</MsgId> </xml>
參數(shù)說明如表4-5所示。
表4-5 參數(shù)說明

const MSG_TYPE_IMAGE='image'; /** *判斷是否是圖片 * @return boolean */ public function isImageMsg(){ return $this->_postData->MsgType == self::MSG_TYPE_IMAGE; } //發(fā)送消息 $this->text("你發(fā)送的是圖片消息,圖片鏈接是: ".$data->PicUrl."\n媒體ID是: ".$data->MediaId);
運(yùn)行結(jié)果如圖4-4所示。

圖4-4
4.3.3 語音消息
語音消息同樣只發(fā)送媒體ID,還提供語音的格式。
<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>1357290913</CreateTime> <MsgType><![CDATA[voice]]></MsgType> <MediaId><![CDATA[media_id]]></MediaId> <Format><![CDATA[Format]]></Format> <MsgId>1234567890123456</MsgId> </xml>
參數(shù)說明如表4-6所示。
表4-6 參數(shù)說明

const MSG_TYPE_VOICE = 'voice'; /** *判斷是否是語音消息 * @return boolean */ public function isVoiceMsg(){ return $this->_postData->MsgType == self::MSG_TYPE_VOICE; } //發(fā)送消息 $this->text("你發(fā)送的是語音消息,媒體ID是: ".$data->MediaId."\n語音格式是: ".$data->Format);
運(yùn)行結(jié)果如圖4-5所示。

圖4-5
4.3.4 地理位置消息
在LBS和O2O的價(jià)值被極大發(fā)掘的今天,知道用戶的位置能提供很多針對性、個(gè)性化的服務(wù)。微信也提供了在輸入中發(fā)送當(dāng)前位置的功能,如圖4-6所示。
消息格式如下:
<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>1351776360</CreateTime> <MsgType><![CDATA[location]]></MsgType> <Location_X>23.134521</Location_X> <Location_Y>113.358803</Location_Y> <Scale>20</Scale> <Label><![CDATA[位置信息]]></Label> <MsgId>1234567890123456</MsgId> </xml>

圖4-6
參數(shù)說明如表4-7所示。
表4-7 參數(shù)說明

const MSG_TYPE_LOCATION = 'location'; /** *判斷是否是位置信息 * @return boolean */ public function isLocationMsg() { return $this->_postData->MsgType == self::MSG_TYPE_LOCATION; } //發(fā)送消息 $this->text("你發(fā)送的是位置消息,維度為: ".$data->Location_X."\n經(jīng)度為: ".$data->Location_Y."\n縮放 級別為: ".$data->Scale."\n位置為: ".$data->Label);
運(yùn)行結(jié)果如圖4-7所示。

圖4-7
4.3.5 鏈接消息

圖4-8
這里的鏈接消息和URL不是相同的概念,微信公眾平臺(tái)將URL作為文本消息。那么怎么發(fā)送鏈接消息呢?打開已有的鏈接(朋友圈或者朋友發(fā)送的分享),單擊右上角的“分享”按鈕,選擇“發(fā)送給朋友”,就可以發(fā)送給微信朋友和微信群了。如果想分享一個(gè)網(wǎng)頁,就復(fù)制URL并粘貼到消息框,再發(fā)送給微信朋友。建議發(fā)送給公共賬號(hào),免得打擾別人。打開鏈接(默認(rèn)用微信瀏覽器打開),單擊右上角的“分享”按鈕就可以分享到朋友圈或發(fā)送給朋友。當(dāng)前微信并不支持發(fā)送鏈接消息給公共賬號(hào),如果想發(fā)送,那么可以先將鏈接收藏到收藏夾,然后在消息框添加“我的收藏”,如圖4-8所示。
鏈接消息的格式如下:
<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>1351776360</CreateTime> <MsgType><![CDATA[link]]></MsgType> <Title><![CDATA[公眾平臺(tái)官方網(wǎng)站鏈接]]></Title> <Description><![CDATA[公眾平臺(tái)官方網(wǎng)站鏈接]]></Description> <Url><![CDATA[url]]></Url> <MsgId>1234567890123456</MsgId> </xml>
參數(shù)說明如表4-8所示。
表4-8 參數(shù)說明

const MSG_TYPE_LINK='link'; /** *判斷是否是鏈接 * @return boolean */ public function isLinkMsg(){ return $this->_postData->MsgType == self::MSG_TYPE_LINK; } //發(fā)送消息 $this->text("你發(fā)送的是鏈接消息,標(biāo)題是: ".$data->Title."\n摘要是: ".$data->Description."\n鏈接是: ".$data->Url);
運(yùn)行結(jié)果如圖4-9所示。

圖4-9
視頻消息也是多媒體消息,與語音消息類似,格式如下:
<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>1357290913</CreateTime> <MsgType><![CDATA[video]]></MsgType> <MediaId><![CDATA[media_id]]></MediaId> <ThumbMediaId><![CDATA[thumb_media_id]]></ThumbMediaId> <MsgId>1234567890123456</MsgId> </xml>
參數(shù)說明如表4-9所示。
表4-9 參數(shù)說明

const MSG_TYPE_VIDEO = 'video'; /** *判斷是否是視頻消息 * @return boolean */ public function isVideoMsg(){ return $this->_postData->MsgType == self::MSG_TYPE_VIDEO; } //發(fā)送消息 $this->text("你發(fā)送的是視頻消息,媒體ID是: ".$data->MediaId."\n縮略圖ID是: ".$data-> ThumbMediaId);
運(yùn)行結(jié)果如圖4-10所示。

圖4-10
4.3.6 公眾平臺(tái)消息體簽名及加、解密
2014年10月14日,公眾平臺(tái)消息體簽名及加密功能上線。該功能主要對公眾平臺(tái)推送給公眾賬號(hào)的基礎(chǔ)消息和公眾賬號(hào)回復(fù)的響應(yīng)消息進(jìn)行加密,以更好地保護(hù)用戶和公眾賬號(hào)的信息安全。
加解密的原理是AES對稱加密。開發(fā)者服務(wù)器和公眾平臺(tái)服務(wù)器在發(fā)送消息時(shí)用EncodingAESKey(加密所用的密鑰)將消息體加密成密文,再進(jìn)行傳輸。這樣在網(wǎng)絡(luò)上傳輸?shù)膬?nèi)容是加密的,即使被截獲也無法得知明文。公眾賬號(hào)用此密鑰對收到的密文消息體進(jìn)行解密,回復(fù)消息體也用此密鑰加密。
公眾平臺(tái)提供了3種加解密的模式供開發(fā)者選擇,即明文模式、兼容模式、安全模式(可在“開發(fā)者中心”選擇相應(yīng)模式)。選擇兼容模式和安全模式前,需在開發(fā)者中心填寫消息加解密密鑰EncodingAESKey,如圖4-11所示。

圖4-11
- 明文模式:維持現(xiàn)有模式,沒有適配加解密新特性,消息體明文收發(fā),默認(rèn)設(shè)置為明文模式。
- 兼容模式:公眾平臺(tái)發(fā)送消息內(nèi)容將同時(shí)包括明文和密文,消息包長度增加到原來的3倍左右。公眾號(hào)回復(fù)明文或密文均可,不影響現(xiàn)有消息收發(fā)。開發(fā)者可在此模式下進(jìn)行調(diào)試。
- 安全模式(推薦):公眾平臺(tái)發(fā)送消息體的內(nèi)容只含有密文,公眾賬號(hào)回復(fù)的消息體也為密文,建議開發(fā)者在調(diào)試成功后使用此模式收發(fā)消息。
公眾平臺(tái)消息體簽名及加解密方案的示例代碼可參考下載資源中的代碼。
- 基于Proteus的Arduino可視化設(shè)計(jì)
- Spring開發(fā)者的Quarkus實(shí)戰(zhàn)
- Scala機(jī)器學(xué)習(xí)
- Knative最佳實(shí)踐
- Android應(yīng)用安全防護(hù)和逆向分析
- AIDevOps:智能微服務(wù)開發(fā)、運(yùn)維原理與實(shí)踐
- 這就是MCP
- 全棧Monorepo開發(fā)實(shí)戰(zhàn)(Vue 3+Fastify+Deno+pnpm)
- 鳳凰項(xiàng)目:一個(gè)IT運(yùn)維的傳奇故事
- 嵌入式軟件測試:方法、案例與模板詳解
- 分布式應(yīng)用系統(tǒng)架構(gòu)設(shè)計(jì)與實(shí)踐
- Web前端性能優(yōu)化
- 鋒利的jQuery(第2版)
- Scrum捷徑:敏捷策略、工具與技巧
- 基于EEG的腦源定位與腦功能網(wǎng)絡(luò)