aura-web/docs/points-mall-api-full.md

15 KiB
Raw Blame History

积分商城后端 API 设计文档

一、整体设计概述

1.1 设计目标

  • 实现 API 调用消费金额与积分的自动累积1 美元 = 1000 积分)
  • 提供完整的积分商城商品管理与兑换流程
  • 支持实物商品的收货地址管理
  • 积分与用户 ID 强绑定,确保数据一致性

1.2 汇率规则

  • 1 USD = 1000 积分
  • 积分计算以实际消费金额为准,精确到小数点后 2 位
  • 消费金额四舍五入后转换为积分

二、数据库表结构设计

2.1 用户积分表 (user_points)

字段名 类型 说明 约束
id BIGINT 主键 PRIMARY KEY, AUTO_INCREMENT
user_id VARCHAR(64) 用户 ID NOT NULL, INDEX
points BIGINT 当前积分余额 NOT NULL, DEFAULT 0
total_earned BIGINT 累计获得积分 NOT NULL, DEFAULT 0
total_spent BIGINT 累计消耗积分 NOT NULL, DEFAULT 0
level VARCHAR(32) 用户等级 DEFAULT 'Lv.1'
created_at DATETIME 创建时间 NOT NULL
updated_at DATETIME 更新时间 NOT NULL
version INT 乐观锁版本 NOT NULL, DEFAULT 0

索引:

  • uk_user_id: UNIQUE INDEX on user_id

2.2 积分流水表 (point_transactions)

字段名 类型 说明 约束
id BIGINT 主键 PRIMARY KEY, AUTO_INCREMENT
user_id VARCHAR(64) 用户 ID NOT NULL, INDEX
type VARCHAR(32) 类型earn/spend NOT NULL
points BIGINT 变动积分(正数获得,负数消耗) NOT NULL
balance BIGINT 变动后余额 NOT NULL
source_type VARCHAR(32) 来源类型 NOT NULL
source_id VARCHAR(64) 来源 ID NULL
description VARCHAR(255) 描述 NULL
created_at DATETIME 创建时间 NOT NULL

说明:

  • source_type 枚举:api_callAPI 调用)、exchange(兑换商品)、activity(活动奖励)
  • source_id:对应 API 调用记录 ID 或订单 ID 等

2.3 积分商城商品表 (point_products)

字段名 类型 说明 约束
id VARCHAR(64) 商品 ID PRIMARY KEY
category_id VARCHAR(64) 分类 ID NOT NULL, INDEX
name VARCHAR(128) 商品名称 NOT NULL
subtitle VARCHAR(255) 副标题 NULL
description TEXT 详细描述 NULL
cover_url VARCHAR(512) 封面图片 NULL
points_price BIGINT 所需积分 NOT NULL
original_price DECIMAL(10,2) 原价(美元) NULL
stock INT 库存 NOT NULL, DEFAULT 0
sold INT 已售数量 NOT NULL, DEFAULT 0
tags JSON 标签数组 NULL
weight DECIMAL(8,2) 重量kg NULL
is_physical TINYINT 是否实物商品 NOT NULL, DEFAULT 1
is_published TINYINT 是否上架 NOT NULL, DEFAULT 0
sort_order INT 排序权重 NOT NULL, DEFAULT 0
created_at DATETIME 创建时间 NOT NULL
updated_at DATETIME 更新时间 NOT NULL

2.4 商品分类表 (point_categories)

字段名 类型 说明 约束
id VARCHAR(64) 分类 ID PRIMARY KEY
name VARCHAR(64) 分类名称 NOT NULL
icon_url VARCHAR(512) 图标 NULL
sort_order INT 排序权重 NOT NULL, DEFAULT 0
is_enabled TINYINT 是否启用 NOT NULL, DEFAULT 1
created_at DATETIME 创建时间 NOT NULL

2.5 兑换订单表 (point_orders)

