【微信公衆號開發】【4】接收消息和消息回覆

前言:java

1,消息推送—— 當普通用戶向公衆賬號發消息時,微信服務器將POST該消息到填寫的URL上(發消息=操做,包括掃描二維碼,點擊菜單等;URL:coreServlet)json

2,消息回覆——對每個POST請求,開發者能夠在響應包中返回特定XML結構,來對該消息進行響應(現支持回覆文本、圖片、圖文、語音、視頻、音樂)服務器

3,消息回覆——假如服務器沒法保證在五秒內處理回覆,則必須回覆「success」或者「」(空串),不然微信後臺會發起三次重試。微信

4,主動發送消息——模板消息(該章節並未說起)app

正文:dom

1,接收消息的封裝(message.req)post

接收消息之基類ui

public class BaseMessage {  
    private String ToUserName;  // 開發者微信號     
    private String FromUserName;  // 發送方賬號(一個OpenID)   
    private long CreateTime;  // 消息建立時間 (整型)   
    private String MsgType;  // 消息類型(text/image/location/link)  
    private long MsgId;  // 消息id,64位整型  
  
    public String getToUserName() {  
        return ToUserName;  
    }  
  
    public void setToUserName(String toUserName) {  
        ToUserName = toUserName;  
    }  
  
    public String getFromUserName() {  
        return FromUserName;  
    }  
  
    public void setFromUserName(String fromUserName) {  
        FromUserName = fromUserName;  
    }  
  
    public long getCreateTime() {  
        return CreateTime;  
    }  
  
    public void setCreateTime(long createTime) {  
        CreateTime = createTime;  
    }  
  
    public String getMsgType() {  
        return MsgType;  
    }  
  
    public void setMsgType(String msgType) {  
        MsgType = msgType;  
    }  
  
    public long getMsgId() {  
        return MsgId;  
    }  
  
    public void setMsgId(long msgId) {  
        MsgId = msgId;  
    }  
}  

接收消息之文本消息編碼

public class TextMessage extends BaseMessage {  
    // 消息內容  
    private String Content;  
  
    public String getContent() {  
        return Content;  
    }  
  
    public void setContent(String content) {  
        Content = content;  
    }  
}  

接收消息之圖片消息url

public class ImageMessage extends BaseMessage {  
    // 圖片連接  
    private String PicUrl;  
  
    public String getPicUrl() {  
        return PicUrl;  
    }  
  
    public void setPicUrl(String picUrl) {  
        PicUrl = picUrl;  
    }  
} 

接收消息之地理位置消息

public class LocationMessage extends BaseMessage {  
    // 地理位置維度  
    private String Location_X;  
    // 地理位置經度  
    private String Location_Y;  
    // 地圖縮放大小  
    private String Scale;  
    // 地理位置信息  
    private String Label;  
  
    public String getLocation_X() {  
        return Location_X;  
    }  
  
    public void setLocation_X(String location_X) {  
        Location_X = location_X;  
    }  
  
    public String getLocation_Y() {  
        return Location_Y;  
    }  
  
    public void setLocation_Y(String location_Y) {  
        Location_Y = location_Y;  
    }  
  
    public String getScale() {  
        return Scale;  
    }  
  
    public void setScale(String scale) {  
        Scale = scale;  
    }  
  
    public String getLabel() {  
        return Label;  
    }  
  
    public void setLabel(String label) {  
        Label = label;  
    }  
}  

接收消息之連接消息

public class LinkMessage extends BaseMessage {  
    // 消息標題  
    private String Title;  
    // 消息描述  
    private String Description;  
    // 消息連接  
    private String Url;  
  
    public String getTitle() {  
        return Title;  
    }  
  
    public void setTitle(String title) {  
        Title = title;  
    }  
  
    public String getDescription() {  
        return Description;  
    }  
  
    public void setDescription(String description) {  
        Description = description;  
    }  
  
    public String getUrl() {  
        return Url;  
    }  
  
    public void setUrl(String url) {  
        Url = url;  
    }  
}  

接收消息之語音消息

public class VoiceMessage extends BaseMessage {  
    // 媒體ID  
    private String MediaId;  
    // 語音格式  
    private String Format;  
  
    public String getMediaId() {  
        return MediaId;  
    }  
  
    public void setMediaId(String mediaId) {  
        MediaId = mediaId;  
    }  
  
