1. 程式人生 > >第四篇 :微信公眾平臺開發實戰Java版之完成訊息接受與相應以及訊息的處理

第四篇 :微信公眾平臺開發實戰Java版之完成訊息接受與相應以及訊息的處理

溫馨提示:

     這篇文章是依賴前幾篇的文章的。

首先,我們看看原來寫的dopost方法:

/**
     * 處理微信伺服器發來的訊息
     */
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // TODO 訊息的接收、處理、響應
    }

doPost方法有兩個引數:

   1.request中封裝了請求相關的所有內容,可以從request中取出微信伺服器發來的訊息;

   2.response我們可以對接收到的訊息進行響應,即傳送訊息。

一、解析微信伺服器傳來的訊息

因為微信伺服器傳送過來的是xml格式的訊息,所以我們可以採用 開源框架dom4j去解析xml 。

所用到的jar 包是:dom4j-1.6.1.jar  

官網下載地址:http://www.dom4j.org/dom4j-1.6.1/

網盤下載地址:http://yunpan.cn/cQyR8KkIXxHXn  訪問密碼 0f2e

二、將響應訊息轉換成xml返回給微信伺服器

如何將響應訊息轉換成xml返回的問題,這裡我們將  採用開源框架xstream來實現Java類到xml的轉換

所用到的jar包為:xstream-1.3.1.jar

網盤下載地址:http://yunpan.cn/cQyBU2vTYAe2f  訪問密碼 ad36

封裝訊息處理工具:

package com.souvc.weixin.util;

