feat: credit-based billing system
- New DB models: credit_packages, subscription_plans, user_credits, credit_consumptions, credit_purchases - CreditService: balance, deduct, add_credits, grant_free_trial, history - User API: /api/v1/credits/* (balance/history/packages/purchase/subscribe) - Admin API: /api/v1/admin/credit-* (CRUD packages/plans, user credits, consumptions) - PaymentService.create_credit_order + handle_callback for credit purchases - Credit deduction on: discovery, translate, marketing, ai_chat, followup - Free trial 30 credits on registration - Documentation: docs/CREDIT_SYSTEM.md
This commit is contained in:
@@ -0,0 +1,399 @@
|
||||
# TradeMate Credit System — 信用计费系统设计方案
|
||||
|
||||
## 1. 业务模式变更
|
||||
|
||||
### 1.1 从工具订阅 → 结果付费
|
||||
|
||||
- **旧模式**:按月订阅解锁功能(Free/Pro/Enterprise)
|
||||
- **新模式**:按次付费购买"结果",所有 AI 功能统一消耗信用额度(Credits)
|
||||
- **核心**:用户不为功能付费,为**产生的价值**(客户线索、分析报告、翻译字符)付费
|
||||
|
||||
### 1.2 目标用户群
|
||||
|
||||
- **国内**:中国外贸 SOHO/小团队 → 中文界面,¥ 计价
|
||||
- **海外**:全球跨境小B → 英文界面,$ 计价
|
||||
- 两端统一产品逻辑,分语言/货币展示
|
||||
|
||||
### 1.3 产品定位
|
||||
|
||||
| 维度 | 旧 | 新 |
|
||||
|------|-----|-----|
|
||||
| 定位 | 外贸工具套装 | 外贸客户发现引擎 |
|
||||
| Slogan | 外贸小助手 | Customer Discovery Engine / 外贸获客引擎 |
|
||||
| 核心价值 | 多功能的工具箱 | 输入产品,找到买家 |
|
||||
| 免费策略 | 限功能免费版 | 注册送 N 次,用完即购 |
|
||||
| 收费锚点 | 按月付费解锁 | 按产出结果扣次 |
|
||||
|
||||
## 2. 信用额度系统(Credits)
|
||||
|
||||
### 2.1 定义
|
||||
|
||||
**1 Credit = 1 次消费单位。** 所有 AI 调用均以 Credits 计价。
|
||||
|
||||
用户持有的 Credits 通过两种方式获得:
|
||||
- **一次性购买(Credit Pack)**:永不过期,用不完的余额留存
|
||||
- **月订阅(Subscription)**:每月自动到账,月底未用完清零
|
||||
|
||||
两种方式的 Credits 统一存放在 `user_credits.balance` 中,消费时按 `source` 记录来源。
|
||||
|
||||
### 2.2 消费价格表
|
||||
|
||||
所有 AI 相关功能均消耗 Credits,覆盖 API 调用成本:
|
||||
|
||||
| 功能 | Credits | 说明 |
|
||||
|------|---------|------|
|
||||
| **客户搜索** (lead_search) | 10 | 多源搜索 + AI 匹配 + 联系方式提取 |
|
||||
| **公司深度分析** (company_analysis) | 5 | 单家公司 AI 分析报告 |
|
||||
| **市场情报报告** (market_intel) | 20 | 多维度市场研究 |
|
||||
| **翻译** (translate, 5000 chars) | 5 | 按字符计费,不足按比例折算 |
|
||||
| **回复建议** (reply_suggest) | 2 | AI 生成 3 条回复建议 |
|
||||
| **开发信生成** (outreach) | 3 | 单封定制开发信 |
|
||||
| **营销素材** (marketing_content) | 5 | 多风格营销文案 |
|
||||
| **竞品分析** (competitor_analysis) | 10 | 多个竞品对比分析 |
|
||||
| **AI 助手对话** (ai_chat, 10条消息) | 1 | 普通 AI 对话 |
|
||||
| **信息提取** (info_extract) | 1 | 询盘/邮件信息提取 |
|
||||
| **报价单生成** (quotation) | 2 | AI 辅助报价 |
|
||||
| **跟进策略** (followup_scan) | 2 | AI 扫描跟进建议 |
|
||||
|
||||
### 2.3 计费规则
|
||||
|
||||
- **按次扣减**:功能调用成功后扣减,失败不扣
|
||||
- **余额不足**:返回 `402 Payment Required` + 当前余额 + 所需额度
|
||||
- **不足扣减**:如余额不足单次消费,允许扣至负数(欠费模式),欠费部分下次充值自动抵扣
|
||||
- **日免费额度**:翻译每日免费 1000 字符(防流失),超出部分扣 Credits
|
||||
- **免费试用**:新用户注册自动赠送 30 Credits(≈ 3 次搜索)
|
||||
|
||||
### 2.4 消费记录
|
||||
|
||||
每次扣减记录在 `credit_consumptions` 表,包含:
|
||||
- user_id, result_type(功能类型)
|
||||
- reference_id(关联业务记录 ID)
|
||||
- credits_change(正数 = 充值,负数 = 消费)
|
||||
- balance_after(扣减后余额)
|
||||
- source(package/subscription/admin_grant)
|
||||
- metadata(Jsonb,保存上下文,如搜索关键词、翻译字符数)
|
||||
|
||||
## 3. 定价体系
|
||||
|
||||
### 3.1 次数包(一次性,永不过期)
|
||||
|
||||
| 次数 | 价格(¥) | 次均 | 价格($) |
|
||||
|------|---------|------|---------|
|
||||
| 20 | ¥19 | ¥0.95 | $3 |
|
||||
| 100 | ¥79 | ¥0.79 | $12 |
|
||||
| 500 | ¥299 | ¥0.60 | $45 |
|
||||
| 2000 | ¥899 | ¥0.45 | $138 |
|
||||
|
||||
### 3.2 订阅套餐(每月重置)
|
||||
|
||||
| 套餐 | 月次数 | 月费(¥) | 月费($) | 次均 |
|
||||
|------|-------|---------|---------|------|
|
||||
| Starter | 100 | ¥69 | $10 | ¥0.69 |
|
||||
| Pro | 500 | ¥269 | $40 | ¥0.54 |
|
||||
| Enterprise | 2000 | ¥699 | $105 | ¥0.35 |
|
||||
|
||||
### 3.3 新旧过渡方案
|
||||
|
||||
- 现有有效订阅用户 → 按剩余天数折算为 Credits 存入余额
|
||||
- Pro 剩余 15 天 ≈ 100 × 0.5 ≈ 50 Credits 一次性赠送
|
||||
- 同时保留原订阅到期日
|
||||
- 新用户 → 走新信用系统
|
||||
- 过渡期两种支付方式并存
|
||||
|
||||
## 4. 数据库设计
|
||||
|
||||
### 4.1 新增表
|
||||
|
||||
```sql
|
||||
-- 次数包定义(一次性购买)
|
||||
CREATE TABLE credit_packages (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name VARCHAR(100) NOT NULL, -- 中文名
|
||||
name_en VARCHAR(100) NOT NULL, -- 英文名
|
||||
credits INTEGER NOT NULL, -- 额定量
|
||||
price NUMERIC(10,2) NOT NULL, -- 人民币价格
|
||||
price_usd NUMERIC(10,2), -- 美元价格
|
||||
original_price NUMERIC(10,2), -- 原价(划线价)
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
sort_order INTEGER DEFAULT 0,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 订阅套餐定义(周期性)
|
||||
CREATE TABLE subscription_plans (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name VARCHAR(100) NOT NULL,
|
||||
name_en VARCHAR(100) NOT NULL,
|
||||
credits_per_month INTEGER NOT NULL,
|
||||
price NUMERIC(10,2) NOT NULL,
|
||||
price_usd NUMERIC(10,2),
|
||||
duration_days INTEGER NOT NULL DEFAULT 30,
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
sort_order INTEGER DEFAULT 0,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 用户信用余额
|
||||
CREATE TABLE user_credits (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL UNIQUE REFERENCES users(id),
|
||||
balance NUMERIC(12,1) NOT NULL DEFAULT 0, -- 当前余额(支持小数)
|
||||
total_purchased NUMERIC(12,1) NOT NULL DEFAULT 0,
|
||||
total_used NUMERIC(12,1) NOT NULL DEFAULT 0,
|
||||
-- 订阅关联
|
||||
subscription_plan_id UUID REFERENCES subscription_plans(id),
|
||||
subscription_expires_at TIMESTAMP,
|
||||
subscription_auto_renew BOOLEAN DEFAULT FALSE,
|
||||
-- 免费赠送标记
|
||||
free_trial_used BOOLEAN DEFAULT FALSE,
|
||||
daily_translate_chars INTEGER DEFAULT 0,
|
||||
daily_translate_date DATE,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 信用消费日志
|
||||
CREATE TABLE credit_consumptions (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id),
|
||||
result_type VARCHAR(50) NOT NULL, -- lead_search / translate / outreach / ...
|
||||
reference_id UUID, -- 关联业务记录
|
||||
credits_change NUMERIC(10,1) NOT NULL, -- 负=消费,正=充值
|
||||
balance_after NUMERIC(12,1) NOT NULL,
|
||||
source VARCHAR(30) NOT NULL, -- package / subscription / admin_grant / free_trial / daily_free
|
||||
description VARCHAR(500),
|
||||
metadata JSONB,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 次数包购买记录
|
||||
CREATE TABLE credit_purchases (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id),
|
||||
package_id UUID REFERENCES credit_packages(id),
|
||||
subscription_plan_id UUID REFERENCES subscription_plans(id),
|
||||
credits INTEGER NOT NULL,
|
||||
amount NUMERIC(10,2) NOT NULL,
|
||||
currency VARCHAR(3) DEFAULT 'CNY',
|
||||
payment_method VARCHAR(20), -- alipay / wechat / stripe
|
||||
status VARCHAR(20) DEFAULT 'pending', -- pending / paid / refunded
|
||||
payment_transaction_id UUID REFERENCES payment_transactions(id),
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
paid_at TIMESTAMP
|
||||
);
|
||||
```
|
||||
|
||||
### 4.2 索引
|
||||
|
||||
```sql
|
||||
CREATE INDEX idx_credit_consumptions_user ON credit_consumptions(user_id, created_at DESC);
|
||||
CREATE INDEX idx_credit_consumptions_type ON credit_consumptions(result_type);
|
||||
CREATE INDEX idx_credit_purchases_user ON credit_purchases(user_id);
|
||||
CREATE INDEX idx_credit_purchases_status ON credit_purchases(status);
|
||||
```
|
||||
|
||||
### 4.3 配置项
|
||||
|
||||
```json
|
||||
{
|
||||
"free_trial_credits": {"value": 30, "desc": "新用户免费赠送次数"},
|
||||
"daily_free_translate_chars": {"value": 1000, "desc": "每日免费翻译字符数"},
|
||||
"credit_consumption_rates": {
|
||||
"value": {
|
||||
"lead_search": 10,
|
||||
"company_analysis": 5,
|
||||
"market_intel": 20,
|
||||
"translate_per_1000chars": 1,
|
||||
"reply_suggest": 2,
|
||||
"outreach": 3,
|
||||
"marketing_content": 5,
|
||||
"competitor_analysis": 10,
|
||||
"ai_chat_per_10msg": 1,
|
||||
"info_extract": 1,
|
||||
"quotation": 2,
|
||||
"followup_scan": 2
|
||||
},
|
||||
"desc": "各功能信用消耗速率"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 5. API 设计
|
||||
|
||||
### 5.1 信用系统
|
||||
|
||||
```
|
||||
GET /api/v1/credits/balance → 余额+订阅信息
|
||||
GET /api/v1/credits/history?page=&size= → 消费历史
|
||||
POST /api/v1/credits/packages → 购买次数包(走支付网关)
|
||||
POST /api/v1/credits/subscribe → 开通订阅
|
||||
POST /api/v1/credits/cancel-subscription → 取消订阅
|
||||
GET /api/v1/credits/packages → 次数包列表
|
||||
GET /api/v1/credits/subscription-plans → 订阅套餐列表
|
||||
GET /api/v1/credits/rates → 各功能消耗速率
|
||||
```
|
||||
|
||||
### 5.2 现有功能增加额度扣减
|
||||
|
||||
所有 AI 功能在返回结果后调用 `CreditService.deduct()`:
|
||||
|
||||
```python
|
||||
# 在每个 AI 功能服务层中(discovery/discovery.py, translate/translation.py, etc.)
|
||||
from app.services.credit import CreditService
|
||||
|
||||
svc = CreditService(db)
|
||||
success, balance = await svc.deduct(user_id, "lead_search", reference_id=record_id)
|
||||
if not success:
|
||||
raise HTTPException(status_code=402, detail="次数不足")
|
||||
```
|
||||
|
||||
### 5.3 管理端
|
||||
|
||||
```
|
||||
GET /api/v1/admin/credit-packages → CRUD
|
||||
POST /api/v1/admin/credit-packages
|
||||
PUT /api/v1/admin/credit-packages/{id}
|
||||
DELETE /api/v1/admin/credit-packages/{id}
|
||||
GET /api/v1/admin/subscription-plans → CRUD
|
||||
POST /api/v1/admin/subscription-plans
|
||||
PUT /api/v1/admin/subscription-plans/{id}
|
||||
GET /api/v1/admin/user-credits → 用户余额列表
|
||||
POST /api/v1/admin/user-credits/adjust → 手动调整余额
|
||||
GET /api/v1/admin/credit-consumptions → 消费流水
|
||||
GET /api/v1/admin/credit-stats → 统计数据
|
||||
```
|
||||
|
||||
## 6. 前端改造
|
||||
|
||||
### 6.1 导航栏重构
|
||||
|
||||
```
|
||||
新用户侧边栏(按优先级):
|
||||
|
||||
【核心】
|
||||
★ 发现客户 /discovery ← 首页
|
||||
市场情报 /market-intel ← 新增
|
||||
我的线索 /my-leads ← 新增(收藏/保存的线索)
|
||||
|
||||
【工具(增值)】
|
||||
客户管理 /customers
|
||||
产品库 /products
|
||||
报价单 /quotations
|
||||
智能翻译 /translate
|
||||
开发信 /outreach
|
||||
营销素材 /marketing
|
||||
|
||||
【查看】
|
||||
工作台 /workspace ← 仪表盘(用量统计/最近操作)
|
||||
团队协作 /team
|
||||
个人中心 /profile
|
||||
```
|
||||
|
||||
### 6.2 Topbar 改造
|
||||
|
||||
顶部始终显示 `余额: X.X 次` 按钮,点击跳转购买页。
|
||||
|
||||
```html
|
||||
<el-button class="credit-balance" @click="$router.push('/credits')">
|
||||
<el-icon><Coin /></el-icon>
|
||||
{{ balance }} 次
|
||||
</el-button>
|
||||
```
|
||||
|
||||
### 6.3 购买页面
|
||||
|
||||
替代现有 `/upgrade` 路由为 `/credits`:
|
||||
|
||||
- Tab1: **次数包** — 多卡片展示(20/100/500/2000次),支付弹窗
|
||||
- Tab2: **订阅套餐** — Starter/Pro/Enterprise,月付/年付
|
||||
- Tab3: **消费明细** — 近期消费流水
|
||||
|
||||
### 6.4 余额不足引导
|
||||
|
||||
所有 AI 功能检测到余额不足时,前端弹窗:
|
||||
```
|
||||
"次数不足,当前剩余 X 次,本次操作需要 Y 次
|
||||
[去购买] [取消]"
|
||||
```
|
||||
|
||||
### 6.5 免费额度提示
|
||||
|
||||
新用户注册后首页显示:
|
||||
```
|
||||
"欢迎使用 TradeMate!您有 30 次免费搜索额度,用完即止。"
|
||||
```
|
||||
|
||||
## 7. 国际化
|
||||
|
||||
### 7.1 第一阶段(核心页面)
|
||||
|
||||
| 页面 | 优先级 |
|
||||
|------|--------|
|
||||
| 登录/注册 | P0 |
|
||||
| 导航栏 | P0 |
|
||||
| 发现客户 | P0 |
|
||||
| 购买页面 | P0 |
|
||||
| 工作台 | P1 |
|
||||
| 翻译 | P1 |
|
||||
| 个人中心 | P1 |
|
||||
|
||||
### 7.2 技术方案
|
||||
|
||||
- 使用 vue-i18n + JSON locale files
|
||||
- `zh-CN.json`(默认)+ `en.json`
|
||||
- 通过 URL query `?lang=en` 或 Cookie 切换
|
||||
- 管理后台跟随用户语言偏好
|
||||
|
||||
```json
|
||||
// en.json
|
||||
{
|
||||
"nav": {
|
||||
"discovery": "Find Buyers",
|
||||
"translate": "Translate",
|
||||
"customers": "Customers",
|
||||
"credits": "Buy Credits"
|
||||
},
|
||||
"discovery": {
|
||||
"search_placeholder": "e.g. LED lighting, solar panels...",
|
||||
"search_button": "Search Buyers",
|
||||
"credits_cost": "This search costs 10 credits"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 8. 实施计划
|
||||
|
||||
### Phase 1 — 信用系统后端(当前)
|
||||
1. 数据库模型 + migration
|
||||
2. CreditService
|
||||
3. 信用系统 API
|
||||
4. 管理端 CRUD
|
||||
|
||||
### Phase 2 — 功能接入扣次
|
||||
1. Discovery 接入(搜索/分析/市场报告)
|
||||
2. Translate 接入
|
||||
3. Marketing 接入
|
||||
4. AI Chat / Outreach 接入
|
||||
|
||||
### Phase 3 — 前端改造
|
||||
1. 新导航 + 余额显示
|
||||
2. 购买/订阅页面
|
||||
3. 余额不足引导
|
||||
4. 工作台改仪表盘
|
||||
|
||||
### Phase 4 — 国际化 + 定价上线
|
||||
1. 中英文切换
|
||||
2. 海外支付(Stripe)
|
||||
3. 定价正式发布
|
||||
4. 老用户数据迁移
|
||||
|
||||
## 9. 关键风险
|
||||
|
||||
| 风险 | 缓解 |
|
||||
|------|------|
|
||||
| 用户觉得按次付费贵 | 免费 30 次让用户先体验价值;套餐价需低于用户感知价值 |
|
||||
| 搜索结果质量不稳 | 多搜索源回退(DB → Bing → Google CSE → AI),持续优化 |
|
||||
| 老用户不满过渡方案 | 老用户按剩余天数高折抵换算,并保留原有套餐期限内权益 |
|
||||
| 翻译用量大成本高 | 每日免费额兜底 + Credits 定价覆盖 API 成本 |
|
||||
Reference in New Issue
Block a user