一、接受消息
用户向公众号发送的消息是通过我们的那个路径的post方法,发送到我们的项目的。
微信通过get的方法将发送给我们以上信息。用户通过这个路径的post方法向公众号发送消息
成为开发者后,用户每次向公众号发送消息、或者产生自定义菜单、或产生微信支付订单等情况时,开发者填写的服务器配置URL将得到微信服务器推送过来的消息和事件,开发者可以依据自身业务逻辑进行响应,如回复消息。
公众号调用各接口时,一般会获得正确的结果,具体结果可见对应接口的说明。返回错误时,可根据返回码来查询错误原因。全局返回码说明
用户向公众号发送消息时,公众号方收到的消息发送者是一个OpenID,是使用用户微信号加密后的结果,每个用户对每个公众号有一个唯一的OpenID。
此外,由于开发者经常有需在多个平台(移动应用、网站、公众帐号)之间共通用户帐号,统一帐号体系的需求,微信开放平台(open.weixin.qq.com)提供了UnionID机制。开发者可通过OpenID来获取用户基本信息,而如果开发者拥有多个应用(移动应用、网站应用和公众帐号,公众帐号只有在被绑定到微信开放平台帐号下后,才会获取UnionID),可通过获取用户基本信息中的UnionID来区分用户的唯一性,因为只要是同一个微信开放平台帐号下的移动应用、网站应用和公众帐号,用户的UnionID是唯一的。换句话说,同一用户,对同一个微信开放平台帐号下的不同应用,UnionID是相同的。详情请在微信开放平台的资源中心-移动应用开发-微信登录-授权关系接口调用指引-获取用户个人信息(UnionID机制)中查看。
另请注意,微信公众号接口必须以http://或https://开头,分别支持80端口和443端口。
将xml数据包解析成Map
注意
使用dom4j
可以将这个xml包解析成一个Map
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
/**
* 使用dom4j包 解析xml数据包 成Map形式
* @param inputStream
* @return
*/
@Override
public Map<String, String> parseRequest(ServletInputStream inputStream) {
HashMap<String, String> hashMap = new HashMap<>();
SAXReader reader = new SAXReader();
try {
//读取输入流 回去文档对象
Document document = reader.read(inputStream);
//根据文档对象 回去根节点
Element rootElement = document.getRootElement();
//根据根节点获取所有的子节点
List<Element> elements = rootElement.elements();
for (Element element : elements) {
hashMap.put(element.getName(), element.getStringValue());
}
} catch (DocumentException e) {
e.printStackTrace();
}
return hashMap;
}
{
Content=你好, CreateTime=1602226910, ToUserName=gh_f7a997c7d45c, FromUserName=oCV_T6IutImdnwuD658EyIMM_goU, MsgType=text, MsgId=22938375251956865}
各种消息的xml数据包的格式
文本消息
<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>
图片消息
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1348831860</CreateTime>
<MsgType><![CDATA[image]]></MsgType>
<PicUrl><![CDATA[this is a url]]></PicUrl>
<MediaId><![CDATA[media_id]]></MediaId>
<MsgId>1234567890123456</MsgId>
</xml>
语音消息
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1357290913</CreateTime>
<MsgType><![CDATA[voice]]></MsgType>
<MediaId><![CDATA[media_id]]></MediaId>
<Format><![CDATA[Format]]></Format>
<MsgId>1234567890123456</MsgId>
</xml>
视频消息
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1357290913</CreateTime>
<MsgType><![CDATA[video]]></MsgType>
<MediaId><![CDATA[media_id]]></MediaId>
<ThumbMediaId><![CDATA[thumb_media_id]]></ThumbMediaId>
<MsgId>1234567890123456</MsgId>
</xml>
小视频消息
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1357290913</CreateTime>
<MsgType><![CDATA[shortvideo]]></MsgType>
<MediaId><![CDATA[media_id]]></MediaId>
<ThumbMediaId><![CDATA[thumb_media_id]]></ThumbMediaId>
<MsgId>1234567890123456</MsgId>
</xml>
位置消息
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1351776360</CreateTime>
<MsgType><![CDATA[location]]></MsgType>
<Location_X>23.134521</Location_X>
<Location_Y>113.358803</Location_Y>
<Scale>20</Scale>
<Label><![CDATA[位置信息]]></Label>
<MsgId>1234567890123456</MsgId>
</xml>
链接消息
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1351776360</CreateTime>
<MsgType><![CDATA[link]]></MsgType>
<Title><![CDATA[公众平台官网链接]]></Title>
<Description><![CDATA[公众平台官网链接]]></Description>
<Url><![CDATA[url]]></Url>
<MsgId>1234567890123456</MsgId>
</xml>
我们需要创建对应的实体类对象来接收这些xml数据包的数据。因为这些不同形式的xml数据包都有一些相同的属性:ToUserName 接收方微信号、FromUserName 发送方微信号,若为普通用户,则是一个OpenID、CreateTime 消息创建时间、MsgType 消息类型,链接为link。所以我们将这些作为基础属性,其他的对象直接继承这个基础类即可。
BaseMessage
package com.wx.model;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.Data;
import java.util.Map;
/**
* @author :LiuShihao
* @date :Created in 2020/10/9 3:49 下午
* @desc :
*/
@Data
@XStreamAlias("xml")
public class BaseMessage {
@XStreamAlias("ToUserName")
private String toUserName;
@XStreamAlias("FromUserName")
private String fromUserName;
@XStreamAlias("CreateTime")
private String createTime;
@XStreamAlias("MsgType")
private String msgType;
public BaseMessage(Map<String ,String> map){
this.fromUserName=map.get("ToUserName");
this.toUserName=map.get("FromUserName");
this.createTime = System.currentTimeMillis()/1000+"";
}
}
TextMessage
@Data
@XStreamAlias("xml")
public class TextMessage extends BaseMessage {
@XStreamAlias("Content")
private String content;
public TextMessage(Map<String ,String> map,String content ){
super(map);
this.setMsgType("text");
this.content=content;
}
}
二、回复消息
将Map转化成xml数据包
注意
使用xstream
包将Map转化成xml数据包的形式发送会微信服务器。实现回复消息的功能。
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.11.1</version>
</dependency>
/**
* 用于处理所有的事件和消息de 回复
* 将Map解析成xml数据包 回复消息
* @param map
* @return 返回的是xml数据包
*/
@Override
public String getRespose(Map<String, String> map) {
String msgType = map.get("MsgType");
BaseMessage msg = null;
XStream stream = new XStream();
switch (msgType){
case "text":
msg = dealText(map);
stream.processAnnotations(TextMessage.class);
break;
case "image":
break;
case "voice":
break;
case "video":
break;
case "shortvideo":
break;
case "location":
break;
case "link":
break;
default:
break;
}
String msgXML = stream.toXML(msg);
System.out.println(msg);
System.out.println(msgXML);
return stream.toXML(msg);
}
/**
* 处理文本消息
* @param map
* @return
*/
private BaseMessage dealText(Map<String, String> map) {
TextMessage textMessage =null;
if (map.get("Content").matches(".*尚祥光.*")){
textMessage = new TextMessage(map,"不好意思,我不认识那个沙雕~~");
}else if (map.get("Content").matches(".*刘世豪.*")){
textMessage = new TextMessage(map,"百度百科:刘世豪是一个聪明能干有吃苦耐劳的好孩子~~");
}else if (map.get("Content").matches(".*王宝智.*")){
textMessage = new TextMessage(map,"保智我知道,你找他有什么事情吗");
}else if (map.get("Content").matches(".*薛亚飞.*")){
textMessage = new TextMessage(map,"大飞哥,可以,月薪过万,光电班领头羊,黄科院之光!");
}else if (map.get("Content").matches(".*王艺曈.*")){
textMessage = new TextMessage(map,"温柔善良可爱美丽,是刘世豪的女朋友~~");
}else if (map.get("Content").matches(".*刘明珠.*")){
textMessage = new TextMessage(map,"一个湖南人,懂得都懂~~");
}else {
textMessage = new TextMessage(map,"尊敬的会员,您好,很高兴为您服务!");
}
return textMessage;
}
注意
这样解析出来的xml包的根节点是包名。这样是无法使用的。
解决方法:
注意
标签是小写这样即使解析了也无法使用,
解决方法:
在属性上也加上@XStreamAlias
注解。