微信小程序实现订阅消息功能

​​​​​​​

         小程序中的订阅内容在日常中大家都会使用到,一般在支付的时候,会收到支持成功的消息,里面有一些基础信息花费多少以及是使用在什么地方,订阅消息是小程序向用户发送消息的方式,小程序本身是不具备接收消息功能,而是通过微信的服务通知功能将消息转达给用户的。下面来简单看一下:

        以上大致知道了订阅消息的这个功能,这里需要客户端和服务器端两者,本篇就来使用客户端,且在客户端中来模拟服务器端,那么在下一篇会使用Node.js搭载的服务器作为服务端。


完成效果

下面来看一下完成的效果:

           在未获取用户信息之前无法进入界面,在获取之后进入操作界面,日志类型默认是日报,可以点击选择周报或月报,点击日期选择可以挑选对应的日期,需要填写提醒人,温馨提示默认是这个尚未提交日志,下面还有一个提示,需要填写提醒人名称,当点击提醒人名称时会获取用户订阅消息的权限,填写完提醒人发送按钮也会从禁用转成启用状态,点击发送就可以在微信上的服务通知可以看到会有这个未提交日志提醒的通知了,下面就来开始实现:


订阅消息相关参数

参数准备

         appid(用户标识),appSecret(app密钥),template_id (订阅模板id)

    登录 微信公众平台 (qq.com) 进入之后,在左侧菜单找到【开发管理】

    现在来获取第三个订阅模板,在左侧菜单的【订阅消息】处,点击【选用】,然后搜一下【未提交日志】

    然后点击【选用】 ,会出现以下这个

     回到【订阅消息】的界面,在【我的模板】中可以找到,打开【详情】,里面就有这个模板id


页面编写

        对页面编写的内容同样也不多说,点击按钮获取到数据就更新状态,通过wx:if或者wx:else来进行显示和隐藏,这里的样式也需要大家自己写了,页面也是比较简单的,还是着重在如何来实现订阅消息这块。

<!-- index.html -->
<!-- 顶部 -->
<view class="content">
  <view class="head">
    当前操作员:{
   
   {admin}}
  </view>
  <block wx:if="{
   
   {!hasUserInfo}}">
    <button bindtap="getUserProfile">获取</button>
  </block>
  <block wx:else>
    <form bindsubmit="formSubmit">
      <view class="log">
        <view class="log_title"> 
          <text>日志类型</text>
          <picker bindchange="changeTitle" name="title" value="{
   
   {index}}" range="{
   
   {logArray}}">
              <view class="nowing">{
   
   {logArray[index]}}</view>
          </picker>
        </view>
        <view class="log_date">
          <text>日期选择</text>
          <picker mode="date" name="date" value="{
   
   {date}}" bindchange="bindDateChange">
            <view class="nowing">{
   
   {date}}</view>   
          </picker>
        </view>
        <view class="log_person">
          <text>提醒人</text>
          <input type="text" name="remind" bindinput="bindRemindPer" bindtap ="allowSubscribeMessage" placeholder="例如:小明(参考)" value="{
   
   {remind}}"/>
        </view>
        <view class="log_tip">
          <text>温馨提示</text> 
          <input type="text" name="tip" bindinput="bindTipCont" value="{
   
   {tip}}"/>
        </view>
        <button form-type="submit" disabled="{
   
   { remind == '' ? true : false}}">发送</button>
        <view class="errMsg">{
   
   { remind == '' ? 'tips:需要填写提醒人名称才可发送!' : '' }}</view>
      </view>
    </form>
  </block>
</view>

监听获取表单信息

        对填写的表单中的input框中数据进行监听,获取到表单数据进行更新;通过bindinput获取

// index.js
// 获取应用实例
const app = getApp()

Page({
  data:{
    index: 0 ,                            // 默认为0,日报
    logArray:['日报','周报','月报'],
    admin:'',                             // 操作员
    lTitle:'未提交日志提醒',               // 提醒标题
    date: new Date(),                     // 日期(未格式化)
    remind:'',                            // 提醒人,默认admin              
    tip:'尚未提交日志',                    // 温馨提示内容
  },
  // 获取提醒标题
  changeTitle(e){
    this.setData({ index : e.detail.value })
  },
  // 获取日期选择
  bindDateChange(e){
    this.setData({ date : e.detail.value })
  },
  // 获取提醒人
  bindRemindPer(e){
    this.setData({ remind : e.detail.value })
  },
  // 获取提示内容
  bindTipCont(e){
    console.log(e)
    this.setData({ tip : e.detail.value })
  },
  // 获取用户信息 - 待写
})

        这里存在一个问题,也就是选择日期的问题,通过new Date() 获取的日期并不符合日期格式,所以这里可以对获取到的日期进行一个格式化处理,这里就不去装moment.js插件这些了,在util/util.js 文件中来编写格式化日期。


