微信小程序 订阅消息使用 详细教程
发布于 3 年前 作者 fpeng 3330 次浏览 来自 分享

微信小程序订阅消息使用

官方文档连接

本说明的使用场景例子为:用户在组队大厅发送招募信息,后台管理系统收到后对用户的信息进行审核,并将审核结果,通过消息推送发送给用户。

逻辑步骤

逻辑步骤0:等待用户点击触发需要发送消息的事件

逻辑步骤1:向用户申请获得发送消息的权限

逻辑步骤2:等待发送的触发行为

逻辑步骤3:向特定用户发送消息


操作步骤

操作步骤1:在微信公众号平台获得合适的模板

在公共模板库搜索适合的模板,找不到的话可以申请。

操作步骤2:编写查询发送权限函数

写一个获得访问权限的函数(也可以直接复制我的),封装好API里面,后面还需要用的话方便调用。

const checkSub = async(params)=>{//传入tmplId,检测用户是否开放权限,允许推送消息
  var tmplIds = params.tmplIds //这里的tmplId是一个数组得注意一下
  console.log(tmplIds)
  return new Promise((resolve,reject)=>{
    wx.getSetting({
      withSubscriptions: true,
      success(res){
        console.log(res)
        if(res.subscriptionsSetting.itemSettings!=undefined){
          var flag = res.subscriptionsSetting.itemSettings[tmplIds[0]]
        }else{
          var flag = undefined
        }
        
        console.log(flag)
        if(flag==undefined){
          console.log("debug")
            wx.requestSubscribeMessage({
              tmplIds: tmplIds,
              success(res){
                console.log(res)
                //点击完成后就返回成功就行
              },
            })
        }else if(flag!='accept'){
          wx.requestSubscribeMessage({
            tmplIds: tmplIds,
            success(res){
              console.log(res)
              resolve(true)//点击完成后就返回成功就行
            }
          })
        }else{//直接返回true,原本以为用户选择一直同意之后,就可以一直推送,这里是一个bug
          wx.requestSubscribeMessage({ 
            tmplIds: tmplIds,
            success(res){
              console.log(res)
              resolve(true)//点击完成后就返回成功就行
            }
          }) 
        }
      }
    })
  })
}

操作步骤3:用户触发点击事件,调起询问权限

在用户触发的事件开始前,调用询问权限函数,获得发送订阅消息的权限

在本例子中,用户提交组队的表单,在成功提交前,询问用户是否接受“审核通过通知”,无论用户选择是或否,表单信息都可以顺利提交。但是选择否,用户则无法顺利收到订阅信息。

代码如下

submit: async function() {
    if(!this.checkTap()){ //防止用户多次点击,重复提交的函数
      return 0 
    }
    
     
      const { contestName,imgs,mates,status,currNum } = this.data
      var imgUrls = [];
      for (var i=0; i<imgs.length; i++) {
        imgUrls.push(imgs[i].url);
      }//提交数据的图片连接
        var tmplIds = ['复制你的templId进来']//审核通过通知权限
        var param = {tmplIds}
        api.subscription.checkSub(param).then(res=>{//在这里调用检查函数
          
        var params = {imgs: imgUrls,contestName,mates,status,currNum}
        api.team.publish(params).then(res=>{ //提交表单的函数
          //提交成功
        })
      })
  }

PS:好了,现在用户点击了"是"之后,我们就可以向用户推送消息了,但是机会只有一次 ! 要好好把握 !

操作步骤4: 编写发出推送的函数

这里我们使用云函数,可以很方便的使用, 将不同的模板封装在同一个函数里面,使用哪个就调用哪个.

下面是我的代码

const cloud = require('wx-server-sdk')
cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV
})

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

  switch(event.action) {   //通过传入的参数 action 来选择模板,其他模板为了方便阅读我删掉了,直接复制一下就搞自己的模板啦
    case 'send1' :return send3(event)//审核模板通过模板
  }
}

