微信開發(5):公眾號消息與事件推送處理(轉)


1.0 開發背景
外包公司,所以各種各樣的項目都有接觸,有個需求,客戶要做不同的二維碼,通過二維碼關注以后,給用戶發送不同的消息,順便統計用戶來源,
本文用到了 微信帶參數二維碼接口和消息管理里的相關接口
注意 :在微信公眾號后台,設置了服務器配置 URL 並啟用后,會導致 微信后台設置的回復規則,以及底部菜單都全部失效!直接清空了!因為這時候 微信已經把公眾號消息和事件 推送給開發者配置的url中,讓開發者進行處理了。
本文先講述微信官方后台設置帶參二維碼,后續更新使用第三方平台開發實現這個功能,從而保證了用戶微信公眾號官方設置底部菜單以及自定義回復沒有失效!

2.0 開發准備
2.1老樣子 官方文檔 來一波 帶參二維碼 接收事件
2.2 需要在微信后台 配置服務器配置 ,微信會在你修改這個配置的時候 給你填寫的URL發送數據,需要提前把項目上傳服務器

這個東西 配置好之后 可以點擊開啟了 ,開啟后啊,這個微信會把所有用戶發送的信息,給轉發給填寫的url 上。開發者必須在五秒內回復微信服務器。否則 微信會進行三次重試,重試均失敗后,會給用戶提示 該公眾號暫時無法提供服務。 而且在公眾平台還有告警通知。

下面看代碼

  1 package com.ysh.wxtest.controller;
  2 
  3 import org.apache.log4j.Logger;
  4 import org.dom4j.Document;
  5 import org.dom4j.Element;
  6 import org.dom4j.io.SAXReader;
  7 import org.springframework.beans.factory.annotation.Autowired;
  8 import org.springframework.stereotype.Controller;
  9 import org.springframework.web.bind.annotation.RequestMapping;
 10 import weixin.popular.bean.xmlmessage.XMLMessage;
 11 import weixin.popular.bean.xmlmessage.XMLTextMessage;
 12 import weixin.popular.support.ExpireKey;
 13 import weixin.popular.support.expirekey.DefaultExpireKey;
 14 import weixin.popular.util.SignatureUtil;
 15 
 16 import javax.servlet.ServletInputStream;
 17 import javax.servlet.ServletOutputStream;
 18 import javax.servlet.http.HttpServletRequest;
 19 import javax.servlet.http.HttpServletResponse;
 20 import java.io.*;
 21 import java.util.HashMap;
 22 import java.util.List;
 23 import java.util.Map;
 24 
 25 /**
 26  * 消息接收控制層
 27  * @author YaoShiHang
 28  * @Date 15:15 2017-10-16
 29  */
 30 @Controller
 31 public class WxqrcodeController {
 32 
 33     private final String TOKEN="xxxxxxxxxx";                      //Wx 開發者設置的 token
 34     private Logger loger = Logger.getLogger(getClass());
 35     //重復通知過濾
 36     private static ExpireKey expireKey = new DefaultExpireKey();
 37 
 38 
 39     //微信推送事件 url
 40     @RequestMapping("/openwx/getticket")
 41     public void getTicket(HttpServletRequest request, HttpServletResponse response)
 42             throws Exception {
 43         ServletInputStream inputStream = request.getInputStream();
 44         ServletOutputStream outputStream = response.getOutputStream(); String signature = request.getParameter("signature");
 45         String timestamp = request.getParameter("timestamp");
 46         String nonce = request.getParameter("nonce");
 47         String echostr = request.getParameter("echostr");
 48 
 49         //首次請求申請驗證,返回echostr
 50         if(echostr!=null){
 51             outputStreamWrite(outputStream,echostr);
 52             return;
 53         }
 54 
 55         //驗證請求簽名
 56         if(!signature.equals(SignatureUtil.generateEventMessageSignature(TOKEN,timestamp,nonce))){
 57             System.out.println("The request signature is invalid");
 58             return;
 59         }
 60 
 61         boolean isreturn= false;
 62         loger.info("1.收到微信服務器消息");
 63         Map<String, String> wxdata=parseXml(request);
 64         if(wxdata.get("MsgType")!=null){
 65             if("event".equals(wxdata.get("MsgType"))){
 66                 loger.info("2.1解析消息內容為:事件推送");
 67                 if( "subscribe".equals(wxdata.get("Event"))){
 68                     loger.info("2.2用戶第一次關注 返回true哦");
 69                     isreturn=true;
 70                 }
 71             }
 72         }
 73 
 74         if(isreturn == true){
 75             //轉換XML
 76             String key = wxdata.get("FromUserName")+ "__"
 77                     + wxdata.get("ToUserName")+ "__"
 78                     + wxdata.get("MsgId") + "__"
 79                     + wxdata.get("CreateTime");
 80             loger.info("3.0 進入回復 轉換對象:"+key);
 81 
 82             if(expireKey.exists(key)){
 83                 //重復通知不作處理
 84                 loger.info("3.1  重復通知了");
 85                 return;
 86             }else{
 87                 loger.info("3.1  第一次通知");
 88                 expireKey.add(key);
 89             }
 90 
 91             loger.info("3.2  回復你好");
 92             //創建回復
 93             XMLMessage xmlTextMessage = new XMLTextMessage(
 94                     wxdata.get("FromUserName"),
 95                     wxdata.get("ToUserName"),
 96                     "你好");
 97             //回復
 98             xmlTextMessage.outputStreamWrite(outputStream);
 99             return;
100         }
101         loger.info("3.2  回復空");
102         outputStreamWrite(outputStream,"");
103     }
104 
105     /**
106      * 數據流輸出
107      * @param outputStream
108      * @param text
109      * @return
110      */
111     private boolean outputStreamWrite(OutputStream outputStream, String text){
112         try {
113             outputStream.write(text.getBytes("utf-8"));
114         } catch (UnsupportedEncodingException e) {
115             // TODO Auto-generated catch block
116             e.printStackTrace();
117             return false;
118         } catch (IOException e) {
119             // TODO Auto-generated catch block
120             e.printStackTrace();
121             return false;
122         }
123         return true;
124     }
125 
126     /**
127      * dom4j 解析 xml 轉換為 map
128      * @param request
129      * @return
130      * @throws Exception
131      */
132     public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {
133         // 將解析結果存儲在HashMap中
134         Map<String, String> map = new HashMap<String, String>();
135         // 從request中取得輸入流
136         InputStream inputStream = request.getInputStream();
137         // 讀取輸入流
138         SAXReader reader = new SAXReader();
139         Document document = reader.read(inputStream);
140         // 得到xml根元素
141         Element root = document.getRootElement();
142         // 得到根元素的所有子節點
143         List<Element> elementList = root.elements();
144 
145         // 遍歷所有子節點
146         for (Element e : elementList)
147             map.put(e.getName(), e.getText());
148 
149         // 釋放資源
150         inputStream.close();
151         inputStream = null;
152         return map;
153     }
154 
155     /**
156      * 回復微信服務器"文本消息"
157      * @param response
158      * @param returnvaleue
159      */
160     public void output(HttpServletResponse response, String returnvaleue) {
161         try {
162             PrintWriter pw = response.getWriter();
163             pw.write(returnvaleue);
164             loger.info("****************return valeue***************="+returnvaleue);
165             pw.flush();
166         } catch (IOException e) {
167             e.printStackTrace();
168         }
169     }
170 }

