微信小程序订阅消息通过服务通知发送

第一步:申请模板获取模板ID: 登录微信公众平台 -> 功能 -> 订阅消息 -> 对里面的模板进行选用或者自定义
在这里插入图片描述
在这里插入图片描述

公共模板库里面的模板分为一次性订阅 和永久订阅,这个是根据你创建小程序时选择的行业进行区分的。
https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/subscribe-message.html 官方文档中有详细说明

第二步: 消息订阅接口:需要在小程序端调起订阅接口,需要前端完成。官方地址:https://developers.weixin.qq.com/miniprogram/dev/api/open-api/subscribe-message/wx.requestSubscribeMessage.html
第三步: 服务端发送消息到服务通知,官方文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.send.html
我这里采用的是https的调用方式

代码实现:

  • 核心代码
package com.minapp.management.service;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Strings;
import com.minapp.management.config.WxProperties;
import com.minapp.management.entity.dto.AppletTemplateMessageSendDTO;
import com.minapp.management.utils.CacheManager;
import com.minapp.management.utils.HttpClientUtil;
import lombok.Synchronized;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Map;

@Component
public class WxAppletRemoteService {

    private Logger logger = LoggerFactory.getLogger(WxAppletRemoteService.class);

    private static final String WXAPPLETURl="https://api.weixin.qq.com/cgi-bin";

    @Autowired
    private WxProperties properties;

    @Autowired
    private ObjectMapper objectMapper;

    /**
     * 获取AccessToken
     * @return
     */
    @Synchronized
    public String getAccessToken() {
        String appid=null;
        String secret=null;
        // 这里我是从配置文件中取得appid和appsecret
        appid=properties.getAppId();
        secret=properties.getAppSecret();

        //查询token是否存在
        String key="dowin"+appid+"_AccessToken";
        // 使用缓存先查询AccessToken是否存在,我这里使用的是本地缓存,如果只是存一个token,本地缓存足以,不需要使用专门缓存的服务,比如reids。
        String accessToken = CacheManager.getData(key);
        // 存在直接返回,不存在重新获取AccessToken
        if (!Strings.isNullOrEmpty(accessToken)){
            return accessToken;
        }
        // 获取AccessToken的url
        String grantType="client_credential";
        String url=WXAPPLETURl+"/token?grant_type="+grantType+"&appid="+appid+"&secret="+secret;
        // 获取到AccessToken
        String token = HttpClientUtil.get(url);
        Map<String,Object> map = null;
        try {
            map = objectMapper.readValue(token, Map.class);
        } catch (IOException e) {
            logger.error("小程序异常通知-获取AccessToken-转化异常",e);
        }
        String access_token = String.valueOf(map.get("access_token"));
        // 把AccessToken存入缓存中,并设置过期时间,因为access_token的过期时间是两小时,我们缓存的时间一定要小于两小时,
        CacheManager.setData(key,access_token,5000);

        if (map.get("errcode")!=null || map.get("errmsg")!=null){
            String errcode = String.valueOf(map.get("errcode"));
            String errmsg = String.valueOf(map.get("errmsg"));
            if (!errcode.equals("0")){
                logger.error("获取token失败:code="+errcode+"msg="+errmsg);
                return null;
            }
        }
        return access_token;
    }

    /**
     * 同一消息发送接口
     * AppletTemplateMessageSendDTO   是一个传输类
     */
    public String uniformMessageSend(AppletTemplateMessageSendDTO data) {
        String token = getAccessToken();
        // 调用发型接口
        String url=WXAPPLETURl+"/message/subscribe/send?access_token="+token;
        String returnData = HttpClientUtil.post(url,JSON.toJSONString(data));
        Map<String,Object> map = null;
        try {
            map = objectMapper.readValue(returnData, Map.class);
        } catch (IOException e) {
           logger.error("小程序异常通知-同一消息发送-转化异常",e);
        }
        String errcode = String.valueOf(map.get("errcode"));
        String errmsg = String.valueOf(map.get("errmsg"));
        if (!errcode.equals("0")){
            logger.error("消息发送失败:code="+errcode+"msg="+errmsg);
        }
        return errcode;
    }

}
  • 传输实体类
package com.minapp.management.entity.dto;

import lombok.Data;

import java.io.Serializable;

//小程序模板消息发送模板
@Data
public class AppletTemplateMessageSendDTO implements Serializable {


    //接收者(用户)的 openid
    private String touser;

