小程序一次性订阅消息(消息通知):java服务端实现

文章目录

引言

最近在开发小程序服务端代码,需要实现一个能够实现消息通知的接口业务,记录一下整个接口业务的开发过程。

一、消息订阅

先附上微信官方文档:订阅消息

1.1 小程序订阅消息功能介绍

消息能力是小程序能力中的重要组成,我们为开发者提供了订阅消息能力,以便实现服务的闭环和更优的体验。

订阅消息推送位置:服务通知

订阅消息下发条件:开发者通过一定的方式触发用户主动订阅

订阅消息卡片跳转能力:点击查看详情可跳转至该小程序的页面

1.2 消息分类

1.2.1 新版一次性订阅消息Beta

新版一次性订阅消息是一种无需用户在弹窗中主动订阅即可向用户下发消息的能力,用户的订阅方式为:

当用户在小程序中进行微信支付后,开发者可将微信支付订单号作为 code 向用户下发服务通知

开发者可在小程序中将触发服务的 button 组件的 open-type 的值设置为 liveActivity,当用户点击 button 后可获得 code ,后续可使用此 code 向用户下发服务通知

此下发方式由平台定义模版,开发者根据自身业务选择模版进行接入。

详见订阅消息接入 Beta开发指南文档。

1.2.2 一次性订阅消息(用户通过弹窗订阅)

一次性订阅消息用于解决用户使用小程序后,后续服务环节的通知问题。

开发者在小程序中调用 requestSubscribeMessage 接口后,将向用户展示弹窗,用户可打开自己想要接受的消息开关。用户订阅后,开发者可不限时间地下发一条对应的服务消息;每条消息可单独订阅或退订。

详见小程序订阅消息开发指南文档。

1.2.3 长期订阅消息(用户通过弹窗订阅)

一次性订阅消息可满足小程序的大部分服务场景需求,但线下公共服务领域存在一次性订阅无法满足的场景,如航班延误,需根据航班实时动态来多次发送消息提醒。为便于服务,我们提供了长期性订阅消息,用户订阅一次后,开发者可长期下发多条消息。

目前长期性订阅消息仅向政务民生、医疗、交通、金融、教育等线下公共服务开放,后期将逐步支持到其他线下公共服务业务。

详见小程序订阅消息开发指南文档。

同时长期订阅消息支持语音提醒添加提醒能力。

1.2.4 设备订阅消息

设备订阅消息是一种特殊类型的订阅消息,它属于长期订阅消息类型,且需要完成设备接入才能使用。

设备订阅消息用于在设备触发某些需要人工介入的事件时(例如设备发生故障、设备耗材不足等),向用户发送消息通知。

详见设备订阅消息文档。

二、获取模板ID

先附上微信官方文档:小程序订阅消息(用户通过弹窗订阅)开发指南

1.登录微信公众平台开通订阅消息

在微信公众平台中的小程序后台找到订阅消息功能模块

开通订阅消息:

由于长期性订阅消息,目前仅向政务民生、医疗、交通、金融、教育等线下公共服务开放,后期将逐步支持到其他线下公共服务业务。仅就线下公共服务这一点,长期性订阅消息就和大部分开发者无缘了。所以我们这里只能以使用一次性订阅消息为例。

2.在微信公众平台手动配置获取模板 ID:

登录 https://mp.weixin.qq.com 获取模板,如果没有合适的模板,可以申请添加新模板,审核通过后可使用。

选择先要的公共模板 ,也可以自己定制,但是公共模板已经可以满足我们绝大多数业务场景了

选择或者自己定制一个合适的模板,然后可以进行订阅模板的编辑,当然这都属于前端的工作了,

我们只需要在模板中拿到模板ID 即可。

三、获取接口调用凭据wx_access_token

先附上微信官方文档:获取接口调用凭据

1、接口说明

接口英文名:getAccessToken

功能描述:

获取小程序全局唯一后台接口调用凭据,token有效期为7200s,开发者需要进行妥善保存。
如使用云开发,可通过云调用免维护 access_token 调用。
如使用云托管,也可以通过微信令牌/开放接口服务免维护 access_token 调用。

2、调用方式

HTTPS 调用

GET https://api.weixin.qq.com/cgi-bin/token 

请求参数

3、Java代码实现

java 复制代码
/**
     * 获取接口调用凭证 access_token
     */
    private static final String ACCESSTOKEN_GET = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&";

 public WxAccessTokenVo getAccessToken() {

        WxAccessTokenVo accessTokenVo  = null;

/*     这个是redis缓存的:没有的话去掉*/
        String wx_access_token = (String) redisTemplate.opsForValue().get("wx_access_token");
        if (wx_access_token != null) {
            accessTokenVo = new WxAccessTokenVo();
            accessTokenVo.setAccess_token(wx_access_token);
            return accessTokenVo;
        }

        String url = ACCESSTOKEN_GET + "appid=" + appId + "&secret=" + appSecret;

        RestTemplate restTemplate = new RestTemplate();
        String response = restTemplate.getForObject(url, String.class);

        try {
            accessTokenVo = JSON.parseObject(response, WxAccessTokenVo.class);

            /* 存储在redis中*/
            if (accessTokenVo.getExpire_in() > 0) {
                redisTemplate.opsForValue().set("wx_access_token", accessTokenVo.getAccess_token(),
                        accessTokenVo.getExpire_in(), TimeUnit.SECONDS);
            }
            

        } catch (Exception e) {
            logger.error("Json转换异常", e);
        }

        return accessTokenVo;

    }

所以在获取到access_token的时候,把access_token存到数据库,或者存到本地缓存,并且还要记录当前时间 ,后面再用的时候先判断这个access_token有没有超过2个小时,如果超过2个小时的话,就要重新获取了。

附微信官方说明:获取 Access token

四、发送消息

先附上微信官方文档:发送订阅消息

1、接口说明

接口英文名:sendMessage

功能描述:

该接口用于发送订阅消息。

调用方式

HTTPS 调用
java 复制代码
POST https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=ACCESS_TOKEN 

请求参数


这些参数都是我们需要封装好发送给微信官方,调用时候需要的。

返回参数

2、注意点(需要前端配合)

这里有个需要特别注意的点,我们要给用户发送消息,就必须前端实现引导用户授权 ,因为用户不点击允许,你是没有办法给用户推送消息的。每一次授权只允许发送一条消息,所以如果你想尽量多的发送消息,就得尽量多的引导用户授权。

3、发送消息的Java代码实现

1)封装前端引导用户授权所需的参数:

java 复制代码
@Data
public class AddMessageSubscribeForm {    // 前端模板需要的参数
    //  小程序的登录凭证code
    private String code;

    //订阅消息模版id   TODO
    private String template_id;

    //默认跳到小程序首页 TODO
    private String page = "pages/index/index";

    //推送文字
    private Map<String, TemplateData> data;

    //   跳转小程序的类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版
    private String miniprogram_state;

    //  进入小程序查看的语言类型:支持zh_CN、en_US、zh_HK、zh_TW,默认为zh_CN
    private String lang;

}

2)封装后台调用微信官方API所需的参数:

java 复制代码
@Data
public class WXMssVO {
    //用户openid
    private String touser;

    //订阅消息模版id
    private String template_id;

    //默认跳到小程序首页 TODO
    private String page = "pages/index/index";

    //推送内容
    private Map<String, TemplateData> data;

    //   跳转小程序的类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版
    private String miniprogram_state;

    //  进入小程序查看的语言类型:支持zh_CN、en_US、zh_HK、zh_TW,默认为zh_CN
    private String lang;
}

3)编写发送消息的内容:

java 复制代码
@AllArgsConstructor
@Data
public class TemplateData {

