前言

为何要订阅消息 & 订阅的好处

相信你也曾被微信的服务通知所骚扰过(bushi)…

没错,微信的订阅消息会发送到用户的服务通知处;

服务通知不同于公众号/服务号等通知;

“服务通知”:属于强提醒,会以大红点的形式出现,而且还会在手机/电脑提醒消息

“公众号/服务号”:属于弱提醒,只会以小红点的形式出现,不会在手机/电脑中提醒。

如图(对比):

在这里插入图片描述

因此,订阅消息的好处就不言而喻了,最显然的就是:提高用户的转化率


一、一次性订阅 & 长期订阅

一次性订阅:用户订阅后,在任意时间发一次消息给用户,不能发第二次。

长期订阅:用户订阅后,可长期发送多条信息。(但是这个要求行业和资质高,只有特定的几个类目才能选)

那么如何实现一次性订阅也能长期发送多条消息呢?

如图:

当你调用wx.requestSubscribeMessage接口时(最多可传入3个模板id),就会触发授权弹窗。

注意!细节来了!

弹窗授权为发送一次以下消息(即一次性订阅);
而下方的总是保持以上选择是默认的选择项(字体这么小而且还是灰色的,是不是不容易发现0.0);

简单来讲:授权发送一次以下消息 + 总是保持以上选择 = 只要你授权一次,我就可以无限次发订阅消息

但是需要用户手动开启授权模板,如下图留言通知/榜单更新通知/新活动通知的授权按钮默认是关闭的

虽然说是这么说,但是可以通过诱导(引导)用户来开启,如:不开启可能会导致功能无法使用…
(懂的都懂)

在这里插入图片描述

二、操作步骤

接下来是简单的代码实现,具体的可以自己添加更多的业务逻辑

1. 创建模板

进入微信小程序后台—“基础功能”—“订阅消息”,进入"公共模板库"挑选合适的模板后,得到模板ID。

在这里插入图片描述

2. 前端授权订阅消息

微信官方文档:小程序订阅消息(用户通过弹窗订阅)开发指南

使用 uni.requestSubscribeMessage 发起授权,传参为模板ID,若有多个则需要传数组。
(最多授权3个模板ID)

注:开发时使用了uni-app框架,微信官方的API为 wx.requestSubscribeMessage,效果是一致的。

代码如下(示例):

Tip:可以在关键业务按钮埋下授权订阅消息代码让用户授权,但也要注意用户体验。

// 创建问题
const createQuestion = async () => {
  // 检查模板消息订阅权限
  try {
    const subscribeResult = await uni.requestSubscribeMessage({
      tmplIds: [
        '模板ID-1xxxxxx',
        '模板ID-2xxxxxx',
      ],
    })
    if (subscribeResult.errMsg === 'requestSubscribeMessage:ok') {
      // 用户同意了订阅或已经订阅过,继续创建问题
      await handleCreateQuestion()
    } else {
      // 用户拒绝了订阅,显示提示后继续创建
      uni.showModal({
        title: '订阅提醒',
        content: '为了及时接收回复通知,建议您开启订阅消息',
        confirmText: '确定',
        success: async (res) => {
          if (res.confirm) {
            // 用户点击确定,继续创建问题
            await handleCreateQuestion()
          }
        },
      })
    }
  } catch (err) {
    console.error('请求订阅消息失败:', err)
    // 发生错误时仍然允许创建问题
    await handleCreateQuestion()
  }
}

3. 后端发送订阅消息

环境 SpringBoot + Java17

引入依赖

提高调用效率

 <!-- 添加WxJava依赖 -->
 <dependency>
     <groupId>com.github.binarywang</groupId>
     <artifactId>weixin-java-mp</artifactId>
     <version>4.5.7.B</version>
 </dependency>
 <dependency>
     <groupId>com.github.binarywang</groupId>
     <artifactId>weixin-java-common</artifactId>
     <version>4.5.7.B</version>
 </dependency>
  <!-- fastjson 用于JSON转换 -->
 <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.75</version>
</dependency>

配置 application.yaml

主要用于获取access_token(发送消息订阅时用)

wx:
  mp:
    app-id: xxxx
    app-secret: xxxx

定义实体类

这里以"活动通知"消息模板为例

@Data
@Accessors(chain = true)
public class ActivityNoticeTemplate {
    
    /**
     * 跳转路径,例如:pages/question/detail?id=123
     */
    private String path;
    
    /**
     * 活动标题
     */
    private Thing title;
    
    /**
     * 活动名称
     */
    private Thing name;
    
    /**
     * 活动内容
     */
    private Thing content;
    
    @Data
    public static class Thing {
        private String value;
    }
    