    //所需下发的订阅模板id
    private String template_id;

    //所跳转的页面
    private String page;

    //模板消息内容
    private Object data;

}

  • 本地缓存类
package com.minapp.management.utils;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

// 本地缓存类
public class CacheManager {
    private static Map<String, CacheData> CACHE_DATA = new ConcurrentHashMap<>();
	
    public static <T> T getData(String key, Load<T> load, int expire) {
        T data = getData(key);
        if (data == null && load != null) {
            data = load.load();
            if (data != null) {
                setData(key, data, expire);
            }
        }
        return data;
    }

	// 根据key获取数据
    public static <T> T getData(String key) {
        CacheData<T> data = CACHE_DATA.get(key);
        if (data != null && (data.getExpire() <= 0 || data.getSaveTime() >= System.currentTimeMillis())) {
            return data.getData();
        }
        return null;
    }
	
	// 存入数据并设置过期时间
    public static <T> void setData(String key, T data, int expire) {
        CACHE_DATA.put(key, new CacheData(data, expire));
    }
	
	// 根据key清除数据
    public static void clear(String key) {
        CACHE_DATA.remove(key);
    }

	// 清除所有缓存数据
    public static void clearAll() {
        CACHE_DATA.clear();
    }

    public interface Load<T> {
        T load();
    }

    private static class CacheData<T> {
        CacheData(T t, int expire) {
            this.data = t;
            this.expire = expire <= 0 ? 0 : expire * 1000;
            this.saveTime = System.currentTimeMillis() + this.expire;
        }

        private T data;
        private long saveTime; // 存活时间
        private long expire;   // 过期时间 小于等于0标识永久存活

        public T getData() {
            return data;
        }

        public long getExpire() {
            return expire;
        }

        public long getSaveTime() {
            return saveTime;
        }
    }
}

测试:

AppletTemplateMessageSendDTO appletTemplateMessageSendDTO = new AppletTemplateMessageSendDTO();
        appletTemplateMessageSendDTO.setTouser("openid");
        appletTemplateMessageSendDTO.setTemplate_id("模板id");
        appletTemplateMessageSendDTO.setPage("跳转的页面");
    Map<String,Object> map = new HashMap<>();
    Map<String,Object> thing6 = new HashMap<>();
    Map<String,Object> time8 = new HashMap<>();
    Map<String,Object> phone_number7 = new HashMap<>();
    Map<String,Object> thing10 = new HashMap<>();
        thing6.put("value","xqd");
        time8.put("value","2020-12-29");
        phone_number7.put("value", "17600026666");
        thing10.put("value","测试一下订阅消息");
        map.put("thing6",thing6);
        map.put("time8",time8);
        map.put("phone_number7",phone_number7);
        map.put("thing10",thing10);
        appletTemplateMessageSendDTO.setData(map);
        wxAppletRemoteService.uniformMessageSend(appletTemplateMessageSendDTO);

发送成功
在这里插入图片描述

  • 5
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
微信小程序订阅消息是一种常用的功能,用于向用户发送即时消息通知。通过调用wx.requestSubscribeMessage()方法,我们可以请求用户订阅相关模板消息,以获取用户的订阅结果。 该方法需要传入一个对象参数,包含以下属性: 1. tmplIds(Array):需要订阅消息模板的模板 ID 列表。 2. success(Function):订阅成功的回调函数。 3. fail(Function):订阅失败的回调函数。 在用户点击订阅按钮后,我们可以调用wx.requestSubscribeMessage()方法,传入相应的模板 ID 列表,并传入成功和失败回调函数。然后,微信会向用户弹出一个订阅消息的授权弹窗,在用户确认订阅后,小程序将会收到订阅成功的回调函数,并返回订阅结果。 订阅成功的回调函数中,我们可以获取订阅成功的模板 ID 列表,以及用户选择的订阅结果。我们可以根据用户的选择,进行后续的业务逻辑,比如发送相关消息通知订阅失败的回调函数中,我们可以获取失败的模板 ID 列表以及错误信息。我们可以根据错误信息做出相应的处理,比如给出友好的提示或重新尝试订阅。 需要注意的是,订阅消息功能需要在小程序配置文件(app.json)中添加相应的权限声明,并在小程序管理后台进行模板消息的设置和配置。 通过wx.requestSubscribeMessage()方法,我们能够方便地实现小程序订阅消息功能,让用户可以及时收到相关的通知,提升用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值