    /**
     *   消息通知的内容
     */
    private String value;
}

4)获取用户的openid

java 复制代码
    /**
     * 获取微信用户唯一标识OpenID
     */
    private static final String CODE2SESSION_GET = "https://api.weixin.qq.com/sns/jscode2session?";
 /**
     * code2sessino接口
     * @param code
     * @return
     */
    public WxCode2SessionVo getCode2Session(String code) {
        String url = CODE2SESSION_GET + "appid=" + appId + "&secret=" + appSecret + "&js_code=" + code + "&grant_type=authorization_code";

        RestTemplate restTemplate = new RestTemplate();
        String response = restTemplate.getForObject(url, String.class);

        WxCode2SessionVo code2SessionVo = null;
        try {
            code2SessionVo = JSON.parseObject(response, WxCode2SessionVo.class);
        } catch (Exception e) {
            logger.error("Json转换异常", e);
        }

        return code2SessionVo;

    }

5)编写发送消息的函数:

java 复制代码
    /**
     *    给用户发送通知
     *    TODO  参数设置
     * @param info
     * @return
     */
/**
     *   给用户发送消息
     */
    public static final String SEND_INFO_URL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=";
  
    public String pushMessage(AddMessageSubscribeForm info){
        RestTemplate restTemplate = new RestTemplate();
        String url = SEND_INFO_URL + getAccessToken().getAccess_token();

        // 通过 appId+appsecret+code三个参数获取微信用户信息 获取用户的openid
        WxCode2SessionVo code2Session = this.getCode2Session(info.getCode());
        if (code2Session == null || (code2Session.getErrcode() != null && code2Session.getErrcode() != 0)) {
            return  "获取用户微信信息失败:" + code2Session.toString();
        }
        String openid = code2Session.getOpenid();

        //  拼接推送的模板
        WXMssVO wxMssVO = new WXMssVO();
        wxMssVO.setTouser(openid);    // 用户的openId
        wxMssVO.setTemplate_id(info.getTemplate_id());    //订阅消息模板id
        wxMssVO.setLang(info.getLang());     //语言类型
        wxMssVO.setMiniprogram_state(info.getMiniprogram_state());   //跳转小程序类型
        //TODO:指定跳转的页面
        wxMssVO.setPage(info.getPage());

        // TODO: 推送的内容
        Map<String, TemplateData> map = new HashMap<>();
        map.put("msg", new TemplateData("发消息了"));
        wxMssVO.setData(map);

        // 发送
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, wxMssVO, String.class);
        return responseEntity.getBody();
    }

到这里我们就可以完整的实现Java发送小程序消息的功能了。

总结

以上就是今天要分享给大家的内容,本文简单的记录了一下小程序发送通知的开发,很多内容其实都来自官方文档,欢迎大家批评指正、共同进步!

相关推荐
小灰灰__12 分钟前
IDEA加载通义灵码插件及使用指南
java·ide·intellij-idea
夜雨翦春韭15 分钟前
Java中的动态代理
java·开发语言·aop·动态代理
程序媛小果36 分钟前
基于java+SpringBoot+Vue的宠物咖啡馆平台设计与实现
java·vue.js·spring boot
追风林41 分钟前
mac m1 docker本地部署canal 监听mysql的binglog日志
java·docker·mac
芒果披萨1 小时前
El表达式和JSTL
java·el
Aloudata2 小时前
从Apache Atlas到Aloudata BIG,数据血缘解析有何改变?
大数据·apache·数据血缘·主动元数据·数据链路
duration~2 小时前
Maven随笔
java·maven
zmgst2 小时前
canal1.1.7使用canal-adapter进行mysql同步数据
java·数据库·mysql
跃ZHD2 小时前
前后端分离,Jackson,Long精度丢失
java
blammmp2 小时前
Java:数据结构-枚举
java·开发语言·数据结构