微信企业号开发之使用SpringMVC接收消息
白羽 2018-06-20 来源 :网络 阅读 1192 评论 0

摘要:本文将带你了解微信企业号开发之使用SpringMVC接收消息,希望本文对大家学微信有所帮助。



将应用设置在回调模式时,企业可以通过回调URL接收员工回复的消息,以及员工关注、点击菜单、上报地理位置等事件。

在接收到事件后,企业可以发送被动响应消息,实现员工与企业的互动。

注意,企业在接收消息,以及发送被动响应消息时,消息体都以AES方式加密,以保证传输的安全。

消息处理流程大致如下

微信企业号开发之使用SpringMVC接收消息

 

接收普通消息

普通消息是指员工向企业号应用发送的消息,包括文本、图片、语音、视频、地理位置等类型。

 微信企业号开发之使用SpringMVC接收消息

 

接收事件

事件是指员工在企业号上的某些操作行为,比如关注、上报地理位置、点击菜单等。(关注事件请参考’关注与取消关注’)

 微信企业号开发之使用SpringMVC接收消息

被动响应消息

 

 微信企业号开发之使用SpringMVC接收消息

以上文档必须仔细阅读,

 

具体实现如下:

在文章 微信企业号接入(使用SpringMVC)的基础上实现!

在消息回复处理中添加自己的业务,对于关注事件和取消关注事件如有需要加入即可!

对于xml的处理有多种方式,大家可以任选一种!

 

此处需要说明的是腾讯的文档必须要完完整整的看,有些看文档就有答案的!

 

