微信小程序实现订阅消息推送的实现步骤

news2025/3/15 18:05:52

1、准备工作

  准备小程序账号、开发环境,我小程序是基于uniapp开发,后台代码基于SpringBoot开发。同时先阅读官方文档,了解小程序订阅消息和后端如何发送订阅消息等相关知识,官方文档地址如下:

  1. 《小程序订阅消息》
  2. 《发送订阅消息》

2、实现步骤

2.1、启用并配置消息推送

   登录微信小程序后台,在开发->开发管理->开发设置,下拉到消息推送面板,填写自己的服务器推送地址。 Token(令牌)和EncodingAESKey(消息加密密钥)随意,设置后最好不要再改变也不要泄露,后台接口校验需要使用。
在这里插入图片描述

2.2、搭建推送接口服务

   在上述的配置中,需要用到相关服务接口,该服务接口需要两个同名的接口,一个支持Get ,另外一个支Post,其中Get方法主要实现权限归属认证,只调用一次;而Post方法, 当用户在微信小程序中主动订阅一次性消息时,腾讯服务器将请求Post的接口,发送用户的相关行为事件结果到开发者服务器,只有用户订阅的用户才允许进行消息推送,其实这里接收的不只是消息订阅事件,各类的交互事件都在这里进行接收的。下面代码,只是简单实现了解析,没有具体实现相关逻辑。

@RequestMapping(value = "get")
    @ResponseBody
    public String get(HttpServletRequest request,String signature, String timestamp, String nonce, String echostr) {
        if(request.getMethod().equalsIgnoreCase("get")){//用来校验,一般会验证前端配置的token等,这里简化了代码。
            return echostr;
        }else if(request.getMethod().equalsIgnoreCase("POST")){//接收用户的相关行为事件结果
            try {
                BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));
                StringBuilder requestContent = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    requestContent.append(line);
                }
                reader.close();
                //接收:{"ToUserName":"gh_ea84a199bf81","FromUserName":"oG0NJ5Oi_3Dd1HlZJ14xfnA0sJ6s","CreateTime":1686131943,"MsgType":"event","Event":"subscribe_msg_popup_event","List":{"PopupScene":"0","SubscribeStatusString":"accept","TemplateId":"4ondVRxk4L20ihrJ3iI15BDK72XatGPxE0MeCVwHasQ"}}
                logger.info("接收:" + requestContent.toString());
                return "";
            } catch (IOException e) {
                // 处理异常情况
                e.printStackTrace();
                logger.error("异常:" + e.getMessage());
                return e.toString();
            }
        }else{
            logger.info("不是get 或 post方法");
            return null;
        }
    }
2.3、消息模板申请

  在微信公众平台选择公共模板或者申请符合自己需求的模板(需要符合规则)。这里我们选择了一个公共的模板,申请通过后,我们就可以获取到消息模板ID和详细内容等信息。

1、对于个人开发者的微信小程序账号,是无法直接添加订阅消息模板的。订阅消息模板的功能只对企业主体的微信公众号和小程序开放。
2、个人开发者账号只能使用已经存在的订阅消息模板进行订阅消息推送,无法自定义和添加新的模板。

在这里插入图片描述
在这里插入图片描述

2.4、用户授权

  在小程序中获取用户订阅消息的授权:在小程序中,你需要调用wx.requestSubscribeMessage接口获取用户的订阅消息授权。用户同意授权后,你可以得到用户的订阅消息订阅状态。

//uniapp封装了wx.requestSubscribeMessage接口
uni.requestSubscribeMessage({
 tmplIds: ['4ondVRxk4L20ihrJ3iI15BDK72XatGPxE0MeCVwHasQ'],
  success (res) {
	  console.log(res);
  }
})

该方法的详细用法,请参考 《wx.requestSubscribeMessage(Object object)用法》官方文档。

  点击调用了上述方法的按钮,就会弹出如下页面,选择允许后,就可以接收后端推送的通知消息了。

在这里插入图片描述

2.5、消息推送实现

  在实际应用中,我们应该维护一张需要推送消息的微信用户数据表,包括该用户是否已订阅,微信用户的openid等信息,这里暂时演示,省略了该信息,直接固定硬编码了模板ID、消息内容、微信用户openId等信息。

