1142346e24
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
69 lines
2.8 KiB
JavaScript
69 lines
2.8 KiB
JavaScript
/**
|
||
* 订阅消息统一入口
|
||
*
|
||
* ⚠️ 最重要的约束: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 }
|