站主运营通知
站主可以选择将已提交的任务成功 / 失败、积分包付款与订阅账单付款发送到一个固定 Discord 频道。该模块默认关闭,与个人任务邮件、营销订阅、活动统计分别配置。管理员可以在后台查看投递记录;普通用户不能配置目的地或发送消息。
本地实际任务、受控付款与捕获接口用于验证实现。捕获回执不能证明真实频道收到了消息;真实供应商和云端定时维护仍需独立验收。
配置与迁移
公开开关位于 packages/core/website.ts:
notifications: {
taskEmail: false,
preferenceVersion: "2026-10-11",
retentionDays: 30,
operator: {
enabled: false,
since: null,
},
}启用时设置 operator.enabled=true,并将 since 改为明确的 UTC 时间,例如 2026-10-11T00:00:00Z。它决定首次纳入的业务事件起点,不使用部署时间猜测,不自动补发之前的历史事件。时间与保留期共同限制扫描范围。
服务端秘密变量为 DISCORD_NOTIFICATION_WEBHOOK_URL,仅接受 https://discord.com/api/webhooks/频道通知编号/令牌 这一固定格式的标准地址。完整地址内的令牌是秘密,不写入公开配置、浏览器、通知表或日志。没有任意用户地址、私有主机、额外端口、查询参数或自动重定向路径。启用缺少地址 / 起点或地址不合格时,配置检查明确失败。
先在目标环境完整升级到 0021_operator_notifications.sql,再重建 API、工作台和公共页。0021 新增最小投递记录及独立订阅检查时间表,保留所有旧迁移。正常预览主库仍为 0012,尚未应用 0020 / 0021,通知开关保持关闭;此时页面和维护不会读取这两张站主通知表。
云端需将秘密变量注入 API Worker,并配置现有每 15 分钟维护入口。没有新增通知队列,也没有公开测试发送接口。支付通知依赖已正确配置、验收的原 Stripe 支付入口,设置通知地址不能开通收款。
事件来源与付款凭证
| 事件 | 纳入依据 | 不纳入的情况 |
|---|---|---|
| 任务完成 / 失败 | 已保存终态、完成时间及当前执行租约版本 | 取消、中间重试、未完成、起点之前和过期任务 |
| 积分包付款 | 原购买已付且发放已提交,金额 / 币种 / 模式与对应积分流水相符 | 待付、仅回跳成功、缺少对应实际发放流水 |
| 订阅账单付款 | 原始通知验签后重新核对当前账单、客户 / 本站订阅、完整付款分配和实际成功收款 | 零元、待付、余额抵扣、线下付款记录、客户或模式不符、不完整分页 |
个人和团队的已核实订阅账单都可形成站主通知;团队付款不会记到某个成员的个人活动统计。付款校验与个人统计共用,但启用、接收者和授权分别检查。运营通知不要求个人开启任务邮件、营销或活动统计,也不会替用户保存这些选择。
记录的是原始付款确认,不是扣除退款后的净收入、利润、订阅留存或阅读证明。通知不改写订阅权限、不额外发积分,不替代财务流水与审计。后续退款属于另一个业务事件,本阶段不提供退款通知。
漏回调恢复使用独立检查时间,每轮最多检查三个有效个人或团队客户,同一客户至少间隔 15 分钟;失败也让出轮换位置。每次最多读取 1,000 张已付账单,每张最多核查 100 个付款分配。按实际付款时间筛选,早期创建但近期付款的账单仍可恢复;重复页、超限和缺页不假报完整恢复。该检查不占用用户账单操作租约,不复用个人活动统计的同意或检查时间。
消息内容与去重
消息只包含固定事件名称、内部任务 / 购买 / 账单编号、付款最小货币单位金额、币种、测试 / 正式模式和本站管理员入口。没有姓名、邮箱、团队名称、原文件名、输入、输出、提示词、附件、签名下载链接、通知令牌或供应商原始错误。明确禁止自动提及频道成员。
任务使用任务编号、当前执行租约版本和结果组成事件键;付款使用购买或账单编号与固定类型。数据库唯一键处理重放与并发,发送前再次核对任务或购买。任务重试替换旧执行时,旧未发通知跳过,新终态可产生新的事件。已核实订阅付款保存最小凭证后独立投递。
目标地址、环境、认证密钥、网站 Origin、起点与消息版本通过 HMAC 摘要绑定。配置变化后旧待发送记录跳过,不把旧消息改投到新频道。管理员入口仍需登录及最新管理员权限,不因收到链接获得访问权。
投递状态与排查
| 状态 | 含义与下一步 |
|---|---|
| 等待发送 | 业务事件已入库,维护尚未领取 |
| 发送中 | 一次两分钟租约,其他维护不能同时领取 |
| 限频等待 | 明确收到 429;按要求等待且至少 15 分钟,最多三次尝试 |
| 渠道接口已接收 | 收到有效消息编号;不代表有人阅读 |
| 已拒绝并停止 | 明确拒绝、耗尽尝试、过长限频等待或本地捕获缺失 |
| 接收未确认并停止 | 断网、超时、服务错误、缺少有效回执或发送租约过期;不自动重发 |
| 已跳过 | 业务来源、保留范围或绑定配置已变化 |
请求超时十秒,不跟随重定向;要求 wait=true 取得实际消息回执。Discord 官方说明于 2026-10-11 核对:执行通知接口可等待返回消息;默认不等待的成功响应不能提供同等回执依据。本模块只接受带有效消息编号的返回。
Discord 没有本模块可用的请求幂等键。响应丢失不能证明消息没发出,因此只有明确限频才自动重试;请求结果不确定或租约过期时停止。不会用新的事件键绕过这项限制。回写还需匹配本次未过期租约,迟到回执不能覆盖已停止的记录。限频要求超过一天时停止,不提前截断等待时间再发送。
管理员后台显示每页 20 条、状态、次数、事件时间、限频的下次时间及有效回执,可刷新、翻页。读取检查最新数据库角色、验证状态和封禁;撤权后原会话不能继续读取,接口限频返回明确响应。列表不暴露目标摘要、秘密地址或供应商错误正文。当前没有强制重发按钮;未确认时先检查实际频道与供应商记录,再决定人工处理。
保留与本地验证
列表隐藏起点之前或超过 retentionDays 的事件;每轮最多删除 100 条过期投递。订阅检查时间表也按最后检查时间清理过期行,每轮最多 100 条。默认保留期 30 天,允许 1—90 天;关闭模块、积压或维护故障可能延迟物理删除。清理后的旧业务不会再次进入扫描。
站主记录不存个人账号编号,不随用户 / 任务删除立即级联,而按本模块保留范围清理;多类型的来源编号仅用于排查,不是跨表外键。供应商客户检查标识同样仅用于轮换。财务和管理员审计继续遵守原独立规则。正式隐私说明需准确披露配置频道的提供方、用途和保留范围。
开发运行时总是注入 LOCAL_OPERATIONS,消息写入独立本地 operations-outbox.jsonl,即使环境提供真实地址也不会外发。开发环境缺少捕获时不回退网络;非开发环境意外带捕获绑定也会停止。捕获文件属于本地排查资料,不能提交或公开分享。
bun --cwd apps/api validate:operator-notifications验证器创建自己的 loopback 临时数据库,应用完整迁移,运行实际 Worker、Queue、R2、原始签名付款回调及受控 SDK 请求。覆盖成功 / 失败任务、积分包已提交发放、零元排除、并发账单、分配分页、通知表故障后的续费恢复、捕获故障停止、普通角色禁止读取与原结果下载。结束删除临时资源;--ui 额外构建专用管理员页面供桌面 / 手机与浅 / 深主题验收。不会提升正常预览账号或升级主数据库。
本地验证与真实外部验收分别记录:实际频道消息回执、真实限频 / 故障、部署秘密及云端维护仍需验收。个人邮件配置见任务邮件通知。