/**
 * 订阅消息推送方法
 */
public class WeChatSubscribeMessageSender {
    private static final String API_URL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send";
    public static void sendSubscribeMessage(String accessToken, String openid, String templateId, String page, String data) {
        try {
            String url = API_URL + "?access_token=" + accessToken;

            URL apiUrl = new URL(url);
            HttpURLConnection connection = (HttpURLConnection) apiUrl.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
            connection.setDoOutput(true);

            // 构建请求体
            String body = buildRequestBody(openid, templateId, page, data);
            byte[] requestBodyBytes = body.getBytes(StandardCharsets.UTF_8);

            // 发送请求
            connection.getOutputStream().write(requestBodyBytes);

            // 读取响应
            int responseCode = connection.getResponseCode();
            BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            StringBuilder response = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }
            reader.close();

            if (responseCode == HttpURLConnection.HTTP_OK) {
                // 请求成功处理逻辑
                System.out.println("发送订阅消息成功");
                System.out.println(response.toString());
            } else {
                // 请求失败处理逻辑
                System.out.println("发送订阅消息失败");
                System.out.println("响应码:" + responseCode);
                System.out.println(response.toString());
            }

            connection.disconnect();
        } catch (IOException e) {
            // 异常处理逻辑
            e.printStackTrace();
        }
    }

    private static String buildRequestBody(String openid, String templateId, String page, String data) {
        // 构建请求体的JSON字符串
        return String.format(
                "{\"touser\":\"%s\",\"template_id\":\"%s\",\"page\":\"%s\",\"data\":%s}",
                openid, templateId, page, data);
    }
}
//推送消息的时候需要accessToken,这里是获取token的方法,在实际环境中,一般是定时刷新,两个小时内有效,获取accesstoken时需要appid和secret信息,一般是后台参数或常量进行配置。
 //获取accessToken的请求接口
private final static String GetAccessToken = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appid}&secret={secret}";

public String refreshAccessToken(String appid, String secret){
        if(StringUtils.isEmpty(appid) || StringUtils.isEmpty(secret)){
            logger.error("刷新微信AccessToken时,缺少appid或secret参数!");
            throw new WxBzException(SysErrorCode.SYS_ERROR_700000,"刷新微信AccessToken时,缺少appid或secret参数!");
        }
        Map<String, Object> param = new HashMap<>();
        param.put("appid",appid);
        param.put("secret",secret);
        ResponseEntity<JSONObject> resp = restTemplate.getForEntity(GetAccessToken, JSONObject.class,param);
        JSONObject jsonObj = resp.getBody();
        String accessToken = null;
        if(jsonObj != null){
            accessToken = jsonObj.getString("access_token");
        }
        return accessToken;
    }
//消息推送的模拟方法
@Controller
@RequestMapping(value = "/api/wx/xcx")
public class WxApi {

    Logger logger = LoggerFactory.getLogger(WxApi.class);

    @Autowired
    private WxCommonService wxCommonService;

    @RequestMapping(value = "sendMsg")
    @ResponseBody
    public String sendMsg(HttpServletRequest request){
        //String token = request.getParameter("token");
        //请求 微信接口 获取 accessToken
        String accessToken = wxCommonService.refreshAccessToken(WxConstants.WX_XCX_APPID,WxConstants.WX_XCX_SECRET);
        String openid = "接收消息的微信用户的openId";
        String templateId = "微信订阅消息模板";
        String page = "点击消息的跳转路径";
        // 构建订阅消息内容的JSON对象
        // 构建订阅消息内容的JSON对象
        JSONObject messageData = new JSONObject();
        messageData.put("thing1", createDataItem("提醒内容", "您有新的提醒"));
        messageData.put("thing2", createDataItem("作业名称", "Java作业"));
        messageData.put("time3", createDataItem("截至日期", "2023-06-30"));
        messageData.put("thing4", createDataItem("发布人员", "张三"));
        // 将订阅消息内容转换为JSON字符串
        String jsonData = messageData.toJSONString();
        WeChatSubscribeMessageSender.sendSubscribeMessage(accessToken,openid,templateId,page,jsonData);
        return null;
    }
    private static Map<String, Object> createDataItem(String name, String value) {
        Map<String, Object> item = new HashMap<>();
        item.put("value", value);
        return item;
    }
}
2.6、测试模拟消息

  完成上述工作后,启动服务,先通过微信小程序进行消息订阅,
