首页 > 编程语言 >重点--自测可以----Java实现微信公众号自动回复

重点--自测可以----Java实现微信公众号自动回复

时间:2022-11-26 20:23:06浏览次数:42  
标签:return String textMessage -- 微信 param 消息 自测 Java

背景
最近准备搭建自己的博客系统,有些软件或资料的下载链接放在网盘中,为了方便下载,同时可以将用户导流到公众号上,因此准备用Java实现微信公众号自动回复的功能

准备工作
微信公众号
首先当然是需要注册一个微信公众号,具体步骤就不在这里赘述了,注册地址:微信公众平台

注册完毕后需要完成认证操作

代码
依赖引入,主要为xml相关依赖, 因为微信公众号采用的xml消息格式进行交互

<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.19</version>
</dependency>
 
自动回复内容一共需要两个接口(两个接口路由完全一致,一个为GET请求,一个为POST请求)

微信公众号认证接口
此接口用于微信公众号后台服务器认证使用,GET请求

/**
* 微信校验
*
* @param signature
* @param timestamp
* @param nonce
* @param echostr
* @param response
*/
@GetMapping("callback")
public void callback(String signature, String timestamp, String nonce, String echostr, HttpServletResponse response) {
PrintWriter out = null;
log.info("微信校验消息,signature:{},timestamp:{},nonce:{},echostr:{}", signature, timestamp, nonce, echostr);
List<WechatConfigPO> configPOList = wechatConfigDao.selectAll();
try {
out = response.getWriter();
out.write(echostr);
} catch (Throwable e) {
log.error("微信校验失败", e);
} finally {
if (out != null) {
out.close();
}
}
}
 
消息接收接口
此接口用于接收公众号消息回调,POST请求

/**
* 微信消息回调
*
* @param request
* @param response
*/
@PostMapping("callback")
public void callback(HttpServletRequest request, HttpServletResponse response) {
PrintWriter out = null;

try {
String respMessage = wechatService.callback(request);
if (StringUtils.isBlank(respMessage)) {
log.info("不回复消息");
return;
}
response.setCharacterEncoding("UTF-8");
out = response.getWriter();
out.write(respMessage);
} catch (Throwable e) {
log.error("微信发送消息失败", e);
} finally {
if (out != null) {
out.close();
}
}
}
 
消息回复service

/**
* @author C.W
* @date 2022/5/18 7:32
* @desc 微信
*/
@Slf4j
@Service
public class WechatService {

@Autowired
private TextReplyService textReplyService;

/**
* 微信回复
*
* @param request
* @return
* @throws UnsupportedEncodingException
*/
public String callback(HttpServletRequest request) throws UnsupportedEncodingException {
request.setCharacterEncoding("UTF-8");

try {
Map<String, String> requestMap = WechatMessageUtils.parseXml(request);
log.info("微信接收到消息:{}", GsonUtils.toJson(requestMap));
// 消息类型
String msgType = requestMap.get("MsgType");

// 处理其他消息,暂时不做回复
switch (msgType) {
case WechatMsgTypeConstant.MESSAGE_TYPE_TEXT:
// 文本消息处理
return textReplyService.reply(requestMap);
default:
return textReplyService.reply(requestMap);
}
} catch (Throwable e) {
log.error("回复消息错误", e);
}
// 不做回复
return null;
}

}
 
文本回复service

