一直想嘗試一下微信公衆號開發,上上週開始弄的,碰到不少坑,如今把經驗分析一下html
微信開發有公衆平臺和開放平臺兩種,公衆平臺是給關注用戶推送信息用的,提供一些接口給開發者,開放平臺是給成熟的app或網站提供接入、支付、分享的功能java
在公衆平臺上註冊的帳號有三種:訂閱號、服務號、企業號,通常我的只能申請訂閱號,並且不能認證,遺憾的是公衆平臺的一些高級接口和開發者自定義菜單功能只開放給認證的用戶git
我申請的是未認證的訂閱號,很快就經過了,幾乎沒有什麼門檻,不過開啓開發者模式之後,就失去了自定義菜單的功能github
微信開放平臺地址:https://mp.weixin.qq.comjson
微信開放平臺開發文檔:https://mp.weixin.qq.com/wiki服務器
要開啓開發者模式,須要對服務器url進行接入認證微信
在接入認證的時候,微信會對URL發送get請求(以後接收用戶消息時,微信會改成對URL發送post請求)微信開發
在基本配置頁面,URL是服務器的地址,Token是約定好的一串字符串,EncodingAESKey是用於驗證的字符串app
驗證方法裏面須要對三個參數作必定規則的運算,獲得結果和echostr同樣,而後返回,就能經過微信接入認證微信公衆平臺
示例代碼:
/** * 接入驗證 */ @ResponseBody @RequestMapping(method = {RequestMethod.GET }, produces = "application/json;charset=UTF-8") public String verifyAccess(VerifyAccessReq req) { try { if(!StringUtils.isEmpty(req.getEchostr())) { String token = Global.getConfig("wx.token"); String[] ArrTmp = {token, req.getTimestamp(), req.getNonce()}; //進行字典序排序 Arrays.sort(ArrTmp); StringBuffer sb = new StringBuffer(); for (int i = 0; i < ArrTmp.length; i++) { sb.append(ArrTmp[i]); } //進行sha1加密 String pwd = Encodes.Encrypt(sb.toString()); //若是相同就返回 if(!StringUtils.isEmpty(pwd) && pwd.equals(req.getSignature())) { log.info("認證經過"); return req.getEchostr(); } } } catch (Exception e) { log.debug("認證失敗"); e.printStackTrace(); } log.info("認證失敗"); return ""; }
接入指南:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319
用戶消息是經過post在xml流裏傳過來的,先要解析成map對象:
/** * 解析微信發來的xml請求 * @param request * @return * @throws Exception */ @SuppressWarnings("unchecked") public static Map<String, String> parseXml(HttpServletRequest request) throws Exception { //將解析結果存儲在HashMap中 Map<String, String> map = new HashMap<String, String>(); //從request中取得輸入流 InputStream inputStream = request.getInputStream(); //讀取輸入流 SAXReader reader = new SAXReader(); Document document = reader.read(inputStream); //獲得xml根元素 Element root = document.getRootElement(); //獲得根元素的全部子節點 List<Element> elementList = root.elements(); //遍歷全部子節點 for (Element e : elementList) { map.put(e.getName(), e.getText()); } //釋放資源 inputStream.close(); inputStream = null; return map; }
消息類型有文本消息、圖片消息、語音消息、視頻消息、地理位置消息、連接消息
目前我只用到文本消息:
//從流中獲取xml數據轉入map Map<String, String> reqMap = MessageUtil.parseXml(request); //獲得接收消息實體 BaseMsgReq msgReq = new BaseMsgReq(); msgReq.setToUserName(reqMap.get("ToUserName")); msgReq.setFromUserName(reqMap.get("FromUserName")); msgReq.setCreateTime(reqMap.get("CreateTime")); msgReq.setMsgType(reqMap.get("MsgType")); msgReq.setMsgId(reqMap.get("MsgId")); msgReq.setContent(reqMap.get("Content")); msgReq.setEvent(reqMap.get("Event"));
收到用戶消息,進過處理之後,公衆號須要返回信息給用戶,微信的回覆消息是xml結構的,有約定的格式要求,好比文本消息:
<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>12345678</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[你好]]></Content> </xml>
轉換xml的示例代碼:
/** * 文本消息對象轉換成xml * @param textMsgRes * @return */ public static String textMessageToXml(TextMsgRes textMsgRes) { xstream.alias("xml", textMsgRes.getClass()); return xstream.toXML(textMsgRes); } /** * 接收消息對象轉換成xml * @param msgReq * @return */ public static String msgReqToXml(BaseMsgReq msgReq, String content) { TextMsgRes textMsgRes = new TextMsgRes(); textMsgRes.setToUserName(msgReq.getFromUserName()); textMsgRes.setFromUserName(msgReq.getToUserName()); textMsgRes.setCreateTime(new Date().getTime()); textMsgRes.setMsgType("text"); textMsgRes.setContent(content); return textMessageToXml(textMsgRes); }
參考的教程:http://blog.csdn.net/u011466609/article/details/50886858
這兩週作的,歡迎來玩