    public String getFormat() {  
        return Format;  
    }  
  
    public void setFormat(String format) {  
        Format = format;  
    }  
}  

 

2,響應消息的封裝(message.resp)

響應消息之基類

public class BaseMessage {    
    private String ToUserName;  // 接收方賬號(收到的OpenID)
    private String FromUserName;  // 開發者微信號  
    private long CreateTime;  // 消息建立時間 (整型)
    private String MsgType;  // 消息類型(text/music/news)
    private int FuncFlag;  // 位0x0001被標誌時,星標剛收到的消息  
  
    public String getToUserName() {  
        return ToUserName;  
    }  
  
    public void setToUserName(String toUserName) {  
        ToUserName = toUserName;  
    }  
  
    public String getFromUserName() {  
        return FromUserName;  
    }  
  
    public void setFromUserName(String fromUserName) {  
        FromUserName = fromUserName;  
    }  
  
    public long getCreateTime() {  
        return CreateTime;  
    }  
  
    public void setCreateTime(long createTime) {  
        CreateTime = createTime;  
    }  
  
    public String getMsgType() {  
        return MsgType;  
    }  
  
    public void setMsgType(String msgType) {  
        MsgType = msgType;  
    }  
  
    public int getFuncFlag() {  
        return FuncFlag;  
    }  
  
    public void setFuncFlag(int funcFlag) {  
        FuncFlag = funcFlag;  
    }  
}  

響應消息之文本消息

public class TextMessage extends BaseMessage {  
    // 回覆的消息內容  
    private String Content;  
  
    public String getContent() {  
        return Content;  
    }  
  
    public void setContent(String content) {  
        Content = content;  
    }  
} 

響應消息之音樂消息

public class MusicMessage extends BaseMessage {  
    // 音樂  
    private Music Music;  
  
    public Music getMusic() {  
        return Music;  
    }  
  
    public void setMusic(Music music) {  
        Music = music;  
    }  
}  

音樂消息中Music類的定義

public class Music {  
    // 音樂名稱  
    private String Title;  
    // 音樂描述  
    private String Description;  
    // 音樂連接  
    private String MusicUrl;  
    // 高質量音樂連接,WIFI環境優先使用該連接播放音樂  
    private String HQMusicUrl;  
  
    public String getTitle() {  
        return Title;  
    }  
  
    public void setTitle(String title) {  
        Title = title;  
    }  
  
    public String getDescription() {  
        return Description;  
    }  
  
    public void setDescription(String description) {  
        Description = description;  
    }  
  
    public String getMusicUrl() {  
        return MusicUrl;  
    }  
  
    public void setMusicUrl(String musicUrl) {  
        MusicUrl = musicUrl;  
    }  
  
    public String getHQMusicUrl() {  
        return HQMusicUrl;  
    }  
  
    public void setHQMusicUrl(String musicUrl) {  
        HQMusicUrl = musicUrl;  
    }  
  
}  

響應消息之圖文消息

public class NewsMessage extends BaseMessage {  
    // 圖文消息個數,限制爲10條之內  
    private int ArticleCount;  
    // 多條圖文消息信息,默認第一個item爲大圖  
    private List<Article> Articles;  
  
    public int getArticleCount() {  
        return ArticleCount;  
    }  
  
    public void setArticleCount(int articleCount) {  
        ArticleCount = articleCount;  
    }  
  
    public List<Article> getArticles() {  
        return Articles;  
    }  
  
    public void setArticles(List<Article> articles) {  
        Articles = articles;  
    }  
}  

圖文消息中Article類的定義

public class Article {  
    // 圖文消息名稱  
    private String Title;  
    // 圖文消息描述  
    private String Description;  
    // 圖片連接,支持JPG、PNG格式,較好的效果爲大圖640*320,小圖80*80,限制圖片連接的域名須要與開發者填寫的基本資料中的Url一致  
    private String PicUrl;  
    // 點擊圖文消息跳轉連接  
    private String Url;  
  
    public String getTitle() {  
        return Title;  
    }  
  
    public void setTitle(String title) {  
        Title = title;  
    }  
  
    public String getDescription() {  
        return null == Description ? "" : Description;  
    }  
  
    public void setDescription(String description) {  
        Description = description;  
    }  
  
    public String getPicUrl() {  
        return null == PicUrl ? "" : PicUrl;  
    }  
  
