java微信開發第二步 擷取訊息和回複訊息_java

來源:互聯網
上載者:User

接著上一篇java微信開發API第一步 伺服器接入進行學習,下面介紹java微信開發第二步:擷取訊息和回複訊息,具體內容如下

* 本樣本根據微信開發文檔:http://mp.weixin.qq.com/wiki/home/index.html最新版(4/3/2016 5:34:36 PM )進行開發示範。
* 編輯平台:myeclipse10.7+win32+jdk1.7+tomcat7.0 
* 伺服器:阿里雲 windows server 2008 64bits
* 平台要求:servlet使用註解方式,平台要求:j2ee6.0+、jdk6.0+、tomcat7.0+
* 示範更加註重於api解析。
* 為了便於測試說明,每個測試案例為獨立,不依賴於其它方法。對於封裝,不多加考慮。
* 示範儘可能按照API要求進行,目的:瞭解文檔使用方式,達到舉一反三的效果。
* 知識要求:牢固的java基礎、瞭解http網路通訊知識、對於javaweb有足夠瞭解、json解析
* 在每篇文章結束會給出該部分示範源碼。在分析完API之後,會以源碼包的形式給出所有示範源碼。
* 目前時間:4/3/2016 5:32:57 PM ,以該時間為準。

一、文檔原文-訊息管理(摘要)

文檔地址:http://mp.weixin.qq.com/wiki/17/f298879f8fb29ab98b2f2971d42552fd.html
訊息管理
接收訊息-接收普通訊息
接收訊息-接收事件推送
發送訊息-被動回複訊息
發送訊息-被動回複時的加解密
發送訊息-客服訊息
發送訊息-群發介面
發送訊息-模板訊息介面
發送訊息-模板訊息運營規範
擷取公眾號自動回複配置

二、文檔理解

1、接收訊息

文檔這樣解釋:​當普通微信使用者向公眾帳號發訊息時,微信伺服器將POST訊息的XML資料包到開發人員填寫的URL上。
理解:微信伺服器將使用者發送的訊息通過Post流的形式返回給req。當我們想要擷取使用者發送的訊息時,可以通過req.getInputStream()擷取。當然,我們可以根據文檔上關於訊息的返回的xml格式,進行必要的解析。
實現:

/* * 該部分我們擷取使用者發送的資訊,並且解析成<K,V>的形式進行顯示 */// 解析使用者發送過來的資訊InputStream is = req.getInputStream();// 拿取請求流// 將解析結果儲存在HashMap中Map<String, String> map = new HashMap<String, String>();// 解析xml,將擷取到的返回結果xml進行解析成我們習慣的文字資訊SAXReader reader = new SAXReader();// 第三方jar:dom4j【百度:saxreader解析xml】Document document = null;try {  document = reader.read(is);} catch (DocumentException e1) {  // TODO Auto-generated catch block  e1.printStackTrace();}// 得到xml根項目Element root = document.getRootElement();// 得到根項目的所有子節點List<Element> elementList = root.elements();// 遍曆所有子節點for (Element e : elementList)  map.put(e.getName(), e.getText());// 測試輸出Set<String> keySet = map.keySet();// 測試輸出解析後使用者發過來的資訊System.out.println(TAG + ":解析使用者發送過來的資訊開始");for (String key : keySet) {  System.out.println(key + ":" + map.get(key));}System.out.println(TAG + ":解析使用者發送過來的資訊結束");   

2、發送訊息

文檔這樣解釋:​當使用者發送訊息給公眾號時(或某些特定的使用者操作引發的事件推送時),會產生一個POST請求,開發人員可以在響應包(Get)中返回特定XML結構,來對該訊息進行響應(現支援回複文本、圖片、圖文、語音、視頻、音樂)。嚴格來說,發送被動響應訊息其實並不是一種介面,而是對微信伺服器發過來訊息的一次回複。
理解:使用者發送請求,會產生一個POST請求,我們可以通過Respone進行回複訊息。但是,回複的內容有嚴格的格式要求,只有滿足格式要求,微信伺服器才會進行處理返回給使用者。通過查看文檔“訊息管理”模組,我們可以看到微信中有各種各樣的訊息,每類訊息都有自己特定的格式要求,我們必須按照要求才可以正常的給使用者返回特定的資訊。我們嘗試按照文檔的要求格式給使用者回複文本資訊、圖文訊息。重點:按照文檔要求構造需要的參數。特別注意:參數區分大小寫。
1)、實現1-回複普通簡訊:

