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

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 ? "订阅成功" : "订阅失败");
相关推荐
CRMEB系统商城11 小时前
CRMEB标准版系统(Java)v3.1正式发布
java·spring·微信小程序·php·教育电商
m0_5873830013 小时前
折扣卡CPS系统源码的技术架构与实战开发指南
人工智能·小程序·数据挖掘·系统架构·需求分析
2501_9151063214 小时前
苹果App Store上架费用及流程全面解析
android·ios·小程序·https·uni-app·iphone·webview
海岳云舟15 小时前
通过Spring Authorization Server对微信小程序应用进行授权防护
微信小程序
T011561818 小时前
全栈项目实战手记|艺培场馆课时预约小程序全项目开发历程完整复盘总结
运维·服务器·小程序
lhldsg19 小时前
多商户团购系统源码:技术架构选型与二次开发实战指南
java·小程序·架构
2601_9499506319 小时前
一套小程序,解决资料整理、在线刷题和错题复盘
人工智能·小程序·刷题·练习·小程序推荐
白远山21 小时前
智慧场馆解决方案小程序系统开发实战与架构设计指南
java·开发语言·小程序·架构
阿祖zu1 天前
训练师 Agent 小程序产品上线啦
微信小程序·llm·agent
Rooting++2 天前
小程序{{ }}和vue{{ }}语法的区别
前端·vue.js·小程序