微信一次性订阅消息

简介: 一次性订阅消息官方文档:消息管理>发送一次性订阅消息 开发者可以通过一次性订阅消息授权让微信用户授权第三方移动应用(接入说明)或公众号,获得发送一次订阅消息给到授权微信用户的机会。

一次性订阅消息官方文档:消息管理>发送一次性订阅消息

开发者可以通过一次性订阅消息授权让微信用户授权第三方移动应用接入说明)或公众号,获得发送一次订阅消息给到授权微信用户的机会。授权微信用户可以不需要关注公众号。微信用户每授权一次,开发者可获得一次下发消息的权限。对于已关注公众号的,消息将下发到公众号会话;未关注公众号的,将下发到服务通知

本篇文章主要讨论公众号

1、确认是否有权限

已认证的公众号即有权限,可登陆公众平台在接口权限列表处查看(如下图)。目前测试号还无法测试一次性订阅消息

一次性订阅消息-查看模板ID

2、配置相关的参数

  • 查看AppId以及AppSecret (发送一次性订阅消息需要ACCESS_TOKEN、获取ACCESS_TOKEN需要使用到)
  • 配置回调域名

image.png

设置授权域名-1

设置授权域名-2

3、授权发送一次性订阅消息

具体的参数看文档这里就不详细介绍了。

public static String getAuthorizeURL(String appId, String scene, String template_id,String redirectUri, String reserved) throws UnsupportedEncodingException {
        StringBuffer sbf = new StringBuffer();
        sbf.append(authorize_uri).append("&appid=").append(appId)
        .append("&scene=").append(scene)
        .append("&template_id=").append(template_id)
        .append("&redirect_uri=").append(URLEncoder.encode(redirectUri, Charsets.UTF_8.name()).replace("+", "%20"));
        if (StrKit.notBlank(reserved)) {
            sbf.append("&reserved=").append(reserved);
        }
        sbf.append("#wechat_redirect");

        return sbf.toString();
    }

用户同意或取消授权后会返回相关信息
如果用户点击同意或取消授权,页面将跳转至:

redirect_url/?openid=OPENID&template_id=TEMPLATE_ID&action=ACTION&scene=SCENE

4、通过API推送订阅模板消息给到授权微信用户

http请求方式: post
https://api.weixin.qq.com/cgi-bin/message/template/subscribe?access_token=ACCESS_TOKEN

{
  "touser": "OPENID",
  "template_id": "TEMPLATE_ID",
  "url": "URL",
  "scene": "SCENE",
  "title": "TITLE",
  "data": {
    "content": {
      "value": "VALUE",
      "color": "COLOR"
    }
  }
}

具体封装代码如下:

/**
     * 发送一次性订阅消息
     * 
     * @param jsonStr
     *            json字符串
     * @return ApiResult 
     * 
     */
    public static ApiResult subscribe(String jsonStr) {
        String jsonResult = HttpUtils.post(subscribe + AccessTokenApi.getAccessTokenStr(), jsonStr);
        return new ApiResult(jsonResult);
    }

    public static ApiResult subscribe(SubscribeInfo subscribeInfo) {
        return new ApiResult(JsonKit.toJson(subscribeInfo));
    }

    public static ApiResult subscribe(String openId, String templateId, String url, int scene, String title,
            String value, String color) {
        SubscribeInfo subscribeInfo = new SubscribeInfo.Builder()
                .setTouser(openId).setTemplate_id(templateId).setUrl(url)
                .setScene(String.valueOf(scene)).setTitle(title)
                .setData(new Data.Builder()
                        .setContent(new Content.Builder()
                                .setColor(color).setValue(value)
                                .create())
                        .create())
                .create();
        System.out.println(JsonUtils.toJson(subscribeInfo));                
        return subscribe(JsonUtils.toJson(subscribeInfo));
    }

Builder模式构建请求参数的json对象

class SubscribeInfo {
    private String touser;
    private String template_id;
    private String url;
    private String scene;
    private String title;
    private Data data;

    public static class Builder{
        private String touser;
        private String template_id;
        private String url;
        private String scene;
        private String title;
        private Data data;

        public Builder setTouser(String touser) {
            this.touser = touser;
            return this;
        }
        public Builder setTemplate_id(String template_id) {
            this.template_id = template_id;
            return this;
        }
        public Builder setUrl(String url) {
            this.url = url;
            return this;
        }
        public Builder setScene(String scene) {
            this.scene = scene;
            return this;
        }
        public Builder setTitle(String title) {
            this.title = title;
            return this;
        }
        public Builder setData(Data data) {
            this.data = data;
            return this;
        }
        public SubscribeInfo create(){    
            return new SubscribeInfo(this);    
        }
    }


