springboot 实现微信小程序订阅消息的信息推送

微信小程序订阅消息推送:参考官方文档

关于小程序订阅消息

「订阅消息」需要用户主动订阅消息通知,开发者才可向用户推送,也就是需要做本文第二大点,第1小点的操作,且用户同意之后才可

1、一次性订阅消息:用户订阅一次后,开发者可下发一条消息,不限时间。
若用户勾选了“总是保持以上选择,不再询问”且点击了允许,那么以后都默认同意订阅这条消息。用户不再做多次选择,开发者也避免了更繁琐的提醒。

2、长期性订阅消息:用户订阅一次后,可长期下发多条消息。目前长期性订阅消息向政务、医疗、交通、金融、教育等线下公共服务开放,后续将综合评估行业需求和用户体验持续完善(长期订阅消息只针对特定行业开放,所以普通开发者并无法使用)

需要注意的是,一次性订阅消息,用户订阅一次才能发送一次消息,订阅一次是无法多次发送的!

先给大家看看模板消息推送之后的效果图
在这里插入图片描述
接下来我们上代码

一、配置小程序相关参数

1、微信小程序相关参数

application.yml 文件中做如下配置


#微信小程序
wx:
  #微信小程序的 appId
  appId: 小程序的appId
  #微信小程序的 appSecret
  appSecret: 小程序的appSecret
  #模板 ID
  templateId: 小程序订阅消息的模板id

2、全局配置文件参数读取类

@Configuration
public class BaseConfiguration {

    //微信小程序
    public static String WX_APPID;
    public static String WX_APPSECRET;
    public static String WX_TEMPLATE_ID;

    @Value("${wx.appId}")
    public void setWxAppid(String param){
        WX_APPID = param;
    }

    @Value("${wx.appSecret}")
    public void setWxAppsecret(String param){
        WX_APPSECRET = param;
    }

    @Value("${wx.templateId}")
    public void setWxTemplateId(String param){
        WX_TEMPLATE_ID = param;
    }
}

二、发送订阅消息前必要参数的获取工作

1、订阅消息认证

这一步一般是小程序代码进行实现
调起客户端小程序订阅消息界面,返回用户订阅消息的操作结果。当用户勾选了订阅面板中的“总是保持以上选择,不再询问”时,模板消息会被添加到用户的小程序设置页,通过 wx.getSetting 接口可获取用户对相关模板消息的订阅状态

wx.requestSubscribeMessage({
  tmplIds: [''],//你的模板id
  success (res) {
	if (res.errMsg == "requestSubscribeMessage:ok") {
		//表示用户同意订阅
	}
 }//回调函数
})

2、获取登录凭证(code)

因为获取用户 openid 需要通过调用接口获取登录凭证(code),通过凭证也就是 code 进而换取用户登录态信息,包括用户的唯一标识(openid)及本次登录的会话密钥(session_key)等

小程序代码中调用接口获取登陆凭证,也就是获取 code ,然后将 code 传到后端,后端通过 code 获取用户 openid

wx.login({
  success (res) {
    if (res.code) {
      //这里可以调用后端方法,让后端去获取 openid
      wx.request({
        url: 'https://test.com/onLogin',
        data: {
          code: res.code
        }
      })
    } else {
      console.log('登录失败!' + res.errMsg)
    }
  }
})

3、根据小程序传入的 code 获取 openid

public class HttpURLConnectionUtil {
private static final CloseableHttpClient httpclient = HttpClients.createDefault();

