微信服务器配置完成之后,我们需要定义接口来接收公众号所发生的事件和消息
1.微信公众号中的消息传递是以服务器地址的post请求方式发送过来的。
2.微信与服务器之间的通讯是以xml之间进行通讯的。maven依赖
com.thoughtworks.xstream
xstream
1.4.9
将对象转换为xml
dom4j
dom4j
1.6.1
xml解析
3.代码
@Path("weixin")
public class WeXinResource
{
@Autowired
private EventDispatcher eventDispatcher;//事件处理器
@Autowired
private MsgDispatcher msgDispatcher;//消息处理器
@POST
@Path("messgae")
@Produces(MediaType.TEXT_XML)
public String returnMessage(InputStream is) throws IOException {
try{
Map map=MessageUtil.parseXml(is);
String msgtype=map.get("MsgType");
if(MessageUtil.REQ_MESSAGE_TYPE_EVENT.equals(msgtype)){
String eventMessage =eventDispatcher.processEvent(map); //进入事件处理
return eventMessage;
}else{
String processMessage= msgDispatcher.processMessage(map); //进入消息处理
return processMessage;
}
}catch(Exception e){
e.printStackTrace();
}
return "";
}
package com.peas.business.weixin;
import com.peas.business.weixin.dto.*;
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;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.InputStream;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by peaimage on 2018/8/14.
*/
public class MessageUtil {
/**
* ClassName: MessageUtil
* @Description: 消息工具类
* @author dapengniao
* @date 视频类型
*/
/**
* 请求消息类型:文本
*/
public static final String REQ_MESSAGE_TYPE_TEXT = "text";
/**
* 请求消息类型:图片
*/
public static final String REQ_MESSAGE_TYPE_IMAGE = "image";
/**
* 请求消息类型:链接
*/
public static final String REQ_MESSAGE_TYPE_LINK = "link";
/**
* 请求消息类型:地理位置
*/
public static final String REQ_MESSAGE_TYPE_LOCATION = "location";
/**
* 请求消息类型:音频
*/
public static final String REQ_MESSAGE_TYPE_VOICE = "voice";
/**
* 请求消息类型:视频
*/
public static final String REQ_MESSAGE_TYPE_VIDEO = "video";
/**
* 请求消息类型:小视频
*/
public static final String REQ_MESSAGE_TYPE_SHORTVIDEO = "shortvideo";
public static final String RESP_MESSAGE_TYPE_NEWS = "news";
// 临时二维码
public static final String QR_SCENE = "QR_SCENE"; //-1
// 永久二维码
public static final String QR_LIMIT_SCENE = "QR_LIMIT_SCENE";//0
// 永久二维码(字符串)
public static final String QR_LIMIT_STR_SCENE = "QR_LIMIT_STR_SCENE";//1
public static final String LONG2SHORT = "long2short";
/**
* 请求消息类型:推送
*/
public static final String REQ_MESSAGE_TYPE_EVENT = "event";
/**
* 事件类型:subscribe(订阅)
*/
public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";
/**
* 事件类型:unsubscribe(取消订阅)
*/
public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";
/**
* 事件类型:SCAN(扫描带参数二维码事件 用户已关注时的事件推送)
*/
public static final String EVENT_TYPE_SCAN = "SCAN";
/**
* 事件类型:LOCATION(上报地理位置事件)
*/
public static final String EVENT_TYPE_LOCATION= "LOCATION";
/**
* 事件类型:CLICK(点击菜单拉取消息时的事件推送)
*/
public static final String EVENT_TYPE_CLICK = "CLICK";
/**
* 事件类型:VIEW(点击菜单跳转链接时的事件推送)
*/
public static final String EVENT_TYPE_VIEW = "VIEW";
/**
* @Description: 解析微信发来的请求(XML)
*/
public static Map parseXml(InputStream ins) throws Exception {
// 将解析结果存储在 HashMap 中
Map map = new HashMap();
SAXReader reader = new SAXReader(); // 使用dom4j解析xml
Document doc = reader.read(ins);
Element root = doc.getRootElement(); // 获取根元素
List list = root.elements(); // 获取所有节点
for (Element e : list) {
map.put(e.getName(), e.getText());
System.out.println(e.getName() + "--->" + e.getText());
}
ins.close();
ins = null;
return map;
}
/**
* 对象到 xml 的处理
*/
private static XStream xstream = new XStream(new XppDriver() {
public HierarchicalStreamWriter createWriter(Writer out) {
return new PrettyPrintWriter(out) {
// 对所有 xml 节点的转换都增加 CDATA 标记
boolean cdata = true;
@SuppressWarnings("rawtypes")
public void startNode(String name, Class clazz) {
super.startNode(name, clazz);
}
protected void writeText(QuickWriter writer, String text) {
if (cdata) {
writer.write("");
} else {
writer.write(text);
}
}
};
}
});
public static String textMessageToXml(TextMessage textMessage) {
xstream.alias("xml", textMessage.getClass());
return xstream.toXML(textMessage);
}
/**
* @Description: 图文消息对象转换成 xml
*/
public static String newsMessageToXml(NewsMessage newsMessage) {
xstream.alias("xml", newsMessage.getClass());
xstream.alias("item", new Article().getClass());
return xstream.toXML(newsMessage);
}
/**
* @Description: 图片消息对象转换成 xml
* @param @param imageMessage
*/
public static String imageMessageToXml(ImageMessage imageMessage) {
xstream.alias("xml", imageMessage.getClass());
return xstream.toXML(imageMessage);
}
/**
* @Description: 语音消息对象转换成 xml
*/
public static String voiceMessageToXml(VoiceMessage voiceMessage) {
xstream.alias("xml", voiceMessage.getClass());
return xstream.toXML(voiceMessage);
}
/**
* @Description: 视频消息对象转换成 xml
*/
public static String videoMessageToXml(VideoMessage videoMessage) {
xstream.alias("xml", videoMessage.getClass());
return xstream.toXML(videoMessage);
}
/**
* @Description: 音乐消息对象转换成 xml
*/
public static String musicMessageToXml(MusicMessage musicMessage) {
xstream.alias("xml", musicMessage.getClass());
return xstream.toXML(musicMessage);
}
}
package com.peas.business.weixin;
import com.peas.business.weixin.dto.TextMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.Map;
/**
* Created by peaimage on 2018/8/14.事件处理器
*/
@Component
public class EventDispatcher {
@Autowired
private WeChatResource weChatResource;
public String processEvent(Map map) throws Exception {
String openid=map.get("FromUserName"); //用户 openid
String mpid=map.get("ToUserName"); //公众号原始 ID
if (map.get("Event").equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) { //关注事件
System.out.println("==============关注事件!");
}
if (map.get("Event").equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) { //取消关注事件
System.out.println("==============这是取消关注事件!");
}
if (map.get("Event").equals(MessageUtil.EVENT_TYPE_SCAN)) { //扫描二维码事件
System.out.println("==============扫描二维码事件!");
}
if (map.get("Event").equals(MessageUtil.EVENT_TYPE_LOCATION)) { //位置上报事件
System.out.println("==============这是位置上报事件!");
}
if (map.get("Event").equals(MessageUtil.EVENT_TYPE_CLICK)) { //自定义菜单点击事件
System.out.println("==============这是自定义菜单点击事件!");
}
if (map.get("Event").equals(MessageUtil.EVENT_TYPE_VIEW)) { //自定义菜单 View 事件
System.out.println("==============这是自定义菜单 View 事件!");
}
return null;
}
}
package com.peas.business.weixin;
import com.peas.business.weixin.dto.Article;
import com.peas.business.weixin.dto.NewsMessage;
import com.peas.business.weixin.dto.TextMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* Created by peaimage on 2018/8/14.
*/
@Component
public class MsgDispatcher {
@Autowired
private WeChatResource weChatResource;
public String processMessage(Map map) {
String openid=map.get("FromUserName"); //用户 openid
String mpid=map.get("ToUserName"); //公众号原始 ID
if (map.get("MsgType").equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) { // 文本消息
TextMessage txtMessgae=new TextMessage();
txtMessgae.setToUserName(openid);
txtMessgae.setFromUserName(mpid);
txtMessgae.setCreateTime(new Date().getTime());
txtMessgae.setMsgType(MessageUtil.REQ_MESSAGE_TYPE_TEXT);
txtMessgae.setContent("nihao");
return MessageUtil.textMessageToXml(txtMessgae);
}
if (map.get("MsgType").equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) { // 图片消息
}
if (map.get("MsgType").equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) { // 链接消息
System.out.println("==============这是链接消息!");
}
if (map.get("MsgType").equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)) { // 位置消息
System.out.println("==============这是位置消息!");
}
if (map.get("MsgType").equals(MessageUtil.REQ_MESSAGE_TYPE_VIDEO)) { // 视频消息
System.out.println("==============这是视频消息!");
}
if (map.get("MsgType").equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) { // 语音消息
System.out.println("==============这是语音消息!");
}
if (map.get("MsgType").equals(MessageUtil.REQ_MESSAGE_TYPE_SHORTVIDEO)) { // 小视频消息
System.out.println("==============这是小视频消息!");
}
return null;
}
}
package com.peas.business.weixin.dto;
import lombok.Data;
/**
* Created by peaimage on 2018/8/14.微信请求消息基本类
*/
@Data
public class BaseMessage {
// 开发者微信号
private String ToUserName;
// 发送方帐号(一个 OpenID)
private String FromUserName;
// 消息创建时间 (整型)
private long CreateTime;
// 消息类型(text/image/location/link/video/shortvideo)
private String MsgType;
// 消息 id,64 位整型
private long MsgId;
//消息文本
private String Content;
}
package com.peas.business.weixin.dto;
import lombok.Data;
/**
* Created by peaimage on 2018/8/14.
* 文本消息
*/
@Data
public class TextMessage extends BaseMessage {
// 消息内容
private String Content;
}
package com.peas.business.weixin.dto;
import lombok.Data;
/**
* Created by peaimage on 2018/8/14.
* 视频/小视屏消息
*/
@Data
public class VideoMessage extends BaseMessage {
private String MediaId; // 视频消息媒体 id,可以调用多媒体文件下载接口拉取数据
private String ThumbMediaId; // 视频消息缩略图的媒体 id,可以调用多媒体文件下载接口拉取数据
}
package com.peas.business.weixin.dto;
import lombok.Data;
import java.util.List;
/**
* Created by peaimage on 2018/8/14.
*/
@Data
public class NewsMessage extends BaseMessage {
// 图文消息个数,限制为 10 条以内
private int ArticleCount;
// 多条图文消息信息,默认第一个 item 为大图
private List Articles;
}
package com.peas.business.weixin.dto;
import lombok.Data;
/**
* Created by peaimage on 2018/8/14.
*/
@Data
public class Music {
private String Title;
// 音乐描述
private String Description;
// 音乐链接
private String MusicUrl;
// 高质量音乐链接,WIFI 环境优先使用该链接播放音乐
private String HQMusicUrl;
private String ThumbMediaId; //缩略图的媒体 id
}
package com.peas.business.weixin.dto;
import lombok.Data;
/**
* Created by peaimage on 2018/8/14.
* 连接消息
*/
@Data
public class LinkMessage extends BaseMessage {
// 消息标题
private String Title;
// 消息描述
private String Description;
// 消息链接
private String Url;
}
package com.peas.business.weixin.dto;
import lombok.Data;
/**
* Created by peaimage on 2018/8/14.
* 图片消息
*
*/
@Data
public class ImageMessage extends BaseMessage {
// 图片链接
private String PicUrl;
}
package com.peas.business.weixin.dto;
import lombok.Data;
/**
* Created by peaimage on 2018/8/14.
*/
@Data
public class Article {
// 图文消息名称
private String Title;
// 图文消息描述
private String Description;
// 图片链接,支持 JPG、PNG 格式,较好的效果为大图 640*320,小图 80*80,
private String PicUrl;
// 点击图文消息跳转链接
private String Url;
}
package com.peas.business.weixin.dto;
import lombok.Data;
/**
* Created by peaimage on 2018/8/16.
*/
@Data
public class Action {
private String action_name;
private String expire_seconds;
private T action_info;
}
@Data
public class VoiceMessage extends BaseMessage {
// 媒体 ID
private String MediaId;
// 语音格式
private String Format;
}
这样我们就根据msgtype消息类型的不同将消息分发到不同的消息处理器 在消息处理器中通过Event的值和MsgType的值将其具体分发具体处理.