【微信公众号】【消息推送】订阅通知(一次性订阅)

1  什么是订阅通知

订阅通知是一个用户主动订阅服务号按需下发的通知能力,详情可见官方文档

2  通知类型分类及区别

通知类型:分为一次性订阅和长期订阅

  • 一次性订阅,指用户订阅一次,服务号可不限时间地下发一条对应的订阅通知;
  • 长期订阅,指用户订阅一次,服务号可长期多次下发通知,长期订阅通知仅向政务民生、医疗等公共服务领域开放。

   两者的使用区别:

  • 一次性是用户同意一次,我们才能给用户发一条通知消息,是用户同意一次,发一次;
  • 长期订阅是用户同意一次,可长期发送多次通知消息,但这个一般申请不下来,只有政务、医疗等才允许创建这种类型的订阅通知;

3  一次性订阅通知的消息发送步骤

3.1  用户授权

进行用户同意授权,获得发送一次消息的机会,详情可见官方文档

(1)准备授权的链接:

       让用户在手机微信端打开如下链接信息,替换下方内容即可。

  https://mp.weixin.qq.com/mp/subscribemsg?action=get_confirm&appid=公众号的APPID&scene=1000&template_id=订阅通知的模板ID&redirect_url=重定向的地址&reserved=test#wechat_redirect  

注意: 

  订阅通知的模板ID,取图1中所示的授权模板ID,千万别取图2的 

  重定向的地址,要取公众号里配置的业务域名下的地址,如图3;

  SDK方式的请求,返回的字符串即是上边手工拼出来的链接,SDK的好处是access_token不需要自己管理。 

<dependency>
    <groupId>com.github.binarywang</groupId>
    <artifactId>weixin-java-mp</artifactId>
    <version>3.2.0</version>
</dependency>

public static void main(String[] args) {
        // 配置公众号信息
        WxMpInMemoryConfigStorage wxStorage = new WxMpInMemoryConfigStorage();
        wxStorage.setAppId("appId");
        wxStorage.setSecret("secret");
        wxStorage.setTemplateId("一次性授权模板ID");
        // 服务
        WxMpService wxMpService = new WxMpServiceImpl();
        wxMpService.setWxMpConfigStorage(wxStorage);
        WxMpSubscribeMsgService subscribeMsgService = new WxMpSubscribeMsgServiceImpl(wxMpService);

        String res = subscribeMsgService.subscribeMsgAuthorizationUrl("跳转的路径", scene, "reserved");
        System.out.println(res);
}

                      图1 一次性订阅通知授权模板ID

                    图2 错误的授权模板ID

                      图3 重定向地址配置的域名位置

(2)微信授权

     准备好授权链接以后,把链接复制到手机微信里打开,会出现如下图的授权弹窗,点击确认接收即可。

    注意:电脑微信打开不行,我试的是不行。

    

3.2  发送订阅通知消息

   用户授权完成,即可调接口发送订阅通知一次。

  http请求方式: post

https://api.weixin.qq.com/cgi-bin/message/template/subscribe?access_token=ACCESS_TOKEN

参数是否必须说明
touser 填接收消息的用户openid
template_id 订阅消息模板ID
url 点击消息跳转的链接,需要有 ICP 备案
miniprogram 跳小程序所需数据,不需跳小程序可不用传该数据
appid 所需跳转到的小程序appid(该小程序 appid 必须与发模板消息的公众号是绑定关联关系,并且小程序要求是已发布的)
pagepath 所需跳转到小程序的具体页面路径,支持带参数,(示例index?foo=bar)
scene 订阅场景值
title 消息标题,15字以内
data 消息正文,value为消息内容文本(200字以内),没有固定格式,可用\n换行,color为整段消息内容的字体颜色(目前仅支持整段消息为一种颜色)
  POST示例数据:
{
    "touser":"OPENID",
    "template_id":"TEMPLATE_ID  !!!注意这里的模板ID 还是取第一步里用户授权模板ID",
    "url":"URL",
    "miniprogram":{
        "appid":"xiaochengxuappid12345",
        "pagepath":"index?foo=bar !!!这里的域名还是要在公众号里配置的业务域名范围里取"
    },
    "scene":"SCENE",
    "title":"TITLE",
    "data":{
        "content":{
            "value":"VALUE",
            "color":"COLOR"
        }
    }
}

  示例代码一(使用SDK的方式):