然后调用模拟消息推送的方法http://localhost:8080/api/wx/xcx/sendMsg,这个时候微信服务中就会收到消息,如下图所示;
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/645814.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++】4.websocket:websocketpp安装与使用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍websocketpp的安装与使用。 学其所用&#xff0c;用其所学。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c;下次更新不迷…

【Java】《On Java》第12章 集合 读书笔记

结合JavaGuide和《On Java》的集合笔记。 不要使用时代的眼泪Vector、HashTable、Stack。 文章目录 1 泛型与类型安全的集合2 基本概念3 添加一组元素★4 集合的打印5 ListtoArray的使用 ★Collection.sort的使用 6 ArrayList6.1 ArrayList成员变量6.2 ArrayList构造函数6.3 A…

没有公网IP,如何实现数据共享?

数据共享就是让在不同地方使用不同计算机、不同软件的用户能够读取他人数据并进行各种操作、运算和分析。不同层次、不同部门信息系统间&#xff0c;信息和信息产品的交流与共用&#xff0c;就是把信息这一种在互联网时代中重要性越趋明显的资源与其他人共同分享。 数据共享有…

SpeechGen:用提示解锁语音语言模型(Speech LM)的生成能力

论文链接&#xff1a; https://arxiv.org/pdf/2306.02207.pdf Demo: https://ga642381.github.io/SpeechPrompt/speechgen.html Code: https://github.com/ga642381/SpeechGen 引言与动机 大型语言模型 &#xff08;LLMs&#xff09;在人工智能生成内容&#xff08;AIGC…

手动渲染农场和自助云渲染农场的区别

手动渲染农场和自助云渲染农场是两种常见的渲染方式&#xff0c;它们各有优缺点。手动渲染农场指的是在本地使用自己的硬件设备进行渲染&#xff0c;而自助云渲染农场则是利用云服务商提供的计算资源进行渲染。对于需要渲染大规模项目的设计师或工作室来说&#xff0c;选择一种…

网络安全主要学些什么比较重要

网络安全学什么&#xff1f; 第一阶段&#xff1a;基础 入门的第一步是学习当下的一些主流的安全工具和配套的原理基础 第二阶段&#xff1a;学习基础知识 这个阶段的时候对网络安全就有了基本的了解&#xff0c;通过第一步的学习&#xff0c;理论上的知识一定都明白了&…

Python精美图快速上手

seaborn是一个基于Python的数据可视化库&#xff0c;它建立在Matplotlib之上&#xff0c;提供了一种更简单、更美观的方式来创建统计图形。seaborn旨在帮助用户轻松地生成有吸引力和信息丰富的可视化结果。 以下是seaborn库的一些主要特点&#xff1a; 美观的默认样式&#xf…

获取jar包所在路径位置,项目文件夹Path

获取jar包所在路径位置,项目文件夹位置 方法1 new ApplicationHome().getDir().getPath();方法1就是调用了方法2 System.getProperty("user.dir") System.getProperty("user.dir")String源码&#x1f447; private File findHomeDir(File source) {File…

Python 标准库 - 并发执行

Python 标准库 - 并发执行 1. 简单介绍2. 程序示例2.1 threading 编程示例2.2 multiprocessing 编程示例2.3 concurrent.futures 编程示例 1. 简单介绍 Python 标准库 非常庞大&#xff0c;所提供的组件涉及范围十分广泛&#xff0c;官方参考链接https://docs.python.org/zh-cn…

【sentinel】令牌桶算法在Sentinel中的应用

令牌桶算法 令牌桶算法介绍 令牌桶算法&#xff0c;又称token bucket。 从图中我们可以看到&#xff0c;令牌桶算法比漏桶算法稍显复杂。首先&#xff0c;我们有一个固定容量的桶&#xff0c;桶里存放着令牌&#xff08;token&#xff09;。桶一开始是空的&#xff0c;token以…

