Giter VIP home page Giter VIP logo

wxxshirley.github.io's Introduction

👋 Hi

Master student @ Fudan University

wxxshirley.github.io's People

Contributors

wxxshirley avatar

Stargazers

 avatar

Watchers

 avatar  avatar

wxxshirley.github.io's Issues

微信小程序 - 发送订阅消息

1.前言

继续上一篇,在餐饮服务类小程序中,向用户发送订阅号消息是一个非常基本的需求。这里我们介绍用户下单后发送下单成功和商家做好后发送取餐提示的消息。

2.在微信公众平台创建订阅消息模版

首先需要在微信公众平台创建订阅消息,具体在功能->订阅消息中。点击选用即可根据自己的需求创建一个新的模版。选择自己需要发送的内容信息即可。
image
下图是我们添加的点餐成功的模版。这里向用户发送订单号、取餐号、点餐内容和时间信息。注意右侧的详细内容构成,之后我们发送消息需要严格遵守其命名规范规则。

 var data = {
   character_string1:{value:"对应的订单号"},
   thing2:{value:"点餐内容"},
   character_string3:{value:"取餐号码"},
   time4:{value:"点餐时间"}
}

image

3.整体流程框架

其实我们要发送的总共是三类消息:

  • 用户:下单成功
  • 商家:新订单
  • 用户:取餐

这里我们仅介绍指定用户的。整体的时序过程是:用户下单,如果是首次会弹出接受订阅消息,都勾选了后会:

  • 调用创建一笔新订单的云函数createOrder,执行对订单数据库的插入操作
  • 调用subscribe云函数存储该下单消息。具体来说,往Message表中存储需要发送的下单成功消息内容。

之后前端下单成功会界面重定向到该笔订单的界面wx.redirectTo。我们会有一个定时的云函数,每隔一分钟轮询Message表中尚未被发送的消息,发送给指定的用户。这样该用户即在下单的1分钟内收到下单成功消息推送。
新的下单信息也会推送给商家(可以在createOrder中把一个新下单消息、即指定发送给管理员的写入Message表中,需要提前在获得权限时使管理员勾选该类消息)。商家完成订单后在CMS后台修改该订单状态为已完成,会触发userCheckoutNotice(Webhook模式)将取餐内容推送给该用户。也是依靠轮询Message机制,用户将在1分钟内接收到消息。

image

3.小程序前端请求用户订阅消息权限

var tmpId = "" // 下单模版ID
var checkoutId = "" // 取餐模版ID,都在微信公众平台

// 申请订阅消息权限
wx.requestSubscribeMessage({
      tmplIds: [tmpId, checkoutId], // ID集合
      success(res){
        // 用户勾选后
        if(res.errMsg == 'requestSubscribeMessage:ok'){
          wx.cloud.callFunction({
            name: 'subscribe', // 调用subscribe云函数,存储“下单”订阅消息
            // 遵守模版格式,订单号、名称、取餐号、时间
            data:{
              data: {
                character_string1: {
                  value: "订单号",
                },
                thing2: {
                  value: title,
                },
                character_string3:{
                  value: "取餐号码",
                },
                time4:{
                  value:utils.formatTime(new Date()),
                }
              },
              // 这里对应下单成功的消息提示,因此传入的templateId是下单成功的模版ID
              templateId: tmpId
            }
          }).then(()=>{
            console.log("订阅成功")
          })
        }
}
})

4. Message表设计与定时机制

我们设计Message表来存储所有需要发送给用户的消息,其中关键字done为布尔型,用以标志消息是否已经被发送。
下图是Message表中一条记录的展示。

  • data: 词典型。对应发送的消息模版格式
  • done:布尔型。消息是否已被发送
  • page:用户点击该订阅号消息跳转的界面
  • templateId: 对应的订阅号消息模版
  • touser:发送给的用户的openid
    image

其中关键是templateId, touser, data构成了要发送的内容数据。
考虑编写一个定时云函数send,每隔1分钟扫描Message表,将未发送的数据发送给指定的用户。

配置config.json

由于我们要使用定时功能和发送订阅消息,需要先配置config.json. 其中triggers定义了定时模式,与Linux中cron定时机制类似,其中0 * * * * * *指明每隔1min执行1次。

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

send云函数:遍历Message表发送未发送数据

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

cloud.init({env: '开发环境'})
const db = cloud.database()
const _ = db.command

// 云函数入口函数
exports.main = async (event, context) => {
  try{
    // 查询尚未发送的消息
    const messages = await db.collection('Message').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("Message").doc(message._id).update({
          data: {done: true}
        });
      }catch(e){
        console.log("发送消息出现错误")
        console.log(e)
        return e;
      }
    })
    return Promise.all(sendPromises)
  }catch(err){
    console.log("Try catch外部发送消息错误")
    console.log(err)
    return err
  }
}

商家行为触发的userCheckOutNotice

商家修改了某订单为完成,可以根据webhook中的过滤条件取到该笔订单和对应用户。向Message表中存储该取餐成功消息,包括:

  • 发送用户touser
  • 数据内容data ( 取餐内容、编号等,与订阅消息模版保持一致)
  • 跳转界面page
  • 是否处理done(初始化为false)
    ...

同样地借助Message表的轮询机制成功地发送给用户

5.总结

本文介绍了处理发送订阅消息的一般流程:

  • 微信公众平台完成订阅号消息模版申请,关键是内容的选择和模版ID
  • 小程序端请求用户权限、编写成功的回调函数
  • (云函数)向用户发送该条消息 (核心:发送用户的openid, 发送内容,跳转界面,模版ID)

但是在本次应用中,由于发送消息的多样性,我们把消息的发送变为轮询定时任务。将上述的最后两步变为插入Message表和轮询发送消息。

微信小程序 - 后台CMS系统

1.前言

今年寒假做了一个小程序点餐的外包项目,最近闲下来逐个对里面的技术点进行复盘和总结。

2.微信小程序后台

对于订餐类的应用,需要有一个完备的后台系统,基础功能包括显示完整的商品信息、订单信息;另外需要有实时新订单提示、修改订单为已完成等功能。
由于全程采用微信小程序云开发,对商家来说登陆微信小程序开发IDE查看数据显然不太现实,需要搭建一个基础的后台。

HTTP访问

微信小程序的云开发提供了使用HTTP接口访问云端数据库的功能。对任何云数据库的操作,包括两部分:

  • 获得access_token
    • 方式: GET
    • 请求域名:https://api.weixin.qq.com/cgi-bin/token
    • 参数(以key-val形式表示):
      var queryParams = { grant_type:  client_credential,
        appid: 微信小程序的APPID,
        secret: 微信小程序的APPSECRET(以上可登陆微信公众平台-开发-开发设置中查看)};
      注意access_token有效期为两小时,但是它提供了平滑期,即已有access_token有效的情况下,再次请求,旧的在五分钟内有效。
  • 利用获得的access_token,请求数据
    • 方式:POST
    • 请求域名:https://api.weixin.qq.com/tcb/databasequery?access_token="上一步的access_token"
    • 参数(form)形式:
       var queryParams = {
          "env":"对应微信小程序云开发的环境",
          "query": "db.collection('Order').where({time: db.RegExp({regexp:'2021/03/17'})}).get()"
          // 查询语句,上面查询了该日的订单信息
         }
      注意使用此类HTTP请求最多返回十条数据。但是依靠返回信息中的分页数据,可以逐次拉取,获得全量数据。
      下面是一个使用Postman的示例。
      image

根据上面的API可以查询任何我们想要的云数据库的信息,在此基础上可以搭建一个后台。不过的确也非常麻烦(个人觉得一大麻烦就是在于每一次至多返回10条数据,分页策略请求很容易造成重复数据,需要有略复杂的处理手段;另外,实时消息提示在后台修改状态后回调小程序端也困难重重。),还不如放弃小程序的云开发自建一个服务端.....

CMS系统

CMS是腾讯云提供的一站式后台管理服务,目前已经适配微信小程序云开发。
如果使用,需要在云开发控制台->更多->内容管理手动开启。之后会提供一个该小程序的后台内容管理网址,在此基础上可以定制打造需要的后台管理服务。
下面是进入到这个后台管理的界面。
我们先介绍左侧的各个工具栏。