日期格式化处理

        在 util/util.js 文件中编写一个公共函数并导出:

// 格式化日期
function formatTime(date) {
    var year = date.getFullYear()
    var month = date.getMonth() + 1
    var day = date.getDate()
    return [year, month, day].map(formatNumber).join('-') 
}

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

module.exports = {
  formatTime
}

        在index.js文件中来引入使用,const time = require('../../util/util')

// index.js
// 获取应用实例
const app = getApp()
const time = require('../../utils/util')

Page({
    data:{
        ...
        date: time.formateTime(new Date())        // 日期(格式化)
    }
    ...
})

         可以拿到的 date 是这种格式的 " xxxx - xx - xx ",下面就来获取用户信息:


获取用户信息

        获取用户信息,一般像这些的话可以写在app.js中然后进行保存,以便全局使用,这里就保存到app.js,就存放在index.js中方便查看。小程序中获取用户信息的方式也有了调整,具体可以看以下 wx.getUserProfile(Object object) | 微信开放文档

// index.js
// 获取应用实例
const app = getApp()
const time = require('../../utils/util')

Page({
  data:{
    hasUserInfo:false,                    // 获取用户信息
    index: 0 ,                            // 默认为0,日报
    logArray:['日报','周报','月报'],
    admin:'',                             // 操作员
    lTitle:'未提交日志提醒',               // 提醒标题
    date: time.formateTime(new Date())    // 日期(格式化)
    remind:'',                            // 提醒人,默认admin              
    tip:'尚未提交日志',                    // 温馨提示内容
  },
  // 获取提醒标题
  // 获取日期选择
  // 获取提醒人
  // 获取提示内容
  // 获取用户信息
  getUserProfile(e) {
    // 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认,开发者妥善保管用户快速填写的头像昵称,避免重复弹窗
    wx.getUserProfile({
      desc: '展示用户信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
      success: (res) => {
        this.setData({
          admin: res.userInfo.nickName,
          hasUserInfo: true
        })
      }
    })
  },
  // 获取用户权限 - 待写
})

        当点击获取时用户信息成功时在回调处理中hasUserInfo会打开,此时填写的界面就会显示出来,而获取按钮将会被隐藏起来。


获取订阅消息权限

        发送订阅消息的时候需要获取到订阅消息的权限,那么可以放到用户在操作的时候进行提示,这里可以在用户在输入提醒人的时候,点击提醒人input输入框的时候触发,为它绑定一个事件 bindtap = "allowSubscribeMessage" 获取用户订阅消息权限,获取之后需要保存它的获取状态,所以需要保存到app.js文件中。

// app.js
App({
  globalData: {
    userInfo: null, 
    hasSubscribeMessage:''
  }
})
// index.js
// 获取应用实例
const app = getApp()
const time = require('../../utils/util')

const tempid = ''     // 填写上你自己的订阅模板id [未提交日志模板]

Page({
  data:{
    ...
  },
  // 获取提醒标题
  // 获取日期选择
  // 获取提醒人
  // 获取提示内容
  // 获取用户信息
  // 获取用户权限
  allowSubscribeMessage(){
    // hasSubscribeMessage 授权状态
    if (!app.globalData.hasSubscribeMessage) {
      wx.requestSubscribeMessage({
        tmplIds: [tempid], // 在此处填写模板id
        success(res) {
          console.log('获取权限:',res)
          app.globalData.hasSubscribeMessage = res.errMsg.split(':')[1]
        }
      })
    }
  },
  // form 提交表单 - 待写 
})

        获取定位权限之后,下面来进行对表单内容的一个提交;


form 提交表单

        后台服务器端发送模板信息中需要用到这个【openid】参数,那么openid参数可以通过appid,appsecret 和 code 才能拿到,前两个参数已经有了,那么 code 参数可以通过wx.login 获取到,通过 wx.login 获取到 code参数,然后提交到后台服务器端;

        这里提交表单会将表单中的 value 进行整理,可以打印一下提交的内容数据:

// form 提交表单
formSubmit(e){
    // e.detail.value 可以拿到用户提交表单的数据
    console.log(e)
    console.log(e.detail.value)

         根据前面data中定义,它是logArray数组下标为0的值,即日报,那么这里需要处理一下然后提交过去,wx.login() 方法获取code成功之后回调将 code 和 提交的数据一并提交过去即可!

Page({
...
// 表单提交
  formSubmit(e){
    // e.detail.value 可以拿到用户提交表单的数据
    // console.log(e.detail.value)
    let formInfo = e.detail.value
    formInfo.title = this.data.logArray[formInfo.title]
    wx.login({
      timeout: 2000,
      // 成功后会返回code,将code提交给服务器
      success: res =>{
        // 获取到code
        console.log('获取到code:' + res.code)
        console.log(res)
        // 提交服务器 -- 待写
      }
    })
  }    
})

        到这客户端的内容基本已经差不多了,就剩下提交到服务器端,在这边写之前,先来模拟后台服务器来接收,接收客户端提交的数据,处理之后再发送订阅消息!


模拟后台服务器端

        在客户端中模拟后台服务器端进行接收,接收来自客户端的表单数据在订阅消息的模板中来使用,以及接收客户端通过 wx.login 方法获取的code

// index.js
const app = getApp()
const time = require('../../utils/util')

const tempid = ''

Page({
    ...
})

// 模拟服务器端
var server = {
    // 响应POST请求
    post(data,success) {
        console.log('收到来自客户端提交的数据:',data);
        // 获取openid - 待写
    }
} 

        这里模拟服务器端后,回到【form提交表单】这里,来发起请求将对应获取到的code和form表单数据提交过来:

...
// 表单提交
  formSubmit(e){
    // e.detail.value 可以拿到用户提交表单的数据
    // console.log(e.detail.value)
    let formInfo = e.detail.value
    formInfo.title = this.data.logArray[formInfo.title]
    wx.login({
      timeout: 2000,
      // 成功后会返回code,将code提交给服务器
      success: res =>{
        // 获取到code
        console.log('获取到code:' + res.code)
        console.log(res)
        // 提交服务器
        server.post({ code : res.code , formInfo},()=>{
            wx.showToast({
                title: '发送成功',
                icon: 'success',
                duration: 2000
            })
            // 成功提交,由服务器发起订阅消息 - 待写
        })
      }
    })
  }    
})
...
// 模拟服务器端
var server = {
    // 响应POST请求
    post(data,success) {
        console.log('收到来自客户端提交的数据:',data);
        // 获取openid - 待写
    }
} 

        在这里来查看一下是否能够正常的收到来自客户端提交的数据:可以看到 title 和日期的处理

         data参数里面有这个 code 和 formInfo 提交表单的数据,接下来就需要在服务器中来获取openid参数了。


获取参数 Openid

        在服务器端来获取这个openid参数,openid参数的获取需要这3个参数:appid,appsecret 和code ,这三个参数现在都已经有了,下面就是获取openid然后进行保存待用。

        可以看一下官方文档的内容:  获取openid | 微信开放文档 ,通过请求如下地址

https://api.weixin.qq.com/sns/jscode2session 

        以及需要如下这些请求参数,主要还是前三个参数的获取;

        成功后会返回以下这些参数

         可以获取到 openid 和 session_key ,下面来进行编写获取,通过 wx.request 方法发起请求,携带上那几个参数,成功之后 success : success ,即触发this.getOpenid()方法的第二个参数是一个回调,(res)=>{ // 处理函数 } 。

...
// 模拟服务器端
var server = {
    appid: '',    // 写上你自己的 appid 
    secret: '',   // 写上你自己的 appsecret
    user:{
        openid: '' // 待接收
    }

    // 响应POST请求
    post(data,success) {
        console.log('收到来自客户端提交的数据:',data);
        // 获取openid
        this.getOpenid(data,(res)=>{
            // 获取code成功回调
            console.log('用户OpenId': res.data.code)
            // 保存
            this.user.openid = res.data.openid
            success()
        })
    },
    // 获取Openid方法
    getOpenid(res,success){
        // res中有 code,formInfo
        wx.request({
            url: 'https://api.weixin.qq.com/sns/jscode2session',
            data: { // 请求参数
                appid: this.appid,
                secret: this.secret,
                js_code: res.code,
                grant_type: 'authorization_code'
            },
            success: success 
        })
    }
} 

        下面来看一下是否获取到了这个用户的Openid:

         拿到 Openid 接下来就可以进行发布订阅消息了。


发布订阅消息

        在前面的【表单】提交内容中,成功返回code之后提交给服务器端,此时就可以从客户端发起请求到服务器端响应发送订阅消息。

...
// 表单提交
  formSubmit(e){
        ...
        // 提交服务器
        server.post({ code : res.code , formInfo},()=>{
            wx.showToast({
                title: '发送成功',
                icon: 'success',
                duration: 2000
            })
            // 成功提交,由服务器发起订阅消息
            server.sendTempMsg(formInfo,(res)=>{
                console.log('订阅消息发送结果:',res.data)
            })
        })
      }
    })
  }    
})
...
// 模拟服务器端
var server = {
  appid: '',    // 写你自己的 appid
  secret:'',    // 写你自己的 appsecret
  user:{
    openid: ''  // 待接收
  },
  // 响应POST请求
  // 获取Openid方法
  // 发送订阅消息 - 待写
}

