微信企業號開發入門(回調模式)java
- 2019 年 10 月 25 日
- 筆記
最近在開發微信企業號,剛接觸時雲里霧裡的,在摸索過程中終於清晰了一點。
剛開始我以為訂閱號、服務號、企業號的介面差不多,就一直用訂閱號的教程來入門,後來才發現差的挺多的。
首先,微信企業號不像訂閱號和服務號,就一個主頁面。企業號的開發其實是對應用的開發。
先附上微信企業號開發官方文檔:https://qydev.weixin.qq.com/wiki/index.php
一、企業微信管理頁面配置
網址:https://work.weixin.qq.com/wework_admin/frame
1、在註冊完企業號後,先創建一個應用
2、在應用管理–自建的應用中配置可信域名
需要注意的是,微信公眾號的開發測試需要訪問到外網的伺服器,且埠只能為80。
這裡推薦使用 natapp進行配置,具體使用看 :https://blog.csdn.net/qq_33922980/article/details/90244160 (自備域名的可以忽略)
啟動後,填寫可信域名
3、配置接收消息的api(這裡我已經配好了)
Token和EncodingAESKey可以使用隨機獲取,url填寫剛剛配置的可信域名,及準備調用的介面。
此時點擊保存,會提示伺服器異常,請稍後再試。
這是由於點擊保存時,微信會向我們添加的url發送一個get請求,需要我們返回值。
附上官方說明:
附上url檢驗程式碼:
1 @RequestMapping(method = RequestMethod.GET) 2 @ResponseBody 3 public String checkToken(@RequestParam(name = "msg_signature") String signature, String timestamp, String nonce, String echostr) throws AesException { 4 //token和encoding_aeskey就是上訴隨機獲取的值,corp_id是企業id,在企業微信管理頁面點擊: 我的企業,拉到最下方可以看到 5 WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(TOTKN, ENCODING_AESKEY, CORP_ID); 6 String sEchoStr = wxcpt.VerifyURL(signature, timestamp,nonce, echostr); 7 System.out.println("-----簽名校驗通過-----"); 8 return sEchoStr; 9 }
其中,WXBizMsgCrypt是官方提供的加解密庫,下載地址:https://qydev.weixin.qq.com/download/java.zip
為方便使用,我直接打成了jar包,有需要的自取。鏈接: https://pan.baidu.com/s/1Xtzd69T8jVL3w8Kg1jnreQ 提取碼: jeeu
再點擊保存,就通過了。
此時後台管理的配置完成。
二、實際功能開發
1、回調模式
該url的調用有兩個,一個是上述的url檢驗時調用,第二個是回調模式調用。不同點是回調模式是發post請求,且攜帶的參數不一樣。
這裡說明一下,第二個回調模式是說,成員發送消息或觸發事件時都會調用該介面,我們根據邏輯處理後再進行回饋。
接收的資訊使用XML數據格式、UTF8編碼,並以AES方式加密。
這裡我們封裝一個類,來接收回調數據。
1 import javax.xml.bind.annotation.XmlAccessType; 2 import javax.xml.bind.annotation.XmlAccessorType; 3 import javax.xml.bind.annotation.XmlElement; 4 import javax.xml.bind.annotation.XmlRootElement; 5 6 @XmlRootElement(name="xml") 7 @XmlAccessorType(XmlAccessType.FIELD) 8 public class InMsgEntity { 9 /** 10 * 接收的應用id,可在應用的設置頁面獲取 11 */ 12 @XmlElement(name = "AgentID") 13 private String agentID; 14 /** 15 * 經過加密的密文 16 */ 17 @XmlElement(name = "Encrypt") 18 private String encrypt; 19 /** 20 * 發送方帳號 21 */ 22 @XmlElement(name="ToUserName") 23 private String toUserName; 24 25 public String getAgentID() { 26 return agentID; 27 } 28 29 public void setAgentID(String agentID) { 30 this.agentID = agentID; 31 } 32 33 public String getEncrypt() { 34 return encrypt; 35 } 36 37 public void setEncrypt(String encrypt) { 38 this.encrypt = encrypt; 39 } 40 41 public String getToUserName() { 42 return toUserName; 43 } 44 45 public void setToUserName(String toUserName) { 46 this.toUserName = toUserName; 47 } 48 }
再寫兩個工具類,來轉換格式。
(1)因為要調用官方的加解密庫,所以要封裝成他需要格式的字元串。
1 import com.newland.bean.InMsgEntity; 2 public class FormatUtils { 3 /** 4 * 接收請求格式封裝 5 * @param msg 6 * @return 7 */ 8 public static String getReqData(InMsgEntity msg){ 9 return "<xml><ToUserName><![CDATA["+msg.getToUserName()+"]]></ToUserName><Encrypt><![CDATA[" +msg.getEncrypt()+ 10 "]]></Encrypt><AgentID><![CDATA["+msg.getAgentID()+"]]></AgentID></xml>"; 11 } 12 13 /** 14 * 發送文字消息格式封裝 15 * @param content 16 * @return 17 */ 18 public static String getTextRespData(String content){ 19 return "<xml><MsgType><![CDATA[text]]></MsgType><Content><![CDATA["+content+"]]></Content></xml>"; 20 } 21 }
(2)為方便處理xml格式的數據,寫一個標籤處理的工具類
1 import org.w3c.dom.Document; 2 import org.w3c.dom.Element; 3 import org.xml.sax.InputSource; 4 import org.xml.sax.SAXException; 5 import javax.xml.parsers.DocumentBuilder; 6 import javax.xml.parsers.DocumentBuilderFactory; 7 import javax.xml.parsers.ParserConfigurationException; 8 import java.io.IOException; 9 import java.io.StringReader; 10 public class ElementUtils { 11 private Element root = null; 12 /** 13 * 根據xml格式的字元串建document 14 * @param sMsg 15 * @throws ParserConfigurationException 16 * @throws IOException 17 * @throws SAXException 18 */ 19 public ElementUtils(String sMsg) throws ParserConfigurationException, IOException, SAXException { 20 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 21 DocumentBuilder db = dbf.newDocumentBuilder(); 22 StringReader sr = new StringReader(sMsg); 23 InputSource is = new InputSource(sr); 24 Document document = db.parse(is); 25 root = document.getDocumentElement(); 26 } 27 28 /** 29 * 根據tagName獲取內容 30 * @param tagName 31 * @return 32 */ 33 public String get(String tagName){ 34 return root.getElementsByTagName(tagName).item(0).getTextContent(); 35 } 36 }
最後回調模式程式碼:(這裡沒寫太多,可以根據自身需要寫邏輯)
1 @RequestMapping(method = RequestMethod.POST,produces = {"application/xml;charset=UTF-8"}) 2 @ResponseBody 3 public Object handlerMessage(@RequestBody InMsgEntity msg, @RequestParam(name = "msg_signature") String signature, 4 String timestamp, String nonce) throws Exception { 5 WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(TOTKN, ENCODING_AESKEY, CORP_ID); 6 String sReqData = FormatUtils.getReqData(msg); 7 String sMsg = wxcpt.DecryptMsg(signature, timestamp, nonce, sReqData); 8 ElementUtils element = new ElementUtils(sMsg); 9 String msgType = element.get("MsgType"); 10 String content = ""; 11 switch (msgType){ 12 /** 13 * 事件類型處理 14 */ 15 case "event":content = "觸發事件";break; 16 /** 17 * 文字消息處理:這裡是將用戶發送的消息原樣返回 18 */ 19 case "text": content = element.get("Content");break; 20 default:break; 21 } 22 String sRespData = FormatUtils.getTextRespData(content); 23 String sEncryptMsg = wxcpt.EncryptMsg(sRespData, timestamp, nonce); 24 return sEncryptMsg; 25 }
很奇怪的是,在企業微信官方文檔里,並沒有給出Encrypt解密之後的格式,要在微信公眾號官方文檔里看:https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_standard_messages.html
或者你也可以通過在上訴程式碼獲得sMsg之後,打斷點或輸出sMsg的值來查看格式。
這裡附上幾種常用類型的數據格式。其中ToUserName、FromUserName、CreateTime、MsgType是公共標籤。
(1)文字消息類型格式:
(2)圖片消息格式
(3)關注取關事件數據格式:
到這裡,可以試著嚮應用發送消息了,或者嘗試重新關注,看看是否有回復消息。
因為我目前這個企業號功能不多,所以只寫了文字格式的回復,有需要的話可以自行去官方文檔那對應消息格式進行改動~