公众号接收到关注者发来的消息,或者系统推送事件会统一发送到我们定义的接口,交给我们处理。
上节课那个接口的doGet方法处理验证功能,今天doPost方法我们来接受公众号推送过来的消息。
1 public void doGet(HttpServletRequest request, HttpServletResponse response) 2 throws ServletException, IOException { 3 4 // 微信加密签名 5 String signature = request.getParameter("signature"); 6 // 时间戳 7 String timestamp = request.getParameter("timestamp"); 8 // 随机数 9 String nonce = request.getParameter("nonce"); 10 // 随机字符串 11 String echostr = request.getParameter("echostr"); 12 13 PrintWriter out = response.getWriter(); 14 // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败 15 if (SignUtil.checkSignature(signature, timestamp, nonce)) { 16 out.print(echostr); 17 } 18 out.close(); 19 out = null; 20 } 21 22 public void doPost(HttpServletRequest request, HttpServletResponse response) 23 throws ServletException, IOException { 24 try { 25 // 将请求、响应的编码均设置为UTF-8(防止中文乱码) 26 request.setCharacterEncoding("UTF-8"); 27 response.setCharacterEncoding("UTF-8"); 28 // 调用核心业务类接收消息、处理消息 29 String respMessage = MessageUtil.processRequest(request); 30 if (!StringUtil.isEmpty(respMessage)) { 31 // 响应消息 32 PrintWriter out = response.getWriter(); 33 out.print(respMessage); 34 out.close(); 35 } 36 } catch (Exception e) { 37 // TODO Auto-generated catch block 38 e.printStackTrace(); 39 } 40 } 41 42 public void init() throws ServletException { 43 } 44 }
所以自动回复的关键在于解析公众号推送的消息,并解析,进行处理后,通过out.print();将消息返回给公众号,微信后台会帮我们发送给我们定义的某些人。
下面来看看消息处理工具类 MessageUtil.java
public static String processRequest(HttpServletRequest request) { String respMessage = null; try { // 默认返回的文本消息内容 String respContent = "请求处理异常,请稍候尝试!"; // xml请求解析 Map<String, String> requestMap = MessageUtil.parseXml(request); // 发送方帐号(open_id) String fromUserName = requestMap.get("FromUserName"); // 公众帐号 String toUserName = requestMap.get("ToUserName"); // 消息类型 String msgType = requestMap.get("MsgType"); // 回复文本消息 TextMessage textMessage = new TextMessage(); textMessage.setToUserName(fromUserName); textMessage.setFromUserName(toUserName); textMessage.setCreateTime(new Date().getTime()); textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT); textMessage.setFuncFlag(0); // 文本消息 if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) { respContent = "您发送的是文本消息!"; } // 图片消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) { respContent = "您发送的是图片消息!"; } // 地理位置消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)) { respContent = "您发送的是地理位置消息!"; } // 链接消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) { respContent = "您发送的是链接消息!"; } // 音频消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) { respContent = "您发送的是音频消息!"; } // 事件推送 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) { // 事件类型 String eventType = requestMap.get("Event"); // 订阅 if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) { respContent = "谢谢您的关注!"; } // 取消订阅 else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) { // TODO 取消订阅后用户再收不到公众号发送的消息,因此不需要回复消息 } // 自定义菜单点击事件 else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) { // TODO 自定义菜单权没有开放,暂不处理该类消息 } } textMessage.setContent(respContent); respMessage = textMessageToXml(textMessage); } catch (Exception e) { e.printStackTrace(); } return respMessage; } /** * 文本消息对象转换成xml * * @param textMessage 文本消息对象 * @return xml */ public static String textMessageToXml(TextMessage textMessage) { xstream.alias("xml", textMessage.getClass()); return xstream.toXML(textMessage); } /** * 音乐消息对象转换成xml * * @param musicMessage 音乐消息对象 * @return xml */ public static String musicMessageToXml(MusicMessage musicMessage) { xstream.alias("xml", musicMessage.getClass()); return xstream.toXML(musicMessage); } /** * 图文消息对象转换成xml * * @param newsMessage 图文消息对象 * @return xml */ public static String newsMessageToXml(NewsMessage newsMessage) { xstream.alias("xml", newsMessage.getClass()); xstream.alias("item", new Article().getClass()); return xstream.toXML(newsMessage); } /** * 扩展xstream,使其支持CDATA块 * * @date 2013-05-19 */ private static XStream xstream = new XStream(new XppDriver() { public HierarchicalStreamWriter createWriter(Writer out) { return new PrettyPrintWriter(out) { // 对所有xml节点的转换都增加CDATA标记 boolean cdata = true; @SuppressWarnings("unchecked") public void startNode(String name, Class clazz) { super.startNode(name, clazz); } protected void writeText(QuickWriter writer, String text) { if (cdata) { writer.write("<![CDATA["); writer.write(text); writer.write("]]>"); } else { writer.write(text); } } }; } });
TextMessage类
public class BaseMessage { // 开发者微信号 private String ToUserName; // 发送方帐号(一个OpenID) private String FromUserName; // 消息创建时间 (整型) private long CreateTime; // 消息类型(text/image/location/link) private String MsgType; // 消息id,64位整型 private long MsgId; public String getToUserName() { return ToUserName; } public void setToUserName(String toUserName) { ToUserName = toUserName; } public String getFromUserName() { return FromUserName; } public void setFromUserName(String fromUserName) { FromUserName = fromUserName; } public long getCreateTime() { return CreateTime; } public void setCreateTime(long createTime) { CreateTime = createTime; } public String getMsgType() { return MsgType; } public void setMsgType(String msgType) { MsgType = msgType; } public long getMsgId() { return MsgId; } public void setMsgId(long msgId) { MsgId = msgId; } }
/** * 文本消息 * * @author liufeng * @date 2013-05-19 */ public class TextMessage extends BaseMessage { // 消息内容 private String Content; public String getContent() { return Content; } public void setContent(String content) { Content = content; } }
额外的jar包(xstream-1.3.1.jar):http://download.csdn.net/detail/yaohucaizi/5120422
更多可以到这个链接查看:http://blog.csdn.net/gebitan505/article/details/24500193