//執行個體1:發送普通簡訊,請查看文檔關於“回複簡訊”的xml格式// 第一步:按照回複文本資訊構造需要的參數TextMsg textMsg = new TextMsg();textMsg.setToUserName(map.get("FromUserName"));// 發送和接收資訊“User”剛好相反textMsg.setFromUserName(map.get("ToUserName"));textMsg.setCreateTime(new Date().getTime());// 訊息建立時間 (整型)textMsg.setMsgType("text");// 文本類型訊息textMsg.setContent("我是伺服器回複給使用者的資訊");// // 第二步,將構造的資訊轉化為微信識別的xml格式【百度:xstream bean轉xml】XStream xStream = new XStream();xStream.alias("xml", textMsg.getClass());String textMsg2Xml = xStream.toXML(textMsg);System.out.println(textMsg2Xml);// // 第三步,發送xml的格式資訊給微信伺服器,伺服器轉寄給使用者PrintWriter printWriter = resp.getWriter();printWriter.print(textMsg2Xml);

2)、實現2-回複圖文訊息:

//執行個體2,發送圖文訊息。請查看文檔關於“回複圖文訊息”的xml格式// 第一步:按照回複圖文資訊構造需要的參數List<Article> articles = new ArrayList<Article>();Article a = new Article();a.setTitle("我是圖片標題");a.setUrl("www.baidu.com");// 該地址是點擊圖片跳轉後a.setPicUrl("yun_qi_img/08f790529822720ea5d058ba7ccb0a46f21fab50.gif");// 該地址是一個有效圖片地址a.setDescription("我是圖片的描述");articles.add(a);PicAndTextMsg picAndTextMsg = new PicAndTextMsg();picAndTextMsg.setToUserName(map.get("FromUserName"));// 發送和接收資訊“User”剛好相反picAndTextMsg.setFromUserName(map.get("ToUserName"));picAndTextMsg.setCreateTime(new Date().getTime());// 訊息建立時間 (整型)picAndTextMsg.setMsgType("news");// 圖文類型訊息picAndTextMsg.setArticleCount(1);picAndTextMsg.setArticles(articles);// 第二步,將構造的資訊轉化為微信識別的xml格式【百度:xstream bean轉xml】XStream xStream = new XStream();xStream.alias("xml", picAndTextMsg.getClass());xStream.alias("item", a.getClass());String picAndTextMsg2Xml = xStream.toXML(picAndTextMsg);System.out.println(picAndTextMsg2Xml);// 第三步,發送xml的格式資訊給微信伺服器,伺服器轉寄給使用者PrintWriter printWriter = resp.getWriter();printWriter.print(picAndTextMsg2Xml);

該部分所有操作源碼,可以直接使用

CoreServlet.java(包括伺服器接入、接收使用者發送訊息、回複普通文字訊息、回複圖文訊息。需要第三方jar:dom4j、xstream)