#发布订阅消息需要的参数

        openid,template_id(订阅模板id),模板的参数

        openid 和 template_id 参数已经拿到了,剩下这个模板的参数,前面我们申请选用了模板,那么发布订阅模板中我们需要其中的哪些参数需要自己来定。

        通过以上这些可以来制定发布订阅消息的模板,发布订阅模板信息需要用到这个微信API接口,可以看一下官方文档提供的接口和所需要的请求参数:

POST https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=ACCESS_TOKEN 

        这里主要缺少的参数就是 access_token 参数,该参数是接口调用的凭据,那么发布订阅消息还需要获取 access_token,这是【获取接口调用凭据】,获取接口调用凭据 | 微信开放文档 ,通过下面这个微信API接口就可以获取到接口调用的凭借。

GET https://api.weixin.qq.com/cgi-bin/token

        所需要的参数也是已经有了的,下面就来开始编写发布订阅消息代码。

// 模拟服务器端
var server = {
  appid: '',    // 写你自己的 appid
  secret:'',    // 写你自己的 appsecret
  user:{
    openid: ''  // 待接收
  },
  // 响应POST请求
  // 获取Openid方法
  // 发送订阅消息
  sendTempMsg(formInfo,success){
      var that = this.user
      var temp = {
          touser: that.openid
          template_id: tempid,   // 订阅模板id
          data: {
              phrase1: { value: formInfo.title },
              date2: { value: formInfo.date },
              name3: {value: formInfo.remind },
              thing4: { value: formInfo.tip }
          },
          miniprogram_state: 'developer',
          lang: 'zh_CN'
      }  
      // 发送订阅
      this.getAccessToken(res=>{
          var token = res.data.access_token
          console.log('服务器access_token:' + token)
          var url = 'https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=' + token
          wx.request({
              url,
              method: 'POST',
              data: temp,
              success
          })
      })
      // 获取 access_token 
      getAccessToken(success){
          var url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' + this.appid + '&secret=' + this.secret
          wx.request({
              url,
              success: success
          })
      }
  }
}

         服务器会返回 access_token ,当服务器发出订阅消息成功时,客户端做监听回调。

         到这里代码内容已经编写完成了,下面来进行测试是否能够发出订阅消息!


发布订阅消息测试

        1. 点击获取按钮时,会获取用户信息,此时会进行提示,当获取到信息时hasUserInfo的状态为 true时,此时填写界面也会随之出现。

        2. 当前的操作员就是获取用户信息中的NiceName,hasUserInfo的值也为true,此时提醒人还没进行填写,有灰色的提示参考填写,以及发布按钮被禁用了,最底部有红色的提示,需要填写后才可以启用按钮进行发送。

         3.点击提醒人的输入框时,会触发获取发布订阅消息的权限事件。

         4. 获取权限之后,输入提醒人 “syan” 之后,可以看到发送按钮以及启用了,同时按钮下面的红色提示字体也隐藏起来了。

         5.点击发送之后可以看到提示发送成功的提示消息。

        6. 拿出你的手机打开微信,或者在电脑上打开微信在服务通知可以看到这条消息。

        微信服务通知能够接收到这条订阅消息,那么本篇的内容也就到此结束了,再下一期中会再出一期使用Node.js后台来搭服务器的篇目供读者参考交流学习,感谢大家的支持!!! 

猜你喜欢

转载自blog.csdn.net/weixin_52203618/article/details/130236946