博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于springboot+mybatis的微信公众号开发第三篇-消息的接收与回复
阅读量:6454 次
发布时间:2019-06-23

本文共 20985 字,大约阅读时间需要 69 分钟。

hot3.png

1、在写处理消息的方法前,我们得把相关的model类写好。 

在model包下创建message(req与resp),具体创建如图所示: 
这里写图片描述

BaseMessage类

/** * 消息基类(普通用户 -> 公众帐号) * */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;    }}

ImageMessage类

/** * 图片消息 * */public class ImageMessage extends BaseMessage {    // 图片链接    private String PicUrl;    public String getPicUrl() {        return PicUrl;    }    public void setPicUrl(String picUrl) {        PicUrl = picUrl;    }}

LinkMessage类

/** * 链接消息 * */public class LinkMessage extends BaseMessage {    // 消息标题    private String Title;    // 消息描述    private String Description;    // 消息链接    private String Url;    public String getTitle() {        return Title;    }    public void setTitle(String title) {        Title = title;    }    public String getDescription() {        return Description;    }    public void setDescription(String description) {        Description = description;    }    public String getUrl() {        return Url;    }    public void setUrl(String url) {        Url = url;    }}

LocationMessage类

/** * 地理位置消息 * */public class LocationMessage extends BaseMessage {    // 地理位置维度    private String Location_X;    // 地理位置经度    private String Location_Y;    // 地图缩放大小    private String Scale;    // 地理位置信息    private String Label;    public String getLocation_X() {        return Location_X;    }    public void setLocation_X(String location_X) {        Location_X = location_X;    }    public String getLocation_Y() {        return Location_Y;    }    public void setLocation_Y(String location_Y) {        Location_Y = location_Y;    }    public String getScale() {        return Scale;    }    public void setScale(String scale) {        Scale = scale;    }    public String getLabel() {        return Label;    }    public void setLabel(String label) {        Label = label;    }}

MenuMessage类

public class MenuMessage extends BaseMessage {    private String EventKey;    public String getEventKey() {        return EventKey;    }    public void setEventKey(String eventKey) {        EventKey = eventKey;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

TextMessage类

/** * 文本消息 * */public class TextMessage extends BaseMessage {    // 消息内容    private String Content;    public String getContent() {        return Content;    }    public void setContent(String content) {        Content = content;    }}

VoiceMessage类

/** * 音频消息 * */public class VoiceMessage extends BaseMessage {    // 媒体ID    private String MediaId;    // 语音格式    private String Format;    public String getMediaId() {        return MediaId;    }    public void setMediaId(String mediaId) {        MediaId = mediaId;    }    public String getFormat() {        return Format;    }    public void setFormat(String format) {        Format = format;    }}

Article类

/** * 图文model * */public class Article {    // 图文消息名称    private String Title;    // 图文消息描述    private String Description;    // 图片链接,支持JPG、PNG格式,较好的效果为大图640*320,小图80*80,限制图片链接的域名需要与开发者填写的基本资料中的Url一致    private String PicUrl;    // 点击图文消息跳转链接    private String Url;    public String getTitle() {        return Title;    }    public void setTitle(String title) {        Title = title;    }    public String getDescription() {        return null == Description ? "" : Description;    }    public void setDescription(String description) {        Description = description;    }    public String getPicUrl() {        return null == PicUrl ? "" : PicUrl;    }    public void setPicUrl(String picUrl) {        PicUrl = picUrl;    }    public String getUrl() {        return null == Url ? "" : Url;    }    public void setUrl(String url) {        Url = url;    }}

BaseMessage类

/** * 消息基类(公众帐号 -> 普通用户) * */public class BaseMessage {    // 接收方帐号(收到的OpenID)    private String ToUserName;    // 开发者微信号    private String FromUserName;    // 消息创建时间 (整型)    private long CreateTime;    // 消息类型(text/music/news)    private String MsgType;    // 位0x0001被标志时,星标刚收到的消息    private int FuncFlag;    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 int getFuncFlag() {        return FuncFlag;    }    public void setFuncFlag(int funcFlag) {        FuncFlag = funcFlag;    }}

NewsMessage类

/** * 文本消息 * */public class NewsMessage extends BaseMessage {    // 图文消息个数,限制为10条以内    private int ArticleCount;    // 多条图文消息信息,默认第一个item为大图    private List
Articles; public int getArticleCount() { return ArticleCount; } public void setArticleCount(int articleCount) { ArticleCount = articleCount; } public List
getArticles() { return Articles; } public void setArticles(List
articles) { Articles = articles; }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

TextMessage类

/** * 文本消息 * */public class TextMessage extends BaseMessage {    // 回复的消息内容    private String Content;    public String getContent() {        return Content;    }    public void setContent(String content) {        Content = content;    }}

2、model类创建好了之后,在util包中建立一个MessageUtil类来解析和响应消息。 

a、接收消息时是xml,所以需要解析,这里我们借助于开源框架dom4j去解析xml(这里使用的是dom4j-1.6.1.jar) 
b、而响应消息要把java类转换成xml,这里我们将采用开源框架xstream来实现两者的转换(这里使用的是xstream-1.3.1.jar)

package com.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 com.model.message.response.Article;import com.model.message.response.NewsMessage;import com.model.message.response.TextMessage;import org.dom4j.Document;import org.dom4j.Element;import org.dom4j.io.SAXReader;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;/** * 消息工具类 * */public class MessageUtil {    /**     * 返回消息类型:文本     */    public static final String RESP_MESSAGE_TYPE_TEXT = "text";    /**     * 返回消息类型:音乐     */    public static final String RESP_MESSAGE_TYPE_MUSIC = "music";    /**     * 返回消息类型:图文     */    public static final String RESP_MESSAGE_TYPE_NEWS = "news";    /**     * 请求消息类型:文本     */    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_EVENT = "event";    /**     * 事件类型:subscribe(订阅)and 未关注群体扫描二维码     */    public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";    /**     * 事件类型:已关注群体扫描二维码     */    public static final String EVENT_TYPE_SCAN="SCAN";    /**     * 事件类型:unsubscribe(取消订阅)     */    public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";    /**     * 事件类型:CLICK(自定义菜单点击事件)     */    public static final String EVENT_TYPE_CLICK = "CLICK";    /**     * 事件类型:VIEW(点击自定义菜单跳转链接时的事件)     */    public static final String EVENT_TYPE_VIEW = "VIEW";    /**     * 事件类型:transfer_customer_service(把消息推送给客服)     */    public static final String EVENT_TYPE_TRANSFER_CUSTOMER_SERVICE = "transfer_customer_service";    /**     * 解析微信发来的请求(XML)     *     * @param request     * @return     * @throws Exception     */    @SuppressWarnings("unchecked")    //屏蔽某些编译时的警告信息(在强制类型转换的时候编译器会给出警告)    public static Map
parseXml(HttpServletRequest request) throws Exception { // 将解析结果存储在HashMap中 Map
map = new HashMap
(); // 从request中取得输入流 InputStream inputStream = request.getInputStream(); // 读取输入流 SAXReader reader = new SAXReader(); Document document = reader.read(inputStream); // 得到xml根元素 Element root = document.getRootElement(); // 得到根元素的所有子节点 List
elementList = root.elements(); // 遍历所有子节点 for (Element e : elementList) map.put(e.getName(), e.getText()); // 释放资源 inputStream.close(); inputStream = null; return map; } /** * 文本消息对象转换成xml * * @param textMessage 文本消息对象 * @return xml */ public static String textMessageToXml(TextMessage textMessage) { xstream.alias("xml", textMessage.getClass()); return xstream.toXML(textMessage); } /** * 图文消息对象转换成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(""); } else { writer.write(text); } } }; } });}

3、在CoreServiceImpl.java中完善processRequest的逻辑

注: 

这里加入了默认回复消息,qq怀旧表情回复(最新的无法识别),单、多图文回复等等。

package com.service.core;import com.model.message.response.Article;import com.model.message.response.NewsMessage;import com.model.message.response.TextMessage;import com.util.MessageUtil;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Service;import javax.servlet.http.HttpServletRequest;import java.util.ArrayList;import java.util.Date;import java.util.List;import java.util.Map;import java.util.regex.Matcher;import java.util.regex.Pattern;/** * 核心服务类 */@Service("coreService")public class CoreServiceImpl implements CoreService {    private static Logger log = LoggerFactory.getLogger(CoreServiceImpl.class);    /**     * 处理微信发来的请求(包括事件的推送)     *     * @param request     * @return     */    public  String processRequest(HttpServletRequest request) {        String respMessage = null;        try {            // 默认返回的文本消息内容            String respContent = "请求处理异常,请稍候尝试!";            // xml请求解析            Map
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); // 创建图文消息 NewsMessage newsMessage = new NewsMessage(); newsMessage.setToUserName(fromUserName); newsMessage.setFromUserName(toUserName); newsMessage.setCreateTime(new Date().getTime()); newsMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_NEWS); newsMessage.setFuncFlag(0); List
articleList = new ArrayList
(); // 接收文本消息内容 String content = requestMap.get("Content"); // 自动回复文本消息 if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) { //如果用户发送表情,则回复同样表情。 if (isQqFace(content)) { respContent = content; textMessage.setContent(respContent); // 将文本消息对象转换成xml字符串 respMessage = MessageUtil.textMessageToXml(textMessage); } else { //回复固定消息 switch (content) { case "1": { StringBuffer buffer = new StringBuffer(); buffer.append("您好,我是小8,请回复数字选择服务:").append("\n\n"); buffer.append("11 可查看测试单图文").append("\n"); buffer.append("12 可测试多图文发送").append("\n"); buffer.append("13 可测试网址").append("\n"); buffer.append("或者您可以尝试发送表情").append("\n\n"); buffer.append("回复“1”显示此帮助菜单").append("\n"); respContent = String.valueOf(buffer); textMessage.setContent(respContent); respMessage = MessageUtil.textMessageToXml(textMessage); break; } case "11": { //测试单图文回复 Article article = new Article(); article.setTitle("微信公众帐号开发教程Java版"); // 图文消息中可以使用QQ表情、符号表情 article.setDescription("这是测试有没有换行\n\n如果有空行就代表换行成功\n\n点击图文可以跳转到百度首页"); // 将图片置为空 article.setPicUrl("http://www.sinaimg.cn/dy/slidenews/31_img/2016_38/28380_733695_698372.jpg"); article.setUrl("http://www.baidu.com"); articleList.add(article); newsMessage.setArticleCount(articleList.size()); newsMessage.setArticles(articleList); respMessage = MessageUtil.newsMessageToXml(newsMessage); break; } case "12": { //多图文发送 Article article1 = new Article(); article1.setTitle("紧急通知,不要捡这种钱!湛江都已经传疯了!\n"); article1.setDescription(""); article1.setPicUrl("http://www.sinaimg.cn/dy/slidenews/31_img/2016_38/28380_733695_698372.jpg"); article1.setUrl("http://mp.weixin.qq.com/s?__biz=MjM5Njc2OTI4NQ==&mid=2650924309&idx=1&sn=8bb6ae54d6396c1faa9182a96f30b225&chksm=bd117e7f8a66f769dc886d38ca2d4e4e675c55e6a5e01e768b383f5859e09384e485da7bed98&scene=4#wechat_redirect"); Article article2 = new Article(); article2.setTitle("湛江谁有这种女儿,请给我来一打!"); article2.setDescription(""); article2.setPicUrl("http://www.sinaimg.cn/dy/slidenews/31_img/2016_38/28380_733695_698372.jpg"); article2.setUrl("http://mp.weixin.qq.com/s?__biz=MjM5Njc2OTI4NQ==&mid=2650924309&idx=2&sn=d7ffc840c7e6d91b0a1c886b16797ee9&chksm=bd117e7f8a66f7698d094c2771a1114853b97dab9c172897c3f9f982eacb6619fba5e6675ea3&scene=4#wechat_redirect"); Article article3 = new Article(); article3.setTitle("以上图片我就随意放了"); article3.setDescription(""); article3.setPicUrl("http://www.sinaimg.cn/dy/slidenews/31_img/2016_38/28380_733695_698372.jpg"); article3.setUrl("http://mp.weixin.qq.com/s?__biz=MjM5Njc2OTI4NQ==&mid=2650924309&idx=3&sn=63e13fe558ff0d564c0da313b7bdfce0&chksm=bd117e7f8a66f7693a26853dc65c3e9ef9495235ef6ed6c7796f1b63abf1df599aaf9b33aafa&scene=4#wechat_redirect"); articleList.add(article1); articleList.add(article2); articleList.add(article3); newsMessage.setArticleCount(articleList.size()); newsMessage.setArticles(articleList); respMessage = MessageUtil.newsMessageToXml(newsMessage); break; } case "13": { //测试网址回复 respContent = "
百度主页"; textMessage.setContent(respContent); // 将文本消息对象转换成xml字符串 respMessage = MessageUtil.textMessageToXml(textMessage); break; } default: { respContent = "(这是里面的)很抱歉,现在小8暂时无法提供此功能给您使用。\n\n回复“1”显示帮助信息"; textMessage.setContent(respContent); // 将文本消息对象转换成xml字符串 respMessage = MessageUtil.textMessageToXml(textMessage); } } } } // 图片消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) { respContent = "您发送的是图片消息!"; textMessage.setContent(respContent); // 将文本消息对象转换成xml字符串 respMessage = MessageUtil.textMessageToXml(textMessage); } // 地理位置消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)) { respContent = "您发送的是地理位置消息!"; textMessage.setContent(respContent); // 将文本消息对象转换成xml字符串 respMessage = MessageUtil.textMessageToXml(textMessage); } // 链接消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) { respContent = "您发送的是链接消息!";textMessage.setContent(respContent); // 将文本消息对象转换成xml字符串 respMessage = MessageUtil.textMessageToXml(textMessage); } // 音频消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) { respContent = "您发送的是音频消息!"; textMessage.setContent(respContent); // 将文本消息对象转换成xml字符串 respMessage = MessageUtil.textMessageToXml(textMessage); } } catch (Exception e) { e.printStackTrace(); } return respMessage; }/** * 判断是否是QQ表情 * * @param content * @return */public static boolean isQqFace(String content) { boolean result = false; // 判断QQ表情的正则表达式 String qqfaceRegex = "/::\\)|/::~|/::B|/::\\||/:8-\\)|/::<|/::$|/::X|/::Z|/::'\\(|/::-\\||/::@|/::P|/::D|/::O|/::\\(|/::\\+|/:--b|/::Q|/::T|/:,@P|/:,@-D|/::d|/:,@o|/::g|/:\\|-\\)|/::!|/::L|/::>|/::,@|/:,@f|/::-S|/:\\?|/:,@x|/:,@@|/::8|/:,@!|/:!!!|/:xx|/:bye|/:wipe|/:dig|/:handclap|/:&-\\(|/:B-\\)|/:<@|/:@>|/::-O|/:>-\\||/:P-\\(|/::'\\||/:X-\\)|/::\\*|/:@x|/:8\\*|/:pd|/:
|/:beer|/:basketb|/:oo|/:coffee|/:eat|/:pig|/:rose|/:fade|/:showlove|/:heart|/:break|/:cake|/:li|/:bome|/:kn|/:footb|/:ladybug|/:shit|/:moon|/:sun|/:gift|/:hug|/:strong|/:weak|/:share|/:v|/:@\\)|/:jj|/:@@|/:bad|/:lvu|/:no|/:ok|/:love|/:
|/:jump|/:shake|/:
|/:circle|/:kotow|/:turn|/:skip|/:oY|/:#-0|/:hiphot|/:kiss|/:<&|/:&>"; Pattern p = Pattern.compile(qqfaceRegex); Matcher m = p.matcher(content); if (m.matches()) { result = true; } return result; }}

因为这里只是一个demo,所有东西都是写死的,在后期扩展时,把写好的数据库的回复模板加入即可。

4、做完以上,相信你在测试号上能够实现相应的消息回复功能了。下一篇讲自定义菜单的操作。

转载于:https://my.oschina.net/rightemperor/blog/1580328

你可能感兴趣的文章
P2627 修剪草坪[dp][单调队列]
查看>>
JS详细入门教程(上)
查看>>
Android学习笔记21-ImageView获取网络图片
查看>>
线段树分治
查看>>
git代码冲突
查看>>
lnmp1.3 配置pathinfo---thinkphp3.2 亲测有效
查看>>
查看Linux 系统的配置和增减用户/增减组/增减权限
查看>>
利用android studio 生成 JNI需要的动态库so文件
查看>>
poll
查看>>
衡量优秀的卓越的前端工程师
查看>>
解析查询 queryString 请求参数的函数
查看>>
学生选课系统数据存文件
查看>>
flutter进行自动编译操作步骤
查看>>
4.6 直接插入排序法
查看>>
我的毕设总结所用的技术和只是要点 基于stm32F4的AGV嵌入式控制系统的设计
查看>>
盘点国内外那些有野心的BI公司
查看>>
JMeter—断言
查看>>
C++的新类创建:继承与组合
查看>>
m5-第9周作业
查看>>
odoo 权限设置
查看>>