字段名 类型 说明 约束
id VARCHAR(64) 订单 ID PRIMARY KEY
user_id VARCHAR(64) 用户 ID NOT NULL, INDEX
product_id VARCHAR(64) 商品 ID NOT NULL
product_name VARCHAR(128) 商品名称快照 NOT NULL
points_price BIGINT 消耗积分 NOT NULL
status VARCHAR(32) 订单状态 NOT NULL, INDEX
recipient_name VARCHAR(64) 收货人姓名 NOT NULL
phone VARCHAR(32) 联系电话 NOT NULL
province VARCHAR(64) 省份 NOT NULL
city VARCHAR(64) 城市 NOT NULL
district VARCHAR(64) 区/县 NOT NULL
address VARCHAR(512) 详细地址 NOT NULL
zip_code VARCHAR(16) 邮政编码 NULL
tracking_company VARCHAR(64) 物流公司 NULL
tracking_number VARCHAR(64) 物流单号 NULL
shipped_at DATETIME 发货时间 NULL
delivered_at DATETIME 签收时间 NULL
remark VARCHAR(255) 备注 NULL
created_at DATETIME 创建时间 NOT NULL
updated_at DATETIME 更新时间 NOT NULL

状态枚举 (status)

  • pending:待处理
  • confirmed:已确认
  • shipped:已发货
  • delivered:已签收
  • cancelled:已取消
  • refunded:已退款

2.6 Banner 表 (point_banners)

字段名 类型 说明 约束
id VARCHAR(64) Banner ID PRIMARY KEY
title VARCHAR(128) 标题 NOT NULL
subtitle VARCHAR(255) 副标题 NULL
image_url VARCHAR(512) 图片 URL NOT NULL
link_url VARCHAR(512) 跳转链接 NULL
sort_order INT 排序权重 NOT NULL, DEFAULT 0
is_enabled TINYINT 是否启用 NOT NULL, DEFAULT 1
created_at DATETIME 创建时间 NOT NULL

2.7 促销入口表 (point_promo_entries)

字段名 类型 说明 约束
id VARCHAR(64) 入口 ID PRIMARY KEY
title VARCHAR(64) 标题 NOT NULL
subtitle VARCHAR(128) 副标题 NULL
icon_url VARCHAR(512) 图标 URL NULL
link_url VARCHAR(512) 跳转链接 NULL
sort_order INT 排序权重 NOT NULL, DEFAULT 0
is_enabled TINYINT 是否启用 NOT NULL, DEFAULT 1
created_at DATETIME 创建时间 NOT NULL

三、API 接口设计

3.1 通用响应格式

{
  "code": 0,
  "message": "success",
  "data": {}
}

3.2 积分商城概览接口

GET /points-mall/overview

描述: 获取积分商城首页概览数据包括用户积分、分类、Banner、促销入口等

响应数据:

{
  "me": {
    "points": 1280,
    "level": "Lv.2",
    "totalEarned": 5680,
    "totalSpent": 4400
  },
  "categories": [
    {
      "id": "all",
      "name": "全部",
      "sort": 0
    },
    {
      "id": "digital",
      "name": "虚拟权益",
      "sort": 1
    }
  ],
  "banners": [
    {
      "id": "b1",
      "title": "限时活动",
      "subtitle": "Up to 25% Off",
      "imageUrl": "https://...",
      "linkUrl": "https://..."
    }
  ],
  "promoEntries": [
    {
      "id": "p1",
      "title": "促销活动",
      "subtitle": "本周精选",
      "iconUrl": "https://...",
      "linkUrl": "https://..."
    }
  ]
}

3.3 商品列表接口

GET /points-mall/products

描述: 获取商品列表,支持分页、筛选、排序

请求参数:

参数名 类型 必填 说明
categoryId String 分类 ID不传则查询全部
q String 搜索关键词
sort String 排序方式:popular(热度)、newest(最新)、price_asc(价格升序)、price_desc(价格降序),默认 popular
page Int 页码,默认 1
pageSize Int 每页数量,默认 24

