新版小程序订阅消息-原模板消息前后端封装实现(Java)

12 篇文章 0 订阅
3 篇文章 0 订阅

小程序原模板消息已在2020年1月10号停止使用,之前通过收集form_id来推送模板消息的日子一去不复返,在看过新版小程序订阅消息后,我重新封装了前后端模板消息(订阅下消息)推送的实现

推送业务流程:点击事件拉起wx.requestSubscribeMessage模板消息授权->用户同意/拒绝->后台API推送

小程序端实现:

利用app.js全局函数来实现-在app.js中添加以下函数,通过版本库的比较来引导用户打开订阅授权以及每一个模板ID授权之后只弹出一次,过期再次重新拉起订阅授权

//拉起订阅模板消息授权 tempId为小程序后台添加的模板消息ID
  subscribeMessage:function(tempId) {
    let _this = this;
    //需要订阅的消息模板,在微信公众平台手动配置获取模板ID
    let message = tempId;
    let messageEx = CACHE.get(tempId,'');
    if (messageEx == 'accept') {
      //用户已经允许过
      return;
    }
    //如果总是拒绝(subscriptionsSetting,2.10.1库才支持)
    if (_this.versionCompare('2.10.1')) {
      wx.getSetting({
        withSubscriptions: true, //是否同时获取用户订阅消息的订阅状态,默认不获取
        success: (res) => {
          if (res.subscriptionsSetting && res.subscriptionsSetting.itemSettings &&
            res.subscriptionsSetting.itemSettings[message] == "reject") {
            //打开设置去设置
            _this.openConfirm('检测到您没打开推送权限,是否去设置打开?')
          } else {
            wx.requestSubscribeMessage({
              tmplIds: [message],
              success: (res) => {
                if (res[message] == 'accept') {
                  //用户允许
                  CACHE.put(message,'accept',259200);//缓存3天
                }
              },
              fail: (res) => {
                console.info(res)
              },
            })
          }
        }
      })
    } else if (app.versionCompare('2.4.4')) {
      wx.requestSubscribeMessage({
        tmplIds: [message],
        success: (res) => {
          if (res[message] == 'accept') {
            //用户允许
            CACHE.put(message,'accept',259200);//缓存3天
          }
        },
        fail: (res) => {
          console.info(res)
        },
      })
    }
  },
   //打开设置
   openConfirm:function(message) {
    wx.showModal({
      content: message,
      confirmText: "确认",
      cancelText: "取消",
      success: (res) => {
        //点击“确认”时打开设置页面
        if (res.confirm) {
          wx.openSetting({
            success: (res) => {
              console.log(res.authSetting)
            },
            fail: (error) => {
              console.log(error)
            }
          })
        } else {
          console.log('用户点击取消')
        }
      }
    });
  },
  //基础库版本比较
  versionCompare:function(v) {
    const version = wx.getSystemInfoSync().SDKVersion
    if (this.compareVersion(version, v) >= 0) {
      return true
    } else {
      return false
    }
  },
  //版本比较
  compareVersion:function(v1, v2) {
    v1 = v1.split('.')
    v2 = v2.split('.')
    var len = Math.max(v1.length, v2.length)
   
    while (v1.length < len) {
      v1.push('0')
    }
    while (v2.length < len) {
      v2.push('0')
    }
    for (var i = 0; i < len; i++) {
      var num1 = parseInt(v1[i])
      var num2 = parseInt(v2[i])
   
      if (num1 > num2) {
        return 1
      } else if (num1 < num2) {
        return -1
      }
    }
    return 0
  },

使用方式:在小程序任何点击事件触发的方法中调用 如:

onClosePop(fn) {
    app.subscribeMessage('BOEzbw5PLtJjuAcWA0V0051y-BZWK5x2EzqK6lOp6W4');
},

至此小程序前台已完成订阅消息授权的操作,接下来通过Java后台根据业务需求来推送消息

新建WeixinSmallAppTemplateService.java

package com.xcloud.api.wechat.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xcloud.api.wechat.entity.Template;
import com.xcloud.api.wechat.entity.TemplateParam;
import com.xcloud.common.utils.https.HttpClientUtil;
import com.xcloud.common.utils.wechat.ListInitializer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class WeixinSmallAppTemplateService {

    public static final String SEND_TEMPLATE_MESSAGE = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token={{ACCESSTOKEN}}";

    /**
     * 推送小程序模板消息
     * @param account 原始ID
     * @param openid 用户微信ID
     * @param templateCode 模板消息ID
     * @param page 跳转页面
     * @param initializer 初始化模板数据
     */
    public void send(String account, String openid, String templateCode, ListInitializer<TemplateParam> initializer, String page, String accessToken) {
        List<TemplateParam> map = new ArrayList<>();
        initializer.init(map);
        Template template = new Template();
        //拼接数据
        template.setTouser(openid);
        template.setTemplate_id(templateCode);
        template.setPage(page);
        template.setData(map);
        template.setMiniprogram_state(MINIAPP_STATE);//跳转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版
        String json =  template.toJSON();
        String url = SEND_TEMPLATE_MESSAGE.replace("{{ACCESSTOKEN}}", accessToken);
        String ret = HttpClientUtil.sendPost(url, json);
        JSONObject jsonResult = JSON.parseObject(ret);
        if(jsonResult!=null){
            System.out.println(jsonResult);
            int errorCode=jsonResult.getInteger("errcode");
            String errorMessage=jsonResult.getString("errmsg");
            if(errorCode==0){
                log.error("Send Success");
            }else{
                log.error("订阅消息发送失败:"+errorCode+","+errorMessage);
            }
        }
    }
}

所用到的工具类和方法

import lombok.*;

@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class TemplateParam {
    private String key;
    private String value;
}
import lombok.*;

import java.util.List;

@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Template {
    private String touser; //接收者(用户)的 openid
    private String template_id; //所需下发的订阅模板id
    private String miniprogram_state; //跳转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版
    private List<TemplateParam> data; //模板内容,格式形如 { "key1": { "value": any }, "key2": { "value": any } }
    private String page; //点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转。

    public String toJSON() {
        StringBuffer buffer = new StringBuffer();
        buffer.append("{");
        buffer.append(String.format("\"touser\":\"%s\"", this.touser)).append(",");
        buffer.append(String.format("\"template_id\":\"%s\"", this.template_id)).append(",");
        buffer.append(String.format("\"page\":\"%s\"", this.page)).append(",");
        buffer.append("\"data\":{");
        TemplateParam param = null;
        for (int i = 0; i < this.data.size(); i++) {
            param = data.get(i);
            // 判断是否追加逗号
            if (i < this.data.size() - 1){
                buffer.append(String.format("\"%s\": {\"value\":\"%s\"},", param.getKey(), param.getValue()));
            }else{
                buffer.append(String.format("\"%s\": {\"value\":\"%s\"}", param.getKey(), param.getValue()));
            }
        }
        buffer.append("}");
        buffer.append("}");
        return buffer.toString();
    }
}
/**
     * 发送post请求 json格式
     * @param url
     * @param param
     * @return
     */
    public static String sendPost(String url, String param) {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("Accept", "application/json");
            conn.setRequestProperty("Content-Type", "application/json");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送 POST 请求出现异常!"+e);
            e.printStackTrace();
        }
        //使用finally块来关闭输出流、输入流
        finally{
            try{
                if(out!=null){
                    out.close();
                }
                if(in!=null){
                    in.close();
                }
            }
            catch(IOException ex){
                ex.printStackTrace();
            }
        }
        return result;
    }
import java.util.List;

/**
 * (description)
 * created at 2014/9/30
 *
 * @author laoWang
 */
public interface ListInitializer<K> {

    void init(List<K> m);
}

推送订阅消息调用方法:

/**
     * 发送用户登记变更订阅提醒
     * @param account
     * @param openId
     * @param userName
     * @param userTitle
     * @throws Exception
     */
    public void sendGradeChangeTemplate(String account, String openId, String userName, String userTitle, String accessToken)  throws Exception{
        Date date = new Date();
        //日期格式化显示,首先定义格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//显示2017-10-27 10:00:00格式
        final String thing1 = userName;
        final String thing2 = userTitle;
        final String time3 = sdf.format(date);

        try {
            weixinSmallAppTemplateService.send(account, openId, "HWLCaIqUjLHYKvDAFXqVa497izzPHjFlcUWozps2lNE",
                    new ListInitializer<TemplateParam>() {
                        @Override
                        public void init(List<TemplateParam> m) {
                            m.add(new TemplateParam("thing1", thing1));
                            m.add(new TemplateParam("thing2", thing2));
                            m.add(new TemplateParam("time3", time3));
                        }
                    }, "pages/mine/mine",accessToken);
        } catch (Exception e) {
            log.error("小程序发送订阅消息失败: " + e.getMessage());
            e.printStackTrace();
            throw new Exception(e.getMessage());//最后一行
        }
    }

至此,完整的小程序订阅消息(原模板消息)前后端封装实现已经完成,以上代码中工具类注解包括accessToken获取请根据自己业务需要进行实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值