手把手教你使用java对接微信公众号-接收和回复基本信息
程序员文章站
2024-01-08 12:58:16
...
文档中(https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Overview.html)已经告诉我们,当普通微信用户向公众账号发送消息时,微信服务器会把该消息封装成XML数据包通过POST的方式发送到开发者填写的URL上。我们设置的URL仅仅只有一个,上篇文章中是用来做接入验证的,当时是微信服务器发送GET请求过来,而现在是用来做消息处理的,此时微信服务器发送的是POST请求,因此想要区分开来应该做什么事情,只需要根据请求方式来判断即可。
1、编写check-token接口的POST请求思路
两次请求的url相同,但是请求方式不同,一个是GET方式一个是POST方式。根据开发文档,接收普通的文本消息是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>
其他还有图片、语音、视频等。接下来,我们可以创建一个封装消息的实体类,把所有可接收到的参数都放进入,其他类型的暂时不演示。
2、pom引入dom4j
<!--解析微信的消息-->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.7</version>
</dependency>
3、编写TextMessage文本实体类
package com.example.mybaties.entity;
import lombok.Data;
/**
* @Description:
* @Author: lst
* @Date 2020-08-19
* 1、文本消息
* <xml>
* <ToUserName>oANl56cC7d7JP88la43243WaA</ToUserName>
* <FromUserName>gh_a1821534134</FromUserName>
* <CreateTime>1597979297984</CreateTime>
* <MsgType>text</MsgType>
* <Content>你</Content>
* </xml>
*
*/
@Data
public class TextMessage {
private String ToUserName;
private String FromUserName;
private Long CreateTime;
private String MsgType;
private String Content;
}
4、编写MessageUtil消息工具类
package com.example.mybaties.utils;
import com.example.mybaties.entity.TextMessage;
import com.thoughtworks.xstream.XStream;
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.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Description: 消息工具类
* @Author: lst
* @Date 2020-08-19
*/
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 RESP_MESSAGE_TYPE_Image = "image";
/**
* 返回消息类型:语音
*/
public static final String RESP_MESSAGE_TYPE_Voice = "voice";
/**
* 返回消息类型:视频
*/
public static final String RESP_MESSAGE_TYPE_Video = "video";
/**
* 请求消息类型:文本
*/
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_VIDEO = "video";
/**
* 请求消息类型:推送
*/
public static final String REQ_MESSAGE_TYPE_EVENT = "event";
/**
* 事件类型:subscribe(订阅)
*/
public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";
/**
* 事件类型:unsubscribe(取消订阅)
*/
public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";
/**
* 事件类型:CLICK(自定义菜单点击事件)
*/
public static final String EVENT_TYPE_CLICK = "CLICK";
/**
* 事件类型:VIEW(自定义菜单URl视图)
*/
public static final String EVENT_TYPE_VIEW = "VIEW";
/**
* 事件类型:LOCATION(上报地理位置事件)
*/
public static final String EVENT_TYPE_LOCATION = "LOCATION";
/**
* 事件类型:LOCATION(上报地理位置事件)
*/
public static final String EVENT_TYPE_SCAN = "SCAN";
/**
* @Description: 解析微信发来的请求(XML)
* @param @param request
* @param @return
* @param @throws Exception
* @author dapengniao
* @date 2016年3月7日 上午10:04:02
*/
public static Map<String, String> parseXml(HttpServletRequest request) {
// 将解析结果存储在HashMap中
Map<String, String> map = new HashMap<String, String>();
// 读取输入流
SAXReader reader = new SAXReader();
Document document = null;
InputStream inputStream = null;
try {
// 从request中取得输入流
inputStream = request.getInputStream();
document = reader.read(inputStream);
// 得到xml根元素
Element root = document.getRootElement();
// 得到根元素的所有子节点
List<Element> elementList = root.elements();
// 遍历所有子节点
elementList.stream().forEach(element -> {
map.put(element.getName(), element.getStringValue());
});
} catch (DocumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
// 释放资源
if(null != inputStream){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return map;
}
/**
* @Description: 文本消息对象转换成xml
* @param @param textMessage
* @param @return
* @author dapengniao
* @date 2016年3月8日 下午4:13:22
*/
public static String textMessageToXml(TextMessage textMessage) {
XStream xStream = new XStream();
xStream.alias("xml", textMessage.getClass());
return xStream.toXML(textMessage);
}
}
5、编写controller接口和实现类
/**
* @Description 接收消息、响应处理代码
* @author lst
* @date 2020-8-20 11:52
* @param request
* @param response
* @return java.lang.String
*/
@PostMapping(value = "/check-token", produces = "application/json; charset=utf-8")
public String messageHandle(HttpServletRequest request, HttpServletResponse response) {
return wxCheckSignatureService.messageHandle(request,response);
}
实现类
package com.example.mybaties.service.impl;
import com.example.mybaties.entity.TextMessage;
import com.example.mybaties.service.WxCheckSignatureService;
import com.example.mybaties.utils.MessageUtil;
import com.example.mybaties.utils.ShaUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.Map;
/**
* @Author: lst
* @Date 2020-08-18
*/
@Slf4j
@Service
public class WxCheckSignatureServiceImpl implements WxCheckSignatureService {
/**
* @Description 接收消息、响应处理代码
* @author lst
* @date 2020-8-20 11:52
* @param request
* @param response
* @return java.lang.String
*/
@Override
public String messageHandle(HttpServletRequest request, HttpServletResponse response) {
response.setCharacterEncoding("utf-8");
Map<String,String> resultMap = MessageUtil.parseXml(request);
log.info("读取的请求resultMap:{}",resultMap);
TextMessage textMessage = new TextMessage();
textMessage.setToUserName(resultMap.get("FromUserName"));
textMessage.setFromUserName(resultMap.get("ToUserName"));
Date date = new Date();
textMessage.setCreateTime(date.getTime());
textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);
if ("text".equals(resultMap.get("MsgType"))){
textMessage.setContent(resultMap.get("Content"));
}else {
textMessage.setContent("目前仅支持文本呦");
}
String outMesStr = MessageUtil.textMessageToXml(textMessage);
log.info("返回消息:{}",outMesStr);
return outMesStr;
}
}
测试并查看后台打印的日志,首先微信测试号发消息,后台打印后将原消息返回。
上一篇: EasyExcel之导入导出
下一篇: ThinkPHP源码分析系列―异常处理