后端及接口说明 - casf73/Software-Engineering-Practice GitHub Wiki
- 文档版本:V3.0
- 修订日期:2026-11-05
- 对应版本:第三轮挑战需求 A 功能完善版
- 源码目录:project/mvp-v1.0/backend
本文说明当前后端业务接口,包含前两轮保留功能以及第三轮商品管理升级、客户升级功能。
erDiagram
categories o|--o{ categories : parent_id
categories o|--o{ products : category_id
products ||--o{ purchase_intents : product_id
customer_accounts o|--o{ purchase_intents : customer_id
categories {
BIGINT id PK
VARCHAR name
BIGINT parent_id FK
}
products {
BIGINT id PK
VARCHAR name
DECIMAL price
VARCHAR description
VARCHAR image_urls
INTEGER stock
BIGINT category_id FK
VARCHAR status
BOOLEAN active_slot
TIMESTAMP created_at
TIMESTAMP updated_at
}
purchase_intents {
BIGINT id PK
BIGINT product_id FK
BIGINT customer_id FK
VARCHAR product_name_snapshot
DECIMAL price_snapshot
VARCHAR meeting_location
VARCHAR name
VARCHAR phone
VARCHAR passcode UK
VARCHAR status
TIMESTAMP submitted_at
TIMESTAMP queue_at
}
customer_accounts {
BIGINT id PK
VARCHAR username
VARCHAR username_key UK
VARCHAR password_hash
VARCHAR phone
VARCHAR default_location
TIMESTAMP created_at
}
seller_accounts {
BIGINT id PK
VARCHAR password_hash
BIGINT session_version
}
| 表或字段 | 说明 |
|---|---|
| categories | 保存一级、二级分类,parent_id为空表示一级分类。 |
| products.stock | 商品库存,成功交易减1,归零自动下架。 |
| products.category_id | 商品分类外键,可为空。 |
| products.image_urls | 保存有序相册地址,最多9张。 |
| products.description | 保存清理后的富文本描述。 |
| customer_accounts | 客户账号表,保存用户名、密码哈希、电话、默认地点和注册时间。 |
| purchase_intents.customer_id | 关联注册客户,访客记录保持空值。 |
| product_name_snapshot | 下单商品名称快照。 |
| price_snapshot | 下单价格快照。 |
| meeting_location | 本次交易地点。 |
客户历史查询索引包含customer_id、submitted_at、id。
当前共43条业务路由,包含兼容路径。
| 分类 | 方法 | 路径 | 身份要求 | 返回类型 |
|---|---|---|---|---|
| 公开商品 | GET | /api/public/products |
无 | PageView<ProductView> |
| 公开商品 | GET | /api/public/products/{id} |
无 | ProductView |
| 公开商品 | GET | /api/public/categories |
无 | CategoryView[] |
| 公开意向 | POST | /api/public/products/{id}/intents |
无 | IssuedIntentView |
| 兼容商品 | GET | /api/public/products/current |
无 | ProductView |
| 兼容意向 | POST | /api/public/intents |
无 | IssuedIntentView |
| 口令码 | GET | /api/public/intents/{passcode} |
有效口令码 | BuyerIntentView |
| 口令码 | PUT | /api/public/intents/{passcode} |
有效口令码 | BuyerIntentView |
| 口令码 | DELETE | /api/public/intents/{passcode} |
有效口令码 | HTTP 204 |
| 卖家会话 | POST | /api/seller/login |
无 | {authenticated:boolean} |
| 卖家会话 | GET | /api/seller/session |
无 | {authenticated:boolean} |
| 卖家会话 | POST | /api/seller/logout |
卖家 | HTTP 204 |
| 卖家账号 | PUT | /api/seller/password |
卖家 | HTTP 204 |
| 卖家商品 | GET | /api/seller/products |
卖家 | PageView<ProductView> |
| 卖家商品 | POST | /api/seller/products |
卖家 | ProductView |
| 卖家商品 | PUT | /api/seller/products/{id} |
卖家 | ProductView |
| 卖家商品 | GET | /api/seller/products/{id}/workbench |
卖家 | WorkbenchView |
| 卖家商品 | POST | /api/seller/products/{id}/freeze |
卖家 | ProductView |
| 卖家商品 | POST | /api/seller/products/{id}/unfreeze |
卖家 | ProductView |
| 卖家商品 | POST | /api/seller/products/{id}/relist |
卖家 | ProductView |
| 卖家商品 | POST | /api/seller/products/{id}/delist |
卖家 | HTTP 204 |
| 卖家媒体 | POST | /api/seller/products/image |
卖家 | {url:string} |
| 卖家分类 | POST | /api/seller/categories |
卖家 | CategoryView |
| 卖家分类 | PUT | /api/seller/categories/{id} |
卖家 | CategoryView |
| 卖家分类 | DELETE | /api/seller/categories/{id} |
卖家 | HTTP 204 |
| 卖家交易 | POST | /api/seller/products/{id}/trades/start |
卖家 | IntentView |
| 卖家交易 | POST | /api/seller/trades/{intentId}/result |
卖家 | HTTP 204 |
| 卖家意向 | POST | /api/seller/intents/{intentId}/action |
卖家 | HTTP 204 |
| 兼容工作台 | GET | /api/seller/workbench |
卖家 | WorkbenchView |
| 兼容商品 | PUT | /api/seller/products/current |
卖家 | ProductView |
| 兼容商品 | POST | /api/seller/products/current/freeze |
卖家 | ProductView |
| 兼容商品 | POST | /api/seller/products/current/unfreeze |
卖家 | ProductView |
| 兼容商品 | POST | /api/seller/products/current/delist |
卖家 | HTTP 204 |
| 兼容交易 | POST | /api/seller/trades/start |
卖家 | IntentView |
| 客户账号 | POST | /api/customer/register |
无 | CustomerSessionView |
| 客户账号 | POST | /api/customer/login |
无 | CustomerSessionView |
| 客户账号 | GET | /api/customer/session |
无 | CustomerSessionView |
| 客户账号 | POST | /api/customer/logout |
可无客户身份 | HTTP 204 |
| 客户历史 | GET | /api/customer/orders |
客户 | PageView<CustomerOrderView> |
| 客户意向 | POST | /api/customer/products/{id}/intents |
客户 | IssuedIntentView |
| 卖家客户 | GET | /api/seller/customers |
卖家 | PageView<CustomerView> |
| 卖家客户 | GET | /api/seller/customers/{id} |
卖家 | CustomerView |
| 卖家客户 | GET | /api/seller/customers/{id}/orders |
卖家 | PageView<CustomerOrderView> |
- 开发基址:
http://localhost:8080 - JSON请求:
Content-Type: application/json - 上传请求:
multipart/form-data - 上传字段:
file - 卖家和客户身份使用HTTP Session Cookie。
- 页码
page从0开始,size范围1~100。
| 数据 | JSON类型 |
|---|---|
| 编号、库存、页码、数量 | number |
| 金额 | number |
| 名称、电话、地点、状态 | string |
| 图片地址列表 | string[] |
| 日期时间 | ISO格式string |
| 不适用或不存在的可空字段 | null |
| 状态码 | 含义 |
|---|---|
| 200 | 查询、登录或更新成功。 |
| 201 | 创建商品、分类、客户或意向成功。 |
| 204 | 操作成功,无响应体。 |
| 400 | 参数不合法。 |
| 401 | 身份无效或未登录。 |
| 404 | 资源不存在,或口令码无效、已失效。 |
| 409 | 重复注册、分类引用或业务状态冲突。 |
| 字段 | 类型 | 规则 |
|---|---|---|
| name | string | 必填,最多80字符。 |
| price | number | 必填,大于0,最多2位小数,整数部分最多10位。 |
| description | string或null | 最多20000字符。 |
| images | string[]或null | 最多9项,每项为有效本地上传地址。 |
| stock | number或null | 0~1000000整数;新建未提供时使用默认库存1,编辑未提供时保留原库存。 |
| categoryId | number或null | 一级或二级分类编号,可不分类。 |
示例:
{
"name": "机械键盘",
"price": 88.50,
"stock": 3,
"categoryId": 2,
"images": [
"/uploads/example-a.png",
"/uploads/example-b.jpg"
],
"description": "<h3>商品介绍</h3><p><strong>九成新</strong></p>"
}图片地址应使用实际上传接口返回值。
| 字段 | 类型 | 规则 |
|---|---|---|
| name | string | 必填,最多80字符。 |
| parentId | number或null | 空值为一级分类,否则只能指向一级分类。 |
| 字段 | 类型 | 规则 |
|---|---|---|
| name | string | 必填,最多80字符。 |
| phone | string | 必填,6~30字符,必须含数字;允许数字、加号、括号、空格、短横线。 |
| 字段 | 类型 | 规则 |
|---|---|---|
| username | string | 3~32位文字、数字、下划线或短横线;大小写归一后唯一。 |
| password | string | 8~128位,不能为空白密码。 |
| phone | string | 符合电话规则。 |
| defaultLocation | string | 必填,最多200字符。 |
{
"username": "buyer01",
"password": "Buyer1234",
"phone": "13800000001",
"defaultLocation": "学校南门"
}{
"username": "buyer01",
"password": "Buyer1234"
}用户名和密码必填,最大长度分别为32和128。
{
"name": "客户联系人",
"phone": "13900000001",
"meetingLocation": "学校南门"
}meetingLocation为本次交易地点,必填且最多200字符,不自动修改账号默认地点。
成功:
{
"success": true,
"disposition": null
}失败重排:
{
"success": false,
"disposition": "REQUEUE"
}失败作废时使用VOID。
| 字段 | 类型 | 说明 |
|---|---|---|
| items | T[] | 当前页数据。 |
| total | number | 匹配总数。 |
| page | number | 当前页码。 |
| size | number | 每页数量。 |
| 字段 | 类型 |
|---|---|
| id | number |
| name | string |
| price | number |
| description | string |
| images | string[] |
| status | string |
| createdAt | string |
| stock | number |
| categoryId | number或null |
| categoryName | string或null |
| parentCategoryId | number或null |
| 字段 | 类型 |
|---|---|
| id | number |
| name | string |
| parentId | number或null |
| 字段 | 类型 |
|---|---|
| id | number |
| username | string |
| phone | string |
| defaultLocation | string |
| createdAt | string |
不返回密码、密码哈希和归一用户名内部字段。
| 字段 | 类型 |
|---|---|
| authenticated | boolean |
| customer | CustomerView或null |
未登录查询客户会话返回:
{
"authenticated": false,
"customer": null
}| 字段 | 类型 | 说明 |
|---|---|---|
| id | number | 意向记录编号。 |
| productId | number | 商品编号。 |
| productName | string | 下单名称快照,兼容旧记录时可使用商品名称。 |
| price | number | 下单价格快照。 |
| name | string | 本次联系人。 |
| phone | string | 本次联系电话。 |
| meetingLocation | string或null | 本次交易地点。 |
| status | string | 意向状态。 |
| submittedAt | string | 原提交时间。 |
| position | number或null | 当前有效等待排位。 |
| passcode | string或null | 客户本人可获得有效口令,卖家历史查询固定返回null。 |
| productStatus | string | 商品当前状态。 |
| 字段 | 类型 |
|---|---|
| id | number |
| name | string |
| phone | string |
| status | string |
| position | number或null |
| queueAt | string |
| meetingLocation | string或null |
| customerUsername | string或null |
| 字段 | 类型 |
|---|---|
| product | ProductView或null |
| intents | IntentView[] |
| waitingCount | number |
| activeIntent | IntentView或null |
返回name、phone、status、position、productStatus。
返回passcode:string和position:number。
GET /api/public/products
| 参数 | 说明 |
|---|---|
| q | 名称或描述可见文字关键词,最多100字符。 |
| categoryId | 可选分类编号,一级筛选包含子类商品。 |
| page | 页码,默认0。 |
| size | 每页数量,默认20,范围1~100。 |
公开列表排除下架商品。手动冻结或交易中的商品可展示,但不接受新意向。
GET /api/public/products/{id}
返回商品及库存、分类、图片和描述。不存在或已下架时返回404。
GET /api/public/categories
返回分类数组,通过parentId组织一级与二级结构。
POST /api/public/products/{id}/intents
仅指定商品在售且有库存时允许提交。成功返回201及口令码、排位。
| 方法 | 路径 | 规则 |
|---|---|---|
| GET | /api/public/intents/{passcode} |
查询意向状态与排位。 |
| PUT | /api/public/intents/{passcode} |
只有等待者可修改姓名电话。 |
| DELETE | /api/public/intents/{passcode} |
只有等待者可撤销。 |
修改不改变原编号、口令码、提交时间及排队顺序。
口令码忽略大小写并去除首尾空格;无效或失效返回404。
-
POST /api/customer/register:创建成功返回201,自动登录。 -
POST /api/customer/login:登录成功返回200,错误账号或密码401。 - 重复用户名忽略大小写,返回409。
- 登录时轮换会话编号。
-
GET /api/customer/session:未登录仍返回200及authenticated=false。 -
POST /api/customer/logout:返回204,仅移除客户身份。
GET /api/customer/orders
需要客户登录,支持page、size。
客户编号从服务端会话取得,不接受其他客户编号作为查询条件。按提交时间和编号倒序返回,包含等待、交易、成功、失败、撤销、作废和下架结束记录。
POST /api/customer/products/{id}/intents
需要客户登录。保存当前客户归属、本次地点和商品名称价格快照,成功返回201。
访客历史不按相同姓名或电话自动认领。
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/seller/products |
包含下架商品,支持关键词、分类和分页。 |
| POST | /api/seller/products |
发布商品,允许多个商品同时有效。 |
| PUT | /api/seller/products/{id} |
编辑指定商品,交易中拒绝修改。 |
| GET | /api/seller/products/{id}/workbench |
查询该商品的独立队列和当前交易。 |
| POST | /api/seller/products/{id}/relist |
仅允许有库存的下架商品重新上架。 |
| POST | /api/seller/products/{id}/delist |
仅允许在售商品主动下架。 |
库存0创建商品时返回201,但商品状态为DELISTED。
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /api/seller/categories |
创建分类。 |
| PUT | /api/seller/categories/{id} |
编辑分类。 |
| DELETE | /api/seller/categories/{id} |
删除无引用分类。 |
禁止三级分类、循环引用、同级重名和有引用分类删除。
POST /api/seller/products/image
上传字段为file,支持JPG和PNG,单张不超过5MB。
成功返回:
{
"url": "/uploads/实际文件名.png"
}商品相册最多9张。富文本支持允许的格式化标签和本地描述图片,服务端清理危险标签及属性,拒绝非法相册地址。
POST /api/seller/products/{id}/freezePOST /api/seller/products/{id}/unfreeze
手动冻结保留队列,停止新意向。交易冻结不能通过手动解冻解除。
POST /api/seller/products/{id}/trades/start
自动选择该商品有效队首,返回当前交易意向。
POST /api/seller/trades/{intentId}/result
- 成功:当前意向成功,库存减1。
- 有库存:商品恢复在售,其他等待者保留。
- 库存归零:商品下架,其他等待意向结束。
- 失败VOID:当前意向失败并清空口令码。
- 失败REQUEUE:保留原码,回到队尾。
- 失败不扣库存。
- 状态不允许或重复登记返回409。
POST /api/seller/intents/{intentId}/action
请求action为VOID或REQUEUE,分别作废或移到队尾。
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/seller/customers |
按用户名或电话搜索,支持分页。 |
| GET | /api/seller/customers/{id} |
查询指定客户基本资料。 |
| GET | /api/seller/customers/{id}/orders |
查询指定客户购买历史。 |
仅卖家可访问。客户资料不包含密码或密码哈希;历史中的passcode固定为null。
-
POST /api/seller/login:验证凭据并建立卖家身份。 -
GET /api/seller/session:返回当前卖家身份是否有效。 -
POST /api/seller/logout:移除卖家身份。 -
PUT /api/seller/password:验证原密码并保存新密码,成功返回204。
改密请求:
{
"currentPassword": "原密码",
"newPassword": "不少于8位的新密码"
}新密码8~128位。改密递增会话版本,使所有旧卖家身份失效。
密码采用PBKDF2-HMAC-SHA256、600000次迭代、16字节随机盐和32字节结果。
客户与卖家身份分开保存。客户退出不清除卖家身份,卖家退出或改密不清除客户身份。
旧current和无商品编号的工作台、交易入口需要唯一有效商品上下文。
当存在多个有效商品、无法唯一确定目标时返回409。当前多商品页面使用带商品编号的接口。
| 值 | 含义 |
|---|---|
| ON_SALE | 在售。 |
| MANUALLY_FROZEN | 手动冻结。 |
| IN_TRADE | 交易中。 |
| DELISTED | 下架。 |
| 值 | 含义 |
|---|---|
| WAITING | 排队中。 |
| IN_TRADE | 交易中。 |
| TRADE_SUCCESS | 交易成功。 |
| TRADE_FAILED | 交易失败或售罄导致结束。 |
| VOIDED | 卖家作废等待意向。 |
| CANCELLED | 买家撤销。 |
| PRODUCT_DELISTED | 商品主动下架导致结束。 |
| 轮次 | 测试范围 |
|---|---|
| 首轮 | 基础商品、意向、FIFO、交易及图片上传。 |
| 第二轮 | 联系信息修改、手动冻结解冻、卖家改密。 |
| 第三轮 | R301~R308,覆盖商品升级与客户升级。 |
第三轮包含64个接口实例及64个功能实例。现有记录中接口实例全部通过,页面功能实例待人工执行。详细数据、步骤与测试设计方法见第三轮测试文档。