提供一個大神的幫助類

 1 package weixin.popular.bean.xmlmessage;
 2 
 3 import java.io.IOException;
 4 import java.io.OutputStream;
 5 import java.io.UnsupportedEncodingException;
 6 import java.util.UUID;
 7 
 8 import com.qq.weixin.mp.aes.AesException;
 9 import com.qq.weixin.mp.aes.WXBizMsgCrypt;
10 
11 import weixin.popular.bean.message.message.Message;
12 
13 public abstract class XMLMessage {
14 
15     protected String toUserName;
16     protected String fromUserName;
17     protected String msgType;
18 
19     protected XMLMessage(String toUserName, String fromUserName, String msgType) {
20         super();
21         this.toUserName = toUserName;
22         this.fromUserName = fromUserName;
23         this.msgType = msgType;
24     }
25 
26     /**
27      * 子類自定義XML
28      * @return XML
29      */
30     public abstract String subXML();
31 
32     /**
33      * 轉換為  Message 對象
34      * @return Message
35      */
36     public abstract Message convert();
37 
38     public String toXML(){
39         StringBuilder sb = new StringBuilder();
40         sb.append("<xml>");
41         sb.append("<ToUserName><![CDATA["+toUserName+"]]></ToUserName>");
42         sb.append("<FromUserName><![CDATA["+fromUserName+"]]></FromUserName>");
43         sb.append("<CreateTime>"+System.currentTimeMillis()/1000+"</CreateTime>");
44         sb.append("<MsgType><![CDATA["+msgType+"]]></MsgType>");
45         sb.append(subXML());
46         sb.append("</xml>");
47         return sb.toString();
48     }
49 
50     public boolean outputStreamWrite(OutputStream outputStream){
51         try {
52             outputStream.write(toXML().getBytes("utf-8"));
53             outputStream.flush();
54         } catch (UnsupportedEncodingException e) {
55             e.printStackTrace();
56             return false;
57         } catch (IOException e) {
58             e.printStackTrace();
59             return false;
60         }
61         return true;
62     }
63 
64     public boolean outputStreamWrite(OutputStream outputStream,WXBizMsgCrypt bizMsgCrypt){
65         if(bizMsgCrypt != null){
66             try {
67                 String outputStr = bizMsgCrypt.encryptMsg(toXML(), System.currentTimeMillis()+"",UUID.randomUUID().toString());
68                 outputStream.write(outputStr.getBytes("utf-8"));
69                 outputStream.flush();
70             } catch (UnsupportedEncodingException e) {
71                 e.printStackTrace();
72                 return false;
73             } catch (IOException e) {
74                 e.printStackTrace();
75                 return false;
76             } catch (AesException e) {
77                 e.printStackTrace();
78                 return false;
79             }
80             return true;
81         }else{
82             return outputStreamWrite(outputStream);
83         }
84     }
85 
86     public String getToUserName() {
87         return toUserName;
88     }
89 
90     public String getFromUserName() {
91         return fromUserName;
92     }
93 
94     public String getMsgType() {
95         return msgType;
96     }
97 
98 
99 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM