乐于分享
好东西不私藏

小程序消息订阅-uniapp实现

小程序消息订阅-uniapp实现

获取模板
1,登录小程序后台:访问 https://mp.weixin.qq.com/,使用小程序账号登录
2,进入订阅消息管理:左侧菜单 → 功能 → 订阅消息
3,选择公共模板:在「公共模板库」中搜索适合的模板,点击「选用」
4,配置模板参数:填写模板名称,选择需要的关键词,点击「提交」
5,获取模板ID:提交后,在「我的模板」中可以看到已添加的模板,记录下模板ID
自定义模板
1,进入模板管理:左侧菜单 → 功能 → 订阅消息 → 我的模板
2,申请自定义模板:点击「申请模板」,填写模板标题、场景描述、内容示例等信息
3,等待审核:自定义模板需要微信官方审核,一般1-3个工作日
4,使用模板:审核通过后,在「我的模板」中可以看到自定义模板,获取模板ID
注意: 每个小程序账号最多可以添加25个模板,包括公共模板和自定义模板。
订阅消息授权
// 订阅消息授权async function requestSubscribeMessage() {  try {    const res = await uni.requestSubscribeMessage({      tmplIds: ['模板ID1''模板ID2'], // 需要订阅的模板ID列表      success(res) => {        console.log('订阅成功', res);        // 处理订阅成功的逻辑      },      fail(err) => {        console.log('订阅失败', err);        // 处理订阅失败的逻辑      }    });    return res;  } catch (error) {    console.log('订阅消息失败', error);    return false;  }}
发送订阅消息(Node.js)
// 后端发送订阅消息示例(Node.js)const axios = require('axios');async function sendSubscribeMessage(openid, templateId, data, page) {  try {    // 获取access_token    const tokenRes = await axios.get(`https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appid}&secret=${secret}`);    const accessToken = tokenRes.data.access_token;    // 发送订阅消息    const sendRes = await axios.post(      `https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=${accessToken}`,      {        touser: openid, // 用户openid        template_id: templateId, // 模板ID        page: page, // 点击消息跳转的页面        data: data // 模板数据      }    );    return sendRes.data;  } catch (error) {    console.log('发送订阅消息失败', error);    return false;  }}
使用案例
<viewclass="container">    <button @click="checkAndSubscribe"type="primary">订阅消息</button></view>
// 检查并订阅消息async checkAndSubscribe() {  try {    // 1. 尝试请求订阅    const subscribeRes = await this.requestSubscribe();    // 2. 根据订阅结果处理    if (subscribeRes) {      console.log('订阅成功');    } else {      // 3. 订阅失败,检查权限状态      await this.checkPermissionStatus();    }  } catch (error) {    console.log('订阅流程出错', error);    uni.showToast({      title'操作失败,请重试',      icon'none'    });  }},// 请求订阅消息async requestSubscribe() {  return new Promise((resolve, reject) => {    uni.requestSubscribeMessage({      tmplIds: [this.templateId],      success(res) => {        console.log('订阅结果', res);        if (res[this.templateId] === 'accept') {          uni.showToast({            title'订阅成功',            icon'success'          });          resolve(true);        } else if (res[this.templateId] === 'reject') {          console.log('用户拒绝订阅');          resolve(false);        } else if (res[this.templateId] === 'ban') {          console.log('用户被禁止订阅');          uni.showToast({            title'您已被禁止订阅消息',            icon'none'          });          resolve(false);        } else {          console.log('订阅状态未知', res[this.templateId]);          resolve(false);        }      },      fail(err) => {        console.log('请求订阅失败', err);        resolve(false);      }    });  });},// 检查权限状态async checkPermissionStatus() {  return new Promise((resolve) => {    uni.getSetting({      success(res) => {        console.log('当前权限设置', res.authSetting);        // 检查订阅消息权限        const hasSubscribePermission = res.authSetting['scope.subscribeMessage'];        if (hasSubscribePermission === false) {          // 权限被拒绝,引导用户去设置页面          this.guideToSetting();        } else {          // 权限未设置或已允许,可能是其他原因导致订阅失败          uni.showToast({            title'订阅失败,请稍后重试',            icon'none'          });        }        resolve();      },      fail(err) => {        console.log('获取设置失败', err);        resolve();      }    });  });},// 引导用户去设置页面guideToSetting() {  uni.showModal({    title'需要权限',    content`您需要开启${this.templateTitle}的订阅权限才能接收相关通知,是否前往设置页面开启?`,    confirmText'去设置',    cancelText'暂不开启',    success(modalRes) => {      if (modalRes.confirm) {        this.openSetting();      }    }  });},// 打开设置页面openSetting() {  uni.openSetting({    success(settingRes) => {      console.log('设置页面操作结果', settingRes.authSetting);      // 检查用户是否开启了订阅消息权限      if (settingRes.authSetting['scope.subscribeMessage']) {        uni.showToast({          title'权限开启成功',          icon'success'        });        // 可以再次尝试订阅        this.requestSubscribe();      } else {        uni.showToast({          title'权限未开启',          icon'none'        });      }    },    fail(err) => {      console.log('打开设置页面失败', err);      uni.showToast({        title'打开设置页面失败',        icon'none'      });    }  });}

代码说明:

1. checkAndSubscribe方法:整合了权限检查、订阅请求和引导设置的完整流程

2. requestSubscribe方法:封装了订阅消息的请求逻辑,返回订阅结果

3. checkPermissionStatus 方法:获取用户当前的权限设置状态

4. guideToSetting 方法:当权限被拒绝时,引导用户去设置页面

5. openSetting方法:打开小程序设置页面,并处理用户操作结果

推荐的订阅时机
1. 用户主动操作时:如点击「预约」、「报名」、「下单」等按钮时
2. 功能开通时:如开通会员、设置提醒等功能时
3. 任务完成时:如任务完成后,询问是否订阅结果通知
4. 场景相关时:如进入特定场景页面时,询问是否需要相关通知
注意事项
1. 必须用户主动触发:订阅消息的请求必须由用户主动点击按钮等操作触发,不能自动弹出
2. 合理使用订阅场景:只在与用户操作相关的场景下请求订阅,避免过度打扰
3. 明确告知用户:在请求订阅前,应该明确告知用户订阅的内容和频率
4. 一次最多订阅3个模板:每次调用 requestSubscribeMessage 最多只能请求3个模板
5. 订阅状态管理:需要在后端记录用户的订阅状态,避免重复发送
重要提醒:如果用户拒绝订阅后,下次调用 requestSubscribeMessage 将不会再次弹出授权弹窗,需要用户手动在小程序设置中开启。
取消订阅
1,小程序设置页: 
打开小程序 → 点击右上角「…」→ 点击「设置」→ 进入「通知管理」→ 关闭对应通知
2,应用设置页:
• iOS:设置 → 微信 → 通知 → 关闭小程序通知
• Android:设置 → 应用管理 → 微信 → 通知 → 关闭小程序通知
3,应用内设置:在小程序内提供消息订阅管理页面,允许用户手动开启/关闭
常见问题与解决方案
1,订阅消息不弹出授权弹窗
原因:用户之前拒绝过订阅,或已被禁止订阅
解决方案:引导用户进入小程序设置页面手动开启
2,发送订阅消息失败
原因:
• 用户未订阅该模板
• 模板ID错误
• access_token过期
• 消息数据格式错误
解决方案:
• 检查用户订阅状态
• 核对模板ID
• 确保access_token有效
• 检查数据格式是否正确
3,订阅消息无法跳转页面
原因:page参数格式错误或页面不存在
解决方案:确保page参数以「/」开头,且对应页面存在