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

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

开发流程图

代码实现

控制层代码

/**
 * 微信核心控制器(验证服务号是否合法,以及消息转发都需要通过此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;

/**
 * <p>Company: B505信息技术研究所 </p> 
 * @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;

/**
 * <p>Company: B505信息技术研究所 </p> 
 * @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<String, String> 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;

/**
 * <p>Company: B505信息技术研究所 </p> 
 * @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<String, String>
	  * @Create Date: 2017年10月11日上午11:41:23
	  * @Version: V1.00 
	  * @author:来日可期
	  */
	public Map<String, String> parseXml(HttpServletRequest request)throws Exception{
		
		// 将解析结果存储在HashMap中
		Map<String, String>map =new HashMap<String, String>();
		// 从request中得到输入流
		InputStream  inputStream=request.getInputStream();
		// 读取输入流
		SAXReader reader = new SAXReader();
		Document document = reader.read(inputStream);
		// 得到XML的根元素
		Element root = document.getRootElement();
		// 得到根元素的所有子节点
		@SuppressWarnings("unchecked")
		List<Element> 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("<![CDATA[");
						 writer.write(text);
						 writer.write("]]>");
					 } else {
						 writer.write(text);
					 }
				 }
			 };
		 }
	    });

}

封装的WeixinMessageInfo类

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

import java.io.Serializable;

import org.springframework.stereotype.Component;

/**
 * <p>Company: B505信息技术研究所 </p> 
 * @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 + "]";
	}
}

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

猜你喜欢

转载自blog.csdn.net/qq_40715775/article/details/79878757