微信公衆號開發(二)消息接收與響應處理

實現思路

我們先打開微信的開發文檔,選擇“消息管理”模塊中的”接收普通消息“

 

文檔中已經告訴我們,當普通微信用戶向公衆賬號發送消息時,微信服務器會把該消息封裝成XML數據包通過POST的方式發送到開發者填寫的URL上。我們設置的URL僅僅只有一個,上篇文章中是用來做接入驗證的,當時是微信服務器發送GET請求過來,而現在是用來做消息處理的,此時微信服務器發送的是POST請求,因此想要區分開來應該做什麼事情,只需要根據請求方式來判斷即可。

因此,我們需要再創建一個handleMessage方法來做消息處理

觀察圖中的兩個方法,其實就是請求路徑相同,但請求方式不同,一個是GET方式一個是POST方式。

參數理解

現在我們再來看下開發文檔,當用戶發送普通消息到公衆號,微信服務器發送的XML數據中會包含下面的參數。

如果是圖片消息會包含下面的參數:

實際上,用戶可發送的類型還有很多,比如語音,視頻,地理位置等等。
我們對比一下不同類型的xml數據包中的參數,ToUserName,FromUserName,CreateTime,MsgType,MsgId這五個是公共的,所有類型都會帶上這些參數。【具體參數意思可以查看官方文檔的解釋】

這裏重點介紹一下MsgId意思:

MsgId:用戶發送的每個消息都有自己的id,可以用於消息排重,比如微信服務器把xml消息包發送到URL了,但是五秒內微信服務器沒有收到我們的響應,則會重新發起請求,總共重試三次。如果不做消息排重,那麼用戶可能就收到多條相同的響應消息了。

接下來,我們可以創建一個封裝消息的實體類,把所有可接收到的參數都放進入,其他類型的暫時不演示,所以只在最後加入了文本和圖片的參數:

這時候大家可能會有個疑問,爲什麼字段名稱都是大寫開頭呢?
因爲微信服務器傳過來的xml數據包中的xml元素都是大寫開頭的,如下所示:

因爲xml解析是大小寫敏感的,所以爲了方便封裝,我直接把字段名設置爲大寫開頭。
當然,如果還是想要小寫開頭的字段,也是可以的,我們待會再說處理方式。

接收消息

實體已經建好之後,我們就可以開始接收微信傳過來的xml數據了。
第1步:在handleMessage方法的形參上添加InMsgEntity類型的參數,並且貼上@RequestBody註解,如下代碼所示:

@RequestBody 該註解用於讀取request請求的body部分數據,根據Content-Type來判斷把數據當做什麼類型來解析,然後把相應的數據綁定到參數上。

第2步:需要配合JAXB的註解來解析xml。
在 InMsgEntity 上添加以下兩個註解:

@XmlRootElement是一個類級別註解,主要屬性爲name,意爲指定根節點的名字。
往上面看前面舉了個微信傳過來的xml數據的例子裏,裏面的根節點就是"xml",所以這裏就直接設置name="xml"

@XmlAccessorType用於定義這個類中的何種類型需要映射到XML中
XmlAccessType.PROPERTY:代表映射這個類中的屬性(get/set方法)到XML
XmlAccessType.FIELD:代表映射這個類中的所有字段到XML(我選用的,現在的字段名剛好是大寫開頭了)

另外,剛纔說到如果字段名是小寫,怎麼解決封裝問題?
在每個字段或屬性上添加@XmlElement註解來指定名稱映射
如:

現在我們可以掃描自己的公衆號二維碼來測試發送消息後臺服務器是否能接收到。

通過打印輸出可知,微信傳過來的xml消息包已經成功轉換爲我們的java對象了。

InMsgEntity [FromUserName=oLc_w0vzRKOP16XnzdVQH_6usu1o, ToUserName=gh_03b242a73270, CreateTime=1565146190, MsgType=text, MsgId=22407502929260367, Content=哈哈哈哈, PicUrl=null, MediaId=null]

響應消息

現在我們可以先來嘗試回覆一條相同的內容給用戶。

打開微信開發文檔,選擇"被動回覆消息"。

發送被動消息其實不是一種接口,而是對微信服務器發過來消息的一次回覆。

我們可以看到文檔裏面接收的普通文本回復的格式和接收的格式基本是一樣的,但是圖片消息或其他消息的還是有些區別。

如上例子,比之前多了Image的元素,所以我們需要再創建一個類來封裝響應的xml消息。
這裏我是把所有類型的屬性統一放到OutMsgEntity類中,大家也可以抽取一個父類,不同的消息創建不同的子類也可以。

@XmlElementWrapper註解可以在原xml結點上再包裝一層xml,但僅允許出現在數組或集合屬性上。

實際上,我們現在的需求比較簡單,用戶給我們發什麼,我們就回復什麼,只需要把接收到 InMsgEntity 的內容設置到 OutMsgEntity 上,並且把ToUserName與FormUserName的值設置爲相反即可。

代碼如下:

切記:produces= {MediaType.TEXT_XML_VALUE}一定要加上,否則就不行了

如果你是初學者,我們一起學習,加我qq1847347046,加q備註微信開發然後拉你進羣

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章