marketing

积分系统

TanStack Ship 忠诚度积分系统,支持积分发放与消费、可配置积分方案和幂等交易处理。

积分发放和消费,基于复式记账和完整审计追踪
可配置的积分方案:一次性、周期性和永久性
幂等操作,使用幂等键防止重复消费
基于积分的购买,作为 Stripe 支付的替代方案
邀请奖励集成,用于推荐奖励
管理面板,用于积分方案、账户和交易管理
交易记录和实时余额追踪
积分操作故障排查调试面板
其他语言:English·Deutsch

概述

TanStack Ship 的积分系统提供了一种灵活的忠诚度货币,推动用户参与和留存。用户通过各种行为——邀请、促销、购买和互动里程碑——获得积分,并可用于订阅、功能或产品升级。

作为 TanStack Ship 平台的一部分,积分系统以可靠性为核心原则设计。它实现了复式记账,具备幂等操作和完整的审计日志,确保每笔积分变动都被准确记录且永不重复。

积分流转流程

积分系统遵循严格的复式记账模型,每次发放和消费都作为不可变交易记录:

设计理念

积分系统基于三个金融可靠性核心原则构建:

  • 复式记账 — 每笔积分变动都记录为包含借方和贷方条目的交易。用户的余额从不作为单一值存储,而是派生为所有交易的总和,确保数学完整性。与 LoyaltyLion 或 Yotpo 不同——它们作为第三方 SaaS 平台运行,需要 API 调用查询余额和 Webhook 集成实现基于事件的奖励——我们的积分引擎直接嵌入在您自己的数据库中,余额检查零外部延迟,所有操作具备完整的事务完整性。
  • 幂等操作 — 每次积分操作携带唯一的幂等键。如果同一操作被重试(由于网络问题、Webhook 重新投递或客户端重试),系统会检测到重复并返回已有结果,而不是再次处理。
  • 审计优先设计 — 所有积分变动都记录完整的元数据:时间戳、金额、原因、引用实体和执行用户。这个完整的审计追踪满足合规要求,并支持调试、对账和客户支持。

核心能力

可配置的积分方案

积分方案决定了如何向用户授予积分。支持三种方案类型:

  • 一次性方案 — 固定金额的单次积分授予,适用于欢迎奖励或一次性促销
  • 周期性方案 — 按周期(月、年)定期授信,在配置的间隔自动续期
  • 永久性方案 — 无限期循环积分,永不过期,适合终身忠诚度计划

每个方案指定积分金额、间隔(对于周期性方案)和可选的过期规则。方案可以从管理面板激活或停用,不会丢失历史数据。

发放与消费引擎

积分操作遵循严格的复式记账模型:

  • 发放 — 创建正向交易记录,增加用户的余额
  • 消费 — 创建负向交易记录,减少用户的余额
  • 余额计算 — 当前余额计算为所有交易的总和
  • 幂等性 — 每次操作携带唯一的幂等键,确保重试不会导致重复处理

积分引擎实时验证所有操作,在处理任何消费请求之前检查用户是否拥有足够的余额。

可靠性与数据完整性

企业级可靠性特性:

  • 幂等键 — 防止 webhook 重试、网络问题或客户端重试导致的重复处理
  • 交易日志 — 每笔操作都记录时间戳、金额、原因和引用实体
  • 余额验证 — 实时余额检查通过原子数据库事务防止超额消费
  • 审计追踪 — 所有积分变动的完整历史记录,用于调试、合规和客户支持
  • 原子操作 — 发放和消费包裹在数据库事务中,防止竞态条件

邀请奖励集成

积分系统与邀请模块集成,驱动推荐奖励:

  1. 被推荐用户订阅时,邀请人获得积分奖励(每个活动可配置金额)
  2. 新用户获得欢迎积分奖励,激励首次参与
  3. 两笔交易都记录并附带唯一的幂等键
  4. 系统处理边界情况——重复推荐尝试、自我推荐预防和奖励限制

客户端积分余额组件示例:

tsx
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 平台模块集成:

  • 账单系统 — 结账时积分可用作 Stripe Checkout 的替代支付方式
  • 邀请系统 — 推荐奖励以积分形式发放,每个活动可配置金额
  • 活动优惠 — 积分赠送优惠在符合条件的购买时向用户余额奖励积分
  • UTM 活动 — 流量来源特定的促销活动可包含积分奖励
  • 用户仪表板 — 用户查看积分余额、交易历史和可用积分方案
  • 管理面板 — 全面的积分管理界面,含审计工具