async function send1(event){

  const {touser,status} = event.data //touser 是发送给用户的openid
  now_db = formatDate2(event.data.now_db)
  createTime = formatDate2(event.data.createTime) //待审核信息的创建时间
  try{//这部分data的内容,和微信公众平台上的模板相对应
    var data = {
      thing2: {
        value: "您发布的信息已审核"
      },
      phrase1: {
        value:status//通过或拒绝
      },
      date3:{
        value:now_db//现在的时间
      },
      date4:{
        value:createTime //消息创建的时间
      }
    }
    const result =await cloud.openapi.subscribeMessage.send({  // 此处发送
      touser:touser,
      page: 'pages/user/index/index',  //用户点击消息后进入程序的页面
      data: data,
      templateId: '这里复制你的templateId',
      miniprogramState: 'developer'     // 跳转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版
    });
    return result
  } catch(err){
    return err
  }
}

function formatDate2 (time) {//时间处理函数
  const date = new Date(time);
  const year = date.getFullYear();
  const month = date.getMonth() + 1;
  const day = date.getDate();
  const hour = date.getHours();
  const minute = date.getMinutes();
  return year + '年' + [month, day].map(formatNumber).join('月') + '日 ' + [hour, minute].map(formatNumber).join(':');
}

function formatNumber(n) {
    n = n.toString();
    return n[1] ? n : '0' + n;
}

操作步骤5:向用户推送消息的时间到,发出推送

就是,我们设定的推送时间,或者其他用户触发了向用户发送给推送消息的事,那么就是现在,发出推送.

这个例子中,就是管理员进行了操作,将用户的组队信息状态,从"wait"等待审核,变成了"accept",通过审核.状态发生改变的同时,我们向用户发出推送.

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

cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV
})

const db = cloud.database()
const _ = db.command
const $ = db.command.aggregate

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

  switch (event.action) {//通过传入action参数选择函数
    case 'changeStatus': return changeStatus(event)
    default: return Promise.reject("unknown action")
  }
}

async function changeStatus(event){//管理员改变信息的状态
  var {teamID,touser,status} = event
  var mp = {'reject':'拒绝','need':'通过'}//通过mp将英文转换为中文
  var status2 = mp[status]
  var time = new Date()
  var createTime = event.createTime
  console.log(createTime)

  return new Promise((reslove,reject)=>{
    db.collection('team').doc(teamID)
    .update({
      data:{
        status:status //更新信息状态
      }
    })
    .then(res=>{//成功之后发送订阅消息
      cloud.callFunction({
        name:'subscribe',
        data:{
          action:"send3",
          data:{status:status2,touser:touser,now_db:time,createTime:createTime}
        }//这里的数据都需要和模板中的数据对应,touser就是发送给目标用户的openid
      }).then(res=>{
        console.log(res)
      }).catch(err=>{
        console.log(err)
      })
      reslove({code:200,message:"转换成功",data:res})
    })
    .catch(err=>{
      reject({code:300,message:"转换失败",data:err})
    })
  })
}

测试

这里因为开发者工具和真机调试弹出来的页面有所不同,所以推荐最好是使用真机进行调试.

用户点击允许之后,再触发发送函数,就可以收到消息了,一开始可以用自己的openid作为touser,来进行测试.

!!!这里注意!!!

如果用户选择了"总是保持以上选择,不在询问",那么以后都不会调起这个界面,但是用户点击一次允许,我们才获得一次发送订阅消息的能力.所以这里会有一个BUG,目前还没有找到解决的方案.只能希望用户不选择这个了.


那么就到这里结束了,有什么问题欢迎留言交流,欢迎点赞关注收藏…好耶!

3 回复

总结得很全面,支持

我的小程序是这么处理需要多次通知用户的。单独有一个订阅按钮,并告诉用户如需多次收到通知请多次点击订阅,就可以了。选中保持以上选择不再询问后,如果是允许,后续点击时会自动允许,如果是不允许,可调用wx.goSetting让用户自己进入通知管理中允许订阅消息。

回到顶部