响应数据:

{
  "page": 1,
  "pageSize": 24,
  "total": 120,
  "items": [
    {
      "id": "prod_001",
      "categoryId": "digital",
      "name": "商品名称",
      "subtitle": "商品简短描述",
      "coverUrl": "https://...",
      "pointsPrice": 1990,
      "stock": 99,
      "sold": 12,
      "tags": ["限时", "热卖"],
      "isPhysical": true
    }
  ]
}

3.4 商品详情接口

GET /points-mall/products/{id}

描述: 获取单个商品的详细信息

路径参数:

  • id: 商品 ID

响应数据:

{
  "id": "prod_001",
  "categoryId": "digital",
  "name": "商品名称",
  "subtitle": "商品简短描述",
  "description": "商品详细描述...",
  "coverUrl": "https://...",
  "imageUrls": ["https://...", "https://..."],
  "pointsPrice": 1990,
  "originalPrice": 19.90,
  "stock": 99,
  "sold": 12,
  "tags": ["限时", "热卖"],
  "isPhysical": true,
  "weight": 0.5
}

3.5 兑换商品接口

POST /points-mall/exchange

描述: 提交兑换订单,扣减积分,创建订单

请求体:

{
  "productId": "prod_001",
  "recipientName": "张三",
  "phone": "13800138000",
  "province": "广东省",
  "city": "深圳市",
  "district": "南山区",
  "address": "科技园南区XX路XX号",
  "zipCode": "518000"
}

字段说明:

字段名 类型 必填 说明
productId String 商品 ID
recipientName String 收货人姓名
phone String 手机号码
province String 省份
city String 城市
district String 区/县
address String 详细地址
zipCode String 邮政编码

响应数据:

{
  "orderId": "order_20240601_0001",
  "pointsDeducted": 1990,
  "remainingPoints": 10810
}

错误码:

code message 说明
40001 积分不足 用户积分不足以兑换该商品
40002 商品已下架 商品未发布或已下架
40003 库存不足 商品库存不足
40004 商品不存在 商品 ID 无效

3.6 兑换订单列表接口

GET /points-mall/orders

描述: 获取用户的兑换订单列表

请求参数:

参数名 类型 必填 说明
status String 订单状态筛选
page Int 页码,默认 1
pageSize Int 每页数量,默认 20

响应数据:

{
  "page": 1,
  "pageSize": 20,
  "total": 5,
  "items": [
    {
      "id": "order_20240601_0001",
      "productId": "prod_001",
      "productName": "商品名称",
      "coverUrl": "https://...",
      "pointsPrice": 1990,
      "status": "shipped",
      "statusText": "已发货",
      "trackingCompany": "顺丰速运",
      "trackingNumber": "SF1234567890",
      "createdAt": "2024-06-01T10:30:00Z"
    }
  ]
}

3.7 订单详情接口

GET /points-mall/orders/{id}

描述: 获取单个订单的详细信息

路径参数:

  • id: 订单 ID

响应数据:

{
  "id": "order_20240601_0001",
  "productId": "prod_001",
  "productName": "商品名称",
  "coverUrl": "https://...",
  "pointsPrice": 1990,
  "status": "shipped",
  "statusText": "已发货",
  "recipientName": "张三",
  "phone": "13800138000",
  "province": "广东省",
  "city": "深圳市",
  "district": "南山区",
  "address": "科技园南区XX路XX号",
  "zipCode": "518000",
  "trackingCompany": "顺丰速运",
  "trackingNumber": "SF1234567890",
  "shippedAt": "2024-06-02T14:00:00Z",
  "createdAt": "2024-06-01T10:30:00Z"
}

3.8 积分流水接口

GET /points-mall/transactions

描述: 获取用户积分变动记录

请求参数:

参数名 类型 必填 说明
type String 类型:earn(收入)、spend(支出)
page Int 页码,默认 1
pageSize Int 每页数量,默认 20