    public void setPicUrl(String picUrl) {  
        PicUrl = picUrl;  
    }  
  
    public String getUrl() {  
        return null == Url ? "" : Url;  
    }  
  
    public void setUrl(String url) {  
        Url = url;  
    }  
  
}  

3,解析接收到的消息及將響應消息轉換成xml返回

前言中說的URL

@ResponseBody  
@RequestMapping(value = "coreServlet", method = RequestMethod.POST)
public void coreServletPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {    
  //獲取微信POST過來的內容。消息爲xml格式
  // 將請求、響應的編碼均設置爲UTF-8(防止中文亂碼)  
  request.setCharacterEncoding("UTF-8");  
  response.setCharacterEncoding("UTF-8");  
  //從請求中讀取整個post數據
  InputStream inputStream = request.getInputStream();
  String postData = IOUtils.toString(inputStream, "UTF-8");
  logger.info("postData = " + postData);
  // 調用核心業務類接收消息、處理消息  
  Message message = CoreService.processRequest(postData);
  String respMessage = message.getRespMessage();         
          
  // 響應消息  
  PrintWriter out = response.getWriter();  
  out.print(respMessage);  
  out.close();  
} 
調用核心業務類接收消息、處理消息 CoreService.processRequest
    private static String UPDATE_MENU = "menu";//更新自定義菜單的口令
    public static Message processRequest(String msg) { 
        Message message = new Message(); 
        String param1 = "";//二維碼帶的參數  
        
        try {                         
            Map<String, String> requestMap = MessageUtil.parseXml(msg);  // xml請求解析                 
            String fromUserName = requestMap.get("FromUserName");  // 發送方賬號  
            String toUserName = requestMap.get("ToUserName");  // 接收方賬號                 
            String msgType = requestMap.get("MsgType");  // 消息類型               
            String eventKey = requestMap.get("EventKey");  // 事件KEY值,與建立自定義菜單時指定的KEY值對應   
            String respContent = "請求處理中...";  // 默認返回的文本消息內容     
            // 回覆文本消息  
            TextMessage textMessage = new TextMessage();  
            textMessage.setToUserName(fromUserName);  
            textMessage.setFromUserName(toUserName);  
            textMessage.setCreateTime(new Date().getTime());  
            textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);  
            textMessage.setFuncFlag(0);  
            // 建立圖文消息  
            NewsMessage newsMessage = new NewsMessage();  
            newsMessage.setToUserName(fromUserName);  
            newsMessage.setFromUserName(toUserName);  
            newsMessage.setCreateTime(new Date().getTime());  
            newsMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_NEWS);  
            newsMessage.setFuncFlag(0); 

            // 文本消息  
            if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {  
                respContent = "您發送的是文本消息!"; 
                if((UPDATE_MENU).equals(requestMap.get("Content"))){ 
                    respContent = MenuManager.menuManager();//更新自定義菜單
                } 
                // 回覆包含「定位跑」
                else if ( requestMap.get("Content").contains("定位跑")) {
                    respContent = "您的願望咱們已經收到,請關注8月8日將發佈的中獎名單信息";
                }
            }            
            // 圖片消息  
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) {  
                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_VOICE)) {  
            }  
            // 事件推送  
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {  
                // 事件類型  
                String eventType = requestMap.get("Event");  
                // 訂閱  
                if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {  
                    respContent = "歡迎關注愛關節網";  
                    if(!StringUtils.isEmpty(eventKey)){
                        param1 = eventKey.substring(eventKey.indexOf("_")+1);
                    }
                } 
                // 掃描  
                if (eventType.equals(MessageUtil.EVENT_TYPE_SCAN)) {  
                    respContent = "";
                    if(!StringUtils.isEmpty(eventKey)){
                        param1 =  eventKey;                        
                    }
                }
                // 取消訂閱  
                else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) {  
                    // TODO 取消訂閱後用戶再收不到公衆號發送的消息,所以不須要回復消息  
                }             
                // 自定義菜單點擊事件  
                else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {                        
                    List<Article> articleList = new ArrayList<Article>(); 
                    
                    if (eventKey.equals("13")) {  
                        respContent = "內容建設中,敬請期待";  
                    } else if (eventKey.equals("14")) {  
                        //單圖文消息
                        Article article = new Article();  
                        article.setTitle("靈動中國|愛關節·不等待 廣場舞公益活動川渝開賽");  
                        article.setDescription("靈動中國|愛關節·不等待 廣場舞公益活動川渝開賽");  
                        article.setPicUrl(Config.domain() + "/UCenter/wx_marathon/img/zuimeiguangchangwu.png");  
                        article.setUrl("http://mp.weixin.qq.com/s/6_-hwdJ6fFV58UD8SLAtcg");  
                        articleList.add(article);  
                        // 設置圖文消息個數  
                        newsMessage.setArticleCount(articleList.size());  
                        // 設置圖文消息包含的圖文集合  
                        newsMessage.setArticles(articleList);  
                        // 將圖文消息對象轉換成xml字符串  
                        respMessage = MessageUtil.newsMessageToXml(newsMessage);
                        message.setParam1("");
                        message.setRespMessage(respMessage);
                        message.setFromUserName(fromUserName);
                        message.setToUserName(toUserName);                                
                        return message;  
                    }
                }  
            }              
            textMessage.setContent(respContent);  
            respMessage = MessageUtil.textMessageToXml(textMessage); 
            message.setParam1(param1);
            message.setRespMessage(respMessage);
            message.setFromUserName(fromUserName);
            message.setToUserName(toUserName);
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
  
        return message;  
    }
