IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 工具类: 小程序消息推送 -> 正文阅读

[移动开发]工具类: 小程序消息推送

背景


前端时间负责小程序后端的老哥离职,所以由本人负责与前端对接开发 - 小程序消息推送,简单封装了个工具类,在此记录一下。

前提


服务通知推送需要申请小程序模板,具体申请细节可百度了解,登录地址:微信公众平台

对接文档地址:微信官方文档

获取用户登录唯一code:唯一code,使用 code 换取 openid、unionid、session_key 等信息
在这里插入图片描述

代码实现


  • 配置类
public class WxProperties {
    /**
     * 小程序appid
     */
    public static String appid = "登录小程序官网账户获取";
    /**
     * 小程序应用密钥
     */
    public static String appsecret = "登录小程序官网账户获取";
    /**
     * 小程序获取token的地址  APPID 和 APPSECRET 记得替换为真实 appId和密钥
     */
    public static String accessTokenUrl ="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";;
    /**
     * 小程序消息推送模板id
     */
    public static String templateId = "前面申请的模板id";
    /**
     * 小程序消息推送地址 ACCESS_TOKEN 记得替换为真实 access_token
     */
    public static String sendMessageUrl = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=ACCESS_TOKEN";
    /**
     * 小程序获取openid地址 APPID 和 APPSECRET 和 JSCODE(通过 wx.login 接口获得临时登录凭证 code,微信前端唯一标识) 需替换
     */
    public static String openIdUrl = "https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=APPSECRET&js_code=JSCODE&grant_type=authorization_code";
    /**
     * 是否启用订阅消息
     */
    public static Boolean sendMessageFlag = true;
}    
  • 微信推送接口请求参数封装
public class WxSendMessageParam {

    /**
     * 接口调用凭证
     */
    @JsonProperty("access_token")
    private String accessToken;
    /**
     * 接收者(用户)的 openid
     */
    private String touser;
    /**
     * 模板内容
     */
    private HashMap data;
    /**
     * 订阅模板id
     */
    @JsonProperty("template_id")
    private String templateId;
    /**
     * 点击模板卡片后的跳转页面
     */
    private String page;
    /**
     * 跳转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版
     */
    @JsonProperty("miniprogram_state")
    private String miniprogramState;

}
  • 获取access_token 工具
public class AccessTokenUtil {

    /**
     * 获取到的凭证
     */
    private String token;
    /**
     * 凭证有效时间(秒)
     */
    private int expiresIn;

    public static AccessTokenUtil getAccessToken() {

        AccessTokenUtil token = new AccessTokenUtil();

        String url = WxProperties.accessTokenUrl.replace(WxCommonConstants.APPID, WxProperties.appid).replace(WxCommonConstants.APPSECRET, WxProperties.appsecret);
        try {
            log.info("appid :" + WxProperties.appid);
            log.info("appsecret :" + WxProperties.appsecret);
            log.info("accessTokenUrl :" + WxProperties.accessTokenUrl);
            log.info("调用微信获取凭证url :" + url);
            String resp = HttpUtil.get(url);
            log.info("调用微信获取凭证接口返回 :" + resp);
            HashMap resMap = JSONUtil.toBean(resp, HashMap.class);
            if (MapUtil.isNotEmpty(resMap)) {
                token.setToken(MapUtil.getStr(resMap, WxCommonConstants.ACCESS_TOKEN));
                token.setExpiresIn(MapUtil.getInt(resMap, WxCommonConstants.EXPIRES_IN));
            }
            log.info("token :" + token.getToken());
            return token;
        } catch (Exception e) {
            log.error("获取access_token失败:" + ExceptionUtil.stacktraceToString(e));
            return token;
        }
    }
}
  • 微信推送工具
@Component
public class WxSendUtil {

    /**
     * 数值3,用于请求次数的判断
     */
    private static final Integer COUNT = 3;

    @Autowired
    RedisService redisService;

    private static WxSendUtil sendUtil;

    @PostConstruct
    public void init() {
        sendUtil = this;
    }

    /**
     * 请求推送接口,并处理响应
     *
     * @param param 微信小程序订阅消息参数类
     * @param accessToken 接口调用凭证 (传空时会重新获取)
     * @param count 用于次数统计,初始传0
     * @return
     * @author  wrx
     * @date  2021/11/3 21:45
     */
    public static R sendAndHandle(WxSendMessageParam param, String accessToken, Integer count) {
        // 重发推送请求前,判断是否已请求2次,是则结束程序
        if (++count >= COUNT) {
            log.info("已请求2次 向用户推送消息失败");
            return R.FAIL("向用户推送消息失败");
        }
        log.info("进入sendAndHandle:{}",count);
        // 请求推送接口,获取响应map
        Map<String, Object> map = reqWxSendAPI(param, accessToken);
        String errCode = MapUtil.getStr(map, WxCommonConstants.ERRCODE);
        if (WxCommonConstants.SUCCESS.equals(errCode)) {
            log.info(StrUtil.format("第{}次 向用户推送消息成功",count));
            return new R<>("向用户推送消息成功");
        } else {
            // ①走到此说明推送失败了
            // ②如果不是因为token过期导致请求失败,直接结束程序
            log.info(StrUtil.format("第{}次 错误 errorCode:" + errCode + ",错误errormsg:" + MapUtil.getStr(map, WxCommonConstants.ERRMSG)),count);
            if (!WxCommonConstants.ERROR_CODE_40001.equals(errCode)) {
                log.info(StrUtil.format("第{}次 向用户推送消息失败"),count);
                return R.FAIL("向用户推送消息失败");
            }else{
                //③走到此说明说明是token过期导致失败则重新获取token,再次发起推送请求
                return sendAndHandle(param, StrUtil.EMPTY, count);
            }
        }
    }

