Java实现微信公众号自动回复
生活随笔
收集整理的這篇文章主要介紹了
Java实现微信公众号自动回复
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
本文最先發表于我的個人博客,CSDN為同步發布,如有需要,請訪問 腿短快跑的個人博客 獲取更多內容
背景
最近準備搭建自己的博客系統,有些軟件或資料的下載鏈接放在網盤中,為了方便下載,同時可以將用戶導流到公眾號上,因此準備用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 {@Autowiredprivate 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";@Autowiredprivate WechatKeywordDao wechatKeywordDao;@Autowiredprivate 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() {@Overridepublic HierarchicalStreamWriter createWriter(Writer out) {return new PrettyPrintWriter(out) {// 對所有xml節點的轉換都增加CDATA標記final boolean cdata = true;@Overrideprotected 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";}其他內容為一些數據庫相關操作,此處不再列出,僅為:查詢關鍵詞及其回復內容,存儲消息記錄
公眾號配置
- 服務器配置
公眾號后臺 -> 設置與開發 -> 基本配置 -> 服務器配置
- 填寫服務器地址
填寫你的服務器回調接口地址(需要為公網地址,否則微信無法調通)
- 生成你的令牌Token
Token 需要記住,一般在微信驗證接口處會校驗相關信息是否是自己的公眾號
驗證方法
/*** @author C.W* @date 2021/11/26 21:59* @description 微信工具*/ @Slf4j public class WechatUtils {private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5','6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};public static boolean checkSignature(String signature, String timestamp, String nonce, String token) {String[] str = new String[]{token, timestamp, nonce};//排序Arrays.sort(str);//拼接字符串StringBuffer buffer = new StringBuffer();for (int i = 0; i < str.length; i++) {buffer.append(str[i]);}//進String temp = encode(buffer.toString());//與微信提供的signature進行匹對return signature.equals(temp);}private static String getFormattedText(byte[] bytes) {int len = bytes.length;StringBuilder buf = new StringBuilder(len * 2);for (int j = 0; j < len; j++) {buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);buf.append(HEX_DIGITS[bytes[j] & 0x0f]);}return buf.toString();}public static String encode(String str) {if (str == null) {return null;}try {MessageDigest messageDigest = MessageDigest.getInstance("SHA1");messageDigest.update(str.getBytes());return getFormattedText(messageDigest.digest());} catch (Exception e) {throw new RuntimeException(e);}}}- 驗證公眾號自動回復是否正確
可以關注公眾號 抓娃程序員,發送關鍵詞:回復 體驗效果
總結
以上是生活随笔為你收集整理的Java实现微信公众号自动回复的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [译]JavaScript:ES6中的模
- 下一篇: 部署及配置Lync Server 201