/**
* @author C.W
* @date 2022/5/18 9:57
* @desc 文本回复
*/
@Service
public class TextReplyService {

private static final String FROM_USER_NAME = "FromUserName";
private static final String TO_USER_NAME = "ToUserName";
private static final String CONTENT = "Content";

@Autowired
private WechatKeywordDao wechatKeywordDao;

@Autowired
private WechatMsgRecordDao wechatMsgRecordDao;

/**
* 自动回复文本内容
*
* @param requestMap
* @return
*/
public String reply(Map<String, String> requestMap) {
String wechatId = requestMap.get(FROM_USER_NAME);
String gongzhonghaoId = requestMap.get(TO_USER_NAME);

TextMessage textMessage = WechatMessageUtils.getDefaultTextMessage(wechatId, gongzhonghaoId);

String content = requestMap.get(CONTENT);
if (content == null) {
textMessage.setContent(WechatConstants.DEFAULT_MSG);
} else {
Example example = new Example(WechatKeywordPO.class);
example.createCriteria().andEqualTo("wechatId", gongzhonghaoId).andEqualTo("keyword", content);
List<WechatKeywordPO> keywordPOList = wechatKeywordDao.selectByExample(example);
if (CollectionUtils.isEmpty(keywordPOList)) {
textMessage.setContent(WechatConstants.DEFAULT_MSG);
} else {
textMessage.setContent(keywordPOList.get(0).getReplyContent());
}
}
// 记录消息记录
wechatMsgRecordDao.insertSelective(WechatMsgRecordPO.builder()
.fromUser(wechatId)
.wechatId(gongzhonghaoId)
.content(content)
.replyContent(textMessage.getContent())
.build()
);

return WechatMessageUtils.textMessageToXml(textMessage);
}

}
 
文本消息model

/**
* @author C.W
* @date 2021/11/26 22:21
* @description 文本消息
*/
@Data
public class TextMessage extends BaseMessage {

/**
* 回复的消息内容
*/
private String Content;

}
 
基础消息model

/**
* @author C.W
* @date 2021/11/26 22:20
* @description 基础消息响应
*/
@Data
public class BaseMessage {

/**
* 接收方帐号(收到的OpenID)
*/
private String ToUserName;
/**
* 开发者微信号
*/
private String FromUserName;
/**
* 消息创建时间 (整型)
*/
private long CreateTime;

/**
* 消息类型
*/
private String MsgType;

/**
* 位0x0001被标志时,星标刚收到的消息
*/
private int FuncFlag;

}
 
消息工具

/**
* @author C.W
* @date 2022/5/18 7:55
* @desc 微信消息
*/
public class WechatMessageUtils {

/**
* 解析微信发来的请求(XML)
*
* @param request
* @return
* @throws Exception
*/
public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {
// 将解析结果存储在HashMap中
Map<String, String> map = new HashMap<>();

// 从request中取得输入流
InputStream inputStream = request.getInputStream();
try {
// 读取输入流
SAXReader reader = new SAXReader();
Document document = reader.read(inputStream);
// 得到xml根元素
Element root = document.getRootElement();
// 得到根元素的所有子节点

List<Element> elementList = root.elements();

// 遍历所有子节点
for (Element e : elementList) {
map.put(e.getName(), e.getText());
}
} finally {
// 释放资源
if (inputStream != null) {
inputStream.close();
}
}

return map;
}

/**
* 文本消息对象转换成xml
*
* @param textMessage 文本消息对象
* @return xml
*/
public static String textMessageToXml(TextMessage textMessage) {
XSTREAM.alias("xml", textMessage.getClass());
return XSTREAM.toXML(textMessage);
}

/**
* 音乐消息对象转换成xml
*
* @param musicMessage 音乐消息对象
* @return xml
*/
public static String musicMessageToXml(MusicMessage musicMessage) {
XSTREAM.alias("xml", musicMessage.getClass());
return XSTREAM.toXML(musicMessage);
}

/**
* 图文消息对象转换成xml
*
* @param newsMessage 图文消息对象
* @return xml
*/
public static String newsMessageToXml(NewsMessage newsMessage) {
XSTREAM.alias("xml", newsMessage.getClass());
XSTREAM.alias("item", Article.class);
return XSTREAM.toXML(newsMessage);
}

/**
* 扩展xstream,使其支持CDATA块
*/
private static final XStream XSTREAM = new XStream(new XppDriver() {
@Override
public HierarchicalStreamWriter createWriter(Writer out) {
return new PrettyPrintWriter(out) {
// 对所有xml节点的转换都增加CDATA标记
final boolean cdata = true;

@Override
protected void writeText(QuickWriter writer, String text) {
if (cdata) {
writer.write("<![CDATA[");
writer.write(text);
writer.write("]]>");
} else {
writer.write(text);
}
}
};
}
});

/**
* 获取默认文本消息
*
* @param receiver 接收人
* @param officialWxid 官方微信id
* @return 文本消息
*/
public static TextMessage getDefaultTextMessage(String receiver, String officialWxid) {
TextMessage textMessage = new TextMessage();
textMessage.setToUserName(receiver);
textMessage.setFromUserName(officialWxid);
textMessage.setCreateTime(System.currentTimeMillis());
textMessage.setMsgType(WechatMsgTypeConstant.MESSAGE_TYPE_TEXT);
textMessage.setFuncFlag(0);

return textMessage;
}

}
 
