springboot框架开发微信公众号(二)之消息的接受与响应

在开发之前我们要先知道用户发送的信息是先传送到微信服务器,微信服务器在以xml的格式发送给进行公众号

springboot框架开发微信公众号(二)之消息的接受与响应_第1张图片

开发流程图

springboot框架开发微信公众号(二)之消息的接受与响应_第2张图片

代码实现

控制层代码

/**
 * 微信核心控制器(验证服务号是否合法,以及消息转发都需要通过此controller)
 */
package com.b505.web;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.b505.tool.DataProcess;
import com.b505.trycatch.TryCatchWeixinCoreService;
import com.b505.weixin.util.WeixinSignUtil;
import com.b505.weixin.util.WeixinVerification;

/**
 * 

Company: B505信息技术研究所

* @Description: 微信核心controller,接入微信服务层 * @Create Date: 2017年10月9日下午7:31:29 * @Version: V1.00 * @Author: 来日可期 */ @RestController @RequestMapping(value = "/wechat") public class WeixinCoreController { private static Logger logger = LoggerFactory.getLogger(WeixinCoreController.class); @Autowired private WeixinSignUtil weixinSignUtil; @Autowired private DataProcess dataProcess; @Autowired private WeixinCoreService weixinCoreService; @RequestMapping(value="/access", method=RequestMethod.POST) public String getWeiXinMessage(HttpServletRequest request, HttpServletResponse response)throws Exception{ logger.info("----------------开始处理微信发过来的消息------------------"); // 微信服务器POST消息时用的是UTF-8编码,在接收时也要用同样的编码,否则中文会乱码; request.setCharacterEncoding("UTF-8"); // 在响应消息(回复消息给用户)时,也将编码方式设置为UTF-8,原理同上; response.setCharacterEncoding("UTF-8"); String respXml = weixinCoreService.weixinMessageHandelCoreService(request, response); if (dataProcess.dataIsNull(respXml)){ logger.error("-------------处理微信消息失败-----------------------"); return null; }else { logger.info("----------返回微信消息处理结果-----------------------:"+respXml); return respXml; } } }
private WeixinCoreService weixinCoreService; @RequestMapping(value="/access", method=RequestMethod.POST) public String getWeiXinMessage(HttpServletRequest request, HttpServletResponse response)throws Exception{ logger.info("----------------开始处理微信发过来的消息------------------"); // 微信服务器POST消息时用的是UTF-8编码,在接收时也要用同样的编码,否则中文会乱码; request.setCharacterEncoding("UTF-8"); // 在响应消息(回复消息给用户)时,也将编码方式设置为UTF-8,原理同上; response.setCharacterEncoding("UTF-8"); String respXml = weixinCoreService.weixinMessageHandelCoreService(request, response); if (dataProcess.dataIsNull(respXml)){ logger.error("-------------处理微信消息失败-----------------------"); return null; }else { logger.info("----------返回微信消息处理结果-----------------------:"+respXml); return respXml; } } }

service层代码

/**
 * 微信消息处理核心service实现类
 */
package com.b505.service.impl;

import java.util.Date;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.b505.dao.UserDao;
import com.b505.service.WeixinCoreService;
import com.b505.tool.DataProcess;
import com.b505.weixin.message.resp.TextMessage;
import com.b505.weixin.pojo.WeixinMessageInfo;
import com.b505.weixin.util.WeixinMessageModelUtil;
import com.b505.weixin.util.WeixinMessageUtil;

/**
 * 

Company: B505信息技术研究所

* @Description: 微信消息处理核心service实现类 * @Create Date: 2017年10月10日下午3:33:16 * @Version: V1.00 * @Author: 来日可期 */ @Service("weixinCoreService") public class WeixinCoreServiceImpl implements WeixinCoreService { private static Logger logger = LoggerFactory.getLogger(WeixinCoreServiceImpl.class); @Autowired private WeixinMessageUtil weixinMessageUtil; @Autowired private WeixinMessageInfo weixinMessageInfo; @Autowired private WeixinMessageModelUtil weixinMessageModelUtil; @Autowired private UserDao userDao; @Autowired private DataProcess dataProcess; @Override public String weixinMessageHandelCoreService(HttpServletRequest request, HttpServletResponse response) { logger.info("------------微信消息开始处理-------------"); // 返回给微信服务器的消息,默认为null String respMessage = null; try { // 默认返回的文本消息内容 String respContent = null; // xml分析 // 调用消息工具类MessageUtil解析微信发来的xml格式的消息,解析的结果放在HashMap里; Map map = weixinMessageUtil.parseXml(request); // 发送方账号 String fromUserName = map.get("FromUserName"); weixinMessageInfo.setFromUserName(fromUserName); System.out.println("fromUserName--->"+fromUserName); // 接受方账号(公众号) String toUserName = map.get("ToUserName"); weixinMessageInfo.setToUserName(toUserName); System.out.println("toUserName----->"+toUserName); // 消息类型 String msgType = map.get("MsgType"); weixinMessageInfo.setMessageType(msgType); logger.info("fromUserName is:" +fromUserName+" toUserName is:" +toUserName+" msgType is:" +msgType); // 默认回复文本消息 TextMessage textMessage = new TextMessage(); textMessage.setToUserName(fromUserName); textMessage.setFromUserName(toUserName); textMessage.setCreateTime(new Date().getTime()); textMessage.setMsgType(weixinMessageUtil.RESP_MESSAGE_TYPE_TEXT); textMessage.setFuncFlag(0); // 分析用户发送的消息类型,并作出相应的处理 // 文本消息 if (msgType.equals(weixinMessageUtil.REQ_MESSAGE_TYPE_TEXT)){ respContent = "亲,这是文本消息!"; textMessage.setContent(respContent); respMessage = weixinMessageUtil.textMessageToXml(textMessage); } // 图片消息 else if (msgType.equals(weixinMessageUtil.REQ_MESSAGE_TYPE_IMAGE)) { respContent = "您发送的是图片消息!"; textMessage.setContent(respContent); respMessage = weixinMessageUtil.textMessageToXml(textMessage); } // 语音消息 else if (msgType.equals(weixinMessageUtil.REQ_MESSAGE_TYPE_VOICE)) { respContent = "您发送的是语音消息!"; textMessage.setContent(respContent); respMessage = weixinMessageUtil.textMessageToXml(textMessage); } // 视频消息 else if (msgType.equals(weixinMessageUtil.REQ_MESSAGE_TYPE_VIDEO)) { respContent = "您发送的是视频消息!"; textMessage.setContent(respContent); respMessage = weixinMessageUtil.textMessageToXml(textMessage); } // 地理位置消息 else if (msgType.equals(weixinMessageUtil.REQ_MESSAGE_TYPE_LOCATION)) { respContent = "您发送的是地理位置消息!"; textMessage.setContent(respContent); respMessage = weixinMessageUtil.textMessageToXml(textMessage); } // 链接消息 else if (msgType.equals(weixinMessageUtil.REQ_MESSAGE_TYPE_LINK)) { respContent = "您发送的是链接消息!"; textMessage.setContent(respContent); respMessage = weixinMessageUtil.textMessageToXml(textMessage); } // 事件推送(当用户主动点击菜单,或者扫面二维码等事件) else if (msgType.equals(weixinMessageUtil.REQ_MESSAGE_TYPE_EVENT)) { // 事件类型 String eventType =map.get("Event"); System.out.println("eventType------>"+eventType); // 关注 if (eventType.equals(weixinMessageUtil.EVENT_TYPE_SUBSCRIBE)){ respMessage = weixinMessageModelUtil.followResponseMessageModel(weixinMessageInfo); } // 取消关注 else if (eventType.equals(weixinMessageUtil.EVENT_TYPE_UNSUBSCRIBE)) { weixinMessageModelUtil.cancelAttention(fromUserName); } // 扫描带参数二维码 else if (eventType.equals(weixinMessageUtil.EVENT_TYPE_SCAN)) { System.out.println("扫描带参数二维码"); } // 上报地理位置 else if (eventType.equals(weixinMessageUtil.EVENT_TYPE_LOCATION)) { System.out.println("上报地理位置"); } // 自定义菜单(点击菜单拉取消息) else if (eventType.equals(weixinMessageUtil.EVENT_TYPE_CLICK)) { // 事件KEY值,与创建自定义菜单时指定的KEY值对应 String eventKey=map.get("EventKey"); System.out.println("eventKey------->"+eventKey); } // 自定义菜单((自定义菜单URl视图)) else if (eventType.equals(weixinMessageUtil.EVENT_TYPE_VIEW)) { System.out.println("处理自定义菜单URI视图"); } } } catch (Exception e) { e.printStackTrace(); logger.error("系统出错"); System.err.println("系统出错"); respMessage = null; } finally{ if (null == respMessage) { respMessage = weixinMessageModelUtil.systemErrorResponseMessageModel(weixinMessageInfo); } } return respMessage; } }

工具类

/**
 * 封装微信消息类型,有一个解析微信发过的xml消息的工具
 */
package com.b505.weixin.util;

import java.io.InputStream;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.stereotype.Component;

import com.b505.Message.model.Article;
import com.b505.weixin.message.resp.ImageMessage;
import com.b505.weixin.message.resp.MusicMessage;
import com.b505.weixin.message.resp.NewsMessage;
import com.b505.weixin.message.resp.TextMessage;
import com.b505.weixin.message.resp.VideoMessage;
import com.b505.weixin.message.resp.VoiceMessage;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;

/**
 * 

Company: B505信息技术研究所

* @Description: 封装微信消息类型,有一个解析xml格式的工具 * @Create Date: 2017年10月11日上午11:28:48 * @Version: V1.00 * @Author: 来日可期 */ @Component public class WeixinMessageUtil { /** * 请求消息类型:文本 */ public final String REQ_MESSAGE_TYPE_TEXT = "text"; /** * 请求消息类型:图片 */ public final String REQ_MESSAGE_TYPE_IMAGE="image"; /** * 请求消息类型:语音 */ public final String REQ_MESSAGE_TYPE_VOICE="voice"; /** * 请求消息类型:视频 */ public final String REQ_MESSAGE_TYPE_VIDEO="video"; /** * 请求消息类型:链接 */ public final String REQ_MESSAGE_TYPE_LINK = "link"; /** * 请求消息类型:地理位置 */ public final String REQ_MESSAGE_TYPE_LOCATION="location"; /** * 请求消息类型:小视频 */ public final String REQ_MESSAGE_TYPE_SHORTVIDEO="shortvideo"; /** *请求消息类型:事件推送 */ public final String REQ_MESSAGE_TYPE_EVENT = "event"; /** * 返回消息类型:文本 */ public final String RESP_MESSAGE_TYPE_TEXT = "text"; /** * 消息返回类型:图片 */ public final String RESP_MESSAGE_TYPE_IMAGE="image"; /** * 消息返回类型:语音 */ public final String RESP_MESSAGE_TYPE_VOICE = "voice"; /** * 消息返回类型:音乐 */ public final String RESP_MESSAGE_TYPE_MUSIC = "music"; /** * 消息返回类型:图文 */ public final String RESP_MESSAGE_TYPE_NEWS = "news"; /** * 消息返回类型:视频 */ public final String RESP_MESSAGE_TYPE_VIDEO="video"; /** * 事件类型:订阅 */ public final String EVENT_TYPE_SUBSCRIBE = "subscribe"; /** * 事件类型:取消订阅 */ public final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe"; /** * 事件类型:scan(关注用户扫描带参二维码) */ public final String EVENT_TYPE_SCAN = "scan"; /** * 事件类型:location(上报地理位置) */ public final String EVENT_TYPE_LOCATION = "location"; /** * 事件类型:CLICK(点击菜单拉取消息) */ public final String EVENT_TYPE_CLICK ="CLICK"; /** * 事件类型:VIEW(自定义菜单URl视图) */ public final String EVENT_TYPE_VIEW ="VIEW"; /** * 事件类型:TEMPLATESENDJOBFINISH(模板消息送达情况提醒) */ public final String EVENT_TYPE_TEMPLATESENDJOBFINISH="TEMPLATESENDJOBFINISH"; /** * @Description: 解析微信服务器发过来的xml格式的消息将其转换为map * @Parameters: WeixinMessageUtil * @Return: Map * @Create Date: 2017年10月11日上午11:41:23 * @Version: V1.00 * @author:来日可期 */ public Map parseXml(HttpServletRequest request)throws Exception{ // 将解析结果存储在HashMap中 Mapmap =new HashMap(); // 从request中得到输入流 InputStream inputStream=request.getInputStream(); // 读取输入流 SAXReader reader = new SAXReader(); Document document = reader.read(inputStream); // 得到XML的根元素 Element root = document.getRootElement(); // 得到根元素的所有子节点 @SuppressWarnings("unchecked") List elementList = root.elements(); // 判断又没有子元素列表 if (elementList.size()==0){ map.put(root.getName(), root.getText()); }else { for (Element e : elementList) map.put(e.getName(), e.getText()); } // 释放资源 inputStream.close(); inputStream = null; System.out.println("---------xml转换为map-----:"+map); return map; } /** * @Description: 文本消息对象转换成xml * @param textMessage * @date 2016-12-01 * @return xml */ public String textMessageToXml(TextMessage textMessage) { xstream.alias("xml", textMessage.getClass()); return xstream.toXML(textMessage); } /** * @Description: 图文消息对象转换成xml * @param newsMessage * @date 2016-12-01 * @return xml */ public String newsMessageToXml(NewsMessage newsMessage) { xstream.alias("xml", newsMessage.getClass()); xstream.alias("item", new Article().getClass()); return xstream.toXML(newsMessage); } /** * @Description: 图片消息对象转换成xml * @param imageMessage * @date 2016-12-01 * @return xml */ public String imageMessageToXml(ImageMessage imageMessage) { xstream.alias("xml", imageMessage.getClass()); return xstream.toXML(imageMessage); } /** * @Description: 语音消息对象转换成xml * @param voiceMessage * @date 2016-12-01 * @return xml */ public String voiceMessageToXml(VoiceMessage voiceMessage) { xstream.alias("xml", voiceMessage.getClass()); return xstream.toXML(voiceMessage); } /** * @Description: 视频消息对象转换成xml * @param videoMessage * @date 2016-12-01 * @return xml */ public String videoMessageToXml(VideoMessage videoMessage) { xstream.alias("xml", videoMessage.getClass()); return xstream.toXML(videoMessage); } /** * @Description: 音乐消息对象转换成xml * @param MusicMessage * @date 2016-12-01 * @return xml */ public String musicMessageToXml(MusicMessage musicMessage) { xstream.alias("xml", musicMessage.getClass()); return xstream.toXML(musicMessage); } /** * 对象到xml的处理 * 扩展xstream,使其支持CDATA块 */ private XStream xstream = new XStream(new XppDriver() { @Override public HierarchicalStreamWriter createWriter(Writer out) { return new PrettyPrintWriter(out) { // 对所有xml节点的转换都增加CDATA标记 boolean cdata = true; @Override @SuppressWarnings("rawtypes") public void startNode(String name, Class clazz) { super.startNode(name, clazz); } @Override protected void writeText(QuickWriter writer, String text) { if (cdata) { writer.write(""); } else { writer.write(text); } } }; } }); }

 

封装的WeixinMessageInfo类

 

/**
 * 将发送方,接收方,微信用户名等封装成类
 */
package com.b505.weixin.pojo;

import java.io.Serializable;

import org.springframework.stereotype.Component;

/**
 * 

Company: B505信息技术研究所

* @Description: 将发送方,接收方,微信用户名封装 * @Create Date: 2017年10月23日上午11:45:44 * @Version: V1.00 * @Author: 来日可期 */ @Component public class WeixinMessageInfo implements Serializable{ private static final long serialVersionUID = 1L; private String fromUserName; // 发送发微信账号 private String toUserName; // 接收方微信账号 private String weixinUserName; // 微信用户名 private String messageType; // 消息类型 /** * @return the fromUserName */ public String getFromUserName() { return fromUserName; } /** * @param fromUserName the fromUserName to set */ public void setFromUserName(String fromUserName) { this.fromUserName = fromUserName; } /** * @return the toUserName */ public String getToUserName() { return toUserName; } /** * @param toUserName the toUserName to set */ public void setToUserName(String toUserName) { this.toUserName = toUserName; } /** * @return the weixinUserName */ public String getWeixinUserName() { return weixinUserName; } /** * @param weixinUserName the weixinUserName to set */ public void setWeixinUserName(String weixinUserName) { this.weixinUserName = weixinUserName; } /** * @return the messageType */ public String getMessageType() { return messageType; } /** * @param messageType the messageType to set */ public void setMessageType(String messageType) { this.messageType = messageType; } @Override public String toString() { return "WeixinMessageInfo [fromUserName=" + fromUserName + ", toUserName=" + toUserName + ", weixinUserName=" + weixinUserName + ", messageType=" + messageType + "]"; } }

文中涉及到的图文消息等回复的消息将在下节中介绍

你可能感兴趣的:(微信公众号开发)