微信小程序订阅消息工具封装,兼容一次性订阅和长期订阅

1.流程图

2.详细代码

js 复制代码
/**
 * @description Promise调用安全包装
 * @param {Promise} p
 * @returns {Promise}
 */
const $sync = (p) => p.then((d) => [null, d]).catch((e) => [e]);

/**
 * @name requestSubscribeMessage
 * @description 处理消息订阅,兼容一次性订阅和长期订阅
 * @param {String} templateId 消息模板id
 * @returns {Boolean} 是否订阅成功
 */
export async function requestSubscribeMessage(templateId) {
	// 检查之前是否授权
	const [, settingRes] = await $sync(checkSubscribeMessageAuth(templateId));

	// 之前已授权,返回true,执行业务逻辑
	if (settingRes) return true;

	// 之前未授权,请求授权
	const [, authRes] = await $sync(doRequestSubscribeMessage(templateId));

	// 用户同意授权,返回true,执行业务逻辑
	if (authRes) return true;

	// 用户拒绝授权,显示引导授权弹窗
	const [, guideRes] = await $sync(showAuthGuideModal());

	// 用户确认去修改配置,打开配置页面
	if (guideRes) {
		const [, openSettingRes] = await $sync(openSettingPage(templateId));

		// 用户在设置页面已授权,返回true,执行业务逻辑
		if (openSettingRes) return true;
	}

	// 默认返回false,代表用户未授权或授权失败
	return false;
}

// 检查订阅消息授权状态的函数
function checkSubscribeMessageAuth(templateId) {
	return new Promise((resolve, reject) => {
		wx.getSetting({
			withSubscriptions: true, // 注意:需要此参数来获取订阅消息状态
			success: (res) => {
				// 检查订阅消息设置是否存在
				if (!res.subscriptionsSetting) {
					reject(new Error("无法获取订阅消息设置"));
					return;
				}

				const { mainSwitch, itemSettings = {} } = res.subscriptionsSetting;

				// 首先检查订阅消息总开关是否开启
				if (!mainSwitch) {
					reject(new Error("订阅消息总开关未打开"));
					return;
				}

				// 如果提供了具体模板ID,检查其授权状态
				if (templateId) {
					const templateAuth = itemSettings[templateId];
					if (templateAuth !== "accept") {
						reject(new Error(`模板消息 ${templateId} 未授权`));
						return;
					}
				} else {
					reject(new Error("未提供模板id"));
				}

				// 授权检查通过
				resolve(itemSettings);
			},
			fail: (err) => {
				reject(err);
			},
		});
	});
}

// 请求订阅消息授权
function doRequestSubscribeMessage(templateId) {
	return new Promise((resolve, reject) => {
		wx.requestSubscribeMessage({
			tmplIds: [templateId], // 需要订阅的消息模板ID的数组
			success: (res) => {
				if (res[templateId] === "accept") {
					// 用户同意订阅
					resolve(true);
				} else {
					// 用户拒绝订阅、被后台封禁、因标题同名被后台过滤等
					reject(new Error("用户拒绝订阅"));
				}
			},
			fail: (err) => {
				reject(new Error("调起授权弹窗失败"));
			},
		});
	});
}

// 显示引导授权弹窗
function showAuthGuideModal() {
	return new Promise((resolve, reject) => {
		wx.showModal({
			title: "温馨提示",
			content: "为了您能及时收到重要通知,请开启消息订阅权限。",
			confirmText: "前往开启",
			success: (res) => {
				res.confirm ? resolve(true) : reject(new Error("用户取消"));
			},
			fail: () => {
				reject(new Error("打开引导弹窗失败"));
			},
		});
	});
}

// 打开设置页面
function openSettingPage(templateId) {
	return new Promise((resolve, reject) => {
		wx.openSetting({
			withSubscriptions: true,
			success: (res) => {
				// 用户从设置页面返回,再次检查授权状态
				const mainSwitch = res?.subscriptionsSetting?.mainSwitch || false;
				const itemSettings = res?.subscriptionsSetting?.itemSettings || {};
				if (mainSwitch && itemSettings[templateId] === "accept") {
					resolve(true);
				} else {
					reject(new Error("用户在设置页面未授权"));
				}
			},
			fail: (err) => {
				reject(new Error("打开设置页面失败"));
			},
		});
	});
}

3. 使用方法

js 复制代码
const templateId = "XXXXXX"; // 消息模板id
const result = await requestSubscribeMessage(templateId);
console.log(result ? "订阅成功" : "订阅失败");
相关推荐
李慕婉学姐11 分钟前
基于微信小程序的运动会信息管理系统k6kqgy34(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·微信小程序·小程序
风月歌31 分钟前
小程序项目之驾校报名小程序源代码(java+vue+小程序+mysql)
java·vue.js·mysql·小程序·毕业设计·源码
咸虾米_42 分钟前
uniapp+unicloud实战项目,九两酒微信小程序商城及后台管理系统前后端部署运行步骤
微信小程序·uni-app·uniapp实战项目·unicloud云开发·vue3后台管理
风月歌1 小时前
小程序项目之使命召唤游戏助手源代码(java+vue+小程序+mysql)
java·mysql·小程序·毕业设计·源码
小码哥0681 小时前
家政服务管理系统(源码+文档+部署+讲解)
小程序·家政系统·家政服务系统·家政服务管理系统
阿里巴巴AI编程社区15 小时前
用Qoder打造自己的AI工作台,普通人也可10倍提效!
微信小程序
星光一影21 小时前
美容/心理咨询/问诊/法律咨询/牙医预约/线上线下预约/牙医行业通用医疗预约咨询小程序
mysql·小程序·vue·php·uniapp
游戏开发爱好者81 天前
H5 混合应用加密 Web 资源暴露到 IPA 层防护的完整技术方案
android·前端·ios·小程序·uni-app·iphone·webview
wangpq1 天前
记录曾经打开半屏小程序遇到的事
前端·微信小程序
2501_915106321 天前
最新版本iOS系统设备管理功能全面指南
android·macos·ios·小程序·uni-app·cocoa·iphone