接收微信消息
开发公众号所需的依赖项
<!--weixin-java-common-->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-common</artifactId>
<version>4.3.0</version>
</dependency>
<!--weixin-java-admin-->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>4.3.0</version>
</dependency>
<!--weixin-java-miniapp-->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-miniapp</artifactId>
<version>4.3.0</version>
</dependency>
<!--weixin-java-pay-->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java-mp-spring-boot-starter</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.22</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-xml-provider</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--httpUtil-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.10</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
</dependency>
<!--解析微信的消息-->
<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.4</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.4</version>
</dependency>
<!-- beat64 -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.9</version>
</dependency>
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1.6</version>
</dependency>
当普通微信用户向公众账号发消息时,微信服务器将 POST 消息的 XML 数据包到开发者填写的 URL 上。
@RequestMapping(value = "/wxConnect", method = RequestMethod.POST)
public void sos(HttpServletRequest request,HttpServletResponse response) throws IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
//回复消息
messageService.messageResponse(request, response);
}
/*
* 响应post请求,微信中消息和菜单交互都是采用post请求
*/
public String newMessageRequest(HttpServletRequest request, HttpServletResponse response) {
String respMessage = null;
try {
// xml请求解析
Map<String, String> requestMap = MessageUtil.xmlToMap(request);
if (requestMap.size() > 0) {
// 发送方帐号(open_id)
String fromUserName = requestMap.get("FromUserName");
// 公众帐号
String toUserName = requestMap.get("ToUserName");
// 消息类型
String msgType = requestMap.get("MsgType");
// 消息内容
String content = requestMap.get("Content");
log.info("FromUserName is:" + fromUserName + ", ToUserName is:" + toUserName + ", MsgType is:" + msgType);
if (MessageUtil.MESSAGE_TEXT.equals(msgType)) {
//这里根据关键字执行相应的逻辑
WxAutoReply wxAutoReply = new WxAutoReply();
wxAutoReply.setType("3");
wxAutoReply.setReqKey(content);
WxAutoReply detail = wxAutoReplyService.selectByType(wxAutoReply);
if (detail != null) {
if ("image".equals(detail.getRepType())) {
ImageMessage imageMessage = imageRep(detail.getRepMediaId(), fromUserName, toUserName);
respMessage = MessageUtil.textImgToXml(imageMessage);
return respMessage;
} else if ("text".equals(detail.getRepType())) {
//文本消息
TextMessage textMessage = textRep(fromUserName, toUserName, detail.getRepContent().replaceAll(">", ">"));
respMessage = MessageUtil.textMessageToXml(textMessage);
}
} else {
respMessage = passiveReply(msgType, fromUserName, toUserName);
}
}
//回复图片消息
else if (MessageUtil.MESSAGE_IMAGE.equals(msgType)) {
respMessage = passiveReply(msgType, fromUserName, toUserName);
}
// 事件推送
else if (MessageUtil.MESSAGE_EVENT.equals(msgType)) {
String eventType = requestMap.get("Event");// 事件类型
String eventKey = requestMap.get("EventKey");
if (MessageUtil.EVENT_CLICK.equals(eventType)) {
//匹配数据库对应appid下的菜单栏EventKey值
WxMenu wxMenu = wxMenuService.selectByQuery(eventType, eventKey);
if (wxMenu != null) {
//文本消息
if ("text".equals(wxMenu.getRepType())) {
TextMessage textMessage = textRep(fromUserName, toUserName, wxMenu.getRepContent().replaceAll(">", ">"));
respMessage = MessageUtil.textMessageToXml(textMessage);
} else if ("image".equals(wxMenu.getRepType())) {
ImageMessage imageMessage = imageRep(wxMenu.getRepMediaId(), fromUserName, toUserName);
respMessage = MessageUtil.textImgToXml(imageMessage);
}
} else {
return null;
}
}
// 订阅
if (eventType.equals(MessageUtil.EVENT_SUB)) {
WxAutoReply wxAutoReply = new WxAutoReply();
wxAutoReply.setType("1");
WxAutoReply detail = wxAutoReplyService.selectAuto(wxAutoReply);
if ("text".equals(detail.getRepType())) {
//文本消息
TextMessage textMessage = textRep(fromUserName, toUserName, detail.getRepContent().replaceAll(">", ">"));
respMessage = MessageUtil.textMessageToXml(textMessage);
} else if ("image".equals(detail.getRepType())) {
ImageMessage imageMessage = imageRep(detail.getRepMediaId(), fromUserName, toUserName);
respMessage = MessageUtil.textImgToXml(imageMessage);
}
}
// 取消订阅后用户再收不到公众号发送的消息,因此不需要回复消息
else if (MessageUtil.EVENT_UNSUB.equals(msgType)) {// 取消订阅
}
}
}
} catch (Exception e) {
log.info("error......" + e);
}
return respMessage;
}
向微信发送消息
public void messageResponse(HttpServletRequest request, HttpServletResponse response) {
try {
String result = this.newMessageRequest(request, response);
log.info("返回消息:{}", result);
//通过文字输出流返还
PrintWriter out = response.getWriter();
out.print(result);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
消息处理类MessageUtil:
/*
* 消息处理工具类
*/
public class MessageUtil {
public static final String MESSAGE_TEXT = "text";
public static final String MESSAGE_IMAGE = "image";
public static final String MESSAGE_VOICE = "voice";
public static final String MESSAGE_VIDEO = "video";
public static final String MESSAGE_LINK = "link";
public static final String MESSAGE_LOCATION = "location";
public static final String MESSAGE_EVENT = "event";
public static final String EVENT_SUB = "subscribe";
public static final String EVENT_UNSUB = "unsubscribe";
public static final String EVENT_CLICK = "CLICK";
public static final String EVENT_VIEW = "VIEW";
public static byte[] readInputStream(InputStream inputStream) throws IOException {
byte[] buffer = new byte[1024];
int len = 0;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while((len = inputStream.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
bos.close();
return bos.toByteArray();
}
/**
* xml转为map
* @param request
* @return
* @throws DocumentException
* @throws IOException
*/
public static Map<String, String> xmlToMap(HttpServletRequest request ) throws DocumentException, IOException
{
Map<String,String> map = new HashMap<String, String>();
SAXReader reader = new SAXReader();
System.out.println(request.getInputStream());
InputStream in ;
in = request.getInputStream();
BOMInputStream bomInputStream = new BOMInputStream(request.getInputStream(),"UTF-8");
//转成xml
Document doc = reader.read(request.getInputStream());
Element root = doc.getRootElement();
List<Element> list = root.elements();
for (Element e : list) {
map.put(e.getName(), e.getText());
}
bomInputStream.close();
return map;
}
/**
* 解析reqString中xml格式消息
* @param reqString HttpServletRequest
* @return Map<节点>
*/
public static Map<String,String> string2Map(String reqString) {
try {
String xml = reqString;
Map<String,String> maps = new HashMap<>();
Document document = DocumentHelper.parseText(xml);
System.out.println(document.asXML());
Element root = document.getRootElement();
List<Element> eles = root.elements();
for (Element e:eles){
maps.put(e.getName(),e.getTextTrim());
}
return maps;
}catch (DocumentException e){
e.printStackTrace();
}
return null;
}
public static String textMessageToXml(TextMessage textMessage){
XStream xstream = new XStream();
xstream.alias("xml", textMessage.getClass());
return xstream.toXML(textMessage);
}
public static String textImgToXml(ImageMessage imageMessage){
XStream xstream = new XStream();
xstream.alias("xml", imageMessage.getClass());
return xstream.toXML(imageMessage);
}
public static String initText(String toUserName, String fromUserName, String content){
TextMessage text = new TextMessage();
text.setFromUserName(toUserName);
text.setToUserName(fromUserName);
text.setMsgType(MESSAGE_TEXT);
text.setCreateTime(new Date().getTime());
text.setContent(content);
return textMessageToXml(text);
}
public static String initImgMessage(String toUserName, String fromUserName,String mediaId){
String message = null;
Image image = new Image();
image.setMediaId(mediaId);
ImageMessage imageMessage = new ImageMessage();
imageMessage.setFromUserName(toUserName);
imageMessage.setToUserName(fromUserName);
imageMessage.setMsgType(MESSAGE_IMAGE);
imageMessage.setCreateTime(new Date().getTime());
imageMessage.setImage(image);
message = textImgToXml(imageMessage);
return message;
}
}
消息实体父类
@Data
public class BaseMessage {
// 开发者微信号
private String ToUserName;
// 发送方帐号(一个OpenID)
private String FromUserName;
// 消息创建时间 (整型)
private long CreateTime;
// 消息类型(text/image/location/link)
private String MsgType;
}
文本消息实体类
@Data
public class TextMessage extends BaseMessage{
@ApiModelProperty(value = "消息类型", hidden = true)
private String MsgType = "text";
// 消息内容
private String Content;
}
图片消息实体类
@Data
public class ImageMessage extends BaseMessage {
private Image Image;
}
public class Image {
//图片mediaId
private String MediaId;
}
数据库消息表
@Data
@TableName("wx_auto_reply")
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "WxAutoReply对象", description = "")
public class WxAutoReply extends Model<WxAutoReply> {
private static final long serialVersionUID = 1L;
@TableId(type = IdType.ASSIGN_ID)
@ApiModelProperty(value = "主键")
private String id;
@ApiModelProperty(value = "创建者")
private String createId;
@ApiModelProperty(value = "创建时间")
private LocalDateTime createTime;
@ApiModelProperty(value = "更新者")
private String updateId;
@ApiModelProperty(value = "更新时间")
private LocalDateTime updateTime;
@ApiModelProperty(value = "备注")
private String remark;
@TableLogic
@ApiModelProperty(value = "逻辑删除标记(0:显示;1:隐藏")
private String delFlag;
@NotNull(message = "类型不能为空")
@ApiModelProperty(value = "类型(1、关注时回复;2、消息回复;3、关键词回复)")
private String type;
@ApiModelProperty(value = "关键词")
private String reqKey;
@ApiModelProperty(value = "请求消息类型(text:文本;image:图片;voice:语音;video:视频;shortvideo:小视频;location:地理位置)")
private String reqType;
@NotNull(message = "回复消息类型不能为空")
@ApiModelProperty(value = "回复消息类型(text:文本;image:图片;voice:语音;video:视频;music:音乐;news:图文; miniprogrampage 小卡片)")
private String repType;
@ApiModelProperty(value = "回复类型文本匹配类型(1、全匹配,2、半匹配")
private String repMate;
@ApiModelProperty(value = "回复类型文本保存文字")
private String repContent;
@ApiModelProperty(value = "回复的素材名、视频和音乐的标题")
private String repName;
@ApiModelProperty(value = "回复类型imge、voice、news、video的mediaID或音乐缩略图的媒体id")
private String repMediaId;
@ApiModelProperty(value = "视频和音乐的描述")
private String repDesc;
@ApiModelProperty(value = "链接")
private String repUrl;
@ApiModelProperty(value = "高质量链接")
private String repHqUrl;
@ApiModelProperty(value = "缩略图的媒体id")
private String repThumbMediaId;
@ApiModelProperty(value = "缩略图url")
private String repThumbUrl;
@TableField(typeHandler = JsonTypeHandler.class, jdbcType= JdbcType.VARCHAR)
@ApiModelProperty(value = "图文消息的内容")
private JSONObject content;
@ApiModelProperty(value = "公众号appId")
private String appId;
@ApiModelProperty(value = "小卡片标题")
private String miniProgramTitle;
}