评论

实战分享: 小程序云开发玩转订阅消息(二)

微信最新推出的小程序订阅消息给小程序开发者带来了更好的触达用户的能力,我们今天会我们会利用小程序·云开发进行一个小程序中实现订阅开课提醒的实战,帮助大家了解如何基于小程序·云开发快速接入小程序订阅消息

这是实战分享: 小程序云开发玩转订阅消息的第二部分

第一部分链接 《实战分享: 小程序云开发玩转订阅消息(一)》

将订阅消息存入云开发数据库

接下来我们创建一个云函数 subscribe ,这个云函数的作用是将用户的订阅信息存入云开发数据库的集合 messages 中,等待将来需要通知用户时进行调用。

在微信开发者工具的云开发面板中创建数据库集合 messages


微信开发者工具新增数据库集合


创建一个 subscribe 云函数,在云函数中我们将小程序端发送过来的课程订阅信息,存储在云开发数据库集合中,开发完成后,在微信开发者工具中右键上传并部署云函数。

cloudfunctions/subscribe/index.js

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

exports.main = async (event, context) => {
 try {
   const {OPENID} = cloud.getWXContext();
   // 在云开发数据库中存储用户订阅的课程
   const result = await db.collection('messages').add({
     data: {
       touser: OPENID, // 订阅者的openid
       page: 'index', // 订阅消息卡片点击后会打开小程序的哪个页面
       data: event.data, // 订阅消息的数据
       templateId: event.templateId, // 订阅消息模板ID
       done: false, // 消息发送状态设置为 false
     },
   });
   return result;
 } catch (err) {
   console.log(err);
   return err;
 }
};

利用定时触发器来定期发送订阅消息

接下来我们需要实现一个定时执行的云函数send,来检查数据库中是否有需要发送给用户的订阅消息。如果有需要发送的订阅消息,会通过云调用 cloud.openapi.subscribeMessage.send 将订阅消息发送给用户。

创建一个名叫 send 的云函数,首先要配置云函数,在 config.json 的 permissions 中新增 subscribeMessage.send的云调用权限,然后新增一个 sendMessagerTimer 的定时触发器,定时触发器的语法和 linux 的 crontab 类似,比如,我们配置的 "0 * * * * * *" 代表每分钟执行一次云函数。

cloudfunctions/send/config.json

{
 "permissions": {
   "openapi": ["subscribeMessage.send"]
 },
 "triggers": [
   {
     "name": "sendMessagerTimer",
     "type": "timer",
     "config": "0 * * * * * *"
   }
 ]
}

接下来是实现发送订阅消息的云函数,这个云函数会从云开发数据库集合messages中查询等待发送的消息列表,检查数据库中是否有需要发送给用户的订阅消息,发送条件可以根据自己的业务实现,比如开课提醒可以根据课程开课日期来检查是否需要发送订阅消息,在我们下面的代码示例里做了简化,筛选条件只检查了状态为未发送。

查询到待发送的消息列表之后,我们会循环消息列表,依次发送每条订阅消息,发送成功后将数据库中消息的状态改为已发送。

cloudfunctions/send/index.js

const cloud = require('wx-server-sdk');

exports.main = async (event, context) => {
 cloud.init();
 const db = cloud.database();

 try {
   // 从云开发数据库中查询等待发送的消息列表
   const messages = await db
     .collection('messages')
     // 查询条件这里做了简化,只查找了状态为未发送的消息
     // 在真正的生产环境,可以根据开课日期等条件筛选应该发送哪些消息
     .where({
       done: false,
     })
     .get();

   // 循环消息列表
   const sendPromises = messages.data.map(async message => {
     try {
       // 发送订阅消息
       await cloud.openapi.subscribeMessage.send({
         touser: message.touser,
         page: message.page,
         data: message.data,
         templateId: message.templateId,
       });
       // 发送成功后将消息的状态改为已发送
       return db
         .collection('messages')
         .doc(message._id)
         .update({
           data: {
             done: true,
           },
         });
     } catch (e) {
       return e;
     }
   });

   return Promise.all(sendPromises);
 } catch (err) {
   console.log(err);
   return err;
 }
};

最终效果


开课提醒订阅消息截图


源代码

https://github.com/binggg/tcb-subscribe-demo[3]

参考资料


[1]

注册小程序帐号: https://tencentcloudbase.github.io/2019-09-03-wx-dev-guide-register/

[2]

开通云开发服务: https://tencentcloudbase.github.io/2019-09-03-wx-dev-guide-service/

[3]

https://github.com/binggg/tcb-subscribe-demo: https://github.com/binggg/tcb-subscribe-demo



最后一次编辑于  2019-10-23  
点赞 14
收藏
评论

9 个评论

  • 陈宇明
    陈宇明
    08-18

    很棒的分享!

    08-18
    赞同 1
    回复
  • kokmike
    kokmike
    11-17

    你好,感谢你的分享。

    有一个问题想问一下,这个订阅消息对于普通的个人小程序来说,不是需要用户确认订阅一次才允许发送一次的吗? 每次允许只能发送一条吧 ?

    11-17
    赞同
    回复
  • Dhui
    Dhui
    08-22

    按源码更换了appid和订阅消息模板id,也按照模板id的值改了,但是无法在对应的时间接受到信息,这该怎么处理呀?

    08-22
    赞同
    回复
  • hh
    hh
    03-12

    send云函数会报错:ReferenceError: _ is not defined

    目前确认是

    startTime: _.lte(new Date().getTime() + 30 * 60 * 1000)
    

    这里有问题,不知道如何解决

    03-12
    赞同
    回复 1
  • 😄
    😄
    02-17

    我的需求是:用户自己设定时间,在设定的时间去提醒对应的用户!这触发器的时间怎么弄啊??

    02-17
    赞同
    回复 6
    • Booker Zhao(赵兵)
      Booker Zhao(赵兵)
      02-18
      触发器相当于定时去检查有没有需要提醒的,你可以把用户设定的时间写入数据库,用触发器定时去检查
      02-18
      1
      回复
    • 😄
      😄
      02-18回复Booker Zhao(赵兵)
      每一分钟去检查一次 会不会造成源资源消耗过快?
      02-18
      回复
    • 何大茂
      何大茂
      02-25回复😄
      同问这个,请问您解决这个问题了吗
      02-25
      回复
    • 😄
      😄
      02-25回复何大茂
      解决了 用的楼主的方法。定时去检查
      02-25
      回复
    • 何大茂
      何大茂
      02-25回复😄
      那样不会很快就用光云开发的配额吗
      02-25
      回复
    查看更多(1)
  • 罗梅光
    罗梅光
    01-02

    const sendPromise=*.data.map;

    Promise(sendPromise);


    厉害,我都是使用for循环的。。。。。

    01-02
    赞同
    回复
  • 悟
    2019-11-29

    按照上面的写的,为什么我收不到发送的订阅通知?我用的测试版本,和小程序是不是发布有关系吗?

    2019-11-29
    赞同
    回复 10
    查看更多(5)
  • Seven Jiao
    Seven Jiao
    2019-11-08

    一直提示Error: errCode: 40037  | errMsg: openapi.subscribeMessage.send:fail invalid template_id hint: [TRdd_05638653] 无效的模板ID,确认模板ID无误。

    2019-11-08
    赞同
    回复
  • 未来_加油
    未来_加油
    2019-11-07

    老哥,你这样测试成功了,我按照文章说的步骤进行,最后日志打印"errCode":-501007,"errMsg":"subscribeMessage.send:fail Invalid request param",请问一下应该怎样解决

    2019-11-07
    赞同
    回复 2
登录 后发表内容