zoukankan      html  css  js  c++  java
  • 快速接入微信小程序的订阅消息

    快速接入微信小程序的订阅消息

    官方文档:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/subscribe-message.html

    2020年11月17日15:59:14  以下内容如有变更,请以官方文档为准。

    小程序订阅消息

    消息能力是小程序能力中的重要组成,我们为开发者提供了订阅消息能力,以便实现服务的闭环和更优的体验。

    订阅消息推送位置:服务通知

    订阅消息下发条件:用户自主订阅

    订阅消息卡片跳转能力:点击查看详情可跳转至该小程序的页面

    intro

    订阅消息包括两种:

    一次性订阅消息

    一次性订阅消息用于解决用户使用小程序后,后续服务环节的通知问题。用户自主订阅后,开发者可不限时间地下发一条对应的服务消息;每条消息可单独订阅或退订。

    长期订阅消息

    一次性订阅消息可满足小程序的大部分服务场景需求,但线下公共服务领域存在一次性订阅无法满足的场景,如航班延误,需根据航班实时动态来多次发送消息提醒。为便于服务,我们提供了长期性订阅消息,用户订阅一次后,开发者可长期下发多条消息。

    目前长期性订阅消息仅向政务民生、医疗、交通、金融、教育等线下公共服务开放,后期将逐步支持到其他线下公共服务业务。

    使用说明

    步骤一:获取模板 ID

    在微信公众平台手动配置获取模板 ID:

    登录 https://mp.weixin.qq.com 获取模板,如果没有合适的模板,可以申请添加新模板,审核通过后可使用。

    步骤二:获取下发权限

    详见小程序端消息订阅接口 wx.requestSubscribeMessage

    步骤三:调用接口下发订阅消息

    详见服务端消息发送接口 subscribeMessage.send

    注意事项

    用户勾选 “总是保持以上选择,不再询问” 之后,下次订阅调用 wx.requestSubscribeMessage 不会弹窗,保持之前的选择,修改选择需要打开小程序设置进行修改。

    快速接入

    请先按照官文文档写的步骤开通好订阅消息模板。

    1、小程序代码

     <!--index.wxml-->
    
    <view class="container">
      <text class="user-motto">{{openId}}</text>
      <button class="btn green" bindtap="onSubscribe" hover-class="btn-hover">
      订阅
      </button>
    </view>
    

      

    //index.js
    //获取应用实例
    const app = getApp()
    
    Page({
      data: {
        openId: '',
        userInfo: {},
        hasUserInfo: false,
        canIUse: wx.canIUse('button.open-type.getUserInfo')
      },
      //事件处理函数
      bindViewTap: function() {
        wx.navigateTo({
          url: '../logs/logs'
        })
      },
      //订阅按钮事件
      onSubscribe: function(e) {
        let that = this 
        //申请订阅消息 模板IDXXX
        wx.requestSubscribeMessage({
          tmplIds: ['模板IDXXX'],
          success(res) {
            let status = res['模板IDXXX']
            if(status === "reject"){
              console.log("拒绝")
              //提示: 您拒绝了消息提示,后续将接收不到消息通知,打开小程序设置进行修改。
            }
            console.log(that.openId)
            //发送测试消息
            wx.request({
              url: 'http://localhost:8080/api/wxmini/sendSubscribeMessage',
              data: {
                openId: that.data.openId
              },
              success(res){
                console.log(res.data)
              }
            })
          }});
      },
      onLoad: function () {
          let that =this
          //获取微信登录openId
          wx.login({
            success (res) {
              //console.log(res.code)
              if (res.code) {
                //发起网络请求
                wx.request({
                  url: 'http://localhost:8080/api/wxmini/jscode2session',
                  data: {
                    code: res.code
                  },
                  success(res){
                    console.log(res.data.openId)
                    that.setData({
                      openId: res.data.openId
                    })
                  }
                })
              } else {
                console.log('登录失败!' + res.errMsg)
              }
            }
          })
      }
    })
    

      

    2、后台接口核心代码
    package com.zhaojie.wechat.demo.controller;
    
    import com.zhaojie.wechat.demo.service.IWxService;
    import com.zhaojie.wechat.demo.vo.Jscode2sessionVo;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiImplicitParam;
    import io.swagger.annotations.ApiImplicitParams;
    import io.swagger.annotations.ApiOperation;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.validation.annotation.Validated;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    
    @Api(tags = {"微信小程序"})
    @Slf4j
    @Validated
    @RestController
    @RequestMapping("/api/wxmini")
    public class WxMiniController {
    
        @Autowired
    private IWxService wxService; 
    
    @ApiOperation(value = "获取小程序用户的openid")
        @GetMapping("/jscode2session")
        @ApiImplicitParams({
                @ApiImplicitParam(name = "code", value = "wx.login返回的code", required = true, dataType = "String")
        })
        public Object jscode2session(@RequestParam String code) {
            Jscode2sessionVo jscode2sessionVo = wxService.jscode2session(code);
            return jscode2sessionVo;
    }
    
        @ApiOperation(value = "小程序订阅消息发送")
        @ApiImplicitParams({
                @ApiImplicitParam(name = "openId", value = "接收者(用户)的 openid", required = true, dataType = "String")
        })
        @GetMapping("/sendSubscribeMessage")
        public Object sendSubscribeMessage(@RequestParam String openId) {
            return "小程序订阅消息" + wxService.sendSubscribeMessage(openId);
    }
    }
    
    package com.zhaojie.wechat.demo.service.impl;
    
    import cn.hutool.json.JSONObject;
    import cn.hutool.json.JSONUtil;
    import com.zhaojie.wechat.demo.common.Constant;
    import com.zhaojie.wechat.demo.service.IWxService;
    import com.zhaojie.wechat.demo.vo.Jscode2sessionVo;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.*;
    import org.springframework.stereotype.Service;
    import org.springframework.web.client.RestTemplate;
    
    @Slf4j
    @Service
    public class WxServiceImpl implements IWxService {
    
        @Autowired
        private RestTemplate restTemplate;
    
        @Override
        public Jscode2sessionVo jscode2session(String code) {
            //登录凭证校验。通过 wx.login 接口获得临时登录凭证 code 后传到开发者服务器调用此接口完成登录流程。
            String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + Constant.WX_APP_ID +
                    "&secret=" + Constant.WX_SECRET + "&js_code=" + code + "&grant_type=authorization_code";
            String forObject = restTemplate.getForObject(url, String.class);
            //返回的 JSON 数据包
            //属性   类型 说明
            //openid   string 用户唯一标识
            //session_key  string 会话密钥
            //unionid  string 用户在开放平台的唯一标识符,在满足 UnionID 下发条件的情况下会返回,详见 UnionID 机制说明。
            //errcode  number 错误码
            //errmsg   string 错误信息
            JSONObject result = JSONUtil.parseObj(forObject);
            Jscode2sessionVo jscode2sessionVo = new Jscode2sessionVo();
            jscode2sessionVo.setOpenId(result.getStr("openid"));
            jscode2sessionVo.setErrmsg(result.getStr("errmsg"));
            jscode2sessionVo.setErrcode(result.getStr("errcode"));
            return jscode2sessionVo;
        }
    
        @Override
        public String getAccessToken() {
            try {
                // 线上不需要每次都去获取access_token,需要把它缓存起来。我这里仅测试就不缓存了!!!
                /*String redisAccessToken = redisSeConstantrvice.get(Constant.WX_ACCESS_TOKEN);
                if (StrUtil.isNotEmpty(redisAccessToken)) {
                    return redisAccessToken;
                }*/
                //获取小程序全局唯一后台接口调用凭据(access_token)。调用绝大多数后台接口时都需使用 access_token,开发者需要进行妥善保存。
                String url = "https://api.weixin.qq.com/cgi-bin/token?appid=" + Constant.WX_APP_ID +
                        "&secret=" + Constant.WX_SECRET + "&grant_type=client_credential";
                String forObject = restTemplate.getForObject(url, String.class);
                //返回的 JSON 数据包
                //属性   类型 说明
                //access_token string 获取到的凭证
                //expires_in   number 凭证有效时间,单位:秒。目前是7200秒之内的值。
                //errcode  number 错误码
                //errmsg   string 错误信息
                log.error("获取小程序全局唯一后台接口调用凭据,msg{}", forObject);
                JSONObject result = JSONUtil.parseObj(forObject);
                String accessToken = result.getStr("access_token");
                /*if (StrUtil.isNotEmpty(accessToken)) {
                    //存入Redis
                    redisService.set(Constant.WX_ACCESS_TOKEN, accessToken, 7200 * 1000L);
                }*/
                return accessToken;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        @Override
        public String sendSubscribeMessage(String openId) {
            String accessToken = this.getAccessToken();
            log.info("accessToken {}", accessToken);
            HttpHeaders httpHeaders = new HttpHeaders();
            //注意这里要是json格式的提交
            httpHeaders.setContentType(MediaType.APPLICATION_JSON);
            //我这里测试直接拼接的,请按照你自己模板的配置去改下面的json字符串
            //官方文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.send.html
            StringBuffer jsonParam = new StringBuffer();
            jsonParam.append("{");
            jsonParam.append(""touser": "" + openId + "",");
            jsonParam.append(""template_id": "" + Constant.WX_TMPL_ID + "",");
            jsonParam.append(""page": "" + Constant.WX_TMPL_PAGE + "",");
            jsonParam.append(""data": {");
            jsonParam.append(""name1": { "value": "zhaojie"},");
            jsonParam.append(""thing13": { "value": "预约产品"},");
            jsonParam.append(""date3": { "value": "2020年11月17日 16:59"},");
            jsonParam.append(""phrase9": { "value": "预约中"},");
            jsonParam.append(""thing7": { "value": "如有疑问请联系客服人员"}");
            jsonParam.append("}");
            jsonParam.append("}");
            HttpEntity<String> httpEntity = new HttpEntity<>(jsonParam.toString(), httpHeaders);
            ResponseEntity<String> entity = restTemplate.exchange("https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + accessToken,
                    HttpMethod.POST, httpEntity, String.class);
            String result = entity.getBody();
            log.info("result {}", result);
            return result;
        }
    }
    

      

    package com.zhaojie.wechat.demo.common;
    
    /**
     * 常量
     */
    public class Constant {
        // 系统前缀
        public static final String SYS_PREFIX = "WECHAT-DEMO:";
        // 小程序全局唯一后台接口调用凭据(access_token)。调用绝大多数后台接口时都需使用 access_token,开发者需要进行妥善保存。
        public static final String WX_ACCESS_TOKEN = SYS_PREFIX + "WX_ACCESS_TOKEN";
        // 小程序订阅消息模板 改成自己的参数
        public static final String WX_TMPL_ID = "XXXXX;
        public static final String WX_TMPL_PAGE = "pages/index/index";
        // 小程序配置信息 改成自己的
        public static final String WX_APP_ID = "XXXX";
        public static final String WX_SECRET = "XXXX";
    }
    

      

     

     

    3、运行结果

    注意未发布体验版无法接收到消息

     

     

     

     

     

  • 相关阅读:
    R语言 单变量重命名与删除
    R语言 查看函数源代码
    R语言 for循环之break,next
    ROC & AUC笔记
    rmarkdown教程
    github教程
    logistic regression与SVM
    sql语句,order by
    将权重加载到不同的结构(有一些共同层)
    人脸识别数据集
  • 原文地址:https://www.cnblogs.com/cnsyear/p/13995565.html
Copyright © 2011-2022 走看看