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

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 ? "订阅成功" : "订阅失败");
相关推荐
说私域1 小时前
日本零售精髓赋能下 链动2+1模式驱动新零售本质回归与发展格局研究
人工智能·小程序·数据挖掘·回归·流量运营·零售·私域运营
程序媛徐师姐1 小时前
Java基于微信小程序的模拟考试系统,附源码+文档说明
java·微信小程序·java模拟考试系统小程序·模拟考试微信小程序·模拟考试系统小程序·模拟考试小程序·java模拟考试小程序
大尚来也1 小时前
微信小程序开发费用全解析:从SaaS到定制的多元选择
微信小程序
如果你好2 小时前
UniApp 路由导航守卫
前端·微信小程序
大尚来也3 小时前
小程序怎么开发自己的小程序
微信小程序
码云数智-园园3 小时前
小程序开发平台有哪些?小程序第三方开发平台评测对比
微信小程序
说私域3 小时前
流量裂变与数字重塑:基于AI智能名片小程序的短视频全域引流范式研究
人工智能·小程序·流量运营·私域运营
蓝帆傲亦15 小时前
支付宝小程序性能暴增秘籍:UniApp项目极限优化全攻略
小程序·uni-app
CHU72903520 小时前
淘宝扭蛋机抽盒小程序前端功能解析:解锁趣味抽盒新体验
前端·小程序
2501_9339072121 小时前
深圳本凡科技专业企业APP开发,助力手机应用创新优化
科技·微信小程序·小程序