image

  • 内容模型:在这里可以定制你想要展示的数据,其中表名要和云数据库保持一致,然后右侧的各类属性可以选择你想要展示的该表的属性,注意也要保持名称的一致。比如对于用户的购物车Cart表,我们想在后台显示每一条记录的商品名、加入时间、用户的openid和数量,那么选择右侧对应的、填写数据库字段名即可。之后云数据库的内容会直接同步到内容集合中展示。这里的内容和云数据库同步,包括插入/删除/更新。
  • 内容集合:展示数据。
    如下图显示,展示了所有的购物车表中数据内容。可以自定义检索和排序工具。直接修改/删除/插入。非常方便。
    image
  • Webhook: Webhook 可以用于在内容管理员修改内容数据后,自动回调外部系统,比如自动构建静态网站、发送通知等。下面会详细介绍它的使用。

3.CMS的Webhook使用

在订单小程序中,有个需求是咖啡厅人员把某个订单从进行中改成了已完成,这个时候我们需要推送给用户取餐通知。这个大家在使用喜茶/乐乐茶都有体验。这个需求的实现就需要使用Webhook。
创建一个Webhook,是监听到CMS中数据项发生变化(包括数据插入、删除和更新后),触发外部回掉。目前支持HTTP和触发云函数。这里我们仅示例触发云函数。
下面是增加一个Webhook的填写表单。
image
这里我们想要监听订单表Order中数据项更新,触发一个名为userCheckoutNotice的云函数。
在小程序cloudfunctions路径下,我们新建一个名为userCheckoutNotice的云函数,可以先只打印该函数入口的内容event, 然后我们在CMS系统中手动更新某笔订单,查看触发userCheckoutNotice云函数中的事件信息。
下面是打印的event内容
image
可以看到,event本身封装了非常多的因素,其中最关键的是actionFilter,即数据过滤条件,指定了本次我们更新的是哪一条数据。我们可以通过取actionFilter, 找到该条数据项、顺理成章地得到该订单对应的用户的openid, 向她/他发送取餐消息即可。

最后是发送消息的核心代码。
这里由于有多类消息需要发送给用户:

  • 成功下单
  • 取餐通知
  • 评价通知
    为了实现上的复用,考虑把所有要发送给用户的订阅号消息插入到一张名为Message表中,每隔一分钟将该表中尚未发送的消息发送给指定的用户、并更新状态为已发送。具体发送消息的设计会在下一篇中介绍。
// 云函数入口函数
exports.main = async (event, context) => {
   // 用户取餐提示
   console.log("触发用户取餐提示")
  
   // 数据库过滤条件
   var filterId = event.actionFilter._id
   
   // 获取该笔订单数据
   var entry = await db.collection('Order').doc(filterId).get()

   console.log("查找到对应数据:")
   console.log(entry)
   if(entry && entry.data){
     // title格式 e.g "美式咖啡,普通咖啡" string格式
     let title = ""
     ... // 生成取餐标题
     
     // 构造发送消息的内容 - 需要和微信公众平台订阅消息模版保持一致
     var data = {
      character_string1:{
        value: entry.data.order_id , // 订单号
      },
      thing5:{
        value: title // 商品详情
      },
      character_string4:{
        value: entry.data.order_id // 取餐号
      }
     }

     // 插入到Message表中,等待轮询被发送
     try{
       const result = await db.collection('Message').add({
         data: {
           touser: entry.data.openid, // 发送用户的openid
           page: "myOrder", // 用户打开该消息进入小程序后进行的界面,这里进入订单界面
           data: data,
           templateId: "", // 对应的内容模版ID, 在微信公众平台
           done: false, // 是否发送
         }
       });
       return result 
     }catch(err){
       console.log("插入到取餐提示消息失败:")
       console.log(err)
     }
   }

}

4.总结

总的来说,微信小程序的云开发功能愈发完善。使用它完成一个全栈开发非常容易,CMS的提供使得后台管理系统也非常轻松。Webhook功能更帮助我们实现了进一步的需求。希望明年这个时候能看到CMS系统直接集成观远数据平台/智能BI,直接一站式可视化所有数据、甚至一些NLP的工具也能使用🤣

以上就是关于我用到的CMS系统的内容。如有更新会即时补充。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.