【订阅消息笔记】获取订阅消息授权

订阅消息

订阅消息是⼩程序能⼒中的重要组成,当⽤户⾃主订阅之后,可以向⽤户以服务通知 的⽅式发送消息的能⼒,当⽤户点击订阅消息卡片可以跳转到⼩程序的⻚⾯,这样就 可以实现服务的闭环和更优的体验,提⾼活跃度和⽤户粘性。

获取订阅消息授权

要获取订阅消息授权,⾸先要调⽤接⼝wx.requestSubscribeMessage,这个接⼝会调 起⼩程序订阅消息界⾯,返回⽤户订阅消息的操作结果。注意这个接⼝只能在⼩程序 端使⽤tap点击或⽀付完成后触发。如果是使⽤⻚⾯加载或其他非⽤户点击类的事件来 调⽤这个接⼝,就会报requestSubscribeMessage:fail can only be invoked by user TAP gesture的错误。

要调⽤wx.requestSubscribeMessage,需要我们⾸先要有订阅消息的模板ID,⼀次性 模板 id 和永久模板 id 不可同时使⽤,基础库2.8.4之后⼀次性可以调起3个模板ID(不 能多于3个)。

使⽤开发者⼯具新建⼀个⻚⾯,如subscribe,然后在subscribe.wxml⾥输入以下代 码,我们通过点击tap来触发事件处理函数

<button bindtap="subscribeMessage">订阅订阅消息</button>

然后再在subscribe.js⾥输入以下代码,我们在事件处理函数subscribeMessage⾥调⽤ wx.requestSubscribeMessage接⼝:

subscribeMessage() {
 wx.requestSubscribeMessage({
 tmplIds: [
 "qY7MhvZOnL0QsRzK_C7FFsXTT7Kz0-knXMwkF1ewY44",//模板
 "RCg8DiM_y1erbOXR9DzW_jKs-qSSJ9KF0h8lbKKmoFU",
 "EGKyfjAO2-mrlJQ1u6H9mZS8QquxutBux1QbnfDDtj0"
 ],
 success(res) {
 console.log("订阅消息API调⽤成功:",res)
 },
 fail(res) {
 console.log("订阅消息API调⽤失败:",res)
 }
 })
}

建议⼤家在⼿机上进⾏真机调试这个接⼝,点击订阅消息button,就能弹出授权弹窗。

  • 当⽤户点击“允许”就会累积⼀次授权,如果点击N次允许就能累积N次授权,这个授权是⻓期的,没
    有时间限制,你可以在⼀天内发完N次授权,也可以在未来分批次发完;也就是说这个虽然是⼀次
    性订阅消息,但是只要⽤户授权了N次,我们在短时间就可以发N次,⽽不是只能发⼀次;累积了
    多少次就可以发送多少次。发送⼀次就会消耗⼀次,累积的授权次数被消耗完之后,还继续发,就
    会报错"errcode":"43101","errmsg":"user refuse to accept the msghint..."。

  • 当⽤户勾选了订阅⾯板中的“总是保持以上选择,不再询问”时,且允许或拒绝之后,订阅消息的授
    权弹窗则永远不会再弹出,订阅消息也会被添加到⽤户的⼩程序设置⻚,我们可以通过 wx.getSetting
    接⼝可获取⽤户对相关模板消息的订阅状态。

  • 如果⽤户勾选了总是允许,那由于⽤户点击按钮都不会弹出授权弹窗,⽤户点击了授权按钮仍然会 累积授权,起到⼀个静默收集授权次数的效果。

注意该接⼝调⽤成功之后返回的对象,[TEMPLATE_ID]是动态的键,即模板id,值包 括’accept’、‘reject’、‘ban’。'accept’表⽰⽤户同意订阅该条id对应的模板消 息,'reject’表⽰⽤户拒绝订阅该条id对应的模板消息,'ban’表⽰已被后台封禁,如下 所⽰(以下值仅为案例):

{errMsg: "requestSubscribeMessage:ok", RCg8DiM_y1erbOXR9DzW_jKsqSSJ9KF0h8lbKKmoFU: "accept", qY7MhvZOnL0QsRzK_C7FFsXTT7Kz0-knXMwkF1ewY44:
"reject", EGKyfjAO2-mrlJQ1u6H9mZS8QquxutBux1QbnfDDtj0: "accept"}

