微信小程序订阅消息

消息能力是小程序能力中的重要组成,以便实现服务的闭环和更优的体验。此前的小程序模板消息接口于2020年1月10日下线,2.10.0 版本开始,开发版和体验版小程序将禁止使用模板消息 fomrId。开发者可使用订阅消息功能。订阅消息特点:

  • 订阅消息推送位置:服务通知
  • 订阅消息下发条件:用户自主订阅
  • 订阅消息卡片跳转能力:点击查看详情可跳转至该小程序的页面

订阅消息的使用主要以下几个步骤:

  1. 获取模板 ID
  2. 获取下发权限
  3. 调用接口下发订阅消息
1. 获取模板 ID

在微信公众平台手动配置获取模板 ID:
登录 https://mp.weixin.qq.com 获取模板,如果没有合适的模板,可以申请添加新模板,审核通过后可使用。
在这里插入图片描述
初始状态下我的模板中没有模板,需要点击添加按钮添加模板。这里需要说明以下,模板库中有两种类型的模板,一次性订阅和长期订阅,长期订阅只会在一些特定的类目下才有。我这里以一次性订阅为例,选择自己合适的模板,设置模板里面要显示的条目即可,确定后就跟我上面截图一样就会看到了。
在这里插入图片描述

这里需要说明的是:一次性订阅和长期订阅。官方社区说明

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

  • 一次性订阅消息可满足小程序的大部分服务场景需求,但线下公共服务领域存在一次性订阅无法满足的场景,如航班延误,需根据航班实时动态来多次发送消息提醒。为便于服务,我们提供了长期性订阅消息,用户订阅一次后,开发者可长期下发多条消息。目前长期性订阅消息仅向政务民生、医疗、交通、金融、教育等线下公共服务开放,后期将逐步支持到其他线下公共服务业务。

2. 获取下发权限

订阅消息的发送同时还需要用户同意接收,否则用户将不会收到消息。在小程序中需要调用下面API,调起客户端小程序订阅消息界面。注意仔细查看该API文档,有很多细节(坑)。先说一个,这个API只会在真机上才生效,模拟器不行,文章结尾再来说说其他的细节。
在这里插入图片描述
如下:

wx.requestSubscribeMessage({
  // 相当于询问用户愿不愿意接收这个模板的订阅消息	
  tmplIds: ['eggfYknjtIhEUupiB3qhbfBt2dHtqe92ff3qgqui6dk'],
  success(res) {
    console.log('已授权接收订阅消息')
  },
  complete(res) {
    console.log(res)
  }
})

所以,简单来说,小程序中需要调用上面的API,并且用户需要同意接收,这样才能接收到发送过来的订阅消息。

3. 调用接口下发订阅消息

我这边是在java服务端程序测试的。首先需要细看发送订阅消息的API

3.1 https请求接口:
POST https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=ACCESS_TOKEN

参数:access_token,后台接口调用凭据,对应的API

GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

所以需要在发送前获取该token_access值。

3.2 post请求体的参数

post请求体中对应的参数,必须是json格式,我这里值传了必须的三项,说明如下,value里面的数据一定要注意按照文档中的格式,否则会包=报数据格式错误的!
在这里插入图片描述
这里面还有一个参数也是需要提前获取的,就是接收消息的用户openid,这个可以在登录时获取,对应API

GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code

这里面有个js_code参数,这个参数可以在小程序端调用wx.login()时获取到。

到这基本上流程已经介绍清楚了,搞清楚相关参数即可。

4. 测试

首先声明,我下面的流程只是作为一次测试,感受下订阅消息的发送效果,实际项目中不要这么整啊,经理会打人的~
流程:
在这里插入图片描述
小程序:
wxml:

<button bindtap="permission" style="margin-bottom:20rpx">权限设定</button>

<button bindtap="send">发送消息</button>

js:

Page({
  onLoad: function () {
  },

  permission(){
    wx.requestSubscribeMessage({
      tmplIds: ['eggfYknjtIhEUupiB3qhbfBt2dHtqe92ff3qgqui6dk'],
      success(res) {
        console.log('已授权接收订阅消息')
      },
      complete(res) {
        console.log(res)
      }
    })

  },

  send(){
    wx.login({
      success(res) {
        if (res.code) {
          console.log(res)
          wx.request({
            url: 'http://自己电脑ip:8090/test/send?code=' + res.code,
            success(res) {
              // console.log(res.data)
            },
            complete(res) {
              // console.log(res)
            }
          })
        }
      }
    })
  }
})

服务端:
pom.xml

<dependency>
   <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>org.junit.vintage</groupId>
            <artifactId>junit-vintage-engine</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.62</version>
</dependency>
<dependency>
    <groupId>cn.gjing</groupId>
    <artifactId>tools-httpclient</artifactId>
    <version>1.2.6</version>
</dependency>

controller:

@RestController
@RequestMapping("/test")
public class TestCtrl {

    @RequestMapping("send")
    public String getToken(@RequestParam("code") String code){
        System.out.println("code:" + code);
        String token = getToken();
        String openid= getOpenId(code);

        Map<String,Object> param = new HashMap<>();
        param.put("touser",openid);
        param.put("template_id","eggfYknjtIhEUupiB3qhbfBt2dHtqe92ff3qgqui6dk");

        Map<String,Object> data = new HashMap<>();
        data.put("thing1",new Value("上海市普陀区"));
        data.put("thing4",new Value("空调清洗"));
        data.put("phone_number8",new Value("17635688803"));
        data.put("thing7",new Value("每周六天,8:00~18:00"));
        data.put("date5",new Value("2019-10-25 12:23"));
        param.put("data",data);
        // 注意检查参数的格式,很容易出现问题
        System.out.println("param:" + JSON.toJSONString(param));

        String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + token;
        Map result = HttpUtils.post(url, param);
        System.out.println("result=" + result);
        return "success";
    }

    private String getToken(){
        String url = "https://api.weixin.qq.com/cgi-bin/token?appid=你的appid&secret=你的appsecret&grant_type=client_credential";
        String result = HttpUtils.get(url);
        Map<String,Object> map = JSON.parseObject(result);
        String access_token = map.get("access_token").toString();
        System.out.println("access_token:" + access_token);
        return access_token;
    }

    private String getOpenId(String code){
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=你的appid" +
                "&secret=你的appsecret" +
                "&js_code="+code+"&grant_type=authorization_code";
        String result = HttpUtils.get(url);
        Map<String,Object> map = JSON.parseObject(result);
        String openid = map.get("openid").toString();
        System.out.println("openid:" + openid);
        return openid;
    }
}

HttpUtils:

package com.example.demo1.ctrl.util;

import cn.gjing.http.HttpClient;
import cn.gjing.http.HttpMethod;

import java.util.Map;

public class HttpUtils {

    public static String get(String url, Map<String, Object> param) {
        String result = HttpClient.builder(url, HttpMethod.GET, String.class)
                .param(param)
                .execute()
                .get();

        return result;
    }

    public static String get(String url) {
        String result = HttpClient.builder(url, HttpMethod.GET, String.class)
                .execute()
                .get();

        return result;
    }

    public static Map post(String url, Map<String, Object> param) {
        Map result = HttpClient.builder(url, HttpMethod.POST, Map.class)
                .body(param)
                .execute()
                .get();
        return result;
    }
}

启动服务器,在手机上打开小程序,先在设置中打开调试功能,否则小程序可能无法调用本地服务端接口。先点击权限按钮,允许接收订阅消息,在点击发送按钮,效果图:
在这里插入图片描述


补充:
一次性订阅消息用户允许一次后,只能接收一次消息,再次发送时会显示用户拒收。长期订阅消息则是可以接收多条。

result={errcode=43101, errmsg=user refuse to accept the msg hint: [NLYvMa06944924]}

如果你勾选了这个“保持以上选择”,那么这个弹框将再也不会出来了~~我这示例中当你再点一次权限按钮,还是能接收到一次消息的,只是弹框不显示了。
在这里插入图片描述

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值