我在小程序的【每日一题】中新增了订阅功能,这篇文章就来讲讲设计及开发过程中遇到的坑。

什么是订阅消息

消息能力是小程序能力中的重要组成,我们为开发者提供了订阅消息能力,以便实现服务的闭环和更优的体验。

订阅消息推送位置:服务通知
订阅消息下发条件:用户自主订阅
订阅消息卡片跳转能力:点击查看详情可跳转至该小程序的页面

小程序“订阅消息”采坑记_服务端

订阅消息包括两种:

一次性订阅消息

一次性订阅消息用于解决用户使用小程序后,后续服务环节的通知问题。用户自主订阅后,开发者可不限时间地下发一条对应的服务消息;每条消息可单独订阅或退订。

长期订阅消息

一次性订阅消息可满足小程序的大部分服务场景需求,但线下公共服务领域存在一次性订阅无法满足的场景,如航班延误,需根据航班实时动态来多次发送消息提醒。为便于服务,我们提供了长期性订阅消息,用户订阅一次后,开发者可长期下发多条消息。

目前长期性订阅消息仅向政务民生、医疗交通金融教育等线下公共服务开放,后期将逐步支持到其他线下公共服务业务。

开始开发

首先要明白一点,当用户订阅【每日一题】后,并不是马上发送订阅消息。用户订阅的目的是,当下次发布题目时,可以提醒用户去答题。因此需要建一个数据库表,把订阅的用户信息存起来。于是就建了一个非常简单的表,只需要保存订阅用户的 openid 即可。

小程序“订阅消息”采坑记_订阅消息_02

然后想到以后万一其他地方有新的订阅功能时,岂不是又要新建表?

为了更好的扩展性,于是增加了一个字段,叫做 template_id,用来存订阅模板的ID。这样所有的订阅都可以只用这一个表解决。

首次测试

在页面中订阅消息,然后可以在任意时间通过服务端发送消息。

小程序“订阅消息”采坑记_服务端_03

在微信的“服务通知”中成功收到消息,NICE

于是迫不及待的又调用了一次,结果报错了,字面意思很容易理解,“用户拒绝接受消息”

{
  errcode: 43101,
  errmsg: 'user refuse to accept the msg rid: 601cebc4-6c7fee57-1d276794'
}

定位问题

在上面提到了有两种订阅消息,我是用的是一次性订阅消息,在描述中有一句话很关键:开发者可不限时间地下发一条对应的服务消息。

也就是说用户订阅后只能发送一条服务消息,如果需要再次发送,那么需要用户重新订阅。经过测试,如果用户订阅了一次后,在服务端发送消息前,用户再次订阅了一次,那么此时服务端可以向用户发送两条服务消息。也就是说用户订阅的次数是可以累加的。

那之前设计的数据库表就有很大的问题,现在无法判断是否还可以向每个用户发送消息,有可能之前已经发送过了,如果对每个用户都尝试发送,那会产生很多不必要的请求。

改进

还是从数据表着手,新增一个 count 字段,用来表示可以向该用户发送对应订阅消息的次数。

订阅:用户首次订阅,count默认值为1,若重复订阅,count + 1。

发送消息:获取对应消息模板ID,及count值大于0的用户。发送成功后把count值减1,拒绝接受则把count置为0,其他错误则不做任何处理。

小程序“订阅消息”采坑记_发送消息_04

界面改进

"明日提醒"按钮最开始是设计成一直显示的,用户可以多次点击订阅,如果点击5次,那接下来的5天内,用户都会收到订阅消息。

到了第六天就会发送失败,这就会导致用户产生误解,难道是今天没发布题目吗?

为了避免这样的误解发生,当用户订阅成功后,会隐藏该按钮。

当然在进入该界面时,也需要查询用户是否已经订阅过“明日提醒”,这里我只需要判断是否有该用户订阅信息及 count 的值是否大于0即可。

小程序“订阅消息”采坑记_开发者_05

自动化脚本

这个功能上线后,那必然是一个每天都要进行的任务,如果每天都手动的发送是一个相当无脑的行为。

来看看整个发送过程要进行哪些步骤吧:

第一步:获取今日题目,如果今日未发布题目,那就无需进行后面的操作,直接终止本次发送任务。并在随后每隔一小时定时执行。

第二步:获取当月的排名信息

第三步:获取当前可以发送订阅消息的用户

第四步:处理数据,这里有许多的情况,如:某个订阅用户在当月无任何打卡信息,那么他的排名应该是最后一名;每日更换“温馨提示”内容;

第五步:给符合条件的用户发送订阅消息

第六步:保存每次发送消息的返回信息,便于出现问题时定位原因

第七步:上面的步骤每天定时执行

欢迎访问我的个人网站 www.dengzhanyong.com
我的公众号:【前端筱园