微信公众号后台服务开发
简述
使用Java SpringBoot框架搭建微信工作号后台实现自定义逻辑自动回复
先注册公众号,公众号的类型有:订阅号,服务号,订阅号的消息会收在订阅号消息中,服务号推送的消息是在用户的消息列表中,但服务号的注册需要企业资质。
这里我注册了服务号
微信平台提供的自动回复机制
在公众号平台上提供了三种自动回复的机制:关键词回复,收到消息回复,被关注回复,公众号平台的自动回复与开发者的后台只能二选一
后台服务开发
微信可将公众号接收到的用户信息转发到指定服务器上,由服务器的返回信息作出响应
接入开发官方文档
我们使用内网穿透做开发测试,介绍一款工具natapp内网穿透
配置指定服务器
首先需要在公众平台上配置服务器URL
微信会向你填写的URL发送Get请求来校验token是否验证成功,以此让你的后端确认消息的确来自微信服务器
流程为:
- 1.开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上,GET请求包含以下参数:
- 2.将token、timestamp、nonce三个参数进行字典序排序
- 3.将三个参数字符串拼接成一个字符串进行sha1加密
- 4.开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
后端代码:
/**
* 验证消息来自微信
* @param request
* @param response
* @return
* @throws BusinessException
*/
@GetMapping("/user/message")
public String replyWxServe(ServletRequest request, ServletResponse response) throws BusinessException {
// 获取数据
String signature = request.getParameter("signature");
String timestamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
String echostr = request.getParameter("echostr");
if (!validateNull(signature, timestamp, nonce, echostr)) {
// 为空不是微信后台
throw new BusinessException(EmBusinessError.SERVICE_AUTHENTICATION_INVALID);
}
List<String> list = new ArrayList<>();
// 配置上所填写的token
list.add(token);
list.add(timestamp);
list.add(nonce);
// 字典序排序
Collections.sort(list);
// 拼接
StringBuilder sb = new StringBuilder();
list.forEach(sb::append);
// sha1加密
String hashCode = DigestUtils.sha1DigestAsHex(sb.toString());
logger.info("hashCode:"+hashCode);
logger.info("signature:"+signature);
// 比对
if (StringUtils.equals(hashCode,signature)){
return echostr;
}else {
return "";
}
}
提交token验证成功后便可绑定服务器
消息自动回复功能开发
官方文档
针对同一个接口的Post处理
微信发送的消息格式:
我们使用XStream做xml解析
首先定义实体类:
/**
* @Description: 微信用户消息实体类
* @Author: lmwis
* @Date 2020-11-28 18:04
* @Version 1.0
*/
@Data
@XStreamAlias("xml")
public class WxUserMessageModel {
@XStreamAlias("ToUserName")
private String toUserName;
@XStreamAlias("FromUserName")
private String fromUserName;
@XStreamAlias("CreateTime")
private Long createTime;
@XStreamAlias("MsgType")
private String msgType;
@XStreamAlias("Content")
private String content;
@XStreamAlias("MsgId")
private String msgId;
@XStreamAlias("Title")
private String title;
@XStreamAlias("Description")
private String description;
@XStreamAlias("Url")
private String url;
/**
* 订阅或者取消订阅的事件
*/
@XStreamAlias("Event")
private String event;
@XStreamAlias("EventKey")
private String eventkey;
}
从request中获取输入流封装为用户信息
/**
* 解析xml数据
*
* @param in 输入流
* @return 微信用户信息实体类
* @throws IOException
*/
private WxUserMessageModel resolveXmlData(InputStream in) throws IOException {
String xmlData = IOUtils.toString(in);
WxUserMessageModel wxXmlData = null;
XStream xstream = new XStream();
// 设置加载类的类加载器
xstream.setClassLoader(WxUserMessageModel.class.getClassLoader());
xstream.processAnnotations(WxUserMessageModel.class);
xstream.alias("xml", WxUserMessageModel.class);
wxXmlData = (WxUserMessageModel) xstream.fromXML(xmlData);
return wxXmlData;
}
controller
/**
* 接受用户信息并作出自动回复
* @param request
* @param response
* @return
* @throws BusinessException
* @throws IOException
*/
@PostMapping("/user/message")
public String replyUserMessage(ServletRequest request, ServletResponse response) throws BusinessException, IOException {
// 数据提取
WxUserMessageModel wxUserMessageModel = resolveXmlData(request.getInputStream());
if (!validateNull(wxUserMessageModel)) {
// 不回消息也需要返回"success"
return "success";
}
// 返回数据
WxUserMessageModel responseXmlData = new WxUserMessageModel();
responseXmlData.setToUserName(wxUserMessageModel.getFromUserName());
responseXmlData.setFromUserName(wxUserMessageModel.getToUserName());
responseXmlData.setCreateTime(new Date().getTime());
responseXmlData.setMsgType("text");
// 按需编写业务
if (StringUtils.equals(wxUserMessageModel.getContent(), "xxx")) {
responseXmlData.setContent(yibanCheckUrl);
} else if (StringUtils.equals(wxUserMessageModel.getContent(), "xx")) {
responseXmlData.setContent(checkCheckState(wxUserMessageModel.getFromUserName()));
} else {
responseXmlData.setContent(wxUserMessageModel.getContent());
}
XStream xstream = new XStream();
xstream.processAnnotations(WxUserMessageModel.class);
xstream.setClassLoader(WxUserMessageModel.class.getClassLoader());
return xstream.toXML(responseXmlData); //XStream的方法,直接将对象转换成 xml数据
}
然后就实现了基本的文字消息自动回复,其他类型消息的按照官方文档开发就大同小异了