订阅消息的累积次数决定了我们是否可以给⽤户发送订阅消息,也决定了可以发送⼏ 次,因此记录⽤户给某个模板ID授权了多少次这个也就显得很重要了,比如我们可以 结合接⼝返回的res对象和inc原⼦⾃增在数据库⾥记录订阅次数,当发送⼀次也会消耗 ⼀次,再⽤inc⾃减:

 subscribeMessage() {
 const tmplIds= [
 "qY7MhvZOnL0QsRzK_C7FFsXTT7Kz0-knXMwkF1ewY44",
 "RCg8DiM_y1erbOXR9DzW_jKs-qSSJ9KF0h8lbKKmoFU",
 "EGKyfjAO2-mrlJQ1u6H9mZS8QquxutBux1QbnfDDtj0"
 ];
 wx.requestSubscribeMessage({
 tmplIds:tmplIds,
 success(res) {
 console.log("订阅消息API调⽤成功:",res) 
 tmplIds.map(function(item,index){
 if(res[item] === "accept"){
 console.log("该模板ID⽤户同意了",item)
 //可以使⽤原⼦⾃增指令inc往数据库⾥某个记录授权次数的字段+1
 }
 })
 },
 fail(res) {
 console.log("订阅消息API调⽤失败:",res)
 }
 })
 },

wx.requestSubscribeMessage的参数tmplIds是数组可以容纳3个模板ID,当⽤户点击授 权弹窗,三个模板ID都是默认勾选的,只要⽤户点击允许,就会同时给三个模板ID累 积次数;如果⽤户取消勾选了其中⼀个模板ID,并点击总是允许,那另外两个勾选的 模板ID将不会再有授权弹窗。

发送订阅消息⽅式说明

当我们在⼩程序端累积了某个模板ID的授权次数之后,就可以通过云函数来调⽤ subscribeMessage.send接⼝发送订阅消息了。⽽这个云函数我们可以在⼩程序端调 ⽤,也可以使⽤云函数来调⽤云函数,还能使⽤定时触发器来调⽤云函数。

  • ⼩程序端发送订阅消息,有些业务需要在⽤户在⼩程序内完成了某个操作之后,就需要向⽤户发送
    订阅消息,⽐如打卡、签到、⽀付、发表成功等,这些业务都依赖于⽤户的操作,当操作完成之后 就可以在回调函数⾥调⽤发送订阅消息的云函数;
  • 还有⼀种就是,如果你是⼩程序的管理员,订阅消息的管理界⾯也在⼩程序⾥,当管理员在⼩程序
    端点击定点或群发订阅消息时,也可以调⽤云函数来发送订阅消息;
  • 使⽤定时触发器发送订阅消息,这时订阅消息就可以周期性、定时发送,不再需要⽤户/管理员点 击就可以结合业务场景发送。

云函数调⽤subscribeMessage.send接⼝的⽅式有两种,⼀种是HTTPS调⽤,还有⼀种 就是云调⽤,建议使⽤云调⽤。调⽤subscribeMessage.send接⼝时有很多细节需要注 意,尤其是data格式,必须符合格式要求。

订阅消息的data必须与模板消息⼀⼀对应
比如我们申请到⼀个订阅课程开课提醒的模板,它的格式如下
订阅消息的data必须与模板消息⼀⼀对应 比如我们申请到⼀个订阅课程开课提醒的模板,它的格式如下

姓名{{phrase1.DATA}}
课程标题{{thing2.DATA}}
课程内容{{thing3.DATA}}
时间{{date5.DATA}}
课程进度{{character_string6.DATA}}

与之相应的data的写法如下phrase1thing2thing3date5character_string6,这 些需要⼀⼀对应,参数不能多也不能少,参数后⾯的数字比如date5不能改成date6, 否则会报"openapi.subscribeMessage.send:fail argument invalid! hint:的错误,也就是模板⾥有什么参数,你就只能按部就班写什么参数

data: {
 "phrase1": {
 "value": '李东'
 },
 "thing2": {
 "value": '零基础云开发技术训练营第7课'
 },
 "thing3": {
 "value": '列表渲染与条件渲染'
 },
 "date5": {
 "value": '2019年10⽉20⽇ 20:00'
 },
 "character_string6": {
 "value": 3
 }
}

订阅消息参数值的内容格式必须要符合要求

在技术⽂档⾥,有⼀个关于订阅消息参数值的内容格式要求,
这个在写订阅消息内容 的时候需要严格的⼀⼀对应,否则会出现格式错误。