响应数据:

{
  "page": 1,
  "pageSize": 20,
  "total": 150,
  "items": [
    {
      "id": 1001,
      "type": "earn",
      "points": 500,
      "balance": 12800,
      "sourceType": "api_call",
      "description": "API 调用奖励",
      "createdAt": "2024-06-01T10:30:00Z"
    },
    {
      "id": 1000,
      "type": "spend",
      "points": -1990,
      "balance": 12300,
      "sourceType": "exchange",
      "sourceId": "order_20240601_0001",
      "description": "兑换商品XXX",
      "createdAt": "2024-06-01T09:00:00Z"
    }
  ]
}

四、积分累积逻辑

4.1 积分累积触发时机

积分累积在以下场景触发:

  1. API 调用完成时:每次成功的 LLM API 调用后,根据实际消费金额计算积分
  2. 活动奖励:通过活动接口手动发放积分

4.2 积分计算公式

积分 = 实际消费金额USD × 1000

示例:

  • 消费 $0.002 → 2 积分
  • 消费 $0.5 → 500 积分
  • 消费 $1.2 → 1200 积分

4.3 积分入账流程

  1. API 调用完成,记录 token 使用量和费用
  2. 计算积分:points = floor(costUSD * 1000) 或四舍五入
  3. 使用事务更新 user_points 表:
    • points += 新增积分
    • total_earned += 新增积分
  4. 写入 point_transactions 流水记录
  5. 注意:需要使用乐观锁防止并发问题

五、兑换流程设计

5.1 兑换流程图

用户点击兑换
    ↓
验证积分是否足够
    ↓
验证商品是否上架
    ↓
验证库存是否充足
    ↓
【事务开始】
扣减用户积分
    ↓
扣减商品库存
    ↓
增加商品已售数量
    ↓
创建兑换订单
    ↓
写入积分消费流水
    ↓
【事务提交】
    ↓
返回订单信息

5.2 并发控制

  1. 用户积分表:使用乐观锁(version 字段)防止超扣
  2. 商品库存:使用 UPDATE ... WHERE stock >= 1 原子操作
  3. 事务隔离使用可重复读REPEATABLE READ级别

六、管理后台接口(可选)

6.1 商品管理

  • POST /admin/points-mall/products - 创建商品
  • PUT /admin/points-mall/products/{id} - 更新商品
  • DELETE /admin/points-mall/products/{id} - 删除商品
  • PATCH /admin/points-mall/products/{id}/publish - 上架/下架商品

6.2 订单管理

  • GET /admin/points-mall/orders - 订单列表
  • PUT /admin/points-mall/orders/{id}/ship - 发货(填写物流信息)
  • PUT /admin/points-mall/orders/{id}/confirm - 确认订单
  • PUT /admin/points-mall/orders/{id}/cancel - 取消订单(退还积分)

七、注意事项

7.1 数据一致性

  • 所有涉及积分变动的操作必须使用数据库事务
  • 使用乐观锁防止并发扣减问题
  • 积分流水表是审计的重要依据,不可删除或修改

7.2 安全考虑

  • 所有接口必须经过用户认证
  • 积分扣减必须验证当前用户的积分余额
  • 防止重复提交兑换请求(可使用幂等键)

7.3 性能优化

  • 用户积分数据可考虑缓存(如 Redis
  • 商品列表接口建议加缓存
  • 积分流水表建议按时间分区

7.4 监控告警

  • 积分扣除失败告警
  • 库存不足告警
  • 异常大额积分变动告警

八、前端已实现功能

前端已完成以下功能开发,等待后端接口对接:

  1. 积分商城首页 UI包含积分展示
  2. 商品分类筛选、搜索、排序
  3. 商品卡片列表展示
  4. 兑换弹窗,包含收货地址表单
  5. 积分不足提示
  6. 统计页面展示消费金额与积分对应关系
  7. 1 USD = 1000 积分汇率展示