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

         * 源码已经上传到资源处,需要的话点击跳转下载 |  源码下载

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

        以上大致知道了订阅消息的这个功能,这里需要客户端和服务器端两者,本篇就来使用客户端,且在客户端中来模拟服务器端,那么在下一篇会使用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后台来搭服务器的篇目供读者参考交流学习,感谢大家的支持!!! 

微信小程序实现订阅消息功能,需要在后端服务器使用Node.js来实现。以下是一个示例的Node.js源码,用于实现微信小程序订阅消息功能。 ```javascript const express = require('express'); const axios = require('axios'); const app = express(); const port = 3000; // 用于接收微信小程序订阅消息的回调 app.post('/callback', async (req, res) => { try { // 解析请求体中的数据 const data = req.body; // 向微信API发送请求,完成订阅消息的下发 await axios.post('https://api.weixin.qq.com/cgi-bin/message/subscribe/send', { touser: data.openid, // 用户的openid access_token: data.access_token, // 小程序的access token template_id: data.template_id, // 订阅消息模板ID data: data.template_data, // 订阅消息模板中的数据 }); // 返回成功响应给微信小程序 res.status(200).send('Success'); } catch (error) { // 返回错误响应给微信小程序 res.status(500).send('Failed'); } }); app.listen(port, () => { console.log(`Server is running on port ${port}`); }); ``` 上述代码中,创建了一个基于Express框架的Node.js服务器。通过定义一个`/callback`的路由,用于接收微信小程序发送的订阅消息的回调。 在回调中,首先解析请求体中的数据,包括用户的openid、小程序的access token、订阅消息模板ID以及要下发的模板数据。然后,使用axios库发送HTTP POST请求到微信API,完成订阅消息的下发。 最后,根据发送请求的结果,返回相应的成功或失败响应给微信小程序。 需要注意的是,此代码仅为示例,实际项目中还需要添加相应的错误处理等逻辑。此外,还需要配置服务器的域名与小程序进行关联,并在小程序端的代码中发送HTTP请求到该服务器。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

灵魂学者

你的鼓励是我最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值