比如:

  • 可能已有的模板消息的格式和你想要的不⼀致,⽐如你希望发送的消息是⽤户的昵称,⽽不是姓名
    {{phrase1.DATA}},因为姓名只能是中⽂,且必须5个字以内,那你就没法擅⾃改动,只能去申 请或复⽤其他的模板ID;
  • 每个格式对字符串的⻓度和类型都有严格的要求,⽐如thing,要求必须是20个以内的字符,不能超
    过20个字符;有些只能是数字或字⺟,就不能是其他格式

使⽤云调⽤发送订阅消息

新建⼀个云函数比如subscribeMessage,然后再在config.json的添加 subscribeMessage.send权限,使⽤云函数增量上传更新这个配置⽂件

{
 "permissions": {
 "openapi": [
 "subscribeMessage.send"
 ]
 }
}

然后再在index.js⾥输入以下代码,注意这⾥的openid,是⽤户⾃⼰的,这种适⽤于⽤ 户在⼩程序端完成某个业务操作之后,就给⽤户⾃⼰发订阅消息;当然这⾥的openid 可以是其他累积了授权次数的⽤户的,也就是当我们在⼩程序端调⽤该云函数就能给 其他⼈发订阅消息了,这主要适⽤于管理员

const cloud = require('wx-server-sdk')
cloud.init({
 env: cloud.DYNAMIC_CURRENT_ENV,
})
exports.main = async (event, context) => {
 const { OPENID } = cloud.getWXContext()
 try {
 const result = await cloud.openapi.subscribeMessage.send({
 touser: "oUL-m5FuRmuVmxvbYOGuXbuEDsn8",
 page: 'index',
 templateId: "qY7MhvZOnL0QsRzK_C7FFsXTT7Kz0-knXMwkF1ewY44",
 data: {
 "phrase1": {
 "value": '⼩明'
 },
 "thing2": {
 "value": '零基础云开发技术训练营第7课'
 },
 "thing3": {
 "value": '列表渲染与条件渲染'
 },
 "date5": {
 "value": '2019年10⽉20⽇ 20:00'
 },
 "character_string6": {
 "value": 3
 }
 }
 })
 return result
 } catch (err) {
 console.log(err)
 return err
 }
}

由于subscribeMessage.send的参数templateIdtouser都是字符串,因此执⾏⼀次 subscribeMessage.send只能给⼀个⽤户发送⼀条订阅消息,那要给更多⽤户比如1000 ⼈以内(云函数⼀次可以获取到1000条数据)发订阅消息,则需要结合数据库的查询 数据库内所有有授权次数的⽤户然后循环执⾏来发消息,并在发完之后使⽤inc⾃减来 减去授权次数。

特别注意的是,不要把查询数据库的语句放到循环⾥⾯,也就是我们可以⼀次性取出1000条需要发订阅消息的⽤户,然后再结合map和Promise.all⽅法给这 1000个⽤户发送订阅消息,然后再⼀次性给所有这1000条数据进⾏原⼦⾃增,不能⼀条⼀条处理,否则会造成数据库性能的极⼤浪费以及超出最⼤连接数, ⽽且也会导致云函数在最⾼60s的⽣命周期⾥也发送不了⼏百条订阅消息。

使⽤定时触发器发订阅消息

但是当要发送订阅消息的⽤户有⼏⼗万⼏百万,那应该怎么处理呢?如果全部让云函 数来执⾏,即使将云函数的执⾏超时时间修改为60s,也应该会超时,这时候我们可以 结合定时器来发送订阅消息。 使⽤定时触发器来发送订阅消息,也就是在⼩程序的云 开发服务端,⽤定时触发器调⽤订阅消息的云调⽤接⼝ openapi.subscribeMessage.send。当我们每天要给数⼗万⼈定时发送订阅消息时,这 时候定时触发器就不仅仅需要比如每天早上9点触发,⽽且还需要在9点之后能够每隔 ⼀段时间比如40s,就来执⾏⼀次云函数以便给数⼗万⽤户发送订阅消息。 这时候Cron表达式可以这样写,意思是每天早上9点到11点每隔40s执⾏⼀次云函数:

0/40 * 9-11 * * * *

当然这⾥的周期设置可以结合云函数实际执⾏的时间来定,要充分考虑到云函数的超时时间。

原创文章 271 获赞 116 访问量 4万+

猜你喜欢

转载自blog.csdn.net/weixin_42554191/article/details/105833962