Credits vs Points 是两套独立系统
| 特性 | Credits | Points |
|---|---|---|
| 本质 | 消费余额(货币) | 生态贡献积分 |
| 可消费 | 是(API 调用扣费) | 否 |
| 可提现 | 是(换回 USDC/法币) | 否 |
| 是否等价法币 | 基本等价 | 不等价 |
| 数量变化 | 实时增减 | 只增(或少量减) |
| 未来用途 | 功能消费 | Token 空投、VIP、治理 |
Credits:平台货币
用户充值后获得 Credits,Credits 直接用于消费:
充值 100 USDT = 获得 100 Credits
调用 API 消费 2 Credits → 余额 98 Credits
提现 50 Credits → 取回约 50 USDT
Credits 必须与真实价值挂钩,用户信任建立在 1 Credit ≈ 1 USD 的基础上。
Points:生态积分
Points 不直接等于钱,是平台的”长期价值记录”:
充值 100 USDT → +100 Points
API 消费 20 USD → +20 Points
邀请好友充值 → +邀请奖励 Points
每日活跃 → +少量 Points
Points 积累后可以用于:
- VIP 等级解锁
- 折扣和返佣
- Token 空投快照
- DAO 治理权重
- 锁仓质押
防止套利:提现扣回 Points
如果充值得 Points、提现不扣,用户会利用套利:
1. 充值 1000 USDT → 得 1000 Credits + 1000 Points
2. 立刻提现 1000 Credits
3. 净得:0 Credits(本金拿回)+ 1000 Points(免费)
解决方案:提现时扣回相应 Points:
提现 1000 Credits → 余额 -1000 Credits,同时 Points -1000
或者更稳健:Points 只按实际消费累计,充值/提现不影响 Points:
充值 → Credits+,Points 不变
消费 1 USD → Points +1
提现 → Credits-,Points 不变
数据库设计
CREATE TABLE user_balance (
user_id BIGINT PRIMARY KEY,
credits DECIMAL(18, 6) DEFAULT 0, -- 可消费余额
points BIGINT DEFAULT 0 -- 累计积分
);
-- 消费记录
CREATE TABLE consumption_log (
id BIGINT AUTO_INCREMENT,
user_id BIGINT,
credits_used DECIMAL(18, 6),
points_earned INT,
action VARCHAR(100),
created_at DATETIME
);
Points 用整数(无小数),Credits 用高精度小数(避免浮点误差)。
Credits 扣费保证原子性
Credits 扣费和 Points 增加应在同一事务中完成:
@Transactional
public void consumeCredits(Long userId, BigDecimal amount, String action) {
// 检查余额
UserBalance balance = balanceMapper.selectForUpdate(userId);
if (balance.getCredits().compareTo(amount) < 0) {
throw new InsufficientCreditsException();
}
// 扣 Credits
balanceMapper.deductCredits(userId, amount);
// 加 Points(按消费比例)
long points = amount.longValue();
balanceMapper.addPoints(userId, points);
// 记录消费日志
consumptionLogMapper.insert(userId, amount, points, action);
}
SELECT FOR UPDATE 防止并发扣款导致余额超扣。
首版设计建议
- Credits 优先实现,这是核心盈利结构
- Points 首版只记录,不设兑换规则(避免承诺后反悔)
- 后期发 Token 时,用 Points 快照作为分配依据
- 积分比例(1 Credits 消费 = 多少 Points)后期可调,但不能追溯修改历史记录