import java.io.InputStream;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; import com.souvc.weixin.message.resp.Article; import com.souvc.weixin.message.resp.ImageMessage; import com.souvc.weixin.message.resp.MusicMessage; import com.souvc.weixin.message.resp.NewsMessage; import com.souvc.weixin.message.resp.TextMessage; import com.souvc.weixin.message.resp.VideoMessage; import com.souvc.weixin.message.resp.VoiceMessage; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.core.util.QuickWriter; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; import com.thoughtworks.xstream.io.xml.PrettyPrintWriter; import com.thoughtworks.xstream.io.xml.XppDriver; /** * 類名: MessageUtil </br> * 描述: 訊息處理工具類</br> * 開發人員: souvc </br> * 建立時間: 2015-9-30 </br> * 釋出版本:V1.0 </br> */ public class MessageUtil { // 請求訊息型別:文字 public static final String REQ_MESSAGE_TYPE_TEXT = "text"; // 請求訊息型別:圖片 public static final String REQ_MESSAGE_TYPE_IMAGE = "image"; // 請求訊息型別:語音 public static final String REQ_MESSAGE_TYPE_VOICE = "voice"; // 請求訊息型別:視訊 public static final String REQ_MESSAGE_TYPE_VIDEO = "video"; // 請求訊息型別:小視訊 public static final String REQ_MESSAGE_TYPE_SHORTVIDEO = "shortvideo"; // 請求訊息型別:地理位置 public static final String REQ_MESSAGE_TYPE_LOCATION = "location"; // 請求訊息型別:連結 public static final String REQ_MESSAGE_TYPE_LINK = "link"; // 請求訊息型別:事件推送 public static final String REQ_MESSAGE_TYPE_EVENT = "event"; // 事件型別:subscribe(訂閱) public static final String EVENT_TYPE_SUBSCRIBE = "subscribe"; // 事件型別:unsubscribe(取消訂閱) public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe"; // 事件型別:scan(使用者已關注時的掃描帶引數二維碼) public static final String EVENT_TYPE_SCAN = "scan"; // 事件型別:LOCATION(上報地理位置) public static final String EVENT_TYPE_LOCATION = "LOCATION"; // 事件型別:CLICK(自定義選單) public static final String EVENT_TYPE_CLICK = "CLICK"; // 響應訊息型別:文字 public static final String RESP_MESSAGE_TYPE_TEXT = "text"; // 響應訊息型別:圖片 public static final String RESP_MESSAGE_TYPE_IMAGE = "image"; // 響應訊息型別:語音 public static final String RESP_MESSAGE_TYPE_VOICE = "voice"; // 響應訊息型別:視訊 public static final String RESP_MESSAGE_TYPE_VIDEO = "video"; // 響應訊息型別:音樂 public static final String RESP_MESSAGE_TYPE_MUSIC = "music"; // 響應訊息型別:圖文 public static final String RESP_MESSAGE_TYPE_NEWS = "news"; /** * 解析微信發來的請求(XML) * * @param request * @return Map<String, String> * @throws Exception */ @SuppressWarnings("unchecked") public static Map<String, String> parseXml(HttpServletRequest request) throws Exception { // 將解析結果儲存在HashMap中 Map<String, String> map = new HashMap<String, String>(); // 從request中取得輸入流 InputStream inputStream = request.getInputStream(); // 讀取輸入流 SAXReader reader = new SAXReader(); Document document = reader.read(inputStream); // 得到xml根元素 Element root = document.getRootElement(); // 得到根元素的所有子節點 List<Element> elementList = root.elements(); // 遍歷所有子節點 for (Element e : elementList) map.put(e.getName(), e.getText()); // 釋放資源 inputStream.close(); inputStream = null; return map; } /** * 擴充套件xstream使其支援CDATA */ private static XStream xstream = new XStream(new XppDriver() { public HierarchicalStreamWriter createWriter(Writer out) { return new PrettyPrintWriter(out) { // 對所有xml節點的轉換都增加CDATA標記 boolean cdata = true; @SuppressWarnings("unchecked") public void startNode(String name, Class clazz) { super.startNode(name, clazz); } protected void writeText(QuickWriter writer, String text) { if (cdata) { writer.write("<![CDATA["); writer.write(text); writer.write("]]>"); } else { writer.write(text); } } }; } }); /** * 文字訊息物件轉換成xml * * @param textMessage 文字訊息物件 * @return xml */ public static String messageToXml(TextMessage textMessage) { xstream.alias("xml", textMessage.getClass()); return xstream.toXML(textMessage); } /** * 圖片訊息物件轉換成xml * * @param imageMessage 圖片訊息物件 * @return xml */ public static String messageToXml(ImageMessage imageMessage) { xstream.alias("xml", imageMessage.getClass()); return xstream.toXML(imageMessage); } /** * 語音訊息物件轉換成xml * * @param voiceMessage 語音訊息物件 * @return xml */ public static String messageToXml(VoiceMessage voiceMessage) { xstream.alias("xml", voiceMessage.getClass()); return xstream.toXML(voiceMessage); } /** * 視訊訊息物件轉換成xml * * @param videoMessage 視訊訊息物件 * @return xml */ public static String messageToXml(VideoMessage videoMessage) { xstream.alias("xml", videoMessage.getClass()); return xstream.toXML(videoMessage); } /** * 音樂訊息物件轉換成xml * * @param musicMessage 音樂訊息物件 * @return xml */ public static String messageToXml(MusicMessage musicMessage) { xstream.alias("xml", musicMessage.getClass()); return xstream.toXML(musicMessage); } /** * 圖文訊息物件轉換成xml * * @param newsMessage 圖文訊息物件 * @return xml */ public static String messageToXml(NewsMessage newsMessage) { xstream.alias("xml", newsMessage.getClass()); xstream.alias("item", new Article().getClass()); return xstream.toXML(newsMessage); } }
View Code

使用CoreServlet 類完成訊息的接受與響應:

package com.souvc.weixin.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.souvc.weixin.service.CoreService;
import com.souvc.weixin.util.SignUtil;

/**
 * 類名: CoreServlet </br> 
 * 描述: 來接收微信伺服器傳來資訊 </br> 
 * 開發人員: souvc</br> 
 * 建立時間:2015-9-29 </br> 
 * 釋出版本:V1.0 </br>
 */
public class CoreServlet extends HttpServlet {

    private static final long serialVersionUID = 4323197796926899691L;

    /**
     * 確認請求來自微信伺服器
     */
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        // 微信加密簽名
        String signature = request.getParameter("signature");
        // 時間戳
        String timestamp = request.getParameter("timestamp");
        // 隨機數
        String nonce = request.getParameter("nonce");
        // 隨機字串
        String echostr = request.getParameter("echostr");

        PrintWriter out = response.getWriter();
        
        // 通過檢驗signature對請求進行校驗,若校驗成功則原樣返回echostr,表示接入成功,否則接入失敗
        if (SignUtil.checkSignature(signature, timestamp, nonce)) {
            out.print(echostr);
        }
        
        out.close();
        out = null;
    }

    /**
     * 處理微信伺服器發來的訊息
     */
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 訊息的接收、處理、響應
        // 將請求、響應的編碼均設定為UTF-8(防止中文亂碼)
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");

        // 呼叫核心業務類接收訊息、處理訊息
        String respXml = CoreService.processRequest(request);

        // 響應訊息
        PrintWriter out = response.getWriter();
        out.print(respXml);
        out.close();
    }

}
View Code

