Java實(shí)現(xiàn)企業(yè)微信回調(diào)配置的詳細(xì)步驟與測試
在使用前閱讀官方文檔:回調(diào)配置文檔
一、配置回調(diào)服務(wù)
一、在企業(yè)微信管理后臺配置三個配置
分別是:URL, Token, EncodingAESKey。打開企業(yè)微信后臺-->管理工具-->通訊錄同步配置回調(diào)地址如下所示
1.1、URL為回調(diào)服務(wù)地址,由開發(fā)者搭建(直白點(diǎn)就是后臺回調(diào)域名地址,你給企業(yè)微信的URL,例如http://127.0.0.1:8085/qiyewx/getCallBack)服務(wù)器如果是云服務(wù)要配置域名
1.2、Token用于計(jì)算簽名,由英文或數(shù)字組成且長度不超過32位的自定義字符串。(可隨機(jī)獲取,但要復(fù)制到本地代碼,后面會用到)
1.3、EncodingAESKey用于消息內(nèi)容加密,由英文或數(shù)字組成且長度為43位的自定義字符串。(可隨機(jī)獲取,但要復(fù)制到本地代碼,后面會用到)
二、在代碼中配置Token和EncodingAESKey
# 企業(yè)微信配置 qiyewx: url: corpid: corpsecret: #回調(diào)配置 token: XXXXXX encodingAESKey: XXXXXX
三、官方加解密庫下載
1、點(diǎn)擊如下鏈接自行下載,下載后結(jié)構(gòu)如下圖所示:
有json版本和xml版本
json版本:
xml版本:
加解密庫下載與返回碼 - 接口文檔 - 企業(yè)微信開發(fā)者中心
2、將下載的示例代碼復(fù)制到你的項(xiàng)目代碼中
二、編碼實(shí)現(xiàn)
一、引入相關(guān)項(xiàng)目依賴
<!--企業(yè)微信相關(guān)--> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> </dependency> <!-- 企業(yè)微信json格式包--> <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>20200518</version> </dependency> <!-- dom4j解析xml --> <dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> <version>1.6.1</version> </dependency>
二、支持Http Get請求驗(yàn)證URL有效性與支持Http Post請求接收業(yè)務(wù)數(shù)據(jù)
切記:將將下載的示例代碼復(fù)制到你的項(xiàng)目代碼中,下面的代碼中有使用。
1、coontroller
/** * 企業(yè)微信回調(diào) * 3.1 支持Http Get請求驗(yàn)證URL有效性 * 3.2 支持Http Post請求接收業(yè)務(wù)數(shù)據(jù) * * @return */ @RequestMapping(value = "/getCallBack", method = {RequestMethod.GET, RequestMethod.POST}) public Object CompanyWeChatChangeNotice(HttpServletRequest request, @RequestBody(required = false) String body) { Map<String, String[]> parameterMap = request.getParameterMap(); String jsonString = JSONObject.toJSONString(parameterMap); log.info("企業(yè)微信回調(diào)參數(shù):{}, 解析參數(shù):{}", jsonString, body); if (body == null) { Object result = qyWxService.verificationUrl(request); return result; } Map<String, String> resultMap = qyWxService.getRequestParameter(request, body); System.err.println(resultMap); return "success"; }
2、驗(yàn)證URL有效性
/** * 驗(yàn)證回調(diào)URL * * @param request * @return */ public Object verificationUrl(HttpServletRequest request) { log.info("=========驗(yàn)證URL有效性開始========="); String sEchoStr; //需要返回的明文 try { WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(qyWxConfig.getToken(), qyWxConfig.getEncodingAESKey(), qyWxConfig.getCorpid()); String msgSignature = request.getParameter("msg_signature"); String timeStamp = request.getParameter("timestamp"); String nonce = request.getParameter("nonce"); String echostr = request.getParameter("echostr"); log.info("企業(yè)微信加密簽名: {},時間戳: {},隨機(jī)數(shù): {},加密的字符串: {}", msgSignature, timeStamp, nonce, echostr); sEchoStr = wxcpt.VerifyURL(msgSignature, timeStamp, nonce, echostr); log.info("給企業(yè)微信返回的明文,{}", sEchoStr); log.info("=========驗(yàn)證URL有效性結(jié)束========="); return sEchoStr; } catch (AesException e) { log.error("驗(yàn)證URL失敗,錯誤原因請查看異常:{}", e.getCode()); throw new AesException(e.getCode()); } }
3、回調(diào)參數(shù)解析
/** * 企業(yè)微信回調(diào)參數(shù)解析 * * @param request * @param body * @return */ public Map<String, String> getRequestParameter(HttpServletRequest request, String body) { log.info("=========參數(shù)解析開始========="); try { WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(qyWxConfig.getToken(), qyWxConfig.getEncodingAESKey(), qyWxConfig.getCorpid()); String msgSignature = request.getParameter("msg_signature"); String timeStamp = request.getParameter("timestamp"); String nonce = request.getParameter("nonce"); log.info("企業(yè)微信加密簽名: {},時間戳: {},隨機(jī)數(shù): {}", msgSignature, timeStamp, nonce); String sMsg = wxcpt.DecryptMsg(msgSignature, timeStamp, nonce, body); Map<String, String> resultMap = new HashMap<String, String>(16); resultMap = ConstantUtil.parseXmlToMap(sMsg, resultMap); log.info("decrypt密文轉(zhuǎn)為map結(jié)果為{}", resultMap); log.info("=========參數(shù)解析結(jié)束========="); return resultMap; } catch (AesException e) { log.error("密文參數(shù)解析失敗,錯誤原因請查看異常:{}", e.getMessage()); throw new AesException(e.getCode()); } }
4、XML轉(zhuǎn)map工具
package com.ruoyi.system.qiwechat.utils; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; import java.io.StringReader; import java.util.Iterator; import java.util.Map; /** * @author XiYuan * @date 2023/2/20 * @Description: XML轉(zhuǎn)換Map */ public class ConstantUtil { /** * 將xml轉(zhuǎn)換為Map。 支持xml標(biāo)簽多層嵌套,并以"."分隔多級標(biāo)簽(不包括根節(jié)點(diǎn))。 不支持XML標(biāo)簽重復(fù)時的情況 * * @param xml * @param map * @return */ public static Map<String, String> parseXmlToMap(String xml, Map<String, String> map) { try { SAXReader reader = new SAXReader(); Document doc = reader.read(new StringReader(xml)); Element root = doc.getRootElement(); String path = ""; if (map.containsKey(root.getName().trim())) { path = map.get(root.getName().trim()); map.remove(root.getName().trim()); } for (Iterator i = root.elementIterator(); i.hasNext();) { Element element = (Element) i.next(); if (element.isTextOnly()) { if (path.length() > 0) { map.put(path + element.getName().trim(), element.getTextTrim()); } else { map.put(element.getName().trim(), element.getTextTrim()); } } else { map.put(element.getName().trim(), path+ element.getName().trim() + "."); parseXmlToMap(element.asXML(), map); } } } catch (Exception e) { e.printStackTrace(); } return map; } }
5、配置文件config
package com.ruoyi.common.config; import lombok.Data; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; @Data @Configuration public class QyWxConfig { /** * 請求路徑 */ @Value("${qiyewx.url}") private String url; /** * 企業(yè)微信ID */ @Value("${qiyewx.corpid}") private String corpid; /** * 企業(yè)應(yīng)用的憑證密鑰 */ @Value("${qiyewx.corpsecret}") private String corpsecret; /** * 開發(fā)者設(shè)置的token */ @Value("${qiyewx.token}") private String token; /** * 開發(fā)者設(shè)置的EncodingAESKey */ @Value("${qiyewx.encodingAESKey}") private String encodingAESKey; }
三、測試示例
一、測試3.1 支持Http Get請求驗(yàn)證URL有效性
所要參數(shù)依次寫入,測試
二、測試3.2支持Http Post請求接收業(yè)務(wù)數(shù)據(jù)
1、演示關(guān)于接收客戶變更事件回調(diào)通知,企業(yè)微信開發(fā)者中心 回調(diào)
2、通俗點(diǎn)就是手機(jī)企業(yè)微信添加客戶將數(shù)據(jù)回調(diào)到本地,按照文檔說明講相關(guān)參數(shù)設(shè)置好。如圖所示:
3、對返回結(jié)果按照自己需求進(jìn)行處理
如下紅框所示:
備注:要根據(jù)事件的類型Event判斷回調(diào)的事件,在回調(diào)事件中根據(jù)ChangeType判斷事件性質(zhì)
4、查看日志
總結(jié)
到此這篇關(guān)于Java實(shí)現(xiàn)企業(yè)微信回調(diào)配置的詳細(xì)步驟與測試的文章就介紹到這了,更多相關(guān)Java企業(yè)微信回調(diào)配置內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中Stream的flatMap與map使用場景及區(qū)別詳解
這篇文章主要介紹了Java中Stream的flatMap與map使用場景及區(qū)別詳解,Stream 流式操作,一般用于操作集合即 List 一類的數(shù)據(jù)結(jié)構(gòu),簡單來說 Stream 的 map 使得其中的元素轉(zhuǎn)為另一種元素的映射(map)方法,需要的朋友可以參考下2024-01-01Spring 事件監(jiān)聽機(jī)制實(shí)現(xiàn)跨模塊調(diào)用的思路詳解
之前一個項(xiàng)目,有兩個模塊,A 模塊需要依賴 B 模塊,但現(xiàn)在 B 模塊有地方需要調(diào)用 A 模塊的方法,如果直接依賴,又會產(chǎn)生循環(huán)依賴問題,最終選擇使用 spring 的事件監(jiān)聽來解決該問題,下面給大家介紹Spring 事件監(jiān)聽機(jī)制實(shí)現(xiàn)跨模塊調(diào)用的思路,感興趣的朋友一起看看吧2024-05-05三分鐘帶你了解SpringBoot真正的啟動引導(dǎo)類
這篇文章主要介紹了三分鐘帶你了解SpringBoot真正的啟動引導(dǎo)類,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11Java 中的FileReader和FileWriter源碼分析_動力節(jié)點(diǎn)Java學(xué)院整理
本文給大家分享一段示例程序,通過示例代碼可以看出FileReader是基于InputStreamReader實(shí)現(xiàn)的,FileWriter是基于OutputStreamWriter實(shí)現(xiàn)的,具體程序代碼大家通過本文了解下吧2017-05-05mybatis中mapper.xml文件的常用屬性及標(biāo)簽講解
這篇文章主要介紹了mybatis中mapper.xml文件的常用屬性及標(biāo)簽講解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09SpringBoot集成ActiveMQ的實(shí)戰(zhàn)全過程
消息隊(duì)列中間件是分布式系統(tǒng)中重要的組件,主要解決應(yīng)用耦合、異步消息、流量削鋒等問題,實(shí)現(xiàn)高性能、高可用、可伸縮和最終一致性架構(gòu),是大型分布式系統(tǒng)不可缺少的中間件,這篇文章主要給大家介紹了關(guān)于SpringBoot集成ActiveMQ的相關(guān)資料,需要的朋友可以參考下2021-11-11