[java] view plain copy
1. <span style="font-size:14px;">package org.oms.qiye.web;  
2.   
3. import java.io.IOException;  
4. import java.io.InputStream;  
5. import java.io.PrintWriter;  
6.   
7. import javax.servlet.http.HttpServletRequest;  
8. import javax.servlet.http.HttpServletResponse;  
9.   
10. import org.oms.qiye.aes.AesException;  
11. import org.oms.qiye.aes.WXBizMsgCrypt;  
12. import org.oms.qiye.service.CoreService;  
13. import org.springframework.stereotype.Controller;  
14. import org.springframework.web.bind.annotation.RequestMapping;  
15. import org.springframework.web.bind.annotation.RequestMethod;  
16. import org.apache.commons.io.IOUtils;  
17. /** 
18.  * 注解方式打开链接 
19.  *  
20.  * @author Sunlight 
21.  * 
22.  */  
23. @Controller  
24. public class CoreController {  
25.     private String token = "sunlight";  
26.     private String encodingAESKey = "s8vFF4f6AWay3uAdJh79WD6imaam4BV6Kl4eL4UzgfM";  
27.     private String corpId = "此处修改为你的企业ID";  
28.   
29.     @RequestMapping(value = { "/coreJoin.do" }, method = RequestMethod.GET)  
30.     public void coreJoinGet(HttpServletRequest request,  
31.             HttpServletResponse response) throws IOException {  
32.         // 微信加密签名  
33.         String msg_signature = request.getParameter("msg_signature");  
34.         // 时间戳  
35.         String timestamp = request.getParameter("timestamp");  
36.         // 随机数  
37.         String nonce = request.getParameter("nonce");  
38.         // 随机字符串  
39.         String echostr = request.getParameter("echostr");  
40.   
41.         System.out.println("request=" + request.getRequestURL());  
42.   
43.         PrintWriter out = response.getWriter();  
44.         // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败  
45.         String result = null;  
46.         try {  
47.             WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(token, encodingAESKey,  
48.                     corpId);  
49.             result = wxcpt.VerifyURL(msg_signature, timestamp, nonce, echostr);  
50.         } catch (AesException e) {  
51.             e.printStackTrace();  
52.         }  
53.         if (result == null) {  
54.             result = token;  
55.         }  
56.         out.print(result);  
57.         out.close();  
58.         out = null;  
59.     }  
60.   
61.     @RequestMapping(value = { "/coreJoin.do" }, method = RequestMethod.POST)  
62.     public void coreJoinPost(HttpServletRequest request,  
63.             HttpServletResponse response) throws IOException {  
64.         // 将请求、响应的编码均设置为UTF-8(防止中文乱码)  
65.         request.setCharacterEncoding("UTF-8");  
66.         response.setCharacterEncoding("UTF-8");  
67.   
68.         // 微信加密签名  
69.         String msg_signature = request.getParameter("msg_signature");  
70.         // 时间戳  
71.         String timestamp = request.getParameter("timestamp");  
72.         // 随机数  
73.         String nonce = request.getParameter("nonce");  
74.           
75.         //从请求中读取整个post数据  
76.         InputStream inputStream = request.getInputStream();  
77.         String postData = IOUtils.toString(inputStream, "UTF-8");  
78.         System.out.println(postData);  
79.           
80.         String msg = "";  
81.         WXBizMsgCrypt wxcpt = null;  
82.         try {  
83.             wxcpt = new WXBizMsgCrypt(token, encodingAESKey, corpId);  
84.             //解密消息  
85.             msg = wxcpt.DecryptMsg(msg_signature, timestamp, nonce, postData);  
86.         } catch (AesException e) {  
87.             e.printStackTrace();  
88.         }  
89.         System.out.println("msg=" + msg);  
90.           
91.         // 调用核心业务类接收消息、处理消息  
92.         String respMessage = CoreService.processRequest(msg);  
93.         System.out.println("respMessage=" + respMessage);  
94.           
95.         String encryptMsg = "";  
96.         try {  
97.             //加密回复消息  
98.             encryptMsg = wxcpt.EncryptMsg(respMessage, timestamp, nonce);  
99.         } catch (AesException e) {  
100.             e.printStackTrace();  
101.         }  
102.           
103.         // 响应消息  
104.         PrintWriter out = response.getWriter();  
105.         out.print(encryptMsg);  
106.         out.close();  
107.   
108.     }  
109.   
110. }  
111. </span>  
CoreService类:
[java] view plain copy
1. <span style="font-size:14px;">package org.oms.qiye.service;  
2.   
3. import java.util.Date;  
4. import java.util.Map;  
5.   
6. import org.oms.qiye.pojo.resp.TextMessage;  
7. import org.oms.qiye.util.MessageUtil;  
8.   
9. /** 
10.  * 处理微信发来的信息 
11.  * @author Sunlight 
12.  * 
13.  */  
14. public class CoreService {  
15.   
16.     public static String processRequest(String msg) {  
17.         String respMessage = null;  
18.         try {  
19.             // 默认返回的文本消息内容  
20.             String respContent = "请求处理异常,请稍候尝试!";  
21.   
22.             // xml请求解析  
23.             Map<String, String> requestMap = MessageUtil.parseXml(msg);  
24.   
25.             System.out.println("Event=="+requestMap.get("Event"));  
26.               
27.             // 发送方帐号(open_id)  
28.             String fromUserName = requestMap.get("FromUserName");  
29.             // 公众帐号  
30.             String toUserName = requestMap.get("ToUserName");  
31.             // 消息类型  
32.             String msgType = requestMap.get("MsgType");  
33.               
34.             // 回复文本消息  
35.             TextMessage textMessage = new TextMessage();  
36.             textMessage.setToUserName(fromUserName);  
37.             textMessage.setFromUserName(toUserName);  
38.             textMessage.setCreateTime(new Date().getTime());  
39.             textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);  
40.             textMessage.setFuncFlag(0);  
41.   
42.             // 文本消息  
43.             if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {  
44.                 String content = requestMap.get("Content");   
45.                 respContent = "Sunlight提示:您发送的是文本消息!内容是:"+content;  
46.             }  
47.             // 图片消息  
48.             else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) {  
49.                 respContent = "Sunlight提示:您发送的是图片消息!";  
50.             }  
51.             // 地理位置消息  
52.             else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)) {  
53.                 respContent = "Sunlight提示:您发送的是地理位置消息!";   
54.             }  
55.             // 链接消息  
56.             else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) {  
57.                 respContent = "Sunlight提示:您发送的是链接消息!";  
58.             }  
59.             // 音频消息  
60.             else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) {  
61.                 respContent = "Sunlight提示:您发送的是音频消息!";  
62.             }  
63.             // 事件推送  
64.             else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {  
65.                 // 事件类型  
66.                 String eventType = requestMap.get("Event");  
67.                 // 自定义菜单点击事件  
68.                 if (eventType.equalsIgnoreCase(MessageUtil.EVENT_TYPE_CLICK)) {  
69.                     // 事件KEY值,与创建自定义菜单时指定的KEY值对应    
70.                     String eventKey = requestMap.get("EventKey");     
71.                     System.out.println("EventKey="+eventKey);  
72.                     respContent = "Sunlight提示:您点击的菜单KEY是"+eventKey;  
73.                 }  
74.             }  
75.   
76.             textMessage.setContent(respContent);  
77.             respMessage = MessageUtil.textMessageToXml(textMessage);  
78.         } catch (Exception e) {  
79.             e.printStackTrace();  
80.             System.out.println(e);  
81.             respMessage="有异常了。。。";  
82.         }  
83.         return respMessage;  
84.     }  
85.   
86. }  
87. </span>  
MessageUtil类需要修改一下,此类使用了 柳峰 大神写的:
[java] view plain copy
1. <span style="font-size:14px;">package org.oms.qiye.util;  
2.   
3. import java.io.ByteArrayInputStream;  
4. import java.io.InputStream;  
5. import java.io.Writer;  
6. import java.util.HashMap;  
7. import java.util.List;  
8. import java.util.Map;  
9.   
10. import org.dom4j.Document;  
11. import org.dom4j.Element;  
12. import org.dom4j.io.SAXReader;  
13. import org.oms.qiye.pojo.resp.Article;  
14. import org.oms.qiye.pojo.resp.MusicMessage;  
15. import org.oms.qiye.pojo.resp.NewsMessage;  
16. import org.oms.qiye.pojo.resp.TextMessage;  
17.   
18. import com.thoughtworks.xstream.XStream;  
19. import com.thoughtworks.xstream.core.util.QuickWriter;  
20. import com.thoughtworks.xstream.io.HierarchicalStreamWriter;  
21. import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;  
22. import com.thoughtworks.xstream.io.xml.XppDriver;  
23.   
24. /** 
25.  * 消息工具类 
26.  *  
27.  * @author sunlight 
28.  * 
29.  */  
30. public class MessageUtil {  
31.     /** 
32.      * 返回消息类型:文本 
33.      */  
34.     public static final String RESP_MESSAGE_TYPE_TEXT = "text";  
35.   
36.     /** 
37.      * 返回消息类型:音乐 
38.      */  
39.     public static final String RESP_MESSAGE_TYPE_MUSIC = "music";  
40.   
41.     /** 
42.      * 返回消息类型:图文 
43.      */  
44.     public static final String RESP_MESSAGE_TYPE_NEWS = "news";  
45.   
46.     /** 
47.      * 请求消息类型:文本 
48.      */  
49.     public static final String REQ_MESSAGE_TYPE_TEXT = "text";  
50.   
51.     /** 
52.      * 请求消息类型:图片 
53.      */  
54.     public static final String REQ_MESSAGE_TYPE_IMAGE = "image";  
55.   
56.     /** 
57.      * 请求消息类型:链接 
58.      */  
59.     public static final String REQ_MESSAGE_TYPE_LINK = "link";  
60.   
61.     /** 
62.      * 请求消息类型:地理位置 
63.      */  
64.     public static final String REQ_MESSAGE_TYPE_LOCATION = "location";  
65.   
66.     /** 
67.      * 请求消息类型:音频 
68.      */  
69.     public static final String REQ_MESSAGE_TYPE_VOICE = "voice";  
70.   
71.     /** 
72.      * 请求消息类型:推送 
73.      */  
74.     public static final String REQ_MESSAGE_TYPE_EVENT = "event";  
75.   
76.     /** 
77.      * 事件类型:subscribe(订阅) 
78.      */  
79.     public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";  
80.   
81.     /** 
82.      * 事件类型:unsubscribe(取消订阅) 
83.      */  
84.     public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";  
85.   
86.     /** 
87.      * 事件类型:CLICK(自定义菜单点击事件) 
88.      */  
89.     public static final String EVENT_TYPE_CLICK = "CLICK";  
90.   
91.     /** 
92.      * 解析微信发来的请求(XML) 
93.      *  
94.      * @param request 
95.      * @return 
96.      * @throws Exception 
97.      */  
98.     @SuppressWarnings("unchecked")  
99.     public static Map<String, String> parseXml(String msg)  
100.             throws Exception {  
101.         // 将解析结果存储在HashMap中  
102.         Map<String, String> map = new HashMap<String, String>();  
103.   
104.         // 从request中取得输入流  
105.         InputStream inputStream = new ByteArrayInputStream(msg.getBytes("UTF-8"));  
106.           
107.         // 读取输入流  
108.         SAXReader reader = new SAXReader();  
109.         Document document = reader.read(inputStream);  
110.         // 得到xml根元素  
111.         Element root = document.getRootElement();  
112.         // 得到根元素的所有子节点  
113.         List<Element> elementList = root.elements();  
114.   
115.         // 遍历所有子节点  
116.         for (Element e : elementList)  
117.             map.put(e.getName(), e.getText());  
118.   
119.         // 释放资源  
120.         inputStream.close();  
121.         inputStream = null;  
122.   
123.         return map;  
124.     }  
125.   
126.     /** 
127.      * 文本消息对象转换成xml 
128.      *  
129.      * @param textMessage 
130.      *            文本消息对象 
131.      * @return xml 
132.      */  
133.     public static String textMessageToXml(TextMessage textMessage) {  
134.         xstream.alias("xml", textMessage.getClass());  
135.         return xstream.toXML(textMessage);  
136.     }  
137.   
138.     /** 
139.      * 音乐消息对象转换成xml 
140.      *  
141.      * @param musicMessage 
142.      *            音乐消息对象 
143.      * @return xml 
144.      */  
145.     public static String musicMessageToXml(MusicMessage musicMessage) {  
146.         xstream.alias("xml", musicMessage.getClass());  
147.         return xstream.toXML(musicMessage);  
148.     }  
149.   
150.     /** 
151.      * 图文消息对象转换成xml 
152.      *  
153.      * @param newsMessage 
154.      *            图文消息对象 
155.      * @return xml 
156.      */  
157.     public static String newsMessageToXml(NewsMessage newsMessage) {  
158.         xstream.alias("xml", newsMessage.getClass());  
159.         xstream.alias("item", new Article().getClass());  
160.         return xstream.toXML(newsMessage);  
161.     }  
162.   
163.     /** 
164.      * 扩展xstream,使其支持CDATA块 
165.      *  
166.      * @date 2013-05-19 
167.      */  
168.     private static XStream xstream = new XStream(new XppDriver() {  
169.         @Override  
170.         public HierarchicalStreamWriter createWriter(Writer out) {  
171.             return new PrettyPrintWriter(out) {  
172.                 // 对所有xml节点的转换都增加CDATA标记  
173.                 boolean cdata = true;  
174.   
175.                 @Override  
176.                 @SuppressWarnings("rawtypes")  
177.                 public void startNode(String name, Class clazz) {  
178.                     super.startNode(name, clazz);  
179.                 }  
180.   
181.                 @Override  
182.                 protected void writeText(QuickWriter writer, String text) {  
183.                     if (cdata) {  
184.                         writer.write("<![CDATA[");  
185.                         writer.write(text);  
186.                         writer.write("]]>");  
187.                     } else {  
188.                         writer.write(text);  
189.                     }  
190.                 }  
191.             };  
192.         }  
193.     });  
194. }  
195. </span>


项目结构图:

 

 微信企业号开发之使用SpringMVC接收消息

此处消息类的封装可以使用公众号的,此处不在列出!

 

测试结果:

 微信企业号开发之使用SpringMVC接收消息


 


本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之微信频道!


本文由 @白羽 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程