All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 10m15s
- 新增单行配置表 tb_asset_auto_renewal_config 与尝试记录表 tb_asset_auto_renewal_attempt(迁移 000229/000230) - 每日按上海自然日扫描,窗口内以同一资产钱包可用余额续购当前主套餐,资金/订单/套餐/审计同一事务闭合 - 唯一键保证每资产每日至多一次尝试,占位中断由后续扫描收敛,当日不重试 - 四类失败原因向客户与店铺各投递每日至多一条站内通知,并注册通知类型与个人客户白名单 - 续费成功后按条件经 Outbox 可靠投递复机,新增恢复扫描只查询回填,不使用即发即弃调用 - 配置读写仅超级管理员与平台账号,保存记录操作者、前后值快照并登记统一审计 - tasks 7.1–7.15 全部验证通过(本机隔离 PostgreSQL/Redis,零外部渠道调用)
168 lines
7.1 KiB
Go
168 lines
7.1 KiB
Go
package constants
|
||
|
||
import "time"
|
||
|
||
// 资产钱包自动续费配置适用范围。
|
||
const (
|
||
// AssetAutoRenewalScopeAll 表示配置适用于全部主套餐。
|
||
AssetAutoRenewalScopeAll = "all"
|
||
// AssetAutoRenewalScopeSpecified 表示配置只适用于指定主套餐集合。
|
||
AssetAutoRenewalScopeSpecified = "specified"
|
||
)
|
||
|
||
// 资产钱包自动续费配置的结构约束。
|
||
const (
|
||
// AssetAutoRenewalConfigSingletonID 是单行配置表的主键,恒为 1。
|
||
AssetAutoRenewalConfigSingletonID = 1
|
||
// AssetAutoRenewalConfigEnabledOff 表示总开关关闭。
|
||
AssetAutoRenewalConfigEnabledOff = 0
|
||
// AssetAutoRenewalConfigEnabledOn 表示总开关开启。
|
||
AssetAutoRenewalConfigEnabledOn = 1
|
||
// AssetAutoRenewalMinDaysBeforeExpiry 是到期前天数的最小值。
|
||
AssetAutoRenewalMinDaysBeforeExpiry = 1
|
||
// AssetAutoRenewalMaxDaysBeforeExpiry 是到期前天数的上限。
|
||
AssetAutoRenewalMaxDaysBeforeExpiry = 90
|
||
)
|
||
|
||
// 资产钱包自动续费尝试状态(ENG-STATE-001:生命周期状态使用整数编码)。
|
||
const (
|
||
// AssetAutoRenewalAttemptStatusProcessing 表示尝试已占位、执行尚未得出终态。
|
||
AssetAutoRenewalAttemptStatusProcessing = 1
|
||
// AssetAutoRenewalAttemptStatusSucceeded 表示本次尝试已完成续费。
|
||
AssetAutoRenewalAttemptStatusSucceeded = 2
|
||
// AssetAutoRenewalAttemptStatusFailed 表示本次尝试以失败终态结束。
|
||
AssetAutoRenewalAttemptStatusFailed = 3
|
||
// AssetAutoRenewalAttemptStatusSkipped 表示本次尝试因人工优先而跳过。
|
||
AssetAutoRenewalAttemptStatusSkipped = 4
|
||
)
|
||
|
||
// 资产钱包自动续费通知原因,固定为四类。
|
||
//
|
||
// 前三类由尝试失败产生通知(写入尝试记录的 failure_reason);
|
||
// 第四类复机失败只由复机子结果(resume_status=失败)产生通知,
|
||
// 绝不回写尝试记录的 failure_reason——复机结果只在复机字段表达,同一事实不两处表达。
|
||
const (
|
||
// AssetAutoRenewalFailureInsufficientBalance 表示可用余额不支持续购。
|
||
AssetAutoRenewalFailureInsufficientBalance = "insufficient_balance"
|
||
// AssetAutoRenewalFailureNotRenewable 表示当前条件不允许自动续购。
|
||
AssetAutoRenewalFailureNotRenewable = "not_renewable"
|
||
// AssetAutoRenewalFailureOrderFailed 表示续购事务本身失败并整体回滚。
|
||
AssetAutoRenewalFailureOrderFailed = "order_failed"
|
||
// AssetAutoRenewalFailureResumeFailed 表示复机最终确认失败(只作为通知原因,不写 failure_reason)。
|
||
AssetAutoRenewalFailureResumeFailed = "resume_failed"
|
||
)
|
||
|
||
// 资产钱包自动续费尝试记录中允许出现的失败归类。
|
||
//
|
||
// 取值域是通知原因中的前三类加上中断收敛值:失败归类只描述「实际进入执行后得出的失败」,
|
||
// 因此不含复机失败。interrupted 是占位后进程中断的收敛表示,不属于四类通知原因,
|
||
// 由 IsAssetAutoRenewalNotifiableFailureReason 显式排除,收敛过程不发送任何通知。
|
||
const (
|
||
// AssetAutoRenewalFailureInterrupted 表示占位写入后进程中断,由后续扫描收敛。
|
||
AssetAutoRenewalFailureInterrupted = "interrupted"
|
||
)
|
||
|
||
// IsAssetAutoRenewalNotifiableFailureReason 判断该失败原因是否触发站内通知。
|
||
// 未登记的原因一律不通知(fail-closed),避免把收敛产生的 interrupted 误当执行失败通知出去。
|
||
func IsAssetAutoRenewalNotifiableFailureReason(reason string) bool {
|
||
switch reason {
|
||
case AssetAutoRenewalFailureInsufficientBalance, AssetAutoRenewalFailureNotRenewable,
|
||
AssetAutoRenewalFailureOrderFailed, AssetAutoRenewalFailureResumeFailed:
|
||
return true
|
||
default:
|
||
return false
|
||
}
|
||
}
|
||
|
||
// 资产钱包自动续费跳过原因。
|
||
const (
|
||
// AssetAutoRenewalSkipManualRenewed 表示人工已完成续购(已存在待生效主套餐)。
|
||
AssetAutoRenewalSkipManualRenewed = "manual_renewed"
|
||
// AssetAutoRenewalSkipManualOrderPending 表示该资产存在未关闭的人工主套餐订单。
|
||
AssetAutoRenewalSkipManualOrderPending = "manual_order_pending"
|
||
)
|
||
|
||
// 资产钱包自动续费尝试的复机状态。
|
||
const (
|
||
// AssetAutoRenewalResumeStatusSkipped 表示可复机条件不成立,未投递复机。
|
||
AssetAutoRenewalResumeStatusSkipped = 1
|
||
// AssetAutoRenewalResumeStatusRequested 表示已可靠投递复机请求,等待结果。
|
||
AssetAutoRenewalResumeStatusRequested = 2
|
||
// AssetAutoRenewalResumeStatusSucceeded 表示复机已确认成功。
|
||
AssetAutoRenewalResumeStatusSucceeded = 3
|
||
// AssetAutoRenewalResumeStatusFailed 表示复机已确认失败。
|
||
AssetAutoRenewalResumeStatusFailed = 4
|
||
// AssetAutoRenewalResumeStatusUnknown 表示复机结果未知,等待恢复扫描确认。
|
||
AssetAutoRenewalResumeStatusUnknown = 5
|
||
)
|
||
|
||
// 资产钱包自动续费尝试的操作者类型:本能力无人工处理入口,恒为系统任务。
|
||
const (
|
||
// AssetAutoRenewalOperatorTypeSystemTask 表示系统任务操作者。
|
||
AssetAutoRenewalOperatorTypeSystemTask = "system_task"
|
||
)
|
||
|
||
// 资产钱包自动续费尝试的批次与查询约束。
|
||
const (
|
||
// AssetAutoRenewalRecoveryBatchSize 是恢复扫描单批处理条数上限。
|
||
AssetAutoRenewalRecoveryBatchSize = 200
|
||
// AssetAutoRenewalConfigDisplayName 是配置资源的展示名。
|
||
AssetAutoRenewalConfigDisplayName = "资产钱包自动续费配置"
|
||
)
|
||
|
||
// 资产钱包自动续费的可靠事件类型。
|
||
const (
|
||
// OutboxEventTypeAssetAutoRenewalResumeRequested 表示续费成功后按条件触发的可靠复机请求。
|
||
OutboxEventTypeAssetAutoRenewalResumeRequested = "asset_auto_renewal.resume.requested"
|
||
)
|
||
|
||
// 资产钱包自动续费复机子任务的查询窗口。
|
||
const (
|
||
// AssetAutoRenewalResumeQueryWindow 是复机子任务自提交起允许自动查询确认的窗口。
|
||
// 语义:复机事件进入已投递/已提交后,恢复扫描只查询运营商状态回填;超过该窗口仍无法确认的
|
||
// 尝试会标记异常并转人工核对,不再重复查询同一笔无法收敛的结果,也不回滚任何续费事实。
|
||
AssetAutoRenewalResumeQueryWindow = 30 * time.Minute
|
||
)
|
||
|
||
// GetAssetAutoRenewalScopeName 返回自动续费适用范围的中文名称。
|
||
func GetAssetAutoRenewalScopeName(scope string) string {
|
||
switch scope {
|
||
case AssetAutoRenewalScopeAll:
|
||
return "全部主套餐"
|
||
case AssetAutoRenewalScopeSpecified:
|
||
return "指定主套餐"
|
||
default:
|
||
return "未知"
|
||
}
|
||
}
|
||
|
||
// GetAssetAutoRenewalFailureReasonName 返回自动续费失败原因的中文名称。
|
||
func GetAssetAutoRenewalFailureReasonName(reason string) string {
|
||
switch reason {
|
||
case AssetAutoRenewalFailureInsufficientBalance:
|
||
return "余额不足"
|
||
case AssetAutoRenewalFailureNotRenewable:
|
||
return "不可续费"
|
||
case AssetAutoRenewalFailureOrderFailed:
|
||
return "订单失败"
|
||
case AssetAutoRenewalFailureResumeFailed:
|
||
return "复机失败"
|
||
case AssetAutoRenewalFailureInterrupted:
|
||
return "中断收敛"
|
||
default:
|
||
return "未知"
|
||
}
|
||
}
|
||
|
||
// GetAssetAutoRenewalSkipReasonName 返回自动续费跳过原因的中文名称。
|
||
func GetAssetAutoRenewalSkipReasonName(reason string) string {
|
||
switch reason {
|
||
case AssetAutoRenewalSkipManualRenewed:
|
||
return "人工已完成续购"
|
||
case AssetAutoRenewalSkipManualOrderPending:
|
||
return "人工订单在途"
|
||
default:
|
||
return "未知"
|
||
}
|
||
}
|