【深度学习】0-2 深度学习相关数学概念的简单总结-概率与信息论

样本空间 样本空间是一个实验或随机试验所有可能结果的集合&#xff0c;随机试验中的每个可能结果称为样本点。例如投掷一个骰子&#xff0c;那么样本空间就是{1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5&#xff0c;6}。 随机变量 随机变量&#xff0c;顾名思义…

IDEA全局设置JDK、Maven、编码格式

本机已安装JDK版本&#xff1a; 本机已安装Maven版本&#xff1a; 一、IDEA设置全局JDK设置 File---->New Projects Settings---->Structure for New Projects... 先将本地安装的JDK添加到SDK 将项目SDK设置为刚刚添加的本地JDK版本 File---->New Projects Settings-…

Webstorm 加载vue项目时,特别卡顿,完美解决。觉得有用加好友打赏

觉得有用加好友打赏&#xff1a;QQ&#xff1a;854138497 上图cpu直接干满。 根据上图提示&#xff0c;直接 disable hints&#xff0c;或者到下图的settings里面设置。 Code vision取消后&#xff0c;webstorm 明显就不卡了。记得重启webstorm。 还有一种方式&#xff0c;根…

完美解决MacOS关于ld: library not found for -lnetcdff错误

1. 问题描述 在使用Intel版本的Mac编译某个程序时出现了错误&#xff0c;显示如下图。 说明&#xff1a;libnetcdff是netcdf的Fortran的接口&#xff0c;如下ChatGPT解释。 2. 出现的原因 原因是Makefile中定义的静态库链接并没有在系统默认的库路径下找到&#xff0c;默认…

Jmeter HTTP Cookie管理器的使用

目录 前言&#xff1a; 1、在HTTP信息头管理器组件中添加Cookie信息 &#xff08;1&#xff09;测试计划内包含的元件 &#xff08;2&#xff09;请求取样器内容 &#xff08;3&#xff09;HTTP信息头管理器内容 &#xff08;4&#xff09;查看结果 2、使用HTTP Cookie管…

你想知道的 MySQL 性能调优方式,都在这里

前言&#xff1a;对于性能测试来说&#xff0c;数据库的监控是尤为的重要&#xff0c;以及对数据库进行调优&#xff0c;用以提升性能&#xff0c;是能在短期内有显著的效果的&#xff0c;本文针对MySQL数据库进行分析如何定位MySQL数据库的性能问题。 关键 MySQL 统计指标 如…

一张软考系统架构设计师证书到底能证明了什么?

软考证书证明你考过了软考高级架构&#xff0c;拥有了评高级职称的资格&#xff01; 证书的作用还有&#xff1a; 1、以考代评&#xff1a;软考证书可以用来评职称 2、积分落户&#xff1a;可用于积分落户&#xff0c;加相应的分&#xff0c;软考高级职业资格都几乎可以直接…

Tinker 组件修复,踩坑

1、You need to use a Theme.AppCompat theme (or descendant) with this activity. 复现步骤 补丁加载成功之后重启应用&#xff0c;再退出应用重进闪退 日志 TinkerUncaughtHandler catch exception:java.lang.IllegalStateException: You need to use a Theme.AppCompat th…

Cesium教程(十七):淹没分析

Cesium教程(十七):淹没分析 1、什么是淹没分析 淹没分析是根据某片区域的地形及洪水流量速度,动态模拟该地形区域水位逐渐上涨的淹没过程。该功能可适用于山区、丘陵等地形起伏较大区域,模拟洪水涨到安全限定高度的淹没过程,为防洪水救灾提供一定的参考。此外,还可以为河…

红帽认证常见答疑(二):电脑配置、实验环境和考试环境、可以自学吗

学习红帽需要配置什么样的电脑&#xff1f; RHCE推荐学员自己的电脑内存在16G左右&#xff0c;RHCA推荐学员电脑内存在32-64G&#xff0c;且最好配置128G以上的固态硬盘&#xff0c;如果自己没有该配置的电脑&#xff0c;誉天可以提供远程学习环境&#xff0c;可以随时随地连接…