8.1 KiB
8.1 KiB
积分商城(Points Mall)接口需求说明
本文档用于对接 aura-web 的「积分商城」页面数据与兑换流程,供后端实现接口与数据表结构时参考。
页面结构对应的数据
页面 UI 由 4 个区域组成:
- 头部商品分类导航栏(横向)
- 公告栏
- banner 区 + 促销活动入口(2 个入口卡片)
- 商品内容区(商品列表 + 搜索/排序/分页)
统一约定
- BaseURL:
https://api.hoyidata.com/aura/v1 - 鉴权:沿用当前登录态(Cookie / Session)或
Authorization: Bearer <token>(以现有登录实现为准),接口需校验登录态 - 图片字段:返回绝对 URL(推荐 CDN 域名),前端不拼接
- 时间字段:建议统一使用毫秒时间戳(number)
- 失败格式:沿用现有 aura 接口的错误格式(HTTP Status + JSON message/error)
接口列表(前端必需)
1) 商城概览
用于首屏一次性拉齐「分类、公告、banner、促销入口、我的积分」。
GET /points-mall/overview
Query
include_me:可选,默认true(是否返回我的积分)
Response
{
"me": {
"points": 1280,
"level": "Lv.2"
},
"categories": [
{ "id": "all", "name": "全部", "sort": 0 },
{ "id": "digital", "name": "虚拟权益", "sort": 1 }
],
"announcements": [
{
"id": "a1",
"title": "公告:积分规则升级中",
"content": "本期暂不开放兑换,页面仅用于 UI 预览。",
"linkUrl": "https://..."
}
],
"banners": [
{
"id": "b1",
"title": "限时上新",
"subtitle": "Up to 25% Off",
"imageUrl": "https://cdn.../banner.png",
"linkUrl": "https://..."
}
],
"promoEntries": [
{
"id": "p1",
"title": "促销活动",
"subtitle": "本周精选",
"iconUrl": "https://cdn.../promo.png",
"linkUrl": "https://..."
},
{
"id": "p2",
"title": "积分任务",
"subtitle": "快速涨积分",
"iconUrl": "https://cdn.../tasks.png",
"linkUrl": "https://..."
}
]
}
2) 商品列表(搜索/筛选/排序/分页)
GET /points-mall/products
Query
categoryId:可选(分类 ID;不传代表全部)q:可选(搜索关键字;匹配 name/subtitle)sort:可选,默认popularpopular:热度优先(建议按 sold 或近期兑换量)newest:最新上架price_asc:积分从低到高price_desc:积分从高到低
page:可选,默认1pageSize:可选,默认24
Response
{
"page": 1,
"pageSize": 24,
"total": 120,
"items": [
{
"id": "prd_001",
"categoryId": "digital",
"name": "Claude Pro 月卡",
"subtitle": "兑换后获得激活码",
"coverUrl": "https://cdn.../cover.png",
"pointsPrice": 1999,
"stock": 99,
"sold": 12,
"tags": ["热卖", "限时"]
}
]
}
3) 商品详情
GET /points-mall/products/{productId}
Response(建议)
{
"id": "prd_001",
"categoryId": "digital",
"name": "Claude Pro 月卡",
"subtitle": "兑换后获得激活码",
"coverUrl": "https://cdn.../cover.png",
"imageUrls": ["https://cdn.../1.png", "https://cdn.../2.png"],
"pointsPrice": 1999,
"stock": 99,
"sold": 12,
"tags": ["热卖", "限时"],
"description": "富文本/Markdown 均可,建议 Markdown",
"type": "virtual",
"delivery": {
"mode": "code",
"tips": "兑换成功后在【订单详情】查看兑换码"
}
}
4) 创建兑换订单(扣积分)
POST /points-mall/orders
Request
{
"productId": "prd_001",
"quantity": 1
}
Response
{
"orderId": "ord_001",
"status": "paid",
"pointsCost": 1999,
"remainingPoints": 281
}
关键规则
- 需要幂等:建议支持
Idempotency-Keyheader,避免重复扣积分 - 校验库存与用户积分
- 虚拟商品/实物商品可共用该接口,但实物商品需要补充收货信息(可扩展字段)
5) 订单列表 / 订单详情
GET /points-mall/orders
Query(建议)
page/pageSizestatus:可选
GET /points-mall/orders/{orderId}
Response(建议)
{
"id": "ord_001",
"status": "paid",
"createdAt": 1730000000000,
"product": {
"id": "prd_001",
"name": "Claude Pro 月卡",
"coverUrl": "https://cdn.../cover.png"
},
"quantity": 1,
"pointsCost": 1999,
"delivery": {
"mode": "code",
"code": "XXXX-YYYY-ZZZZ"
}
}
6) 积分流水(可选,但强烈建议)
用于解释积分变动与对账。
GET /points-mall/me/points-ledger
Query(建议)
page/pageSize
Response(建议)
{
"page": 1,
"pageSize": 20,
"total": 300,
"items": [
{
"id": "pl_001",
"createdAt": 1730000000000,
"change": -1999,
"balance": 281,
"reason": "兑换 Claude Pro 月卡",
"bizType": "points_mall_order",
"bizId": "ord_001"
}
]
}
数据表结构建议(后端实现参考)
说明:下述为建议表结构,字段类型可按现有数据库规范调整;建议均包含 created_at / updated_at 与必要索引。
1) points_mall_categories(分类)
id(PK, string/uuid)name(varchar)sort(int)enabled(bool)
索引:
enabled, sort
2) points_mall_announcements(公告)
id(PK)title(varchar)content(text)link_url(varchar, nullable)start_at(bigint, nullable)end_at(bigint, nullable)enabled(bool)sort(int)
索引:
enabled, sortstart_at, end_at
3) points_mall_banners(banner)
id(PK)title(varchar)subtitle(varchar, nullable)image_url(varchar)link_url(varchar, nullable)start_at(bigint, nullable)end_at(bigint, nullable)enabled(bool)sort(int)
索引:
enabled, sortstart_at, end_at
4) points_mall_promo_entries(促销入口)
id(PK)title(varchar)subtitle(varchar, nullable)icon_url(varchar, nullable)link_url(varchar, nullable)enabled(bool)sort(int)
索引:
enabled, sort
5) points_mall_products(商品)
id(PK)category_id(FK -> categories.id)name(varchar)subtitle(varchar, nullable)description(text / markdown)cover_url(varchar)image_urls(json/text,数组)type(enum:virtual|physical)points_price(int)stock(int)sold(int,累计兑换量,或可由订单聚合)tags(json/text,数组)enabled(bool)start_at(bigint, nullable)end_at(bigint, nullable)sort(int)
索引:
enabled, start_at, end_atcategory_id, enabled, sort- 搜索:
name/subtitle建议全文索引或 LIKE(视数据库而定)
6) points_mall_orders(订单)
id(PK)user_id(FK)product_id(FK)quantity(int)points_cost(int)status(enum:created|paid|delivered|canceled|refunded)delivery_mode(enum:code|shipping)delivery_payload(json,虚拟码/物流信息等)idempotency_key(varchar, nullable,建议唯一索引 + user_id 组合)
索引:
user_id, created_at descstatus, created_at descuser_id, idempotency_key(唯一)
7) points_ledger(积分流水)
id(PK)user_id(FK)change(int,正负)balance(int)reason(varchar)biz_type(varchar)biz_id(varchar)
索引:
user_id, created_at descbiz_type, biz_id
前端实现已对齐的字段
前端已按以下字段读取:
- 分类:
id/name/sort - 公告:
title/content/linkUrl - banner:
title/subtitle/imageUrl/linkUrl - 促销入口:
title/subtitle/iconUrl/linkUrl - 商品列表:
id/categoryId/name/subtitle/coverUrl/pointsPrice/stock/sold/tags
如后端字段命名需要用 snake_case,可在接口层做映射,但建议直接使用上述 camelCase,减少前端 mapping。