新增前端订阅模块,收敛模板 ID 到唯一来源
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@ const storage = require('../../utils/storage')
|
|||||||
const dateUtils = require('../../utils/date')
|
const dateUtils = require('../../utils/date')
|
||||||
const sync = require('../../utils/sync')
|
const sync = require('../../utils/sync')
|
||||||
const lunar = require('../../utils/lunar')
|
const lunar = require('../../utils/lunar')
|
||||||
|
const subscribe = require('../../utils/subscribe')
|
||||||
|
|
||||||
Page({
|
Page({
|
||||||
data: {
|
data: {
|
||||||
@@ -373,7 +374,7 @@ Page({
|
|||||||
requestSubscribe() {
|
requestSubscribe() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
wx.requestSubscribeMessage({
|
wx.requestSubscribeMessage({
|
||||||
tmplIds: ['6J7Stt-lu7DKU6jblJ0nZGq_D81z5glnksf7qWfy5Yw'],
|
tmplIds: [subscribe.TEMPLATE_ID],
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
console.log('订阅消息授权结果:', res)
|
console.log('订阅消息授权结果:', res)
|
||||||
resolve(res)
|
resolve(res)
|
||||||
|
|||||||
+6
-1
@@ -72,4 +72,9 @@ function person(action, data) {
|
|||||||
return request({ url: '/api/person', data: { action, data } })
|
return request({ url: '/api/person', data: { action, data } })
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { request, login, anniversary, person, BASE_URL }
|
// 订阅额度:grant 上报授权,get 查询余额与风险
|
||||||
|
function subscribe(action, data) {
|
||||||
|
return request({ url: '/api/subscribe', data: { action, data } })
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { request, login, anniversary, person, subscribe, BASE_URL }
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/**
|
||||||
|
* 订阅消息统一入口
|
||||||
|
*
|
||||||
|
* ⚠️ 最重要的约束: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 }
|
||||||
@@ -24,6 +24,7 @@ function enqueue(item) {
|
|||||||
async function dispatch(item) {
|
async function dispatch(item) {
|
||||||
if (item.kind === 'person') return api.person(item.action, item.data)
|
if (item.kind === 'person') return api.person(item.action, item.data)
|
||||||
if (item.kind === 'anniversary') return api.anniversary(item.action, item.data)
|
if (item.kind === 'anniversary') return api.anniversary(item.action, item.data)
|
||||||
|
if (item.kind === 'subscribe') return api.subscribe(item.action, item.data)
|
||||||
throw new Error('unknown sync kind: ' + item.kind)
|
throw new Error('unknown sync kind: ' + item.kind)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user