上一篇文章写了接入,这篇文章写接收用户消息和根据用户消息推送图文消息
maven2个依赖:<dependency> <groupId>org.dom4j</groupId> <artifactId>dom4j</artifactId> <version>2.1.1</version></dependency>
<dependency> <groupId>com.thoughtworks.xstream</groupId> <artifactId>xstream</artifactId> <version>1.4.11.1</version></dependency>
PART1
微信提供的官方文档已经写明了:
提供一个post请求、按照文本消息的格式返回给微信客户端就达到了消息推送的目的:
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1348831860</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[this is a test]]></Content>
<MsgId>1234567890123456</MsgId>
</xml>
PART2
conllter类:这里边有个坑,@PostMapping和上一篇文章的@GetMapping路径必须一致
@ResponseBody @PostMapping(value = "/msg") public String msg(HttpServletResponse response, HttpServletRequest request) throws Exception { //Map<String,String> map = WxService.parseRequest(response,request); String xml = wxCoreService.weixinMessageHandelCoreService(request,response); //String xml = "<xml><ToUserName>opSgm1sB8VlAfsdBnHwTAPJMAlfY</ToUserName> // <FromUserName>gh_ba3ffb3b11c8</FromUserName> // <CreateTime>1548574358</CreateTime> // <MsgType>text</MsgType> // <Content>我不能识别你发送的内容!</Content></xml>"; request.setCharacterEncoding("UTF-8"); // 在响应消息(回复消息给用户)时,也将编码方式设置为UTF-8,原理同上; response.setCharacterEncoding("UTF-8"); //wxCoreService.g if (!StringUtils.isEmpty(xml)){ log.info("返回微信消息成功!"); System.out.println(xml); return xml; }else { log.info("微信消息处理失败!"); return "error"; } }
向测试号发送一个信息
后台把消息封装成了map
流读取微信发送的文本,把文本转成map格式
public static Map<String,String> parseRequest(HttpServletResponse response, HttpServletRequest request) { logger.info("开始处理微信消息"); Map<String,String> map = new HashMap<>(); SAXReader saxReader = new SAXReader(); try { //读取输入流,获取文档对象 InputStream inputStream = request.getInputStream(); Document document = saxReader.read(inputStream); //根据文档对象获取根节点 Element rootElement = document.getRootElement(); //获取根节点的所有子节点 List<Element> elements = rootElement.elements(); for (Element element : elements) { map.put(element.getName(),element.getStringValue()); } inputStream.close(); } catch (DocumentException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return map;
}
PART3
拿到用户发送的消息,就可以开始做消息回复了,可以根据用户发送的内容,自定义回复内容,机器人也就是这个原理,有开源的微信机器人API,可以直接调用,这里不详细说明,感兴趣的可以自己百度
微信公众号回复图文消息的文本格式:
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<ArticleCount>1</ArticleCount>
<Articles>
<item>
<Title><![CDATA[title1]]></Title>
<Description><![CDATA[description1]]></Description>
<PicUrl><![CDATA[picurl]]></PicUrl>
<Url><![CDATA[url]]></Url>
</item>
</Articles>
</xml>
接下来处理用户消息内容,文本里有msgtype提供了消息类型,不同类型返回的文本格式是不一样的,具体参考微信公众号开发文档,这边拿消息文本做示例:
@Override public String weixinMessageHandelCoreService(HttpServletRequest request, HttpServletResponse response) { BaseMessage msg = null; Map<String, String> map = WxMsgHandlerUtil.parseRequest(response, request); System.out.println("接收到的消息:" + map);
log.info("开始处理消息类型"); String msgType = map.get("MsgType"); switch(msgType){ //文本 case "text": msg = WxMsgHandlerUtil.dealTextMessage(map); break; //图片 case "image": break; }
//把消息对象处理为xml System.out.println(msg);
return msg != null?WxMsgHandlerUtil.beanToXml(msg):null; }
这边把消息类型封装为Bean,此处省略getter、setter,方便转为XML格式以此适合微信消息文本格式
public class BaseMessage {
@XStreamAlias("ToUserName") private String toUserName;//开发者微信号
@XStreamAlias("FromUserName") private String fromUserName;//发送方帐号(一个OpenID)
@XStreamAlias("CreateTime") private Long createTime;//消息创建时间 (整型)
@XStreamAlias("MsgType") private String msgType;//消息类型}
@XStreamAlias("xml")public class NewsMessage extends BaseMessage {
@XStreamAlias("ArticleCount") private String articleCount; @XStreamAlias("Articles") private List<Articles> articles = new ArrayList<>();}
@XStreamAlias("item")public class Articles {
@XStreamAlias("Title") private String title;//标题
@XStreamAlias("Description") private String description;//描述
@XStreamAlias("PicUrl") private String picUrl;//图片链接
@XStreamAlias("Url") private String url;//点击图文消息跳转链接}
自定义消息回复、并转为XML格式,返回,注意:这边的图片URL必须是微信上的,怎么取呢,先给测试号发一张图片,后台输出来复制到就好了
public static BaseMessage dealTextMessage(Map<String, String> map) { //用户发来的消息 String content = map.get("Content"); //String msg = chatWithRobort(content); List<Articles> articles = null; if("1".equals(content)){ articles = new ArrayList<>(); String picUrl = "http://mmbiz.qpic.cn/mmbiz_jpg/V6sQHCpiblmCTG1LiaFuSgCJ3wicxTs1s2tBoveCvicZ" + "Q6LjGniajyCB6ItPxkjXgS3UopwnHGFvyj25RziacknAytrA/"; articles.add(new Articles("哪有那么多惊喜,惊吓就有!","赶紧点进去看看吧!记得收藏", picUrl, "https://www.leemus.cn")); NewsMessage news = new NewsMessage(map,"1",articles); System.out.println("news:" + news); return news; }else { TextMessage tm = new TextMessage(map,"回复1有惊喜哦!"); System.out.println("text:" +tm); return tm; }
}
/** * bean处理成xml * @param msg * @return */ public static String beanToXml(BaseMessage msg) { XStream stream = new XStream(); stream.processAnnotations(TextMessage.class); stream.processAnnotations(ImageMessage.class); stream.processAnnotations(VideoMessage.class); stream.processAnnotations(VoiceMessage.class); stream.processAnnotations(MusicMessage.class); stream.processAnnotations(NewsMessage.class); String s = stream.toXML(msg); return s; }
后面controller拿到解析好的xml返回给微信客户端就完成了消息推送!