微信-服务器消息接受与回复-代码

com.wtxy.weixin.service
  1 package com.wtxy.weixin.service;
  2 
  3 import java.util.Date;
  4 import java.util.Map;
  5 
  6 import javax.servlet.http.HttpServletRequest;
  7 
  8 import com.wtxy.util.MessageUtil;
  9 import com.wtxy.weixin.message.TextMessage;
 10 
 11 /**
 12  * 核心服务类
 13  * 
 14  * @author Ran
 15  * @date 2016-04-21
 16  */
 17 public class CoreService {
 18     /**
 19      * 处理微信发来的请求
 20      * 
 21      * @param request
 22      * @return xml
 23      */
 24     public static String processRequest(HttpServletRequest request) {
 25         // xml格式的消息数据
 26         String respXML = null;
 27         
 28         TextMessage textMessage = new TextMessage();
 29         // 默认返回的文本消息内容
 30         String respContent = "未知的消息类型!";
 31         try {
 32             // 调用parseXml方法解析请求消息
 33             Map<String, String> requestMap = MessageUtil.parseXML(request);
 34             // 发送方帐号
 35             String fromUserName = requestMap.get("FromUserName");
 36             // 开发者微信号
 37             String toUserName = requestMap.get("ToUserName");
 38             // 消息类型
 39             String msgType = requestMap.get("MsgType");
 40 
 41             // 回复文本消息
 42             textMessage.setToUserName(fromUserName);
 43             textMessage.setFromUserName(toUserName);
 44             textMessage.setCreateTime(new Date().getTime());
 45             textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);
 46 
 47             // 文本消息
 48             if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
 49                 String content = requestMap.get("Content"); 
 50                 if (content.equals("开灯")){
 51                     respContent = "灯已开!";
 52                //respContent = "您发送的是文本消息!内容是:
"+content;
 53                 }else if(content.equals("关灯")){
 54                     respContent = "灯已关!";
 55                 }
 56 
 57             }
 58             // 图片消息
 59             else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) {
 60                 respContent = "您发送的是图片消息!";
 61             }
 62             // 语音消息
 63             else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) {
 64                 respContent = "您发送的是语音消息!";
 65             }
 66             // 视频消息
 67             else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VIDEO)) {
 68                 respContent = "您发送的是视频消息!";
 69             }
 70             // 地理位置消息
 71             else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)) {
 72                 respContent = "您发送的是地理位置消息!";
 73             }
 74             // 链接消息
 75             else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) {
 76                 respContent = "您发送的是链接消息!";
 77             }
 78             // 事件推送
 79             else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {
 80                 // 事件类型
 81                 String eventType = requestMap.get("Event");
 82                 // 关注
 83                 if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {
 84                     respContent = "欢迎关注 智能管家wtxy!";
 85                 }
 86                 // 取消关注
 87                 else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) {
 88                     // TODO 取消订阅后用户不会再收到公众账号发送的消息,因此不需要回复
 89                 }
 90                 // 扫描带参数二维码
 91                 else if (eventType.equals(MessageUtil.EVENT_TYPE_SCAN)) {
 92                     // TODO 处理扫描带参数二维码事件
 93                 }
 94                 // 上报地理位置
 95                 else if (eventType.equals(MessageUtil.EVENT_TYPE_LOCATION)) {
 96                     // TODO 处理上报地理位置事件
 97                 }
 98                 // 自定义菜单
 99                 else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {
100                     // TODO 处理菜单点击事件
101                 }
102             }
103             // 设置文本消息的内容
104             textMessage.setContent(respContent);
105             // 将文本消息对象转换成xml
106             respXML = MessageUtil.messageToXML(textMessage);
107         } catch (Exception e) {
108             e.printStackTrace();
109         }
110         return respXML;
111     }
112 }
CoreService.java
com.wtxy.servlet
 1 package com.wtxy.servlet;
 2 
 3 import java.io.IOException;
 4 import java.io.PrintWriter;
 5 
 6 import javax.servlet.ServletException;
 7 import javax.servlet.http.HttpServlet;
 8 import javax.servlet.http.HttpServletRequest;
 9 import javax.servlet.http.HttpServletResponse;