使用CoreService類完成訊息的處理:

package com.souvc.weixin.service;

import java.util.Date;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import com.souvc.weixin.message.resp.TextMessage;
import com.souvc.weixin.util.MessageUtil;

/**
* 類名: CoreService </br>
* 描述: 核心服務類 </br>
* 開發人員: souvc </br>
* 建立時間:  2015-9-30 </br>
* 釋出版本:V1.0  </br>
 */
public class CoreService {
    /**
     * 處理微信發來的請求
     * @param request
     * @return xml
     */
    public static String processRequest(HttpServletRequest request) {
        // xml格式的訊息資料
        String respXml = null;
        // 預設返回的文字訊息內容
        String respContent = "未知的訊息型別!";
        try {
            // 呼叫parseXml方法解析請求訊息
            Map<String, String> requestMap = MessageUtil.parseXml(request);
            // 傳送方帳號
            String fromUserName = requestMap.get("FromUserName");
            // 開發者微訊號
            String toUserName = requestMap.get("ToUserName");
            // 訊息型別
            String msgType = requestMap.get("MsgType");

            // 回覆文字訊息
            TextMessage textMessage = new TextMessage();
            textMessage.setToUserName(fromUserName);
            textMessage.setFromUserName(toUserName);
            textMessage.setCreateTime(new Date().getTime());
            textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);

            // 文字訊息
            if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
                respContent = "您傳送的是文字訊息!";
            }
            // 圖片訊息
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) {
                respContent = "您傳送的是圖片訊息!";
            }
            // 語音訊息
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) {
                respContent = "您傳送的是語音訊息!";
            }
            // 視訊訊息
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VIDEO)) {
                respContent = "您傳送的是視訊訊息!";
            }
            // 視訊訊息
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_SHORTVIDEO)) {
                respContent = "您傳送的是小視訊訊息!";
            }
            // 地理位置訊息
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)) {
                respContent = "您傳送的是地理位置訊息!";
            }
            // 連結訊息
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) {
                respContent = "您傳送的是連結訊息!";
            }
            // 事件推送
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {
                // 事件型別
                String eventType = requestMap.get("Event");
                // 關注
                if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {
                    respContent = "謝謝您的關注!";
                }
                // 取消關注
                else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) {
                    // TODO 取消訂閱後用戶不會再收到公眾賬號傳送的訊息,因此不需要回復
                }
                // 掃描帶引數二維碼
                else if (eventType.equals(MessageUtil.EVENT_TYPE_SCAN)) {
                    // TODO 處理掃描帶引數二維碼事件
                }
                // 上報地理位置
                else if (eventType.equals(MessageUtil.EVENT_TYPE_LOCATION)) {
                    // TODO 處理上報地理位置事件
                }
                // 自定義選單
                else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {
                    // TODO 處理選單點選事件
                }
            }
            // 設定文字訊息的內容
            textMessage.setContent(respContent);
            // 將文字訊息物件轉換成xml
            respXml = MessageUtil.messageToXml(textMessage);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return respXml;
    }
}
View Code

效果如下:

其他文章關聯:

相關推薦

公眾平臺開發實戰Java完成訊息接受相應以及訊息處理