public static void main(String[] args) {
        // 配置公众号信息
        WxMpInMemoryConfigStorage wxStorage = new WxMpInMemoryConfigStorage();
        wxStorage.setAppId("appId");
        wxStorage.setSecret("secret");
        // 服务
        WxMpService wxMpService = new WxMpServiceImpl();
        wxMpService.setWxMpConfigStorage(wxStorage);
        WxMpSubscribeMsgService subscribeMsgService = new WxMpSubscribeMsgServiceImpl(wxMpService);
        // 配置小程序信息
        WxMpSubscribeMessage.MiniProgram miniProgram = new WxMpSubscribeMessage.MiniProgram();
        miniProgram.setAppid("跳转小程序appId");

        WxMpSubscribeMessage subscribeMessage = WxMpSubscribeMessage.builder()
                .toUser("发送用户openId")
                .templateId("一次性授权模板ID")
                .miniProgram(miniProgram)
                .title("我是标题")
                .scene("scene")
                .contentValue("我是value\n 你好不好\n我不好")
                .build();

        try {
            boolean b = subscribeMsgService.sendSubscribeMessage(subscribeMessage);
            System.out.println(b);
        } catch (WxErrorException e) {
            e.printStackTrace();
        }
}

  示例代码二(不使用SDK的方式):

public static void main(String[] args) {
        // 请求的API地址
        String url = "https://api.weixin.qq.com/cgi-bin/message/template/subscribe";
        // API token
        String accessToken = "你的access_token 这个你不会不知道怎么获取吧= = 不会的话建议改行吧";

        // 准备内容数据 --消息主体内容
        Map<String, Object> data = Maps.newHashMap();
        data.put("content", Maps.immutableEntry("value", "尊敬的\n你好不好\n我不好"));

        // 准备请求数据
        Map<String, Object> req = Maps.newHashMap();
        req.put("touser", "发送用户的open_id");  //必须
        req.put("template_id", "第一步里授权模板ID"); //必须
        req.put("title", "我是标题"); //必须
        req.put("scene", "1000"); //必须 不传的话  也会出现43101 user refuse to accept the msg
        req.put("miniprogram", Maps.immutableEntry("appid", "自己的小程序APPID")); //非必须
        req.put("data", data); //必须

        // 发送请求
        String sendRes = HttpUtil
                .createPost(url + "?access_token=" + accessToken)
                .body(JSONObject.toJSONString(req)).execute().body();
        System.out.println(sendRes);

        // 正常返回结果{ "errcode":0, "errmsg":"ok" }
    }

  

4  使用中常见问题及解决办法

4.1  错误码42001、错误码40001

{"errcode":42001,"errmsg":"access_token expired rid: 63800a69-7dccc6da-44475ab8"}  access_token过期了

{"errcode":40001,"errmsg":"invalid credential, access_token is invalid or not latest rid: 63800a97-1ddcaeff-058ec99c"}  access_token非法值不对

都需要检查一下access_token的获取对不对

4.2  错误码43101  这个很频繁!!!

  {"errcode":43101,"errmsg":"user refuse to accept the msg rid: 63800af8-2c456ad2-71a09b6f"}

  检查步骤:

  (1)3.1 中的第一步,用户是否确认允许接受的授权 !!! 这个很重要 用户没允许的话  你再怎么发,微信都会拒绝掉

  (2)检查参数里发送的url

  (3)检查参数里的模板ID,是不是和你授权用户订阅通知的模板ID是否一致,都是接口权限菜单里的一次性订阅模板ID

  (4)检查参数里是否有scene  这个不传也会报错

5  总结

我第一次摸索的时候,导致卡顿的点在

1、压根不知道要先授权然后才能调接口发通知,否则你参数都对的话也会报错误码43101

2、模板ID 我一直是取的订阅通知里具体的哪个模板的ID 这个取的是错的,所以一直导致莫名的43101

希望大家能调试顺利,大家加油。

posted @ 2022-11-24 07:56  酷酷-  阅读(22217)  评论(0)    收藏  举报