java微信企業(yè)號(hào)開發(fā)之發(fā)送消息(文本、圖片、語音)
上篇文章介紹了開啟回調(diào)模式,開始回調(diào)模式后我們就要實(shí)現(xiàn)聊天功能了。平時(shí)使用微信聊天可以發(fā)送文本消息、語音、圖片、視頻等,這里只實(shí)現(xiàn)了其中的一些功能和大家分享。
一、與微信企業(yè)號(hào)建立連接
1、企業(yè)應(yīng)用調(diào)用企業(yè)號(hào)提供的接口,管理或查詢企業(yè)號(hào)后臺(tái)所管理的資源、或給成員發(fā)送消息等,以下稱主動(dòng)調(diào)用模式。
2、企業(yè)號(hào)把用戶發(fā)送的消息或用戶觸發(fā)的事件推送給企業(yè)應(yīng)用,由企業(yè)應(yīng)用處理,以下稱回調(diào)模式。
3、用戶在微信中閱讀企業(yè)應(yīng)用下發(fā)的H5頁面,該頁面可以調(diào)用微信提供的原生接口,使用微信開放的終端能力,以下稱JSAPI模式。
這是微信企業(yè)號(hào)的開發(fā)文檔中寫的,但是我們一般使用前兩種方式。
其實(shí)主動(dòng)調(diào)用和回調(diào)都是相對的,這是站在微信服務(wù)器的角度,微信服務(wù)器通過企業(yè)號(hào)給微信客戶端發(fā)送消息是主動(dòng)調(diào)用,微信客戶端主動(dòng)發(fā)送消息去調(diào)用微信服務(wù)器相對服務(wù)器來說就是被動(dòng)調(diào)用(回調(diào))。
二、主被動(dòng)調(diào)用微信服務(wù)器處理的數(shù)據(jù)格式
1.主調(diào):服務(wù)器向微信客戶端發(fā)送json格式的數(shù)據(jù),數(shù)據(jù)不需要加密
2.回調(diào):微信客戶端發(fā)送的消息需要AES加密,服務(wù)器接受的消息是xml格式
這兩條用一張圖表示如下:
三、聊天原理圖
首先微信客戶端發(fā)送消息到服務(wù)器處理,數(shù)據(jù)以xml格式傳輸?shù)降谌椒?wù)器后,第三方服務(wù)器再將數(shù)據(jù)轉(zhuǎn)為json格式,傳送給微信服務(wù)器,發(fā)送給客戶端。
四、代碼實(shí)現(xiàn)
有了上面的原理基礎(chǔ),下面是代碼部分
1.servlet
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); String msg_signature = request.getParameter("msg_signature"); String timestamp = request.getParameter("timestamp"); String nonce = request.getParameter("nonce"); InputStream inputStream = request.getInputStream(); String postData = IOUtils.toString(inputStream, "UTF-8"); System.out.println(postData); String msg = ""; WXBizMsgCrypt wxcpt = null; try { wxcpt = new WXBizMsgCrypt(sToken , sEncodingAESKey , sCorpID ); msg = wxcpt.DecryptMsg(msg_signature, timestamp, nonce, postData); } catch (AesException e) { e.printStackTrace(); } System.out.println("msg=" + msg); //獲取接口訪問憑證 String accessToken = CommonUtil.getToken("wxe510946434680dab", "eWTaho766INvp4e1MCsz1mHYuT2DAleb62REQ3vsFizhY4vtmwZpKweuxUVh33G0").getAccessToken(); try { @SuppressWarnings("unused") boolean flag = ChatService1.sendMessage(accessToken,msg); } catch (Exception e) { e.printStackTrace(); } }
2.service
public class ChatService1 { public static boolean sendMessage(String accessToken,String msg) throws Exception{ boolean flag = false; Map<String, String> requestMap = MessageUtil.parseXml(msg); // 發(fā)送者 String fromUserName = requestMap.get("FromUserName"); // 消息類型 String msgType = requestMap.get("MsgType"); if(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)){//如果是文本客服消息 String Content = requestMap.get("Content");//文本消息的消息內(nèi)容 //組裝文本客服消息,參數(shù)1:用戶id;參數(shù)2:發(fā)送的內(nèi)容 jsonMsg = AdvancedUtil.makeTextCustomMessage("lishehe|zhisheng|zhangwenyuan|lixinjiang", Content); }else if(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)){//發(fā)送的是圖片 String mediaId = requestMap.get("MediaId"); jsonMsg = AdvancedUtil.makeImageCustomMessage("lishehe|zhisheng|zhangwenyuan|lixinjiang", mediaId); }else if(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)){ String mediaId = requestMap.get("MediaId"); jsonMsg= AdvancedUtil.makeVoiceCustomMessage("lishehe|zhisheng|zhangwenyuan|lixinjiang", mediaId); } flag = AdvancedUtil.sendCustomMessage(accessToken, jsonMsg); return flag; } }
3.工具類
public class AdvancedUtil { private static Logger log = LoggerFactory.getLogger(AdvancedUtil.class); /** * 組裝發(fā)送文本消息 * @return */ public static String makeTextCustomMessage(String openId, String content) { content = content.replace("\"", "\\\""); String jsonMsg = "{\"touser\":\"%s\",\"msgtype\":\"text\",\"agentid\":\"%s\",\"text\":{\"content\":\"%s\"}}"; return String.format(jsonMsg, openId, 14,content); } /** * 組裝發(fā)送圖片消息 * * @return */ public static String makeImageCustomMessage(String openId, String mediaId) { String jsonMsg = "{\"touser\":\"%s\",\"msgtype\":\"image\",\"agentid\":\"%s\",\"image\":{\"media_id\":\"%s\"}}"; return String.format(jsonMsg, openId,14, mediaId); } /** * 組裝發(fā)送語音消息 * * @return */ public static String makeVoiceCustomMessage(String openId, String mediaId) { String jsonMsg = "{\"touser\":\"%s\",\"msgtype\":\"voice\",\"agentid\":\"%s\",\"voice\":{\"media_id\":\"%s\"}}"; return String.format(jsonMsg, openId,14, mediaId); }
四、總結(jié)
這樣就實(shí)現(xiàn)了消息的接收和推送,第三方服務(wù)器將接受的xml數(shù)據(jù)先解密解析,從中獲取消息類型,然后將要發(fā)送的消息封裝后轉(zhuǎn)為json格式,并傳送給微信服務(wù)器在發(fā)送到客戶端。
本文已被整理到了《Android微信開發(fā)教程匯總》,《java微信開發(fā)教程匯總》歡迎大家學(xué)習(xí)閱讀。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot整合SQLite數(shù)據(jù)庫全過程
sqlite是一個(gè)很輕量級(jí)的數(shù)據(jù)庫,可以滿足日常sql的需求,下面這篇文章主要給大家介紹了關(guān)于SpringBoot整合SQLite數(shù)據(jù)庫的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-03-03Spring?Cloud?Gateway?整合?knife4j?聚合接口文檔功能
這篇文章主要介紹了Spring?Cloud?Gateway?整合?knife4j?聚合接口文檔的相關(guān)知識(shí),我們可以基于?Spring?Cloud?Gateway?網(wǎng)關(guān)?+?nacos?+?knife4j?對所有微服務(wù)項(xiàng)目的接口文檔進(jìn)行聚合,從而實(shí)現(xiàn)我們想要的文檔管理功能,需要的朋友可以參考下2022-02-02以Spring Boot的方式顯示圖片或下載文件到瀏覽器的示例代碼
這篇文章主要介紹了以Spring Boot的方式顯示圖片或下載文件到瀏覽器的示例代碼,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01詳解如何獲取PreparedStatement參數(shù)示例詳解
這篇文章主要為大家介紹了詳解如何獲取PreparedStatement參數(shù)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09使用SpringMVC的@Validated注解驗(yàn)證的實(shí)現(xiàn)
這篇文章主要介紹了使用SpringMVC的@Validated注解驗(yàn)證的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08使用RestTemplate調(diào)用RESTful?API的代碼示例
在開發(fā)?Web?應(yīng)用程序時(shí),調(diào)用?RESTful?API?是一個(gè)常見的任務(wù),本文將介紹如何使用?RestTemplate?調(diào)用?RESTful?API,并提供示例代碼,感興趣的同學(xué)可以跟著小編一起來看看2023-06-06java Spring松耦合高效應(yīng)用簡單實(shí)例分析
在Java項(xiàng)目,龐大的對象依賴關(guān)系將一直緊密耦合引起對象難以管理或修改。在這種情況下,可以使用Spring框架作為一個(gè)核心模塊輕松高效地管理所有的對象依賴。本文章向大家介紹Spring松耦合的實(shí)例,需要的朋友可以參考一下。2016-12-12解決mysql字符串類型的數(shù)字排序出錯(cuò):cast(year as signed)
這篇文章主要介紹了解決mysql字符串類型的數(shù)字排序出錯(cuò)問題 :cast(year as signed),如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08mybatis-plus攔截器、字段填充器、類型處理器、表名替換、SqlInjector(聯(lián)合主鍵處理)
本文主要介紹了mybatis-plus攔截器、字段填充器、類型處理器、表名替換、SqlInjector(聯(lián)合主鍵處理),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11