springboot公众号模板消息推送

2024-08-26 23:28

本文主要是介绍springboot公众号模板消息推送,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 参考
    • 1、微信公众平台测试号管理
      • 1.1 访问微信公众平台测试账号页面
      • 1.2 获取appID和appsecret
      • 1.3 扫码二维码添加测试号
      • 1.4 添加模版消息
    • 2、集成微信SDK
      • 2.1 引入微信工具包
      • 2.2 添加配置文件
    • 3、API调用
      • 3.1 发送消息模版的实现
      • 3.2 测试类调用
      • 3.3 效果展示
    • 4、回调
      • 配置回调URL和token
      • 处理用户消息和事件
    • 5、获取AccessToken

参考

微信开发包 Binary Wang/WxJava

SpringBoot助力!轻松实现微信模版消息推送

微信开发专栏 - 跟着这个搞一下,里面的代码不错 - 对应的代码

SpringBoot整合调用微信模板方法实现微信公众号消息通知推送,Java实现微信公众号给关注用户推送自定义消息通知(手把手从0到1)

微信小程序 专栏

对接第三方接口/微信/阿里云/通联/创蓝等

【微信开发第三章】SpringBoot实现微信授权登录

基于SpringBoot实现微信消息推送

本篇文章的主题是 如何通过springboot来实现微信的模版消息推送

实现效果: 在这里插入图片描述

在当今的信息化时代,微信作为国人最为常用的通讯工具之一,已经不仅仅是一个简单的社交应用,更是连接人与服务、人与信息的桥梁。企业微信模板消息作为一种高效、便捷的信息传递方式,被广泛应用于各类业务场景中,如订单通知、会议提醒、活动推送等。

通过本教程的学习,您将掌握如何在Spring Boot项目中集成微信SDK,如何编写代码发送微信模板消息,并了解整个推送的过程。

简要说明: 由于发送模版消息需要微信的服务号,申请服务号的话需要营业执照,个人是没有办法申请的,但是微信为了给开发者们提供测试特意开放了公众平台测试账号号,大家可以申请测试号来进行模版推送的开发和测试

开发步骤:

  1. 访问微信公众平台测试账号页面
  2. 获取appID和appsecret
  3. 扫码二维码添加测试号
  4. 添加模版消息
  5. 集成微信SDK
  6. 调用相关API

1、微信公众平台测试号管理

1.1 访问微信公众平台测试账号页面

大家首先访问微信公众平台地址:https://mp.weixin.qq.com/ 如果还没有注册账号的可以申请一个个人订阅号,这个教程大家网上自行查阅,很简单~

登录成功之后选择 开发者工具 --> 公众平台测试账号

在这里插入图片描述

测试号管理页面如下: 在这里插入图片描述

1.2 获取appID和appsecret

获取你的测试号信息 在这里插入图片描述

1.3 扫码二维码添加测试号

使用你的微信扫描这个测试公众号的二维码并关注 然后会得到你的**微信号(openId)**这个后面会用到 在这里插入图片描述

1.4 添加模版消息

点击新增测试模版
在这里插入图片描述

添加模板信息 一定要按照注意事项填写 参数需以{

{开头,以.DATA}}结尾 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/4e13f07460ad4d9e8901a76b9eec3471.png)

我这边创建了两个模版,这个模版id后面也会用到 在这里插入图片描述

2、集成微信SDK

2.1 引入微信工具包

<dependency><groupId>com.github.binarywang</groupId><artifactId>weixin-java-mp</artifactId><version>3.0.0</version></dependency>

2.2 添加配置文件

appId、appSecret和orderTemplateId就是上面微信公众平台测试号管理中我们获取到的几个参数,现在把这三个参数配置到我们的项目中。 callBackUrl暂时先不用管 在这里插入图片描述

创建配置类

@ConfigurationProperties(prefix = "wechat.public")
@Component
@Data
@RefreshScope
public class WeChatProperties {private String appId;private String appSecret;private String callBackUrl;private String orderTemplateId;
}

