/** * 微信订阅消息工具 * 统一管理订阅消息的请求和状态 * * 服务端记录的是授权登记,不代表微信侧仍有剩余次数。 */ const { api } = require('./request'); // 统一使用「每日记录提醒」模板,所有操作都通过这个模板通知 const SUBSCRIBE_TEMPLATES = { notify: 'tOaqM_Z6pNSih2pVpaUmP86MgwnDT5ZlwOqd0lgmXP8', }; // 只合并正在进行的授权请求,后续用户点击仍可补充一次性授权。 let _pendingSubscribe = null; /** * 请求用户订阅指定模板 * @param {string|string[]} templateTypes - 模板类型或模板类型数组 * @returns {Promise} 订阅结果 { templateType: true/false } */ function requestSubscribe(templateTypes) { if (_pendingSubscribe) return _pendingSubscribe; const pending = new Promise((resolve, reject) => { if (!Array.isArray(templateTypes)) { templateTypes = [templateTypes]; } // 获取模板ID列表 const tmplIds = templateTypes .map(type => SUBSCRIBE_TEMPLATES[type]) .filter(id => id && id !== 'TEMPLATE_ID_'); if (tmplIds.length === 0) { console.warn('[subscribe] 模板ID未配置,请在微信小程序管理后台申请模板后更新'); resolve({}); return; } wx.requestSubscribeMessage({ tmplIds: tmplIds, success: (res) => { // 处理每个模板的授权结果 const results = {}; templateTypes.forEach((type) => { const tmplId = SUBSCRIBE_TEMPLATES[type]; const status = res[tmplId]; results[type] = status === 'accept'; }); // 将授权结果同步到后端 syncSubscribeResults(results).then(() => resolve(results), reject); }, fail: (err) => { console.error('[subscribe] 请求订阅失败:', err); reject(err); } }); }); _pendingSubscribe = pending.finally(() => { _pendingSubscribe = null; }); return _pendingSubscribe; } /** * 将订阅结果同步到后端 */ function syncSubscribeResults(results) { return Promise.all(Object.keys(results).filter(type => results[type]).map(type => { return api.subscribeTemplate({template_type:type, template_id:SUBSCRIBE_TEMPLATES[type]}).then(result => { if (!result || !result.success) throw new Error('订阅授权保存失败'); wx.setStorageSync('subscribed_notify', true); }); })); } // 必须由用户点击直接调用;补充的是当前用户接收TA提醒的次数。 function requestSubscribeAfterAction(scene) { if (wx.getStorageSync('subscribed_notify') === false || !wx.getStorageSync('coupleId')) return Promise.resolve({}); return requestSubscribe('notify').catch(error => { console.warn('[subscribe] 授权或保存失败,下次点击可重试:', error); return {}; }); } /** * 获取用户当前的订阅状态 * 从后端获取 * @param {boolean} forceRefresh - 保留旧调用参数 * @returns {Promise} 订阅状态 { template_type: true/false } */ async function getSubscribeStatus(forceRefresh = false) { try { const res = await api.mySubscribeTemplates(); const status = {}; Object.keys(SUBSCRIBE_TEMPLATES).forEach(type => { status[type] = !!res.templates[type]; }); return status; } catch (e) { return {}; } } module.exports = { requestSubscribe, requestSubscribeAfterAction, getSubscribeStatus };