10 
11 import com.wtxy.util.SignUtil;
12 import com.wtxy.weixin.service.CoreService;
13 
14 
15 public class CoreServlet extends HttpServlet {
16 
17     private static final long serialVersionUID = 4440739483644821987L;
18 
19     /**
20      * 请求校验(确认请求来自微信服务器)
21      */
22     public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
23         // 微信加密签名
24         String signature = request.getParameter("signature");
25         // 时间戳
26         String timestamp = request.getParameter("timestamp");
27         // 随机数
28         String nonce = request.getParameter("nonce");
29         // 随机字符串
30         String echostr = request.getParameter("echostr");
31 
32         PrintWriter out = response.getWriter();
33         // 请求校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
34         if (SignUtil.checkSignature(signature, timestamp, nonce)) {
35             out.print(echostr);
36         }
37         out.close();
38         out = null;
39     }
40 
41     /**
42      * 处理微信服务器发来的消息
43      */
44     public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
45         // 将请求、响应的编码均设置为UTF-8(防止中文乱码)
46                 request.setCharacterEncoding("UTF-8");
47                 response.setCharacterEncoding("UTF-8");
48 
49                 // 接收参数微信加密签名、 时间戳、随机数
50                 String signature = request.getParameter("signature");
51                 String timestamp = request.getParameter("timestamp");
52                 String nonce = request.getParameter("nonce");
53 
54                 PrintWriter out = response.getWriter();
55                 // 请求校验
56                 if (SignUtil.checkSignature(signature, timestamp, nonce)) {
57                     // 调用核心服务类接收处理请求
58                     String respXML = CoreService.processRequest(request);
59                     out.write(respXML);
60                 }
61                 out.close();
62                 out = null;
63     }
64 
65 }
CoreServlet.java
com.wtxy.util
  1 package com.wtxy.util;
  2 
  3 import java.io.InputStream;
  4 import java.io.Writer;
  5 import java.util.HashMap;
  6 import java.util.List;
  7 import java.util.Map;
  8 
  9 import javax.servlet.http.HttpServletRequest;
 10 
 11 import org.dom4j.Document;
 12 import org.dom4j.Element;
 13 import org.dom4j.io.SAXReader;
 14 
 15 import com.thoughtworks.xstream.XStream;
 16 import com.thoughtworks.xstream.core.util.QuickWriter;
 17 import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
 18 import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
 19 import com.thoughtworks.xstream.io.xml.XppDriver;
 20 import com.wtxy.weixin.message.Article;
 21 import com.wtxy.weixin.message.ImageMessage;
 22 import com.wtxy.weixin.message.MusicMessage;
 23 import com.wtxy.weixin.message.NewsMessage;
 24 import com.wtxy.weixin.message.TextMessage;
 25 import com.wtxy.weixin.message.VideoMessage;
 26 import com.wtxy.weixin.message.VoiceMessage;
 27 
 28 public class MessageUtil {
 29     // 请求消息类型:文本
 30         public static final String REQ_MESSAGE_TYPE_TEXT = "text";
 31         // 请求消息类型:图片
 32         public static final String REQ_MESSAGE_TYPE_IMAGE = "image";
 33         // 请求消息类型:语音
 34         public static final String REQ_MESSAGE_TYPE_VOICE = "voice";
 35         // 请求消息类型:视频
 36         public static final String REQ_MESSAGE_TYPE_VIDEO = "video";
 37         // 请求消息类型:地理位置
 38         public static final String REQ_MESSAGE_TYPE_LOCATION = "location";
 39         // 请求消息类型:链接
 40         public static final String REQ_MESSAGE_TYPE_LINK = "link";
 41 
 42         // 请求消息类型:事件推送
 43         public static final String REQ_MESSAGE_TYPE_EVENT = "event";
 44 
 45         // 事件类型:subscribe(订阅)
 46         public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";
 47         // 事件类型:unsubscribe(取消订阅)
 48         public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";
 49         // 事件类型:scan(用户已关注时的扫描带参数二维码)
 50         public static final String EVENT_TYPE_SCAN = "scan";
 51         // 事件类型:LOCATION(上报地理位置)
 52         public static final String EVENT_TYPE_LOCATION = "LOCATION";
 53         // 事件类型:CLICK(自定义菜单)
 54         public static final String EVENT_TYPE_CLICK = "CLICK";
 55 
 56         // 响应消息类型:文本
 57         public static final String RESP_MESSAGE_TYPE_TEXT = "text";
 58         // 响应消息类型:图片
 59         public static final String RESP_MESSAGE_TYPE_IMAGE = "image";
 60         // 响应消息类型:语音
 61         public static final String RESP_MESSAGE_TYPE_VOICE = "voice";
 62         // 响应消息类型:视频
 63         public static final String RESP_MESSAGE_TYPE_VIDEO = "video";
 64         // 响应消息类型:音乐
 65         public static final String RESP_MESSAGE_TYPE_MUSIC = "music";
 66         // 响应消息类型:图文
 67         public static final String RESP_MESSAGE_TYPE_NEWS = "news";
 68 
 69         /**
 70          * 解析微信发来的请求(XML)
 71          * 
 72          * @param request
 73          * @return Map<String, String>
 74          * @throws Exception
 75          */
 76         //@SuppressWarnings("unchecked")
 77         public static HashMap<String, String> parseXML(HttpServletRequest request) throws Exception {
 78             // 将解析结果存储在HashMap中
 79             HashMap<String, String> map = new HashMap<String, String>();
 80 
 81             // 从request中取得输入流
 82             InputStream inputStream = request.getInputStream();
 83             // 读取输入流
 84             SAXReader reader = new SAXReader();
 85             Document document = reader.read(request.getInputStream());
 86             // 得到xml根元素
 87             Element root = document.getRootElement();
 88             
 89             recursiveParseXML(root,map);
 90 
 91             inputStream.close();
 92             inputStream = null;
 93 
 94             return map;
 95         }
 96         
 97         private static void recursiveParseXML(Element root,HashMap<String, String> map){
 98             // 得到根元素的所有子节点
 99             List<Element> elementList = root.elements();
100             //判断有没有子元素列表
101             if(elementList.size() == 0){
102                 map.put(root.getName(), root.getText());
103             }else{
104                 //遍历
105                 for (Element e : elementList){
106                     recursiveParseXML(e,map);
107                 }
108             }
109         }
110 
111         /**
112          * 扩展xstream使其支持CDATA
113          */
114         private static XStream xstream = new XStream(new XppDriver() {
115             public HierarchicalStreamWriter createWriter(Writer out) {
116                 return new PrettyPrintWriter(out) {
117                     // 对所有xml节点的转换都增加CDATA标记
118                     boolean cdata = true;
119 
120                     //@SuppressWarnings("unchecked")
121                     public void startNode(String name, Class clazz) {
122                         super.startNode(name, clazz);
123                     }
124 
125                     protected void writeText(QuickWriter writer, String text) {
126                         if (cdata) {
127                             writer.write("<![CDATA[");
128                             writer.write(text);
129                             writer.write("]]>");
130                         } else {
131                             writer.write(text);
132                         }
133                     }
134                 };
135             }
136         });
137 
138         /**
139          * 文本消息对象转换成xml
140          * 
141          * @param textMessage 文本消息对象
142          * @return xml
143          */
144         public static String messageToXML(TextMessage textMessage) {
145             xstream.alias("xml", TextMessage.class);
146             return xstream.toXML(textMessage);
147         }
148 
149         /**
150          * 图片消息对象转换成xml
151          * 
152          * @param imageMessage 图片消息对象
153          * @return xml
154          */
155         public static String messageToXML(ImageMessage imageMessage) {
156             xstream.alias("xml", ImageMessage.class);
157             return xstream.toXML(imageMessage);
158         }
159 
160         /**
161          * 语音消息对象转换成xml
162          * 
163          * @param voiceMessage 语音消息对象
164          * @return xml
165          */
166         public static String messageToXML(VoiceMessage voiceMessage) {
167             xstream.alias("xml", VoiceMessage.class);
168             return xstream.toXML(voiceMessage);
169         }
170 
171         /**
172          * 视频消息对象转换成xml
173          * 
174          * @param videoMessage 视频消息对象
175          * @return xml
176          */
177         public static String messageToXML(VideoMessage videoMessage) {
178             xstream.alias("xml", VideoMessage.class);
179             return xstream.toXML(videoMessage);
180         }
181 
182         /**
183          * 音乐消息对象转换成xml
184          * 
185          * @param musicMessage 音乐消息对象
186          * @return xml
187          */
188         public static String messageToXML(MusicMessage musicMessage) {
189             xstream.alias("xml", MusicMessage.class);
190             return xstream.toXML(musicMessage);
191         }
192 
193         /**
194          * 图文消息对象转换成xml
195          * 
196          * @param newsMessage 图文消息对象
197          * @return xml
198          */
199         public static String messageToXML(NewsMessage newsMessage) {
200             xstream.alias("xml", NewsMessage.class);
201             xstream.alias("item", Article.class);
202             return xstream.toXML(newsMessage);
203         }
204     }
MessageUtil.java
 1 package com.wtxy.util;
 2 
 3 import java.security.MessageDigest;
 4 import java.security.NoSuchAlgorithmException;
 5 import java.util.Arrays;
 6 
 7 /**
 8  * 请求校验工具类
 9  * 
10  * @author Ran
11  * @date 2016-04-21
12  */
13 public class SignUtil {
14     // 与开发模式接口配置信息中的Token保持一致
15     private static String token = "weixin";
16 
17     /**
18      * 校验签名
19      * 
20      * @param signature 微信加密签名
21      * @param timestamp 时间戳
22      * @param nonce 随机数
23      * @return
24      */
25     public static boolean checkSignature(String signature, String timestamp, String nonce) {
26         // 对token、timestamp和nonce按字典排序
27         String[] paramArr = new String[] { token, timestamp, nonce };
28         Arrays.sort(paramArr);
29 
30         // 将排序后的结果拼接成一个字符串
31         String content = paramArr[0].concat(paramArr[1]).concat(paramArr[2]);
32 
33         String ciphertext = null;
34         try {
35             MessageDigest md = MessageDigest.getInstance("SHA-1");
36             // 对接后的字符串进行sha1加密
37             byte[] digest = md.digest(content.toString().getBytes());
38             ciphertext = byteToStr(digest);
39         } catch (NoSuchAlgorithmException e) {
40             e.printStackTrace();
41         }
42         
43         // 将sha1加密后的字符串与signature进行对比
44         return ciphertext != null ? ciphertext.equals(signature.toUpperCase()) : false;
45     }
46 
47     /**
48      * 将字节数组转换为十六进制字符串
49      * 
50      * @param byteArray
51      * @return
52      */
53     private static String byteToStr(byte[] byteArray) {
54         String strDigest = "";
55         for (int i = 0; i < byteArray.length; i++) {
56             strDigest += byteToHexStr(byteArray[i]);
57         }
58         return strDigest;
59     }
60 
61     /**
62      * 将字节转换为十六进制字符串
63      * 
64      * @param mByte
65      * @return
66      */
67     private static String byteToHexStr(byte mByte) {
68         char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
69         char[] tempArr = new char[2];
70         tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
71         tempArr[1] = Digit[mByte & 0X0F];
72 
73         String s = new String(tempArr);
74         return s;
75     }
76 }
SignUtil
com.wtxy.weixin.message
 1 package com.wtxy.weixin.message;
 2 
 3 public class Article {
 4     private String Title;
 5     private String Description;
 6     private String PicUrl;
 7     private String Url;
 8     
 9     public String getTitle() {
10         return Title;
11     }
12     public void setTitle(String title) {
13         Title = title;
14     }
15     public String getDescription() {
16         return Description;
17     }
18     public void setDescription(String description) {
19         Description = description;
20     }
21     public String getPicUrl() {
22         return PicUrl;
23     }
24     public void setPicUrl(String picUrl) {
25         PicUrl = picUrl;
26     }
27     public String getUrl() {
28         return Url;
29     }
30     public void setUrl(String url) {
31         Url = url;
32     }
33     
34     
35 
36 }
Article.java
 1 package com.wtxy.weixin.message;
 2 
 3 public class BaseMessage {
 4         // 接收方帐号(收到的OpenID)
 5         private String ToUserName;
 6         // 开发者微信号
 7         private String FromUserName;
 8         // 消息创建时间 (整型)
 9         private long CreateTime;
10         // 消息类型(text/music/news)
11         private String MsgType;
12         
13         
14         public String getToUserName() {
15             return ToUserName;
16         }
17         public void setToUserName(String toUserName) {
18             ToUserName = toUserName;
19         }
20         public String getFromUserName() {
21             return FromUserName;
22         }
23         public void setFromUserName(String fromUserName) {
24             FromUserName = fromUserName;
25         }
26         public long getCreateTime() {
27             return CreateTime;
28         }
29         public void setCreateTime(long createTime) {
30             CreateTime = createTime;
31         }
32         public String getMsgType() {
33             return MsgType;
34         }
35         public void setMsgType(String msgType) {
36             MsgType = msgType;
37         }
38 
39 
40     }
BaseMessage.java
 1 package com.wtxy.weixin.message;
 2 
 3 public class Image {
 4     private String Mediald;
 5 
 6     public String getMediald() {
 7         return Mediald;
 8     }
 9 
10     public void setMediald(String mediald) {
11         Mediald = mediald;
12     }
13 
14 }
Image.java
 1 package com.wtxy.weixin.message;
 2 
 3 public class ImageMessage extends BaseMessage {
 4     private Image Image;
 5 
 6     public Image getImage() {
 7         return Image;
 8     }
 9 
10     public void setImage(Image image) {
11         Image = image;
12     }
13 
14 }
ImageMessage.java
 1 package com.wtxy.weixin.message;
 2 
 3 public class Music {
 4     private String Title;
 5     private String Description;
 6     private String MusicUrl;
 7     private String HQMusicUrl;
 8     private String ThumbMediaId;
 9     public String getTitle() {
10         return Title;
11     }
12     public void setTitle(String title) {
13         Title = title;
14     }
15     public String getDescription() {
16         return Description;
17     }
18     public void setDescription(String description) {
19         Description = description;
20     }
21     public String getMusicUrl() {
22         return MusicUrl;
23     }
24     public void setMusicUrl(String musicUrl) {
25         MusicUrl = musicUrl;
26     }
27     public String getHQMusicUrl() {
28         return HQMusicUrl;
29     }
30     public void setHQMusicUrl(String hQMusicUrl) {
31         HQMusicUrl = hQMusicUrl;
32     }
33     public String getThumbMediaId() {
34         return ThumbMediaId;
35     }
36     public void setThumbMediaId(String thumbMediaId) {
37         ThumbMediaId = thumbMediaId;
38     }
39     
40     
41 
42 }
Music.java
 1 package com.wtxy.weixin.message;
 2 
 3 public class MusicMessage extends BaseMessage {
 4     private Music Music;
 5 
 6     public Music getMusic() {
 7         return Music;
 8     }
 9 
10     public void setMusic(Music music) {
11         Music = music;
12     }
13     
14 
15 }
MusicMessage.java
 1 package com.wtxy.weixin.message;
 2 
 3 import java.util.List;
 4 
 5 public class NewsMessage extends BaseMessage {
 6     private int ArticleCount;
 7     private List<Article>Articles;
 8     
 9     public int getArticleCount() {
10         return ArticleCount;
11     }
12     public void setArticleCount(int articleCount) {
13         ArticleCount = articleCount;
14     }
15     public List<Article> getArticles() {
16         return Articles;
17     }
18     public void setArticles(List<Article> articles) {
19         Articles = articles;
20     }
21     
22     
23 
24 }
NewsMessage.java
 1 package com.wtxy.weixin.message;
 2 
 3 public class TextMessage extends BaseMessage {
 4     private String Content;
 5 
 6     public String getContent() {
 7         return Content;
 8     }
 9 
10     public void setContent(String content) {
11         Content = content;
12     }
13 
14 }
TextMessage.java
 1 package com.wtxy.weixin.message;
 2 
 3 public class Video {
 4     //媒体文件id
 5     private String MediaId;
 6     //
 7     private String Title;
 8     
 9     private String Description;
10     
11 
12     public String getMediaId() {
13         return MediaId;
14     }
15 
16     public void setMediaId(String mediaId) {
17         MediaId = mediaId;
18     }
19 
20     public String getTitle() {
21         return Title;
22     }
23 
24     public void setTitle(String title) {
25         Title = title;
26     }
27 
28     public String getDescription() {
29         return Description;
30     }
31 
32     public void setDescription(String description) {
33         Description = description;
34     }
35 }
Video.java
 1 package com.wtxy.weixin.message;
 2 
 3 public class VideoMessage extends BaseMessage {
 4     //语音
 5     private Video Video;
 6 
 7     public Video getVideo() {
 8         return Video;
 9     }
10 
11     public void setVideo(Video video) {
12         Video = video;
13     }
14 
15 }
VideoMessage.java
 1 package com.wtxy.weixin.message;
 2 
 3 public class Voice {
 4     //媒体文件id
 5     private String MediaId;
 6 
 7     public String getMediaId() {
 8         return MediaId;
 9     }
10 
11     public void setMediaId(String mediaId) {
12         MediaId = mediaId;
13     }
14     
15 }
Voice.java
 1 package com.wtxy.weixin.message;
 2 
 3 public class VoiceMessage extends BaseMessage {
 4     private Voice Voice;
 5 
 6     public Voice getVoice() {
 7         return Voice;
 8     }
 9 
10     public void setVoice(Voice voice) {
11         Voice = voice;
12     }
13 
14 }
VoiceMessage.java
原文地址:https://www.cnblogs.com/lantian729308328/p/5415924.html