3、API调用

3.1 发送消息模版的实现

package com.mdx.user.manager;import com.mdx.user.config.WeChatProperties;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;/*** @author : jiagang* @date : Created in 2022/7/26 10:42*/
@Component
@Slf4j
public class WxMessagesManager {@Autowiredprivate WeChatProperties weChatProperties;public void sendOrderMsg(String openId, String orderId, String serviceName){String templateId = weChatProperties.getOrderTemplateId();// 订单时间SimpleDateFormat sdf = new SimpleDateFormat();sdf.applyPattern("yyyy-MM-dd HH:mm");Date date = new Date();String timeNow = sdf.format(date);WxMpInMemoryConfigStorage wxStorage = new WxMpInMemoryConfigStorage();wxStorage.setAppId(weChatProperties.getAppId());wxStorage.setSecret(weChatProperties.getAppSecret());WxMpService wxMpService = new WxMpServiceImpl();wxMpService.setWxMpConfigStorage(wxStorage);// 此处的 key/value 需和模板消息对应List<WxMpTemplateData> wxMpTemplateDataList = Arrays.asList(new WxMpTemplateData("first", "您有一个新的订货单", "#FF0000"),new WxMpTemplateData("keyword1", orderId),new WxMpTemplateData("keyword2", serviceName),new WxMpTemplateData("keyword3", timeNow),new WxMpTemplateData("remark", "请登录系统查看订单详情并及时配货"));WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder().toUser(openId) // openId为1.3步骤中得到的微信号.templateId(templateId).data(wxMpTemplateDataList).url("https://blog.csdn.net/qq_38374397?type=blog")  // 跳转详情地址.build();try {wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);log.info("消息模版发送成功~");} catch (Exception e) {log.error("推送失败:" + e.getMessage());}}
}

3.2 测试类调用

openId为1.3步骤中得到的微信号,其余参数可自定义 在这里插入图片描述
在这里插入图片描述

3.3 效果展示

移动端: 在这里插入图片描述
点击详情:

在这里插入图片描述

PC端: 在这里插入图片描述

4、回调

在这里插入图片描述

配置回调URL和token

启动natapp,开启内网穿透
在这里插入图片描述

@GetMapping("/master")
@ResponseBodypublic String init(@RequestParam("signature") String signature,@RequestParam("timestamp") String timestamp,@RequestParam("nonce") String nonce,@RequestParam("echostr") String echostr) {log.info("/myWeXin/master: 收到请求");if (CheckUtil.checkSignature("myToken", signature, timestamp, nonce)) {return echostr; // 将这个返回就代表配置成功}return null;}
public class CheckUtil {/*** 验证微信get请求* @param token* @param signature* @param timestamp* @param nonce* @return*/public static boolean checkSignature(String token,String signature,String timestamp,String nonce){String[] arr = new String[]{token,timestamp,nonce};Arrays.sort(arr);StringBuffer content = new StringBuffer();for(int i = 0 ; i < arr.length ; i++){content.append(arr[i]);}String temp = Sha1Util.getSha1(content.toString());return temp.equals(signature);}
}
import java.security.MessageDigest;public class Sha1Util {public static String getSha1(String str){if(str==null||str.length()==0){return null;}char hexDigits[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};try {MessageDigest mdTemp = MessageDigest.getInstance("SHA1");mdTemp.update(str.getBytes("UTF-8"));byte[] md = mdTemp.digest();int j = md.length;char buf[] = new char[j*2];int k = 0;for (int i = 0; i < j; i++) {byte byte0 = md[i];buf[k++] = hexDigits[byte0 >>> 4 & 0xf];buf[k++] = hexDigits[byte0 & 0xf];}return new String(buf);} catch (Exception e) {// TODO: handle exceptionreturn null;}}
}

填写回调URL和Token,点击提交,我们本地的服务器将收到1个GET请求,然后显示配置成功
在这里插入图片描述在这里插入图片描述

处理用户消息和事件

上面使用的是GET请求,这里使用的是POST请求。
当用户发生的是消息时,

/master 收到消息: <xml><ToUserName><![CDATA[gh_e86239ea7bd5]]></ToUserName>
<FromUserName><![CDATA[oSbIc6sxvTBJh-QEgMIGv3K9SosE]]></FromUserName>
<CreateTime>1724679387</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[测试消息]]></Content>
<MsgId>24691472136157010</MsgId>
</xml>
收到用户消息:{Content=测试消息, CreateTime=1724679387, ToUserName=gh_e86239ea7bd5, FromUserName=oSbIc6sxvTBJh-QEgMIGv3K9SosE, MsgType=text, MsgId=24691472136157010}

当用取消关注时,

/master 收到消息: <xml><ToUserName><![CDATA[gh_e86239ea7bd5]]></ToUserName>
<FromUserName><![CDATA[oSbIc6sxvTBJh-QEgMIGv3K9SosE]]></FromUserName>
<CreateTime>1724679471</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[unsubscribe]]></Event>
<EventKey><![CDATA[]]></EventKey>
</xml>
收到用户消息:{CreateTime=1724679471, EventKey=, Event=unsubscribe, ToUserName=gh_e86239ea7bd5, FromUserName=oSbIc6sxvTBJh-QEgMIGv3K9SosE, MsgType=event}

当用户再次关注时,

/master 收到消息: <xml><ToUserName><![CDATA[gh_e86239ea7bd5]]></ToUserName>
<FromUserName><![CDATA[oSbIc6sxvTBJh-QEgMIGv3K9SosE]]></FromUserName>
<CreateTime>1724679529</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[subscribe]]></Event>
<EventKey><![CDATA[]]></EventKey>
</xml>
收到用户消息:{CreateTime=1724679529, EventKey=, Event=subscribe, ToUserName=gh_e86239ea7bd5, FromUserName=oSbIc6sxvTBJh-QEgMIGv3K9SosE, MsgType=event}
@PostMapping(value = "/master")
public void receiver(@RequestBody String xml, HttpServletResponse resp, HttpServletRequest request) {try {log.info("/master 收到消息: {}", xml);Map<String, String> msgMap = MessageUtil.string2Map(xml);log.info("收到用户消息:{}", msgMap);String res = PassiveMsgUtil.getInstance().textMessage(msgMap.get("FromUserName"), msgMap.get("ToUserName"), "你好");resp.setContentType("text/xml;charset=UTF-8");resp.setCharacterEncoding("UTF-8");resp.getWriter().write(res);} catch (Exception e) {e.printStackTrace();}
}
public class PassiveMsgUtil {//私有构造方法private PassiveMsgUtil() {}// 静态内部类实现单例模式private static class PassiveMsgUtilInstance {private static final PassiveMsgUtil INSTANCE = new PassiveMsgUtil();}public static PassiveMsgUtil getInstance() {return PassiveMsgUtilInstance.INSTANCE;}public String textMessage(String toUserName, String fromUserName, String content) {return "<xml>\n" +"<ToUserName><![CDATA[" + toUserName + "]]></ToUserName>\n" +"<FromUserName><![CDATA[" + fromUserName + "]]></FromUserName>\n" +"<CreateTime>" + new Date().getTime() + "</CreateTime>\n" +"<MsgType><![CDATA[text]]></MsgType>\n" +"<Content><![CDATA[" + content + "]]></Content>\n" +"</xml>";}
}
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;import java.util.HashMap;
import java.util.List;
import java.util.Map;public class MessageUtil {/*** 解析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);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;}
}

5、获取AccessToken

在这里插入图片描述

access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。
在这里插入图片描述
在这里插入图片描述

@Test
void test02() {RestTemplate restTemplate = new RestTemplate();String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={APPID}&secret={APPSECRET}";AccessTokenDTO tokenDTO = restTemplate.getForObject(url, AccessTokenDTO.class, new HashMap<String, Object>() {{put("APPID", "~~~");put("APPSECRET", "~~~");}});// WxMessageTest.AccessTokenDTO(accessToken=83_5M9JRCgu94nmbTfsD4eoDXw2nWzmoLnHVOYWpdMqT-NsfyBfFFB6gUt5711m4ETlQZZxFejSA6-X5SgELSv7hNXz37fUjamS3zC6M3uagXBriwoMbXgxWNSpvVgRBLgAFAUe1, expiresIn=7200)System.out.println(tokenDTO);
}@Data
static class AccessTokenDTO {@JsonSetter("access_token")private String accessToken;@JsonSetter("expires_in")private Integer expiresIn;
}

这篇关于springboot公众号模板消息推送的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1109983

相关文章

springboot的调度服务与异步服务使用详解

《springboot的调度服务与异步服务使用详解》本文主要介绍了Java的ScheduledExecutorService接口和SpringBoot中如何使用调度线程池,包括核心参数、创建方式、自定... 目录1.调度服务1.1.JDK之ScheduledExecutorService1.2.spring

将java程序打包成可执行文件的实现方式

《将java程序打包成可执行文件的实现方式》本文介绍了将Java程序打包成可执行文件的三种方法:手动打包(将编译后的代码及JRE运行环境一起打包),使用第三方打包工具(如Launch4j)和JDK自带... 目录1.问题提出2.如何将Java程序打包成可执行文件2.1将编译后的代码及jre运行环境一起打包2

Java使用Tesseract-OCR实战教程

《Java使用Tesseract-OCR实战教程》本文介绍了如何在Java中使用Tesseract-OCR进行文本提取,包括Tesseract-OCR的安装、中文训练库的配置、依赖库的引入以及具体的代... 目录Java使用Tesseract-OCRTesseract-OCR安装配置中文训练库引入依赖代码实

Java中对象的创建和销毁过程详析

《Java中对象的创建和销毁过程详析》:本文主要介绍Java中对象的创建和销毁过程,对象的创建过程包括类加载检查、内存分配、初始化零值内存、设置对象头和执行init方法,对象的销毁过程由垃圾回收机... 目录前言对象的创建过程1. 类加载检查2China编程. 分配内存3. 初始化零值4. 设置对象头5. 执行

SpringBoot整合easy-es的详细过程

《SpringBoot整合easy-es的详细过程》本文介绍了EasyES,一个基于Elasticsearch的ORM框架,旨在简化开发流程并提高效率,EasyES支持SpringBoot框架,并提供... 目录一、easy-es简介二、实现基于Spring Boot框架的应用程序代码1.添加相关依赖2.添

通俗易懂的Java常见限流算法具体实现

《通俗易懂的Java常见限流算法具体实现》:本文主要介绍Java常见限流算法具体实现的相关资料,包括漏桶算法、令牌桶算法、Nginx限流和Redis+Lua限流的实现原理和具体步骤,并比较了它们的... 目录一、漏桶算法1.漏桶算法的思想和原理2.具体实现二、令牌桶算法1.令牌桶算法流程:2.具体实现2.1

SpringBoot中整合RabbitMQ(测试+部署上线最新完整)的过程

《SpringBoot中整合RabbitMQ(测试+部署上线最新完整)的过程》本文详细介绍了如何在虚拟机和宝塔面板中安装RabbitMQ,并使用Java代码实现消息的发送和接收,通过异步通讯,可以优化... 目录一、RabbitMQ安装二、启动RabbitMQ三、javascript编写Java代码1、引入

spring-boot-starter-thymeleaf加载外部html文件方式

《spring-boot-starter-thymeleaf加载外部html文件方式》本文介绍了在SpringMVC中使用Thymeleaf模板引擎加载外部HTML文件的方法,以及在SpringBoo... 目录1.Thymeleaf介绍2.springboot使用thymeleaf2.1.引入spring

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满