积分系统
TanStack Ship 忠诚度积分系统,支持积分发放与消费、可配置积分方案和幂等交易处理。
概述
TanStack Ship 的积分系统提供了一种灵活的忠诚度货币,推动用户参与和留存。用户通过各种行为——邀请、促销、购买和互动里程碑——获得积分,并可用于订阅、功能或产品升级。
作为 TanStack Ship 平台的一部分,积分系统以可靠性为核心原则设计。它实现了复式记账,具备幂等操作和完整的审计日志,确保每笔积分变动都被准确记录且永不重复。
积分流转流程
积分系统遵循严格的复式记账模型,每次发放和消费都作为不可变交易记录:
设计理念
积分系统基于三个金融可靠性核心原则构建:
- 复式记账 — 每笔积分变动都记录为包含借方和贷方条目的交易。用户的余额从不作为单一值存储,而是派生为所有交易的总和,确保数学完整性。与 LoyaltyLion 或 Yotpo 不同——它们作为第三方 SaaS 平台运行,需要 API 调用查询余额和 Webhook 集成实现基于事件的奖励——我们的积分引擎直接嵌入在您自己的数据库中,余额检查零外部延迟,所有操作具备完整的事务完整性。
- 幂等操作 — 每次积分操作携带唯一的幂等键。如果同一操作被重试(由于网络问题、Webhook 重新投递或客户端重试),系统会检测到重复并返回已有结果,而不是再次处理。
- 审计优先设计 — 所有积分变动都记录完整的元数据:时间戳、金额、原因、引用实体和执行用户。这个完整的审计追踪满足合规要求,并支持调试、对账和客户支持。
核心能力
可配置的积分方案
积分方案决定了如何向用户授予积分。支持三种方案类型:
- 一次性方案 — 固定金额的单次积分授予,适用于欢迎奖励或一次性促销
- 周期性方案 — 按周期(月、年)定期授信,在配置的间隔自动续期
- 永久性方案 — 无限期循环积分,永不过期,适合终身忠诚度计划
每个方案指定积分金额、间隔(对于周期性方案)和可选的过期规则。方案可以从管理面板激活或停用,不会丢失历史数据。
发放与消费引擎
积分操作遵循严格的复式记账模型:
- 发放 — 创建正向交易记录,增加用户的余额
- 消费 — 创建负向交易记录,减少用户的余额
- 余额计算 — 当前余额计算为所有交易的总和
- 幂等性 — 每次操作携带唯一的幂等键,确保重试不会导致重复处理
积分引擎实时验证所有操作,在处理任何消费请求之前检查用户是否拥有足够的余额。
可靠性与数据完整性
企业级可靠性特性:
- 幂等键 — 防止 webhook 重试、网络问题或客户端重试导致的重复处理
- 交易日志 — 每笔操作都记录时间戳、金额、原因和引用实体
- 余额验证 — 实时余额检查通过原子数据库事务防止超额消费
- 审计追踪 — 所有积分变动的完整历史记录,用于调试、合规和客户支持
- 原子操作 — 发放和消费包裹在数据库事务中,防止竞态条件
邀请奖励集成
积分系统与邀请模块集成,驱动推荐奖励:
- 被推荐用户订阅时,邀请人获得积分奖励(每个活动可配置金额)
- 新用户获得欢迎积分奖励,激励首次参与
- 两笔交易都记录并附带唯一的幂等键
- 系统处理边界情况——重复推荐尝试、自我推荐预防和奖励限制
客户端积分余额组件示例:
import { useQuery } from '@tanstack/react-query'
export function CreditBalance() {
const { data } = useQuery({
queryKey: ['credit-account'],
queryFn: () =>
fetch('/api/credits/balance').then((r) => r.json()) as Promise<{
balance: number
transactions: Array<{ id: string; amount: number; reason: string }>
}>,
})
return (
<div className="rounded-lg border p-4">
<div className="mb-3">
<p className="text-sm text-muted-foreground">积分余额</p>
<p className="text-3xl font-bold">{data?.balance.toLocaleString() ?? '—'}</p>
</div>
<p className="mb-2 text-xs font-semibold uppercase text-muted-foreground">最近记录</p>
{data?.transactions.slice(0, 3).map((tx) => (
<div key={tx.id} className="flex justify-between py-1 text-sm">
<span>{tx.reason}</span>
<span className={tx.amount > 0 ? 'text-green-600' : 'text-red-600'}>
{tx.amount > 0 ? '+' : ''}{tx.amount}
</span>
</div>
))}
</div>
)
}
最佳实践
幂等键管理
始终为每次积分操作生成唯一的幂等键。使用实体类型、实体 ID 和操作类型的组合(例如 invitation_reward_{invitation_id})确保唯一性。
余额验证
向用户显示实时余额,但始终在服务器上验证余额充足后再处理消费。客户端的余额检查仅用于用户体验。
余额不足的优雅处理
当用户积分不足以完成购买时,提供清晰的反馈,显示他们当前的余额和所需金额。提供替代支付方式。
定期审计对账
定期运行对账报告,将交易日志与预期余额进行比较。管理面板提供了用于此分析的工具。
常见问题
用户如何获得积分? 积分可以通过多种渠道获得:邀请推荐、促销活动、月度忠诚度奖励、管理员手动调整和积分赠送优惠。
积分会过期吗? 可以。积分方案可以选择性地包含过期规则。管理员可以配置积分在一段设定时间后过期(例如发放后 12 个月)。
积分如何用于购买? 结账时,用户可以选择"用积分支付"作为信用卡的替代方式。系统计算 Stripe 支付金额减去应用的积分价值。
如果用户订阅被退款了怎么办? 如果使用积分购买的订阅被退款,相应的积分会通过冲正交易恢复到用户账户。
我能否手动调整用户积分? 可以。管理面板提供了积分调整工具,用于手动授予或扣除积分。所有调整都记录在审计追踪中。
积分操作是线程安全的吗? 是的。积分引擎使用带行级锁的数据库事务,确保并发操作不会导致竞态条件或余额不一致。
系统如何防止欺诈? 系统实施多种欺诈预防措施:积分操作的限流、通过幂等键的重复检测,以及可疑活动日志记录。
配置
从管理面板管理积分方案和账户:
/dashboard/admin/credits/plans— 创建和管理积分方案(一次性、周期性、永久性)/dashboard/admin/credits/accounts— 查看用户积分余额和交易历史/dashboard/admin/credits/transactions— 完整交易日志,支持筛选和搜索/dashboard/admin/credits/debug— 积分操作故障排查调试面板
除了标准数据库配置外,不需要额外的环境变量。
集成点
积分系统与以下 TanStack Ship 平台模块集成: