Files
yuming 1142346e24 新增前端订阅模块,收敛模板 ID 到唯一来源
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-16 09:25:12 +08:00

69 lines
2.8 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 订阅消息统一入口
*
* ⚠️ 最重要的约束:wx.requestSubscribeMessage 和 wx.openSetting 必须由真实点击手势
* 直接触发(基础库 2.8.2+),且调用前不能有 await 等异步操作,否则手势上下文丢失、
* 调用必然失败(报 fail can only be invoked by user TAP gesture)。
* 所以本模块的 requestAndReport 必须在 bindtap 处理函数里同步调用,
* 用户状态要提前用 getStatus 查好缓存起来,不能现查现用。
*/
const sync = require('./sync')
const TEMPLATE_ID = '6J7Stt-lu7DKU6jblJ0nZGq_D81z5glnksf7qWfy5Yw'
/**
* 查询用户当前的订阅设置状态
* itemSettings 只包含用户勾选过「总是保持以上选择」的模板,据此可判断调用会不会弹窗。
* @returns {Promise<string>}
* silent — 已长期同意,调用不弹窗,可在任意点击上搭车静默补额度
* willPrompt — 没勾过,调用会弹窗,只在用户主动点击时才调
* rejected — 已长期拒绝或被封禁,再调也没用,需引导去设置页
* mainSwitchOff — 通知总开关关闭,需引导去设置页
* unknown — 查询失败,按 willPrompt 保守处理
*/
function getStatus() {
return new Promise((resolve) => {
wx.getSetting({
withSubscriptions: true,
success: (res) => {
const s = res.subscriptionsSetting || {}
if (s.mainSwitch === false) return resolve('mainSwitchOff')
const item = s.itemSettings && s.itemSettings[TEMPLATE_ID]
if (item === 'accept') return resolve('silent')
if (item === 'reject' || item === 'ban') return resolve('rejected')
resolve('willPrompt')
},
fail: () => resolve('unknown')
})
})
}
/**
* 请求订阅并把新增额度上报后端
* 必须在 tap handler 中同步调用(本函数第一条语句就是 wx.requestSubscribeMessage
* @returns {Promise<boolean>} 用户是否同意
*/
function requestAndReport() {
return new Promise((resolve) => {
wx.requestSubscribeMessage({
tmplIds: [TEMPLATE_ID],
success: (res) => {
const accepted = res[TEMPLATE_ID] === 'accept'
if (!accepted) return resolve(false)
// 走同步队列上报:失败会自动入队,下次启动 flush。
// 不能静默吞掉——用户已经同意、微信侧额度确实 +1 了,我们漏记会导致余额低估,
// 进而白白跳过本可以发出去的提醒。
sync.syncOrEnqueue({ kind: 'subscribe', action: 'grant', data: { count: 1 } })
.then(() => resolve(true))
},
fail: (err) => {
console.warn('[subscribe] 订阅失败', err)
resolve(false)
}
})
})
}
module.exports = { TEMPLATE_ID, getStatus, requestAndReport }