    public static ActivityNoticeTemplate build(String path, String title, String name, String content) {
        ActivityNoticeTemplate template = new ActivityNoticeTemplate();
        template.setPath(path);
        
        Thing titleThing = new Thing();
        titleThing.setValue(title);
        template.setTitle(titleThing);
        
        Thing nameThing = new Thing();
        nameThing.setValue(name);
        template.setName(nameThing);
        
        Thing contentThing = new Thing();
        contentThing.setValue(content);
        template.setContent(contentThing);
        
        return template;
    }
} 

发送请求

构建内容需要根据你选择的模板内容来构建
在这里插入图片描述

实现发送订阅消息

参考代码如下:

private static final String ACTIVITY_NOTICE_TEMPLATE_ID = "模板ID-1xxxxx";
private static final String SUBSCRIBE_MSG_URL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send";

@Resource
private WxMpService wxMpService;

@Override
public boolean sendActivityNotice(String openId, ActivityNoticeTemplate template) {
    try {
        // 构建请求数据
        JSONObject messageJson = new JSONObject();
        messageJson.put("touser", openId);
        messageJson.put("template_id", ACTIVITY_NOTICE_TEMPLATE_ID);
        messageJson.put("page", template.getPath());
        messageJson.put("miniprogram_state", "formal"); // developer为开发版;trial为体验版;formal为正式版
        
        // 构建模板数据 - 根据你选择模板来构建
        JSONObject data = new JSONObject();
        
        // 活动标题
        JSONObject thing16 = new JSONObject();
        thing16.put("value", template.getTitle().getValue());
        data.put("thing16", thing16);
        
        // 活动名称
        JSONObject thing11 = new JSONObject();
        thing11.put("value", template.getName().getValue());
        data.put("thing11", thing11);
        
        // 活动内容
        JSONObject thing4 = new JSONObject();
        thing4.put("value", template.getContent().getValue());
        data.put("thing4", thing4);
        
        messageJson.put("data", data);
        
        // 使用SDK发送订阅消息
        String responseContent = wxMpService.post(SUBSCRIBE_MSG_URL, messageJson.toJSONString());
        
        // 解析响应
        JSONObject response = JSONObject.parseObject(responseContent);
        int errcode = response.getIntValue("errcode");
        
        if (errcode == 0) {
            log.info("发送活动通知订阅消息成功,openId: {}", openId);
            return true;
        } else {
            log.error("发送活动通知订阅消息失败,openId: {}, errcode: {}, errmsg: {}", 
                openId, errcode, response.getString("errmsg"));
            return false;
        }
        
    } catch (WxErrorException e) {
        log.error("发送活动通知订阅消息失败,openId: {}, error: {}", openId, e.getMessage(), e);
        return false;
    }
}

这样就能实现发送订阅消息了~

拓展实现

  • 群发:可以遍历数据库中的用户openid来实现。
  • 定时:可以根据业务实现,如节日促销。
  • 结合业务:如用户消息回复。

总结

没想到吧,一次性订阅也能无限发送,疯狂轰炸你的微信哈哈哈(bushi)

细节

1. 为什么发请求不传 ACCESS_TOKEN?

答:依赖引入的WxJavaSDK底层实现了access_token的获取和拼接
access_token是根据你的application.yaml配置的app-idapp-secret来获取)

在这里插入图片描述

2. 我怎么知道用户授权订阅消息了没?

好问题,亲测,微信的服务器会记录用户授权了哪个消息模板ID;

咱们开发者只管发,能不能成功就交给微信服务器来判断。

因此,开发者无需记录用户授权了哪个模板,发就完事了!

PS:如果有业务需求的可以记录

⭐⭐⭐纠错

一次性订阅的“总是保持以上” 仅用来实现后续不弹窗、无感接收的效果,和次数统计无关。

订阅次数是用户从该入口进入并同意订阅的次数,可叠加累计,每同意一次次数加一,每下发一条消息消耗一次。

这些次数永久有效,直到全部消耗完;只有用户在设置里主动关闭订阅消息,已存储的次数才会被清零。

PS:小程序的长期订阅模板需要特殊类目才能申请,一般人拿不到;

折中方案:继续使用一次性订阅模板,多放钩子,让用户多点击(有一定的风险)

  • 优点:只需要在小程序实现,简单
  • 缺点:可发送次数依赖于用户点击的次数

平替方案:使用服务号模板消息替代(只要用户关注服务号,即永久可推送)

  • 优点:可发送无数次
  • 缺点:开发成本增加;需引导用户关注服务号;多花300¥开通微信开发者平台关联服务号和小程序。

实现思路:使用微信开发者平台关联小程序和服务号,即可对小程序的用户进行服务号的模板消息推送(前提是用户关注了服务号)

案例:顺丰快递、京东等服务号,其推送是模板消息。

在这里插入图片描述

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