引言
公众号经常会有一些自动回复,最近顺便研究了一下公众号被动回复的代码实现,并不是特别难;下面我用代码演示一下;
注:公众号的一些准备工作已经在《获取公众号二维码》一文中说过了,这里就不多说了,配置步骤是一样的;
看文档
先以文档为主,文档说的关键一句就是:
这里我们填写的url已经配置好了,就是上次配置的这个:
这个post消息一开始我不明白,其实就是实现一个post接口,和填入的接口对应即可:
这个接口其实在配置时我们实现的是一个get请求接口,而这里是post请求
先不用急着实现接口功能,可以打个断点在这个接口上,然后关注公众号,或者给公众号发送消息,就会发现请求会走该接口;
接下来就是具体接收并回复消息了;
代码逻辑
看文档可以发现,微信的消息交互好像都是通过xml文件格式进行交互的,其实和使用json交互没什么区别,我们就只需要把request中的xml文本拿到,然后把xml解析成为对应数据就好了;(代码中是将xml解析成了map,这样更易于取数据)
当然回复数据也要变成xml格式,然后只需要把该xml字符串返回即可;
下面就是具体代码:
/**
* 接收微信公众号消息
*/
@PostMapping("/callback")
public String responseMsg(HttpServletRequest req, HttpServletResponse resp) throws IOException {
req.setCharacterEncoding("UTF-8");
String message = "success";
// 把微信返回的xml信息转义成map
try {
Map<String, String> xmlMessage = WxMessageUtil.xmlToMap(req);
String fromUserName = xmlMessage.get("FromUserName"); // 这个就是你关注公众号的openId
String toUserName = xmlMessage.get("ToUserName"); // 这个是用户微信的id
String msgType = xmlMessage.get("MsgType"); // 消息类型(event或者text)
String createTime = xmlMessage.get("CreateTime"); // 消息创建时间 (整型)
log.info("消息来自(公众号的openId)=>" + fromUserName);
log.info("用户微信的id=>" + toUserName);
log.info("消息类型为=>" + msgType);
log.info("消息创建时间 (整型)=>" + createTime);
if ("event".equals(msgType)) { // 如果是事件推送
String eventType = xmlMessage.get("Event"); // 事件类型
if ("subscribe".equals(eventType)) { // 如果是订阅消息
String subscribeContent = "感谢关注";
String subscribeReturnXml = WxMessageUtil.getWxReturnMsg(xmlMessage, subscribeContent);
return subscribeReturnXml;
}
if ("SCAN".equals(eventType)) { // 如果是扫码消息
String scanContent = "扫码成功";
String scanReturnXml = WxMessageUtil.getWxReturnMsg(xmlMessage, scanContent);
return scanReturnXml;
}
}
if ("text".equals(msgType)) { // 如果是文本消息推送
String content = xmlMessage.get("Content"); // 接收到的消息内容
String textReturnXml = WxMessageUtil.getWxReturnMsg(xmlMessage, content);
return textReturnXml; // 将接收到的文本消息变成xml格式再返回
}
} catch (Exception e) {
e.printStackTrace();
}
return message;
}
可以看看效果:
后台输出
当然你可以看文档实现更多类型的消息互动,就是加几个if的问题;
上面示例代码中用到了一个WxMessageUtil工具类,这里放一下工具类的代码:
需要先引入一个dom4j依赖:
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
import com.yang.model.wx.TextMessage;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 微信消息处理类(微信消息交互大部分就是xml格式交互)
*/
@Slf4j
public class WxMessageUtil {
/*
* xml转map
*/
public static Map<String, String> xmlToMap(HttpServletRequest request) throws IOException, DocumentException {
HashMap<String, String> map = new HashMap<String,String>();
SAXReader reader = new SAXReader();
InputStream ins = request.getInputStream();
Document doc = reader.read(ins);
Element root = doc.getRootElement();
@SuppressWarnings("unchecked")
List<Element> list = (List<Element>)root.elements();
for(Element e:list){
map.put(e.getName(), e.getText());
}
ins.close();
return map;
}
/**
* 获取公众号回复信息(xml格式)
*/
public static String getWxReturnMsg(Map<String, String> decryptMap, String content) throws UnsupportedEncodingException {
log.info("---开始封装xml---decryptMap:" + decryptMap.toString());
TextMessage textMessage = new TextMessage();
textMessage.setToUserName(decryptMap.get("FromUserName"));
textMessage.setFromUserName(decryptMap.get("ToUserName"));
textMessage.setCreateTime(System.currentTimeMillis());
textMessage.setMsgType("text"); // 设置回复消息类型
textMessage.setContent(content); // 设置回复内容
String xmlMsg = getXmlString(textMessage);
// 设置返回信息编码,防止中文乱码
String encodeXmlMsg = new String(xmlMsg.getBytes(), "ISO-8859-1");
return encodeXmlMsg;
}
/**
* 设置回复消息xml格式
*/
private static String getXmlString(TextMessage textMessage) {
String xml = "";
if (textMessage != null) {
xml = "<xml>";
xml += "<ToUserName><![CDATA[";
xml += textMessage.getToUserName();
xml += "]]></ToUserName>";
xml += "<FromUserName><![CDATA[";
xml += textMessage.getFromUserName();
xml += "]]></FromUserName>";
xml += "<CreateTime>";
xml += textMessage.getCreateTime();
xml += "</CreateTime>";
xml += "<MsgType><![CDATA[";
xml += textMessage.getMsgType();
xml += "]]></MsgType>";
xml += "<Content><![CDATA[";
xml += textMessage.getContent();
xml += "]]></Content>";
xml += "</xml>";
}
log.info("xml封装结果=>" + xml);
return xml;
}
}
其中封装的消息模板TextMessage的代码:
import lombok.Data;
/**
* 微信消息自动回复模板类
*/
@Data
public class TextMessage {
private String toUserName;
private String fromUserName;
private Long createTime;
private String msgType;
private String content;
}
总结
其实消息回复并不是特别难的,主要是能看懂文档就很容易就实现,但是微信文档有点抽象(其实是我菜)不好看懂,所以还是需要自己多尝试一下;
文档地址:传送门