微信公眾號02 接收文字訊息、回覆文字訊息、接入百度翻譯功能
1 說明
本篇博文承接上一篇博文:https://www.cnblogs.com/NeverCtrl-C/p/10241763.html
2 接收文字訊息
微信公眾號官方文件:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140453
說明:接收文字訊息屬於接收普通訊息的範圍,當公眾號粉絲向公眾號傳送訊息時,微信伺服器會向開發者伺服器傳送一個POST請求,這個POST請求攜帶XML格式的資料包到開發者填寫的URL上
2.1 文字訊息XML格式
<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>
2.2 文字訊息引數說明
引數 | 描述 |
---|---|
ToUserName | 開發者微訊號 |
FromUserName | 傳送方帳號(一個OpenID) |
CreateTime | 訊息建立時間 (整型) |
MsgType | text |
Content | 文字訊息內容 |
MsgId | 訊息id,64位整型 |
step01 建立一個com.xunyji.xunyjitest.comm.TransformUtils類用來存放一下資料型別轉換相關的工具方法2.3 Java程式碼實現
step02 引入XML和物件相互轉換相關的jar包
<!--xml2物件 start--> <!-- https://mvnrepository.com/artifact/dom4j/dom4j --> <dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> <version>1.6.1</version> </dependency> <!--xml2物件 end--> <!--物件2XML start--> <!-- https://mvnrepository.com/artifact/com.thoughtworks.xstream/xstream --> <dependency> <groupId>com.thoughtworks.xstream</groupId> <artifactId>xstream</artifactId> <version>1.3.1</version> </dependency> <!--物件2XML end-->
step03 建立com.xunyji.xunyjitest.comm.TransformUtils#xml2Map方法用於將XML轉化成Map型別
/** * xml轉換成map【微信平臺請求開發者平臺時的資料格式都是XML格式的】 * @param request * @return * @throws IOException * @throws DocumentException */ public static Map<String, String> xml2Map(HttpServletRequest request) throws IOException, DocumentException { // 01 定義Map物件用來存放資料 Map<String, String> map = new HashMap<>(); // 02 建立SAXReader用於讀取xml檔案 SAXReader reader = new SAXReader(); // 03 讀取Request中的資訊 InputStream ins = request.getInputStream(); Document doc = reader.read(ins); // 04 獲取xml的根元素 Element root = doc.getRootElement(); // 05 獲取根元素中的所有子元素 List<Element> list = root.elements(); // 06 遍歷所有子元素並將資料存放到定義好的集合中 for (Element e : list) { map.put(e.getName(), e.getText()); } // 07 關閉輸入流 ins.close(); // 08 返回存放xml內容的Map物件 return map; }
step04 建立一個com.xunyji.xunyjitest.web.weixin.WeixinController#receiveMessage方法用於接收微信平臺傳送的POST請求
step0401 該方法接收POST請求
step0402 通過 HttpServletRequest 物件獲取微信平臺傳過來的XML資料包
step0403 將XML資料轉化成Map資料並列印輸出
@PostMapping public void receiveMessage(HttpServletRequest request, HttpServletResponse response) throws IOException, DocumentException { // 01 請求、響應編碼格式設定 request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); // 02 獲取輸出物件 PrintWriter out = response.getWriter(); // 03 獲取微信平臺傳過來的請求引數【PS:預設是XML格式的,這裡轉化成了Mapl型別】 Map<String, String> receiveMap = TransformUtils.xml2Map(request); log.info("接收微信訊息時獲取到的資訊為:" + receiveMap); // 04 從Map物件中獲取單個數據 String fromUserName = receiveMap.get("FromUserName"); String toUserName = receiveMap.get("ToUserName"); String msgType = receiveMap.get("MsgType"); String content = receiveMap.get("Content"); }
step0404 啟動專案並通過粉絲賬戶向公眾號傳送文字訊息,效果如圖所示
3 回覆文字訊息
回覆文字訊息屬於被動回覆訊息的範圍,微信官網提供的被動回覆訊息文件:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140543
技巧01:粉絲向公眾號傳送訊息時微信伺服器會向開發者伺服器傳送一個POST請求,開發者可以從這個POST請求中獲取到一些資訊,也可以像傳送者返回一些資訊
3.1 回覆文字訊息XML格式
<xml> <ToUserName>< ![CDATA[toUser] ]></ToUserName> <FromUserName>< ![CDATA[fromUser] ]></FromUserName> <CreateTime>12345678</CreateTime> <MsgType>< ![CDATA[text] ]></MsgType> <Content>< ![CDATA[你好] ]></Content> </xml>
3.2 回覆文字訊息引數說明
引數 | 是否必須 | 說明 |
---|---|---|
ToUserName | 是 | 接收方帳號(收到的OpenID) |
FromUserName | 是 | 開發者微訊號 |
CreateTime | 是 | 訊息建立時間 (整型) |
MsgType | 是 | image |
MediaId | 是 | 通過素材管理中的介面上傳多媒體檔案,得到的id。 |
3.3 Java程式碼實現
step01 建立一個com.xunyji.xunyjitest.model.weixin.send.SendBaseMessage類作為所有被動回覆訊息的基類
step02 建立一個com.xunyji.xunyjitest.model.weixin.send.ReplyTextMessage類作為回覆文字訊息的實體類
@Data @NoArgsConstructor @AllArgsConstructor public class ReplyTextMessage extends ReplyBaseMessage { /** 回覆的訊息內容(換行:在content中能夠換行,微信客戶端就支援換行顯示) */ private String Content; }
step03 建立一個com.xunyji.xunyjitest.comm.enums.weixin.MessageTypeEnum列舉類來存放各種訊息型別
@Getter public enum MessageTypeEnum { // 接收普通訊息型別【0開頭表示接收的訊息型別】 start /** 被動回覆文字訊息 */ RECEIVE_MESSAGE_TEXT(001, "text"), RECEIVE_MESSAGE_IMAGE(002, "image"), RECEIVE_MESSAGE_VOICE(003, "voice"), RECEIVE_MESSAGE_LOCATION(004, "location"), RECEIVE_MESSAGE_LINK(005, "link"), RECEIVE_MESSAGE_SHORTVIDEO(06, "shortvideo"), RECEIVE_MESSAGE_VIDEO(007, "video"), // 接收普通訊息型別【0開頭表示接收的訊息型別】 end ; /** 訊息型別編號 */ private Integer code; /** 訊息型別(和微信文件中保持一致) */ private String type; MessageTypeEnum(Integer code, String type) { this.code = code; this.type = type; } }
step04 建立一個com.xunyji.xunyjitest.comm.util.weixin.MessageUtils類作為各種訊息封裝類
step0401 建立com.xunyji.xunyjitest.comm.util.weixin.MessageUtils#replyTextMessageToXml方法實現將ReplyTextMessage 轉化成 XML
/** * ReplyTextMessage 轉化成 XML * @param replyTextMessage * @return */ private String replyTextMessageToXml(ReplyTextMessage replyTextMessage) { XStream xStream = new XStream(); xStream.alias("xml", replyTextMessage.getClass()); return xStream.toXML(replyTextMessage); }
step0402 建立com.xunyji.xunyjitest.comm.util.weixin.MessageUtils#initReplyTextMessage方法實現封裝回覆文本訊息時所需的XML格式字串
/** * 封裝XML格式的"傳送文字訊息" * @param fromUserName 粉絲appId * @param toUserName 公眾號appId * @param content XML格式的字串 * @return */ public String initReplyTextMessage(String fromUserName, String toUserName, String content) { ReplyTextMessage text = new ReplyTextMessage(); text.setToUserName(fromUserName); text.setFromUserName(toUserName); text.setMsgType(MessageTypeEnum.RECEIVE_MESSAGE_TEXT.getType()); long time = System.currentTimeMillis(); text.setCreateTime(String.valueOf(time)); text.setContent("逆向公眾號傳送了:" + content); return replyTextMessageToXml(text); }
step05 重構com.xunyji.xunyjitest.web.weixin.WeixinController#receiveMessage方法實現接收文字訊息時回覆文字訊息,其他訊息不做任何處理
step0501 從封裝了請求資料的map集合中獲取公眾號appid(toUserName)、粉絲appid(fromUserName)、接收訊息型別(msgType)
step0502 判斷接收訊息型別並做相應處理,此處以接收到的訊息型別為文字訊息為例
如果是文字訊息就獲取文字內容,然後封裝響應資料即可
step0503 必須對響應資料進行非空處理,因為如果響應資料為null就會出現一個錯誤,很影響使用者體驗
@PostMapping public void receiveMessage(HttpServletRequest request, HttpServletResponse response) throws IOException, DocumentException { // 01 請求、響應編碼格式設定 request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); // 02 獲取輸出物件 PrintWriter out = response.getWriter(); // 03 獲取微信平臺傳過來的請求引數【PS:預設是XML格式的,這裡轉化成了Mapl型別】 Map<String, String> receiveMap = TransformUtils.xml2Map(request); log.info("接收微信訊息時獲取到的資訊為:" + receiveMap); // 04 從Map物件中獲取單個數據 String fromUserName = receiveMap.get("FromUserName"); String toUserName = receiveMap.get("ToUserName"); String msgType = receiveMap.get("MsgType"); // 05 用於存放String型別的XML格式響應資料 String message = null; // 06 如果接收的訊息型別是text型別的處理邏輯 if (MessageTypeEnum.RECEIVE_MESSAGE_TEXT.getType().equals(msgType)) { String content = receiveMap.get("Content"); message = new MessageUtils().initReplyTextMessage(fromUserName, toUserName, content); } // 07 響應物件非空處理,如果返回null會報異常(影響使用者體驗) if (message == null) { message = ""; } // 08 列印XML格式的響應訊息 log.info("被動回覆訊息的XML格式為:" + message); // 09 響應XML格式資料給微信伺服器 out.print(message); }View Code
step06 啟動專案並向公眾號傳送文字訊息,效果如圖所示
3.4 程式碼重構
應該根據不同的訊息型別呼叫不同的服務層方法來實現業務邏輯,不應該將所有業務邏輯都放到controller層中
step01 引入fastjson依賴,因為需要將Map轉化成Bean
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.54</version> </dependency>
step02 建立com.xunyji.xunyjitest.service.ReceiveMessageService介面用於定義處理各種接收到的訊息
step03 建立com.xunyji.xunyjitest.service.ReceiveMessageServiceImpl實現了實現處理各種接收到的訊息
step04 建立com.xunyji.xunyjitest.comm.TransformUtils#parseMap2Object方法用於將Map轉化成Bean
/** * Map型別轉化成指定型別 * @param paramMap 待轉化的Map物件 * @param clazz 目標型別的類型別 * @param <T> 目標型別 * @return */ public static <T> T parseMap2Object(Map<String, String> paramMap, Class<T> clazz) { return JSONObject.parseObject(JSONObject.toJSONString(paramMap), clazz); }
step05 建立com.xunyji.xunyjitest.service.ReceiveMessageServiceImpl#textMessageHandler方法用於處理文字型別訊息
@Override public String textMessageHandler(Map<String, String> receiveParam) { // 01 用於存放封裝好的回覆文字訊息的XML資料 String message = null; // 02 將Map型別引數轉化成ReceiveTextMessage型別 ReceiveTextMessage receiveTextMessage = TransformUtils.parseMap2Object(receiveParam, ReceiveTextMessage.class); log.info("接收到的text訊息請求引數為:" + receiveTextMessage); // 03 獲取文字內容和雙方資訊 // 0301 粉絲appId String fromUserName = receiveTextMessage.getFromUserName(); // 0302 公眾號appId String toUserName = receiveTextMessage.getToUserName(); // 0303 接收到的文字內容 String content = receiveTextMessage.getContent(); content = content.trim(); // 04 根據文字內容響應不同的資料 TODO: 應該將接收到的訊息資訊儲存到資料庫或者快取中 if ("1".equals(content)) { message = messageUtils.initReplyTextMessage(fromUserName, toUserName, messageUtils.firstMenu()); } else if ("2".equals(content)) { message = messageUtils.initReplyTextMessage(fromUserName, toUserName, messageUtils.secondMenu()); } else if ("?".equals(content) || "?".equals(content)) { message = messageUtils.initReplyTextMessage(fromUserName, toUserName, messageUtils.menuText()); } else { message = messageUtils.initReplyTextMessage(fromUserName, toUserName, content); } return message; }View Code
step06 在com.xunyji.xunyjitest.web.weixin.WeixinController#receiveMessage方法中,如果是文字訊息型別就呼叫com.xunyji.xunyjitest.service.ReceiveMessageService#textMessageHandler實現業務處理
step07 啟動應用並以此傳送 1、2、?、?,效果圖如下:
4 接入百度翻譯功能
待定更新時間:2019年1月10日23:23:02
掃碼獲取原始碼