消息类型枚举

/**
* @author C.W
* @date 2022/5/18 8:00
* @desc 微信消息类型
*/
public class WechatMsgTypeConstant {

/**
* 文本消息
*/
public static final String MESSAGE_TYPE_TEXT = "text";

}
 
其他内容为一些数据库相关操作,此处不再列出,仅为:查询关键词及其回复内容,存储消息记录

公众号配置
服务器配置
公众号后台 -> 设置与开发 -> 基本配置 -> 服务器配置


————————————————
版权声明:本文为CSDN博主「腿短,快跑」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_35092597/article/details/125177037

标签:return,String,textMessage,--,微信,param,消息,自测,Java
From: https://www.cnblogs.com/javalinux/p/16928200.html

相关文章

  • Android 将函数放到主线程运行
    有时候,app会检测加密函数是否在主线程运行,为了逃避这种检测,要将函数放到主线程运行Class<?>aClass=RposedHelpers.findClass("com.yuanrenxue.challenge.three.Challen......
  • Vulnhub之KiraCTF靶机解题过程
    KiraCTF作者:jason_huawen靶机基本信息名称:Kira:CTF地址:https://www.vulnhub.com/entry/kira-ctf,594/识别目标主机IP地址──(kali㉿kali)-[~/Vulnhub/KiraCTF]......
  • 3,4,10编译程序的组成部分
       ......
  • rinetd tcp/udp 端口重定向服务
    rinetd支持tcp以及udp协议的端口重定向,功能还是比较有用的,比如进行一些流量转发,配置上也是比较方便的,同时支持一些简单的访问控制处理构建 gitcloneht......
  • 第十章代码优化
    一、基本块和流图基本块;  基本块的一些特点:①   流图: 二、常见代码优化方法(1)删除公共子表达式(2)删除无用代码三、基本块优化基本块的DAG表示 ......
  • 初识春秋云镜靶场
    春秋云镜靶场2022.11.26这个靶场里面有很多CVE的漏洞,有免费的也有收费的(价格有点小贵),十分推荐大家去打一打这个靶场,去巩固自己的知识这篇文章的话是我个人的思路笔记,所......
  • 表单
    <!DOCTYPEhtml><html><head><metacharset="utf-8"><title></title></head><body><!--<form></form>表单标签-->......
  • iptables防火墙
    iptables命令-F清除链中所有规则-P为链设置一条默认策略或者目标-A为链增加一条规则说明-D从链中删除一条规则-L查看当前表中的链和规则一般上述命令均已sudo......
  • Node工程使用云服务器中的redis镜像做数据库
     Redis镜像安装在云服务器中执行指令dockerpullredis添加redis镜像实例的配置[root@VM-0-11-centos~]#cd/home[root@VM-0-11-centoshome]#lsmongote......
  • 模板方法模式(Template)
    做一件事情,流程是固定的,其中存在不确定的同一类事务。例如:去店里吃饭:1、进入店铺。2、点单。3、吃饭。不确定的是第二步:点单。实现:在父类中定义好统一的......