uni-app微信小程序订阅消息推送实践

11,082 阅读8分钟

我正在参加跨端技术专题征文活动,详情查看:juejin.cn/post/710123…

大家好!

上次介绍了使用uni-app实现微信小程序授权登录的详细过程(链接),这次介绍下了使用跨端开发框架uni-app开发微信小程序模板订阅消息推送的详细步骤。

微信小程序消息推送是我们常见的业务开发场景,经研究实践,发送订阅消息可分成四个步骤:

  1. 申请消息模板:生成消息模板ID,确定模板详情:标题、内容等;
  2. 前端订阅消息:通过按钮或者支付回调向用户发起订阅消息的询问;
  3. 后端进行推送:用户同意订阅后,后端请求微信消息推送接口携带模板ID、模板内容(可理解成数据字段)用户open_id、跳转地址等参数进行推送;
  4. 用户收到消息:用户在服务通知中收到该模板消息的卡片,点击可转向小程序中的跳转地址,可传参。

1 申请消息模板

小程序管理员或运营者可在小程序后台的功能->消息模板的公共模板库中选择适合自己业务需求的模板。

该模板库所列模板是根据小程序所属类目来确定,我们可以通过设置->基本设置来修改小程序类目。Ps:每个月修改小程序类目有次数限制,且部分类目还需提供证明材料。

image-20220604152800062.png

另,微信小程序订阅消息有三种订阅模式:一次性订阅、长期订阅和设备订阅,其中设备订阅主要接入设备,不再此文讨论之列。一次性订阅和长期订阅的区别,简单来说是:

  • 一次性订阅:需要用户接收该消息订阅后,开发者可不限时间地下发一条对应的服务消息
  • 长期订阅:用户订阅一次后,开发者可长期下发多条消息。

那你当然想到了,那就申请长期订阅呗,订阅一次,永久可用。但根据官方文档介绍,长期订阅消息仅向政务民生、医疗、交通、金融、教育等线下公共服务开放,企业或个人暂时无法正常申请。但看社区帖子,用户可通过微信社区向官方人员进行申请长期订阅消息,从而使自己的小程序使用长期订阅消息,具体方法可社区内搜索一下。

回到创建消息模板来,以此次示例的小程序类目:工具->消息查询这个来看,默认所列的公共模板库中有800多个消息模板,覆盖了较多业务应用场景,我们可以从中选取一个。此外,我们还可以创建自定义模板,其入口比较隐蔽,需要我们要手动跳转到公共模板库最后一页,页面左下方有“帮我们完善模板库”的链接。

image-20220604154526623.png

根据自身业务需求,创建适合自己的模板,需等待微信官方审核通过后,方可使用。

image-20220604154623137.png

本文中,我们选择了一个标题为审核结果通知一次性订阅的公共模板,然后在详细内容中选择了三个数据:发起时间、审批结果和问题标题。

下图中是申请后的模板详情页,左侧是消息模板的预览页面,右侧的模板ID和详细内容的变量名,是开发需要使用的。

image-20220604154811492.png

2 前端订阅消息

消息推送的前提是需用户点击按钮或支付回调里触发弹出授权消息框,Ps:仅此两种方式。用户同意后,服务器方可将消息推送该微信用户。

我们先在template中创建一个button按钮,用户点击按钮执行openAuth()方法,弹出授权消息框。

 <template>
     <view class="content">
         <view class="msg">
             <button type="primary" @click="openAuth()">发送消息</button>
         </view>
     </view>
 </template>

在data中定义一个数组tmplIds来存放模板id集(最多存放三个),定义两个同名变量存放小程序的AppId和AppSecret。

 data() {
     return {
         tmplIds:['TknXJKdubbcKDpmLGDkvoxeDn-4ReD3dLDmHRHwSB_M'],
         AppId: 'wxae5813756948397b',
         AppSecret: '3656299fd4ae977e0de01XXXXXXXXX',
     }
 },

在openAuth()方法中,我们调用uni-app的 uni.requestSubscribeMessage(Object object)接口,该接口的参数说明:

属性类型默认值必填说明
tmplIdsArray需要订阅的消息模板的id的集合,一次调用最多可订阅3条消息(注意:iOS客户端7.0.6版本、Android客户端7.0.7版本之后的一次性订阅/长期订阅才支持多个模板消息,iOS客户端7.0.5版本、Android客户端7.0.6版本之前的一次订阅只支持一个模板消息)消息模板id在[微信公众平台(mp.weixin.qq.com)-功能-订阅消息]中配置
successfunction接口调用成功的回调函数
failfunction接口调用失败的回调函数
completefunction接口调用结束的回调函数(调用成功、失败都会执行)

success返回值

属性类型说明
errMsgString接口调用成功时errMsg值为'requestSubscribeMessage:ok'
TEMPLATE_IDString[TEMPLATE_ID]是动态的键,即模板id,值包括'accept'、'reject'、'ban'。'accept'表示用户同意订阅该条id对应的模板消息,'reject'表示用户拒绝订阅该条id对应的模板消息,'ban'表示已被后台封禁。例如 { errMsg: "requestSubscribeMessage:ok", zun-LzcQyW-edafCVvzPkK4de2Rllr1fFpw2A_x0oXE: "accept"} 表示用户同意订阅zun-LzcQyW-edafCVvzPkK4de2Rllr1fFpw2A_x0oXE这条消息
 openAuth() {
     uni.requestSubscribeMessage({
         tmplIds: this.tmplIds,
         success: (res) => {
             console.log(res);
         }
     })
 },