MessageUtil
public class MessageUtil {
    
    public static final String RESP_MESSAGE_TYPE_TEXT = "text";  //返回消息類型:文本  
    public static final String RESP_MESSAGE_TYPE_MUSIC = "music";  //返回消息類型:音樂 
    public static final String RESP_MESSAGE_TYPE_NEWS = "news";  //返回消息類型:圖文  
    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_LINK = "link";  //請求消息類型:連接 
    public static final String REQ_MESSAGE_TYPE_LOCATION = "location";  //請求消息類型:地理位置  
    public static final String REQ_MESSAGE_TYPE_VOICE = "voice";  //請求消息類型:音頻 
    public static final String REQ_MESSAGE_TYPE_EVENT = "event";  //請求消息類型:推送 
    public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";  //事件類型:subscribe(訂閱) 
    public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";  //事件類型:unsubscribe(取消訂閱) 
    public static final String EVENT_TYPE_CLICK = "CLICK";  //事件類型:CLICK(自定義菜單點擊事件) 
    public static final String EVENT_TYPE_SCAN = "SCAN";  //事件類型:SCAN(掃描)
  
    //解析微信發來的請求(XML) 
    @SuppressWarnings("unchecked") 
    public static Map<String, String> parseXml(String msg) throws IOException 
    {  
        // 將解析結果存儲在HashMap中  
        Map<String, String> map = new HashMap<String, String>();            
 
        //讀取輸入流  
        SAXReader reader = new SAXReader();
        try {
            InputStream inputStream = new ByteArrayInputStream(msg.getBytes("UTF-8")); 
            Document document = reader.read(inputStream);  
            Element root = document.getRootElement();         // 獲得xml根元素               
            List<Element> elementList = root.elements();      // 獲得根元素的全部子節點  
       
             for (Element e : elementList)  
                 map.put(e.getName(), e.getText()); 
       
             inputStream.close(); 
             inputStream = null;  
        } catch (DocumentException e) {
            logger.error("解析失敗",e);
        }
  
        return map;  
    }  
  
   
    //文本消息對象轉換成xml 
    public static String textMessageToXml(TextMessage textMessage) {  
        xstream.alias("xml", textMessage.getClass());  
        return xstream.toXML(textMessage);  
    }  
  
    //音樂消息對象轉換成xml  
    public static String musicMessageToXml(MusicMessage musicMessage) {  
        xstream.alias("xml", musicMessage.getClass());  
        return xstream.toXML(musicMessage);  
    }  
  
    //圖文消息對象轉換成xml  
    public static String newsMessageToXml(NewsMessage newsMessage) {  
        xstream.alias("xml", newsMessage.getClass());  
        xstream.alias("item", new Article().getClass());  
        return xstream.toXML(newsMessage);  
    }  
  
    //擴展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);  
                    }  
                }  
            };  
        }  
    });  

    //將java對象轉換爲json對象  
    public static String Object2Json(Object obj){  
        JSONObject json = JSONObject.fromObject(obj);
        // 將json對象轉換爲字符串
        String str = json.toString();
        return str;  
    }  
}  
相關文章
相關標籤/搜索