Files
trade-assistant/docs/CREDIT_SYSTEM.md
T
TradeMate Dev 2a107a42f3 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
2026-06-12 10:39:45 +08:00

13 KiB
Raw Blame History

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(扣减后余额)
  • sourcepackage/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 新增表

-- 次数包定义(一次性购买)
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 索引

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 配置项

{
    "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()

# 在每个 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 次 按钮,点击跳转购买页。

<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 切换
  • 管理后台跟随用户语言偏好
// 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 成本