在HbuilderX中,选择菜单栏->运行->运行到微信小程序开发者工具,将uni-app代码自动编译到微信开发者工具中,在预览页面中单击授权提示时,会弹出下图中订阅消息对话框。

image-20220604160607574.png

当用户点击允许时,success返回值res中,会有一个键为TEMPLATE_ID,值为accept的属性。该操作即说明了用户同意订阅一个来自模板ID为TknXJKdubbcKDpmLGDkvoxeDn-4ReD3dLDmHRHwSB_M的模板消息。

3 后端进行推送

用户同意订阅后,请求微信的接口携带模板ID、模板内容(可理解成数据字段)用户open_id、跳转地址等参数进行推送。实际业务中要保证敏感信息不泄露,应将获得openid的过程放到后端来请求,为方便演示推送接口的使用,这里我们在前端发起请求,步骤如下:

3.1 获取openid

用户openid的获取过程有以下两个步骤:

  1. 通过uni-app的uni.login()来获得js_code
  2. 通过微信服务端登录接口auth.code2Session(官网文档),传递appid、secret、js_code等参数来拿到openid。

示例中创建了两个方法getJsCode()和getOpenId(),在sendMsg()方法中依次执行来获得openid。

 getJsCode() {
     return new Promise((resolve, reject) => {
         uni.login({
             success(res) {
                 resolve(res.code)
             },
             fail: (err) => {
                 reject(err)
             }
         })
     })
 },
 getOpenId(js_code) {
     return new Promise((resolve, reject) => {
         uni.request({
             url: `https://api.weixin.qq.com/sns/jscode2session`,
             data: {
                 appid: this.AppId,
                 secret: this.AppSecret,
                 js_code: js_code,
                 grant_type: 'authorization_code'
             },
             success: (res) => {
                 resolve(res.data.openid)
             },
             fail(err) {
                 reject(err)
             }
         })
     })
 },
 async sendMsg(){
     const js_code = await this.getJsCode();
     const openid = await this.getOpenId(js_code);
     console.log("js_code: ",js_code); // => js_code:  051b4pFa1rv9iD0tfbHa1rNjFd0b4pFS
     console.log("openid: ",openid); // => openid:  oC44P5JYnIsJs_dltf3vZuEPbrag
 },

3.2 获取access_token

access_token是小程序全局后台接口调用凭证,大部分的服务端接口都需要传递此鉴权凭证。在发送模板消息的接口中,也需此凭证,下面演示如何通过auth.getAccessToken(官方文档)来获取access_token。

请求地址:

 GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

请求参数:

属性类型默认值必填说明
grant_typestring填写 client_credential
appidstring小程序唯一凭证,即 AppID,可在「微信公众平台 - 设置 - 开发设置」页中获得。(需要已经成为开发者,且帐号没有异常状态)
secretstring小程序唯一凭证密钥,即 AppSecret,获取方式同 appid

返回值:返回的 JSON 数据包

属性类型说明
access_tokenstring获取到的凭证
expires_innumber凭证有效时间,单位:秒。目前是7200秒之内的值。
errcodenumber错误码
errmsgstring错误信息

我们创建一个getAccessToken()的方法来获取access_token

 // 获取access_token
 getAccessToken() {
     return new Promise((resolve, reject) => {
         uni.request({
             url: 'https://api.weixin.qq.com/cgi-bin/token',
             data: {
                 appid: this.AppId,
                 secret: this.AppSecret,
                 grant_type: 'client_credential'
             },
             success: (res) => {
                 resolve(res.data.access_token)
             },
             fail: (err) => {
                 reject(err)
             }
         })
     })
 },

3.3 发送模板消息

发送模板消息是通过微信subscribeMessage.send(官方文档)来实现,代码如下:

 async sendMsg(){
     const js_code = await this.getJsCode();
     const openid = await this.getOpenId(js_code);
     const access_token = await this.getAccessToken();
     uni.request({
         url: 'https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=' +
         access_token,
         method: 'POST',
         data: {
             touser: openid,
             template_id: this.tmplIds[0], // 第一个模板id
             page: "pages/index/index",    // 点击消息卡片跳转地址
             data: {                       // data是模板内容,属性名为模板中所给,value值是需要传递的。
                 time2: {
                     value: '2022-06-04 20:33:44'
                 },
                 phrase3: {
                     value: '审批通过'
                 },
                 thing10: {
                     value: '请求审批'
                 }
             }
         },
         success: (res) => {
             console.log(res);
         }
     })
 },

改造openAuth(),增加sendMsg()的调用,实现用户同意订阅消息模板后,发送模板消息。

 openAuth() {
     let templateId = this.tmplIds[0]
     uni.requestSubscribeMessage({
         tmplIds: this.tmplIds,
         success: (res) => {
             if (res[templateId] === 'accept') {
                 this.sendMsg()
             }
         }
     })
 },

4 用户收到消息

用户点击按钮,发起授权同意后,就会在微信的服务通知里收到如下消息,点击“进入小程序查看”,就会跳转到我们page属性的路径里。

image-20220604164419711.png

以上就是使用uni-app开发微信小程序模板消息推送的全过程,如有问题可到评论区留言,记得点赞!