微信小程序订阅消息通过服务通知发送
程序员文章站
2022-03-10 22:00:32
第一步:申请模板获取模板ID: 登录微信公众平台 -> 功能 -> 订阅消息 -> 对里面的模板进行选用或者自定义公共模板库里面的模板分为一次性订阅 和永久订阅,这个是根据你创建小程序时选择的行业进行区分的。https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/subscribe-message.html 官方文档中有详细说明第二步: 消息订阅接口:需要在小程序端调起订阅接口,...
第一步:申请模板获取模板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);
发送成功
本文地址:https://blog.csdn.net/weixin_44467567/article/details/111942539
上一篇: 方法的递归经典问题--八皇后问题
下一篇: 画世界怎么设置水印?画世界设置水印教程