评论

[填坑手册]小程序新版订阅消息+云开发实战与跳坑

新版订阅一条龙,前端站撸不求人

老版本的订阅消息在2020年1月10日就下线了,相信不少人在接入新版本订阅系统的时候,或多或少会遇到一些问题,这里智库君跟大家介绍下新版订阅的机制和不需要node/后端的情况下 独立完成功能开发。

一、新版订阅的机制

其实开发过程不难,但是要理清楚它里面的机制,智库君还是花了一些时间的,也踩了不少坑

先来看下官方介绍:

  1. 可以设置多个订阅选项
  2. 感叹号里面可以看到详情
  3. 有个默认不被选中的“总是”选项

这些就是新不同的地方,智库君在开发的时候也有很多疑问,点了“总是”再点“取消”按钮会怎样?部分选择订阅会怎样?下面为大家一一梳理

(1)部分选中


比如现在有三个选项 A,B,C,用户**“部分选中”**返回的情况:

这里用真机调试可以看到,有个返回值状态为“reject”。
如果我们反复几点点击同一个订阅后,这些值是如何计算的呢?

举例:

从这里看出,微信系统会自动记录用户点击的次数,并且做累加记录,如果用户只允许2次发送,而开发者发送了3次,最后一次将会被拒绝。

(2)点击“总是保持以上选择,不再询问”的情况

当用户点击“总是”之后,同一个类型的订阅将不再弹出,那如果有多个订阅选项呢?

举例

订阅AAA 三个订阅模板为 X Y Z

订阅BBB 二个订阅模板为 Y W

这时候如果“订阅AAA”按钮选择了“总是”,那么再点击“订阅BBB”按钮,将只会弹出一个选项“W”,不会有 “Y” 的模板,因为在之前 “订阅AAA” 按钮中已经包含了。

wx.requestSubscribeMessage({
  tmplIds: ["MECDDOdhbC3SrQmMY5XrfqiIGbMTzpEN8Z7ScXJfcd0", "iSb2NIlNnnO60wlI-8Wx5Pe82jR7TRdwjotSXtM1-ww"],
  success(res) {
    console.log(res);
  }
})

显示内容仅一个选项:

这里需要注意,“总是”选项是全局有效,不区分页面,选中“总是”的 W,X,Y,Z的模板,在全局任意页面中再次调用,再次调用将不再会显示!

返回值无提示用户是否选中“总是”。

(3)用户点击“总是”后,获取状态

wx.getSetting({
  withSubscriptions: true,
  success(res) {
    console.log(res.authSetting)
    // res.authSetting = {
    //   "scope.userInfo": true,
    //   "scope.subscribeMessage": true
    // }
    console.log(res.subscriptionsSetting)
    // res.subscriptionsSetting = {
    //   SYS_MSG_TYPE_INTERACTIVE: 'accept',
    //   SYS_MSG_TYPE_RANK: 'accept',
    //   zun-LzcQyW-edafCVvzPkK4de2Rllr1fFpw2A_x0oXE: 'reject',
    //   ke_OZC_66gZxALLcsuI7ilCJSP2OJ2vWo2ooUPpkWrw: 'ban',
    // }
  }
});

这里可以调用wx.getSetting方法,但是需要注意:如果用户第一次选“总是”后点击“取消”按钮或者订阅模板全部是未选中/reject的,那将获取不到状态(这里可能是BUG,期待官方未来修复)。

(4)用户点击“总是”后,让用户手动修改

前面说到用户点击“总是”后,系统将不再弹窗,但是我们可以通过**“wx.openSetting”**引导用户手动修改。

wx.openSetting({
  success(res) {
    console.log(res.authSetting)
    // res.authSetting = {
    //   "scope.userInfo": true,
    //   "scope.userLocation": true
    // }
  }
})


当然用户自己也可以修改

总结

  • 【重点】选择“总是”,很多人认为就可无限发送订阅消息,这个是错误的,勾选和不勾选唯一的区别就是每次触发订阅的时候会不会弹授权窗口!!!
  • 用户点击次数系统会自动累加,直接影响后台发送通知的次数。
  • 用户选择“总是”后,小程序界面不再弹窗,但仍然有回调/callback。
  • 任意订阅模板在用户选中“总是”(包括接受/拒绝2个状态)后,全局有效,就算其他订阅包含“此模板”也不再显示/弹出
  • 当用户选择“总是”中“accept/选中/接受”的状态后,可以在wx.getSetting查询到用户是否选择“总是”。
  • 当用户选择“总是”中“reject/未选中/拒绝”的状态后,返回值“无感知”(这里可能是BUG)

二、功能开发

使用微信自带的云开发,可以在没有node/后端开发支持下,完成整个订阅流程的开发。

(1)微信后台设置订阅模板和获取模板ID

1、打开小程序后台,找到订阅消息设置

2、在公共模板库找模板或者自己申请新模板,建议能用现成模板用现成的,因为申请周期可能较长,且容易被拒

3、选好模板后,点击详情

4、查看模板内容和发送DATA的结构

5、复制模板ID

(2)配置云函数



1、新建getOpenId云函数,用于获取用户的openID

// 云函数入口文件
const cloud = require('wx-server-sdk')

cloud.init()

// 云函数入口函数
exports.main = async (event, context) => {
  const wxContext = cloud.getWXContext()

  return {
    event,
    openid: wxContext.OPENID,
    appid: wxContext.APPID,
    unionid: wxContext.UNIONID,
  }
}

2、新建订阅推送通知云函数

// 云函数入口文件

const cloud = require('wx-server-sdk')
cloud.init()

//订阅推送通知
exports.main = async (event, context) => {
  try {
    const result = await cloud.openapi.subscribeMessage.send({
      touser: event.openid, //接收用户的openId
      page: 'pages/my/index', //订阅通知 需要跳转的页面
      data: {   //设置通知的内容
        thing1: {
          value: '小程序订阅填坑'
        },
        thing2: {
          value: '智库方程式'
        },
        thing3: {
          value: '一起学习,一起进步'
        }
      },
      templateId: '5Efr7IqIooYO9nPw047Iggxbm9Ge2Km10GQ4amGOUac' //模板id
    })
    console.log(result)
    return result
  } catch (err) {
    console.log(err)
    return err
  }
}

写完云函数记得右键部署下!!!

(3)小程序代码部分

<!------------html ------------->
<button bindtap="getOpenId" type='primary'>获取openId</button>

<view class="subBtn" catch:tap="sub">订阅AAA</view>

<view class="subBtn" catch:tap="send">订阅推送测试</view>

<view class="subBtn" catch:tap="setting">设置“总是”后,跳转修改</view>
//JS 部分
//获取用户的openid
  getOpenId() {
    wx.cloud.callFunction({
      name: "getOpenId"
    }).then(res => {
      let openid = res.result.openid
      console.log("获取openid成功", openid)
    }).catch(res => {
      console.log("获取openid失败", res)
    })
  },
//发送模板消息给指定的openId用户
  send(openid){
      wx.cloud.callFunction({
        name: "sendSub",
        data: {
          openid: openid
        }
      }).then(res => {
        console.log("发送通知成功", res)
      }).catch(res => {
        console.log("发送通知失败", res)
      });
  },
//消息订阅
  sub: function () {
    wx.requestSubscribeMessage({
      tmplIds: ["5Efr7IqIooYO9nPw047Iggxbm9Ge2Km10GQ4amGOUac"],
      success(res) {
        console.log("订阅授权成功:"+res);
      },
      fail(res){
        console.log("订阅授权失败:" + res);
      }
    })
  },
//帮助用户跳转修改订阅状态
  setting:function(){
    wx.openSetting({
      success(res) {
        console.log(res.authSetting)
        // res.authSetting = {
        //   "scope.userInfo": true,
        //   "scope.userLocation": true
        // }
      }
    })
  },

(4)测试流程

点击发送通知后,获得这样的效果:

获得对应返回值:

当errCode为0时,即发送通知成功。
当errCode为43101,说明用户只授权了一次,但是你发送了2次,超过用户授权次数。

三、进阶与思考

1、当你有多个订阅模板同时需要用户选择时,你可以通过以下代码记录,用户哪些选了,哪些没选。