    private SubscribeInfo(Builder builder) {
        if (StrKit.isBlank(builder.touser)) {
            throw new IllegalStateException("touser is null");
        }
        if (StrKit.isBlank(builder.template_id)) {
            throw new IllegalStateException("template_id is null");
        }
        if (StrKit.isBlank(builder.url)) {
            throw new IllegalStateException("url is null");
        }
        if (StrKit.isBlank(builder.scene)) {
            throw new IllegalStateException("scene is null");
        }
        if (StrKit.isBlank(builder.title)) {
            throw new IllegalStateException("title is null");
        }
        if (!StrKit.notNull(builder.data)) {
            throw new IllegalStateException("data is null");
        }

        this.touser = builder.touser;
        this.template_id = builder.template_id;
        this.url = builder.url;
        this.scene = builder.scene;
        this.title = builder.title;
        this.data = builder.data;
    }

    public String getTouser() {
        return touser;
    }

    public String getTemplate_id() {
        return template_id;
    }

    public String getUrl() {
        return url;
    }

    public String getScene() {
        return scene;
    }

    public String getTitle() {
        return title;
    }

    public Data getData() {
        return data;
    }
}

class Data {
    private Content content;

    public static class Builder {
        private Content content;

        public Builder setContent(Content content) {
            this.content = content;
            return this;
        }
        public Data create(){    
           return new Data(this);    
        }    
    }

    private Data(Builder builder) {
        if (!StrKit.notNull(builder.content)) {
            throw new IllegalStateException("content is null");
        }
        this.content = builder.content;
    }

    public Content getContent() {
        return content;
    }


}

class Content {
    private String value;
    private String color;

    public static class  Builder{
        private String value;
        private String color;

        public Builder setValue(String value) {
            this.value = value;
            return this;
        }
        public Builder setColor(String color) {
            this.color = color;
            return this;
        }

        public Content create(){
            return new Content(this);
        }

    }

    private Content(Builder builder) {
        if (StrKit.isBlank(builder.value)) {
            throw new IllegalStateException("value is null");
        }
        if (StrKit.isBlank(builder.color)) {
            throw new IllegalStateException("color is null");
        }
        this.value = builder.value;
        this.color = builder.color;
    }

    public String getValue() {
        return value;
    }

    public String getColor() {
        return color;
    }
}

5、遗留问题

1、授权后页面跳转无效redirect_url
2、发送一次性订阅消息提示没有权限(认证的服务号)

{"errcode":48001,"errmsg":"api unauthorized hint: [uAi6Za0855sz10!]"}

猜测:应该是官方接口存在问题

推荐阅读
10分钟搭建属于自己的ngork服务器,实现内网穿透
极速开发微信公众号
IJPay让支付触手可及
微信、支付宝App支付

目录
相关文章
|
11月前
|
JSON 小程序 API
小程序(三十四)微信小程序开启订阅消息推送
我这里记录一下我在配置订阅消息推送的时候发生的一些小问题吧,算是经验,给没有做过的同学避个坑。 官方文档地址:小程序订阅消息 | 微信开放文档 (qq.com)
352 0
|
小程序 开发工具 开发者
微信小程序订阅消息点了 “总保持以上选择、全部拒绝,不在询问” 无法再次弹出
微信小程序订阅消息点了 “总保持以上选择、全部拒绝,不在询问” 无法再次弹出
1356 0
|
小程序 Java 开发者
微信小程序+Springboot实现订阅消息推送
微信小程序+Springboot实现订阅消息推送
635 0
|
JSON JavaScript 安全
基于Windows微信实现实时收发微信消息App
基于Windows微信实现实时收发微信消息App
1396 0
基于Windows微信实现实时收发微信消息App
|
小程序 前端开发 API
(前端)微信小程序订阅消息功能实现
步骤一:获取模板 ID 步骤二:获取下发权限 步骤三:调用接口下发订阅消息
296 0
(前端)微信小程序订阅消息功能实现
|
NoSQL Redis 开发者
数据类型-案例:微信接收消息顺序控制| 学习笔记
快速学习数据类型-案例:微信接收消息顺序控制
数据类型-案例:微信接收消息顺序控制| 学习笔记
|
存储 JSON 小程序
unicloud云函数开发微信客服消息自动回复图片消息(完整步骤)
unicloud云函数开发微信客服消息自动回复图片消息(完整步骤)
418 0
unicloud云函数开发微信客服消息自动回复图片消息(完整步骤)
|
JSON 小程序 数据格式
.NET之微信消息模板推送
.NET之微信消息模板推送
230 0
.NET之微信消息模板推送
|
小程序 开发工具
微信小程序订阅消息:用云服务编写订阅消息超详细描述
微信小程序订阅消息:用云服务编写订阅消息超详细描述
微信小程序订阅消息:用云服务编写订阅消息超详细描述