java微信公众开发(原始篇-消息管理)
上一章:java微信公众开发(原始篇-自定义菜单)
大家都知道,我们是可以对公众号发送消息的,既然能够发送消息,那么在我们的后台就一定有办法接收这些消息,并且可以针对一些指定的消息对用户进行回复,就大概类似于聊天机器人一样,你发一句我回一句。
文本消息
由官方提供信息,我们创建在model包下创建包----》request------》创建类Message.java 用于包装接收到的消息
Message.java
//接收消息类
public class Message {
// 开发者微信号
private String ToUserName;
// 发送方帐号(一个OpenID)
private String FromUserName;
// 消息创建时间 (整型)
private long CreateTime;
// 消息类型(text/image/location/link)
private String MsgType;
// 消息id,64位整型
private long MsgId;
//省略get和set方法。。。。
}
接着在创建文本消息类-----》TextMessage.java 继承Message.java类
TextMessage.java
//文本消息
public class TextMessage extends Message{
private String Content;
public String getContent() {
return Content;
}
public void setContent(String content) {
Content = content;
}
}
既然有接收就有回复,继续在model包下创建包-----》response------》创建类----》Message.java 响应消息基类
Message.java
/响应消息基类
public class Message {
// 接收方帐号(收到的OpenID)
private String ToUserName;
// 开发者微信号
private String FromUserName;
// 消息创建时间 (整型)
private long CreateTime;
// 消息类型(text/music/news)
private String MsgType;
// 位0x0001被标志时,星标刚收到的消息
private int FuncFlag;
//此处省略get和set方法。。。
}
接着创建响应文本类----》TextMessage.java 继承Message.java 响应文本基类
//文本消息
public class TextMessage extends Message{
// 回复的消息内容
private String Content;
public String getContent() {
return Content;
}
public void setContent(String content) {
Content = content;
}
}
创建包----》service-----》创建类 ------》MessageService.java 消息处理类
//消息处理类
@Service
public class MessageService {
/**
* 处理微信发来的请求(包括事件的推送)
* @param request
* @return
*/
public String handleRequest(HttpServletRequest request) throws Exception {
String respMessage = null;
// 默认返回的文本消息内容
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);
// 接收文本消息内容
String content = requestMap.get("Content");
// 自动回复文本消息
if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
//回复固定消息
switch (content) {
case "1": {
StringBuffer buffer = new StringBuffer();
buffer.append("您好,请回复数字选择服务:").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;
}
default: {
respContent = "暂时无法提供此功能给您使用。\n\n回复“1”显示帮助信息";
textMessage.setContent(respContent);
// 将文本消息对象转换成xml字符串
respMessage = MessageUtil.textMessageToXml(textMessage);
}
}
}
return respMessage;
}
}
MessageUtil 消息工具类
/**
* 消息工具类
*
*/
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<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();
// 得到根元素的所有子节点
List<Element> 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块
*
*/
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);
}
}
};
}
});
}
ok,最后一步代码,接收所有事件入口,在WxController.java 里加入代码:
@Autowired
private MessageService messageService;
@RequestMapping(value = "/coreController",method= RequestMethod.POST)
public void handleEvent(HttpServletRequest request,HttpServletResponse response){
// 将请求、响应的编码均设置为UTF-8(防止中文乱码)
try {
request.setCharacterEncoding("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
response.setCharacterEncoding("UTF-8");
// 调用核心业务类接收消息、处理消息
String respMessage = null;
try {
respMessage = messageService.handleRequest(request);
} catch (Exception e) {
e.printStackTrace();
}
// 响应消息
PrintWriter out = null;
try {
out = response.getWriter();
out.print(respMessage);
} catch (IOException e) {
e.printStackTrace();
} finally {
out.close();
}
}
启动项目,启动natapp ,将natapp生成的链接添加进测试号接口配置信息处
测试结果:
其他消息类型接收与回复的方式都差不多,在这里不多介绍,后续我会将这些消息类型的接收与回复完善上传github中,大家下载源码后就可以参考与学习。
本章结束,有疑问或者有建议的小伙伴可以在下方评论区留言。
git源码分享:----》》》戳这里