package com.gist.servlet;import java.io.IOException;import java.io.InputStream;import java.io.PrintWriter;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.util.ArrayList;import java.util.Arrays;import java.util.Date;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Set;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.dom4j.Document;import org.dom4j.DocumentException;import org.dom4j.Element;import org.dom4j.io.SAXReader;import com.gist.bean.Article;import com.gist.bean.PicAndTextMsg;import com.thoughtworks.xstream.XStream;/** * @author 高遠</n> 郵箱:wgyscsf@163.com</n> 部落格 http://blog.csdn.net/wgyscsf</n> *     編寫時期 2016-4-3 下午4:34:05 */@WebServlet("/CoreServlet")public class CoreServlet extends HttpServlet {  private static final long serialVersionUID = 1L;  String TAG = "CoreServlet";  /*   * 第二步:驗證伺服器位址的有效性 開發人員提交資訊後,微信伺服器將發送GET請求到填寫的伺服器位址URL上,   * GET請求攜帶四個參數:signature、timestamp、nonce、echostr   * 開發人員通過檢驗signature對請求進行校正(下面有校正方式)。 若確認此次GET請求來自微信伺服器,請原樣返回echostr參數內容,   * 則接入生效, 成為開發人員成功,否則接入失敗。   *    * 加密/校正流程如下: 1. 將token、timestamp、nonce三個參數進行字典序排序 2.   * 將三個參數字串拼接成一個字串進行sha1加密 3. 開發人員獲得加密後的字串可與signature對比,標識該請求來源於微信   */  /*   * 字典排序(lexicographical   * order)是一種對於隨機變數形成序列的排序方法。其方法是,按照字母順序,或者數字小大順序,由小到大的形成序列。   */  @Override  protected void doGet(HttpServletRequest req, HttpServletResponse resp)      throws ServletException, IOException {    // 設定編碼    req.setCharacterEncoding("utf-8");    resp.setContentType("html/text;charset=utf-8");    resp.setCharacterEncoding("utf-8");    // 擷取輸出資料流    PrintWriter printWriter = resp.getWriter();    // 設定一個全域的token,開發人員自己設定。api這樣解釋:Token可由開發人員可以任意填寫,    // 用作產生簽名(該Token會和介面URL中包含的Token進行比對,從而驗證安全性)    String token = "wgyscsf";    // 根據api說明,擷取上述四個參數    String signature = req.getParameter("signature");    String timestamp = req.getParameter("timestamp");    String nonce = req.getParameter("nonce");    String echostr = req.getParameter("echostr");    // // temp:臨時列印,觀看返回參數情況    // System.out.println(TAG + ":signature:" + signature + ",timestamp:"    // + timestamp + ",nonce:" + nonce + ",echostr:" + echostr);    // 根據api所說的“加密/校正流程”進行接入。共計三步    // 第一步:將token、timestamp、nonce三個參數進行字典序排序    String[] parms = new String[] { token, timestamp, nonce };// 將需要字典序排列的字串放到數組中    Arrays.sort(parms);// 按照api要求進行字典序排序    // 第二步:將三個參數字串拼接成一個字串進行sha1加密    // 拼接字串    String parmsString = "";// 注意,此處不能=null。    for (int i = 0; i < parms.length; i++) {      parmsString += parms[i];    }    // sha1加密    String mParms = null;// 加密後的結果    MessageDigest digest = null;    try {      digest = java.security.MessageDigest.getInstance("SHA");    } catch (NoSuchAlgorithmException e) {      // TODO Auto-generated catch block      e.printStackTrace();    }    digest.update(parmsString.getBytes());    byte messageDigest[] = digest.digest();    // Create Hex String    StringBuffer hexString = new StringBuffer();    // 位元組數群組轉換為 十六進位 數    for (int i = 0; i < messageDigest.length; i++) {      String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);      if (shaHex.length() < 2) {        hexString.append(0);      }      hexString.append(shaHex);    }    mParms = hexString.toString();// 加密結果    /*     * api要求: 若確認此次GET請求來自微信伺服器,請原樣返回echostr參數內容, 則接入生效, 成為開發人員成功,否則接入失敗。     */    // 第三步: 開發人員獲得加密後的字串可與signature對比,標識該請求來源於微信接入成功。    // System.out.println(TAG + ":" + mParms + "---->" + signature);    if (mParms.equals(signature)) {      // System.out.println(TAG + ":" + mParms + "---->" + signature);      printWriter.write(echostr);    } else {      // 接入失敗,不用回寫      // System.out.println(TAG + "接入失敗");    }  }  /*   * 查看api文檔關於收發訊息推送的訊息格式基本一致。 如以下格式: <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> 那麼,我們就可以進行統一處理。   */  /*   * 我們先擷取輸入資料流,看輸入資料流裡面的資訊。通過測試列印輸出資料流,我們可以看到每次使用者請求,都會收到req請求,請求格式是xml格式,該資訊在文檔中有說明。   */  /*   * 特別注意,req.getInputStream()只能擷取一次,並且只能讀取一次。如果想要多次讀取,需要另外想辦法。為了簡單起見,   * 我們只擷取一次req.getInputStream(),不再列印輸出資料流資訊。直接列印解析後的資訊。   */  @Override  protected void doPost(HttpServletRequest req, HttpServletResponse resp)      throws ServletException, IOException {    // 設定編碼    req.setCharacterEncoding("utf-8");    resp.setContentType("html/text;charset=utf-8");    resp.setCharacterEncoding("utf-8");    /*     * 該部分我們擷取使用者發送的資訊,並且解析成<K,V>的形式進行顯示     */    // 解析使用者發送過來的資訊    InputStream is = req.getInputStream();// 拿取請求流    // 將解析結果儲存在HashMap中    Map<String, String> map = new HashMap<String, String>();    // 解析xml,將擷取到的返回結果xml進行解析成我們習慣的文字資訊    SAXReader reader = new SAXReader();// 第三方jar:dom4j【百度:saxreader解析xml】    Document document = null;    try {      document = reader.read(is);    } catch (DocumentException e1) {      // TODO Auto-generated catch block      e1.printStackTrace();    }    // 得到xml根項目    Element root = document.getRootElement();    // 得到根項目的所有子節點    List<Element> elementList = root.elements();    // 遍曆所有子節點    for (Element e : elementList)      map.put(e.getName(), e.getText());    // 測試輸出    Set<String> keySet = map.keySet();    // 測試輸出解析後使用者發過來的資訊    System.out.println(TAG + ":解析使用者發送過來的資訊開始");    for (String key : keySet) {      System.out.println(key + ":" + map.get(key));    }    System.out.println(TAG + ":解析使用者發送過來的資訊結束");    /*     * 該部分我們嘗試按照文檔的要求格式給使用者回複文本資訊、圖文訊息。重點:按照文檔要求構造需要的參數。特別注意:參數區分大小寫。     */    // //執行個體1:發送普通簡訊,請查看文檔關於“回複簡訊”的xml格式    //    // // 第一步:按照回複文本資訊構造需要的參數    // TextMsg textMsg = new TextMsg();    // textMsg.setToUserName(map.get("FromUserName"));// 發送和接收資訊“User”剛好相反    // textMsg.setFromUserName(map.get("ToUserName"));    // textMsg.setCreateTime(new Date().getTime());// 訊息建立時間 (整型)    // textMsg.setMsgType("text");// 文本類型訊息    // textMsg.setContent("我是伺服器回複給使用者的資訊");    //    // // // 第二步,將構造的資訊轉化為微信識別的xml格式【百度:xstream bean轉xml】    // XStream xStream = new XStream();    // xStream.alias("xml", textMsg.getClass());    // String textMsg2Xml = xStream.toXML(textMsg);    // System.out.println(textMsg2Xml);    //    // // // 第三步,發送xml的格式資訊給微信伺服器,伺服器轉寄給使用者    // PrintWriter printWriter = resp.getWriter();    // printWriter.print(textMsg2Xml);    // //執行個體2,發送圖文訊息。請查看文檔關於“回複圖文訊息”的xml格式    // 第一步:按照回複圖文資訊構造需要的參數    List<Article> articles = new ArrayList<Article>();    Article a = new Article();    a.setTitle("我是圖片標題");    a.setUrl("www.baidu.com");// 該地址是點擊圖片跳轉後    a.setPicUrl("yun_qi_img/08f790529822720ea5d058ba7ccb0a46f21fab50.gif");// 該地址是一個有效圖片地址    a.setDescription("我是圖片的描述");    articles.add(a);    PicAndTextMsg picAndTextMsg = new PicAndTextMsg();    picAndTextMsg.setToUserName(map.get("FromUserName"));// 發送和接收資訊“User”剛好相反    picAndTextMsg.setFromUserName(map.get("ToUserName"));    picAndTextMsg.setCreateTime(new Date().getTime());// 訊息建立時間 (整型)    picAndTextMsg.setMsgType("news");// 圖文類型訊息    picAndTextMsg.setArticleCount(1);    picAndTextMsg.setArticles(articles);    // 第二步,將構造的資訊轉化為微信識別的xml格式【百度:xstream bean轉xml】    XStream xStream = new XStream();    xStream.alias("xml", picAndTextMsg.getClass());    xStream.alias("item", a.getClass());    String picAndTextMsg2Xml = xStream.toXML(picAndTextMsg);    System.out.println(picAndTextMsg2Xml);    // 第三步,發送xml的格式資訊給微信伺服器,伺服器轉寄給使用者    PrintWriter printWriter = resp.getWriter();    printWriter.print(picAndTextMsg2Xml);  }}

TestMsg.java(普通文字訊息bean)

package com.gist.bean;/** * @author 高遠</n> 郵箱:wgyscsf@163.com</n> 部落格 http://blog.csdn.net/wgyscsf</n> *     編寫時期 2016-4-4 下午2:09:27 */public class TextMsg {  private String ToUserName;  private String FromUserName;  private long CreateTime;  private String MsgType;  @Override  public String toString() {    return "TextMsg [ToUserName=" + ToUserName + ", FromUserName="        + FromUserName + ", CreateTime=" + CreateTime + ", MsgType="        + MsgType + ", Content=" + Content + "]";  }  private String Content;  public TextMsg(String toUserName, String fromUserName, long createTime,      String msgType, String content) {    super();    ToUserName = toUserName;    FromUserName = fromUserName;    CreateTime = createTime;    MsgType = msgType;    Content = content;  }  public TextMsg() {    super();  }  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 String getContent() {    return Content;  }  public void setContent(String content) {    Content = content;  }}

Article.java(圖文訊息內部Article bean)

package com.gist.bean;/** * @author 高遠</n> 郵箱:wgyscsf@163.com</n> 部落格 http://blog.csdn.net/wgyscsf</n> *     編寫時期 2016-4-4 下午2:47:08 */public class Article {  private String Title;  @Override  public String toString() {    return "item [Title=" + Title + ", Description=" + Description        + ", PicUrl=" + PicUrl + ", Url=" + 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 getPicUrl() {    return PicUrl;  }  public void setPicUrl(String picUrl) {    PicUrl = picUrl;  }  public String getUrl() {    return Url;  }  public void setUrl(String url) {    Url = url;  }  private String Description;  private String PicUrl;  private String Url;}

PicAndTextMsg.java(圖文訊息 bean)

package com.gist.bean;import java.util.List;/** * @author 高遠</n> 郵箱:wgyscsf@163.com</n> 部落格 http://blog.csdn.net/wgyscsf</n> *     編寫時期 2016-4-4 下午2:47:08 */public class PicAndTextMsg {  private String ToUserName;  private String FromUserName;  private long CreateTime;  private String MsgType;  private int ArticleCount;  private List<Article> Articles;  @Override  public String toString() {    return "PicAndTextMsg [ToUserName=" + ToUserName + ", FromUserName="        + FromUserName + ", CreateTime=" + CreateTime + ", MsgType="        + MsgType + ", ArticleCount=" + ArticleCount + ", Articles="        + Articles + "]";  }  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 getArticleCount() {    return ArticleCount;  }  public void setArticleCount(int articleCount) {    ArticleCount = articleCount;  }  public List<Article> getArticles() {    return Articles;  }  public void setArticles(List<Article> articles) {    Articles = articles;  }}

以上就是本文的全部內容,希望對大家學習開java微信API有所協助,也希望大家繼續關注新內容的更新,不要錯過哦!

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.