溫馨提示:      這篇文章是依賴前幾篇的文章的。 首先,我們看看原來寫的dopost方法: /** * 處理微信伺服器發來的訊息 */ public void doPost(HttpServletRequest request, Http

公眾平臺開發實戰Java如何網頁授權獲取使用者基本資訊

第一部分:微信授權獲取基本資訊的介紹 我們首先來看看官方的文件怎麼說: 如果使用者在微信客戶端中訪問第三方網頁,公眾號可以通過微信網頁授權機制,來獲取使用者基本資訊,進而實現業務邏輯。 關於網頁授權回撥域名的說明 1、在微信公眾號請求使用者網頁授權之前,開發者需要先到公眾平臺官網中的開發者中心頁配置授權

公眾平臺開發實戰Java如何實現自定義分享內容

第一部分:微信JS-SDK介紹 微信JS-SDK是微信公眾平臺面向網頁開發者提供的基於微信內的網頁開發工具包。 通過使用微信JS-SDK,網頁開發者可藉助微信高效地使用拍照、選圖、語音、位置等手機系統的能力,同時可以直接使用微信分享、掃一掃、卡券、支付等微信特有的能力,為微信使用者提供更優質的網頁

公眾平臺開發實戰Java如何自定義公眾號選單

我們來了解一下 自定義選單建立介面: 自定義選單查詢介面: 自定義選單刪除介面: 自定義選單介面可實現多種型別按鈕,如下: 1、click:點選推事件 使用者點選click型別按鈕後,微信伺服器會通過訊息介面推送訊息型別為event 的結構給開發者(參考訊息介面指

公眾平臺開發實戰Java如何獲取公眾號的access_token以及快取access_token

一、access_token簡介 為了使第三方開發者能夠為使用者提供更多更有價值的個性化服務,微信公眾平臺 開放了許多介面,包括自定義選單介面、客服介面、獲取使用者資訊介面、使用者分組介面、群發介面等, 開發者在呼叫這些介面時,都需要傳入一個相同的引數 access_token,它是公眾賬號的全域性唯一票

公眾平臺開發實戰Java請求訊息,響應訊息以及事件訊息類的封裝

微信伺服器和第三方伺服器之間究竟是通過什麼方式進行對話的? 下面,我們先看下圖: 其實我們可以簡單的理解: (1)首先,使用者向微信伺服器傳送訊息; (2)微信伺服器接收到使用者的訊息處理之後,通過開發者配置的URL和Token 來找到第三方伺服器,並以XML形式向第三方伺服器傳送訊息

公眾平臺開發實戰Java如何獲取信使用者基本資訊

在關注者與公眾號產生訊息互動後,公眾號可獲得關注者的OpenID(加密後的微訊號,每個使用者對每個公眾號的OpenID是唯一的。對於不同公眾號,同一使用者的openid不同)。 公眾號可通過本介面來根據OpenID獲取使用者基本資訊,包括暱稱、頭像、性別、所在城市、語言和關注時間。 開發者可通過Ope

第一公眾平臺開發實戰Java瞭解公眾平臺基礎知識以及資料準備

相信很多人或多或少聽說了微信公眾平臺的火熱。但是開發還是有一點門檻,鑑於挺多朋友問我怎麼開發,問多了,自己平時也進行以下總結。 所以下面給大家分享一下我的經驗: 第一部分   介紹微信公眾號的一些簡單介紹以及微信扮演的一些角色,微信公眾號的重要性。 1. 微信公眾號是什麼?    官網

第二 公眾平臺開發實戰Java開啟開發者模式,接入微公眾平臺開發

第一部分:微信公眾號對接的基本介紹 一、填寫伺服器配置資訊的介紹 登入微信公眾平臺官網後,進入到公眾平臺後臺管理頁面。 選擇 公眾號基本設定-》基本配置 ,點選“修改配置”按鈕,填寫伺服器地址(URL)、Token和EncodingAESKey。 微信公眾號配置介面:  以上

公眾平臺開發實戰Java獲取使用者基本資訊

在關注者與公眾號產生訊息互動後,公眾號可獲得關注者的OpenID(加密後的微訊號,每個使用者對每個公眾號的OpenID是唯一的。對於不同公眾號,同一使用者的openid不同)。 公眾號可通過本介面來根據OpenID獲取使用者基本資訊,包括暱稱、頭像、性別、所在城市、語言和

公眾平臺開發實戰Java如何獲取公眾號的access_token以及快取access_token

一、access_token簡介 為了使第三方開發者能夠為使用者提供更多更有價值的個性化服務,微信公眾平臺 開放了許多介面,包括自定義選單介面、客服介面、獲取使用者資訊介面、使用者分組介面、群發介面等, 開發者在呼叫這些介面時,都需要傳入一個相同的引數 access_token,它是公眾賬號的全域性唯一票據,

公眾平臺開發教程Java(六) 事件處理(選單點選/關注/取消關注)

前言: 事件處理是非常重要的,這一章講講常見的事件處理 1、關注/取消關注 2、選單點選 事件型別介紹: 在微信中有事件請求是訊息請求中的一種。請求型別為:event 而event事件型別又分多種事件型別,具體分關注:subscribe取消關注:unsubscribe自定義選單點選:CLICK    根

公眾平臺開發(PHP)(三) 訂閱事件(subscribe)處理

一、簡介 新使用者關注微信公眾平臺,將產生一個訂閱事件,即subscribe事件,預設程式碼中沒有對這一事件進行相應回覆處理。 在新使用者關注公眾平臺後,可能想知道該平臺提供了哪些功能,以及怎樣使用該平臺,通俗一點講就是該平臺的“使用說明書”。 本文將詳細講述對su

Java公眾平臺開發(十)【番外】--web開發者工具使用

str weixin ron log 返回 nbsp 地址欄 alt 直接 轉自:http://www.cuiyongzhi.com/post/58.html 為幫助開發者更方便、更安全地開發和調試基於微信的網頁,微信推出了 web 開發者工具。它是一個桌面應用,通過模擬微

[043] 公眾平臺開發教程19-應用例項人臉檢測

CSDN2013年度部落格之星評選活動開始,本人有幸入圍參加評選,如果部落格中的文章對你有所幫助,請為柳峰投上寶貴一票,非常感謝!        在筆者的公眾賬號小q機器人(微訊號:xiaoqrobot)中有一個非常好玩的功能"人臉檢測",它能夠檢測出使用者傳送的圖片中有多少

公眾平臺開發進入(Web App開發入門)

WebApp與Native App有何區別呢? Native App: 1、開發成本非常大。一般使用的開發語言為Java、C++、Objective-C。 2、更新體驗較差、同時也比較麻煩。每一次釋出新的版本,都需要做版本打包,且需要使用者手動更新(有些應用程式即使不需要使用者手動更新,但是也需要有一個噁心

[053] 公眾平臺開發教程23-SAE不支援XStream框架的解決方案

問題描述最近幾天(2014年8月20日之後),突然有不少網友反應,柳峰部落格中的微信公眾平臺開發程式碼在SAE上執行會報錯,或者是能正常部署,但向公眾號發訊息沒反應。以前也有一些初學者質疑過我部落格中的程式碼是否能正常執行,最後都被我一一證明是由於他們的不理解和粗心導致,但這

[044] 公眾平臺開發教程20-新手解惑40則

        筆者在CSDN部落格頻道推出微信公眾平臺開發教程之後,接觸了許多公眾平臺開發愛好者,也幫助他們解決了許多實際的問題,當然這其中有很多問題都是重複的,因此,筆者將這些問題及解答整理出來,以幫助更多初學者少走彎路。1、訂閱號與服務號的主要區別是什麼?訂閱號每天能群

粉絲一鍵同步工具類

1、前言   在公眾號開發的過程中,一般都需要獲取粉絲資料,針對單個粉絲,我們可以通過openid獲取其粉絲資訊; 但不排除這種業務,比如目前開發的公眾號已經在使用中,,當前的框架或者功能已經不能夠滿足使用者的需求、需要重新開發,那麼這個時候你開發的新的微信專案將要接入到之前老的微