    /**
     * 发送HttpGet请求
     * @param url
     * @return
     */
    public static String sendGet(String url) {

        HttpGet httpget = new HttpGet(url);
        CloseableHttpResponse response = null;
        try {
            response = httpclient.execute(httpget);
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        String result = null;
        try {
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                result = EntityUtils.toString(entity);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }
}
 		//根据微信用户 code 获取 openID
        String requestUrl = "https://api.weixin.qq.com/sns/jscode2session?appid=" + BaseConfiguration.WX_APPID + "&secret=" + BaseConfiguration.WX_APPSECRET + "&js_code=" + baseRequest.getCode() + "&grant_type=authorization_code";
        Map<String, Object> result = new HashMap<String, Object>();

        String response = HttpURLConnectionUtil.sendGet(requestUrl);
        JSONObject OpenidJSONO = JSONObject.fromObject(response);
        //OpenidJSONO可以得到的内容:access_token expires_in  refresh_token openid scope
        String Openid = String.valueOf(OpenidJSONO.get("openid"));
        String AccessToken = String.valueOf(OpenidJSONO.get("access_token"));
        String Scope = String.valueOf(OpenidJSONO.get("scope"));//用户保存的作用域
        String refresh_token = String.valueOf(OpenidJSONO.get("refresh_token"));

        result.put("openid", Openid);
        result.put("AccessToken", AccessToken);
        result.put("scope", Scope);
        result.put("refresh_token", refresh_token);

4、获取 access_token

获取小程序全局唯一后台接口调用凭据(access_token)。调用绝大多数后台接口时都需使用 access_token

/**
     * 获取access_token
     *
     * @return
     */
    public static String getAccessToken() {
        String url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential" +
                "&appid=" + BaseConfiguration.WX_APPID +
                "&secret=" + BaseConfiguration.WX_APPSECRET;
        String result = HttpURLConnectionUtil.sendGet(url);
        JSONObject object=JSON.parseObject(result);
        String accessToken = object.getString("access_token");
        String errcode = object.getString("errcode");
        String errmsg = object.getString("errmsg");
        if (StringUtils.isNotBlank(accessToken)) {
            log.info("获取 access_token 成功, Send Success");
            return accessToken;
        } else {
            log.info("获取 access_token 失败:", errcode, errmsg);
        }
        return null;
    }

三、封装订阅消息的模板参数

1、模板参数类

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TemplateParam {

    private String key;
    private String value;

}

2、订阅消息参数对象

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Template {

    //用户 openid
    private String touser;
    //模板id
    private String template_id;
    //点击模板跳转的页面
    private String page;
    //模板参数
    private List<TemplateParam> data;



    //由于模板参数格式问题,自定义转换 JSON
    public String toJSON() {
        StringBuffer buffer = new StringBuffer();
        buffer.append("{");
        //"touser":"1234"
        buffer.append(String.format("\"touser\":\"%s\"", this.touser)).append(",");
        //"template_id":"1234"
        buffer.append(String.format("\"template_id\":\"%s\"", this.template_id)).append(",");
        //"page":"pages/index/index"
        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){
                //"thing1": {"value":"001"},
                buffer.append(String.format("\"%s\": {\"value\":\"%s\"},", param.getKey(), param.getValue()));
            }else{
                //"thing1": {"value":"001"}
                buffer.append(String.format("\"%s\": {\"value\":\"%s\"}", param.getKey(), param.getValue()));
            }
        }
        buffer.append("}");
        buffer.append("}");
        return buffer.toString();
    }

    //格式转换测试
    public static void main(String[] args) {
        System.out.println(String.format("\"%s\": {\"value\":\"%s\"}", "thing1", "001"));//"thing1": {"value":"001"}
    }
}

四、开始推送模板消息

@RestController
@RequestMapping("/sendMessageWx")
@Slf4j
public class SendMessageWxController {

    @GetMapping("/sendMessageWx")
    @ApiOperation("订阅消息推送测试")
    public static void SendMessage() {

        String accessToken = SendMessageWxController.getAccessToken();

        List<TemplateParam> templateParams = new ArrayList<>();
        //当前进度
        templateParams.add(TemplateParam.builder().key("thing3").value("创建").build());
        //事项编码
        templateParams.add(TemplateParam.builder().key("character_string6").value("001").build());
        //事项名称
        templateParams.add(TemplateParam.builder().key("thing2").value("这里是事项名称").build());
        //备注
        templateParams.add(TemplateParam.builder().key("thing9").value("这里是备注").build());

        Template template = Template.builder()
                .template_id(BaseConfiguration.WX_TEMPLATE_ID)//模板 ID
                .touser("填写获取到的用户openid")//用户 openid
                .data(templateParams) //模板参数
                .page("填写你要跳转的小程序的页面")//点击消息跳转页面
                .build();

        //请求地址
        String requestUrl = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token="+accessToken;

         log.info("推送的模板参数信息:"+ template.toJSON());

        String jsonResult = null;
        try {
            jsonResult = HttpURLConnectionUtil.GetPostUrl(requestUrl, template.toJSON());
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (jsonResult != null) {
            JSONObject OpenidJSONO = JSONObject.parseObject(jsonResult);
            System.out.println(jsonResult);
            String errorCode = OpenidJSONO.get("errcode").toString();
            String errorMessage = OpenidJSONO.get("errmsg").toString();
            if ("0".equals(errorCode)) {
                log.info("推送订阅消息: Send Success");
            } else {
                log.info("订阅消息发送失败:"+ errorCode+errorMessage);
            }
        } else {
            log.info("订阅消息发送失败");
        }
    }

五、效果图

本效果图来自电脑微信
在这里插入图片描述

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值