    /**
     * 请求微信推送api接口
     *
     * @param param 微信小程序订阅消息参数类
     * @param accessToken 接口调用凭证 (传空时会重新获取)
     * @return
     * @author  wrx
     * @date  2021/11/3 19:56
     */
    private static Map<String, Object> reqWxSendAPI(WxSendMessageParam param, String accessToken)  {
        // ①如果accessToken为空,则重新获取
        param.setAccessToken(StrUtil.isBlank(accessToken) ? getAndRefreshToken() : accessToken);
        // ②发送推送请求
        String url = WxProperties.sendMessageUrl + param.getAccessToken();
        log.info("发送订阅消息请求 :" + url + "&" + JsonUtil.toJson(param));
        String resp = HttpUtil.post(url, JsonUtil.toJson(param));
        log.info("发送订阅消息请求响应 :" + resp);
        Map<String, Object> map = JSONUtil.toBean(resp, HashMap.class);
        if (MapUtil.isEmpty(map)) {
            log.info("请求微信推送接口时,发生了未知的情况,响应为空");
            throw new ServiceException(WxCodeMsg.REQ_API_EXCEPTION.fillArgs("未知的响应结果"));
        }
        return map;
    }

    /**
     * 获取并刷新缓存中的access_token
     *
     * @return  token
     * @author  wrx
     * @date  2021/11/3 17:02
     */
    private static String getAndRefreshToken() {
        AccessTokenUtil token = AccessTokenUtil.getAccessToken();
        log.info("获取到的token:" + JSONUtil.toJsonStr(token));
        String accessToken = token.getToken();
        //更新redis中的微信凭证和过期时间
        sendUtil.redisService.set(WxCommonConstants.ACCESS_TOKEN_REDIS_PREFIX, accessToken, token.getExpiresIn());
        return accessToken;
    }
}
  • 业务层组装WxSendMessageParam 并远程调用工具
@Slf4j
@Component
public class HkWxSendUtil {
    /**
     * 微信小程序推送消息远程服务
     */
    @Autowired
    RemoteWxSendMessageService remoteWxSendMessageService;

    private static HkWxSendUtil sendUtil;

    @PostConstruct
    public void init() {
        sendUtil = this;
    }

    /**
     * 发送小程序推送消息
     *
     * @param  createrId 单证创建人id
     * @param  sourceMap 存储模板内容的源map
     * @param  pageUrl 点击推送详情要跳转的页面
     * @param  templateId 模板id
     * @return
     * @author  wrx
     * @date  2021/11/3 16:22
     */
    public static void sendMessage(HashMap<String, Object> sourceMap,String openId,String pageUrl,String templateId) {
        WxSendMessageParam messageParam = new WxSendMessageParam();
        messageParam.setTouser(openId);
        messageParam.setData(sourceMap);
        messageParam.setTemplateId(templateId);
        messageParam.setPage(pageUrl);
        log.info("微信订阅消息参数 :" + JSONUtil.toJsonStr(messageParam));
        R r = sendUtil.remoteWxSendMessageService.newSendWxMessage(messageParam, SecurityConstants.FROM_IN);
        log.info("微信订阅消息返回 :" + JSONUtil.toJsonStr(r));
    }

    /**
     * 添加模板内容
     *
     * @param  source 存储模板内容的源map
     * @param  keyword key
     * @param  value value
     * @return
     * @author  wrx
     * @date  2021/11/3 14:26
     */
    public static void putWxParamMap(HashMap<String, Object> source, String keyword, Object value) {
        HashMap<String, Object> paramMap = new HashMap<>(2);
        paramMap.put("value",value);
        source.put(keyword,paramMap);
    }
}
  • 调用推送工具(伪代码
main:
 log.info("进入小程序推送方法");
 //① 业务校验
 //② 组装推送对象
 HashMap<String,Object> sourceMap = new HashMap<>(8);
 HkWxSendUtil.putWxParamMap(sourceMap,"模板key1","key1对应的值");
 HkWxSendUtil.putWxParamMap(sourceMap,"模板key2","key2对应的值");
 HkWxSendUtil.putWxParamMap(sourceMap,"模板key3","key3对应的值");
 HkWxSendUtil.putWxParamMap(sourceMap,"模板key4","key4对应的值");
 HkWxSendUtil.putWxParamMap(sourceMap,"模板key5","key5对应的值");
 //③调用业务层工具推送
 HkWxSendUtil.sendMessage(sourceMap,openId, pageUrl,templateId);

推送成功效果


在这里插入图片描述

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-11-12 19:42:39  更:2021-11-12 19:44:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 2:41:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码