wx.requestSubscribeMessage({
  tmplIds: ["5Efr7IqIooYO9nPw047Iggxbm9Ge2Km10GQ4amGOUac", "OBB_Z10eh_Inm9p8EU6Ml_NS_mijXgTz3T07cxgKvX0","5Efr7IqIooYO9nPw047Iggxbm9Ge2Km10GQ4amGOUac"],
  success(res) {
    //console.log(res);
    if (res.errMsg == "requestSubscribeMessage:ok") {
      let acceptArray = [];  //用户授权模板列表
      for (let i = 0; i < tmplIds.length; i++) {
        const element = tmplIds[i];
        if (res[element] == "accept") {
          acceptArray.push(element);
        }
      };
      console.log(acceptArray);
      if (acceptArray.length > 0) {
      //执行下一步函数
      }
    }
  }
})

2、一个关于是否需要记录用户对某个“订阅模板授权的次数”,以控制后台“发送的次数”,智库君在实战中认为,其实没有必要,顶多就是你发送返回一个错误码,微信之所有记录用户授权次数,也是为了保护用户不被骚扰。

3、你只需要记录用户点击了哪些需要授权的模板就行,为了是用户点击订阅后,改变按钮的状态,避免订阅按钮反复弹窗的问题,同时当检测到用户点错“总是”按钮后,可以自动跳转到“设置”界面。

4、这次智库君主要给大家简单介绍了下订阅全流程。后面大家可以根据自己的需要,添加和改进这些代码。比如:

  • 配置云函数中的node函数,实现定时发送
  • 配置云函数中的数据库,实现内容的自定义发送

最后,希望这篇文章能帮助到大家,一起学习,一起进步!

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

往期回顾:

最后一次编辑于  2021-09-13  
点赞 17
收藏
评论

6 个评论

  • 。
    2022-08-29

    请教一下,能不能获取到他人的openid然后在其他小程序上调用订阅消息再发送,比如说我获取到客户的openid然后保存起来,点击按钮手动给该客户发送一次消息,我自己试了下,报错errCode: 40003 errMsg: "openapi.subscribeMessage.send:fail invalid openid rid: 630c3425-75e3db85-0726404e"

    2022-08-29
    赞同
    回复 2
    • 游戏人生
      游戏人生
      2022-09-05
      在其他小程序调用订阅?首先每个小程序同一个unionId 对应的openId都是不一样的哦
      2022-09-05
      回复
    • 游戏人生
      游戏人生
      2022-09-05
      其次订阅是需要用户在小程序端授权的,A订阅,B没有订阅是发不了的
      2022-09-05
      回复
  • 粟悟饭和龟波功
    粟悟饭和龟波功
    2022-03-08

    您好,请问你是怎么吧openid传到后端去的


    2022-03-08
    赞同
    回复
  • 这个名字怎么样
    这个名字怎么样
    2021-12-21

    订阅页面该放在那里呢

    2021-12-21
    赞同
    回复 1
    • 游戏人生
      游戏人生
      2021-12-21
      订阅页面?他是一个系统弹窗
      2021-12-21
      回复
  • 汪小露
    汪小露
    2020-06-17

    请问下,模板消息里面的内容可以绑定程序里面的变量吗?实时更新状态

    2020-06-17
    赞同
    回复 1
    • 游戏人生
      游戏人生
      2020-06-17
      [授权]消息模板ID对应的名称是不能变的,但是你可以传参给云函数改变模板[推送]的内容
      2020-06-17
      回复
  • 小肥羊🍊
    小肥羊🍊
    2020-03-01
    非常详细,花了不少功夫整理,加油
    2020-03-01
    赞同
    回复 1
    • 游戏人生
      游戏人生
      2020-03-01
      嗯,一起加油,一起进步
      2020-03-01
      回复
  • "
    2020-02-26

    大量的订阅消息能否用云函数定时推送?还是用自己的服务器靠谱些?延迟大吗?

    2020-02-26
    赞同
    回复 2
    • 游戏人生
      游戏人生
      2020-02-26
      朋友,首先我不知道你说的“大量”是多大? 云函数是有上限的,没具体测试过云函数的上限,如果超过1w+,建议还是用服务器定时推,之前公司项目都是服务器推的。自己的小项目,流量不大,1k以下,直接挂云函数美滋滋
      2020-02-26
      回复
    • "
      2020-02-26回复游戏人生
      好的 谢谢 超过1w的
      2020-02-26
      回复
登录 后发表内容