257 lines
8.9 KiB
Markdown
257 lines
8.9 KiB
Markdown
# 萌芽小店 · 后端
|
||
|
||
基于 **Go + Gin + GORM** 构建的 RESTful API 服务,负责商品管理、订单处理、用户认证、聊天消息等核心业务。
|
||
|
||
## 技术依赖
|
||
|
||
| 包 | 版本 | 用途 |
|
||
|----|------|------|
|
||
| gin | v1.9 | HTTP 路由框架 |
|
||
| gorm | v1.31 | ORM |
|
||
| gorm/driver/mysql | v1.6 | MySQL 驱动 |
|
||
| go-sql-driver/mysql | v1.9 | 底层 MySQL 连接 |
|
||
| gin-contrib/cors | latest | CORS 中间件 |
|
||
| google/uuid | latest | UUID 生成 |
|
||
|
||
## 目录结构
|
||
|
||
```
|
||
mengyastore-backend/
|
||
├── main.go # 程序入口,路由注册
|
||
├── cmd/
|
||
│ └── migrate/
|
||
│ └── main.go # 一次性 JSON→MySQL 数据迁移脚本
|
||
├── data/
|
||
│ └── json/
|
||
│ └── settings.json # 服务配置(adminToken、DSN 等)
|
||
├── internal/
|
||
│ ├── config/
|
||
│ │ └── config.go # 配置加载
|
||
│ ├── database/
|
||
│ │ ├── db.go # GORM 初始化 + AutoMigrate
|
||
│ │ └── models.go # 数据库行结构体(GORM 模型)
|
||
│ ├── models/
|
||
│ │ ├── product.go # 业务模型 Product
|
||
│ │ ├── order.go # 业务模型 Order
|
||
│ │ └── chat.go # 业务模型 ChatMessage
|
||
│ ├── storage/
|
||
│ │ ├── jsonstore.go # 商品存储(GORM 实现)
|
||
│ │ ├── orderstore.go # 订单存储
|
||
│ │ ├── sitestore.go # 站点设置存储
|
||
│ │ ├── wishliststore.go # 收藏夹存储
|
||
│ │ └── chatstore.go # 聊天消息存储(含内存级频率限制)
|
||
│ ├── handlers/
|
||
│ │ ├── admin.go # AdminHandler 结构体 + requireAdmin
|
||
│ │ ├── admin_product.go # 商品 CRUD 接口
|
||
│ │ ├── admin_site.go # 维护模式接口
|
||
│ │ ├── admin_orders.go # 订单管理接口
|
||
│ │ ├── admin_chat.go # 管理员聊天接口
|
||
│ │ ├── public.go # 公开接口(商品列表、浏览量)
|
||
│ │ ├── order.go # 下单、确认订单接口
|
||
│ │ ├── stats.go # 统计信息接口
|
||
│ │ ├── wishlist.go # 收藏夹接口(用户)
|
||
│ │ └── chat.go # 聊天接口(用户)
|
||
│ └── auth/
|
||
│ └── sproutgate.go # SproutGate OAuth 客户端
|
||
```
|
||
|
||
## API 路由一览
|
||
|
||
### 公开接口
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/api/health` | 健康检查 |
|
||
| GET | `/api/products` | 获取商品列表(仅 active) |
|
||
| POST | `/api/products/:id/view` | 记录商品浏览量 |
|
||
| GET | `/api/stats` | 获取总订单数和总访问量 |
|
||
| POST | `/api/site/visit` | 记录站点访问 |
|
||
| GET | `/api/site/maintenance` | 获取维护状态 |
|
||
| POST | `/api/checkout` | 创建订单(生成支付二维码) |
|
||
| GET | `/api/orders` | 获取当前用户订单(需 Bearer token) |
|
||
| POST | `/api/orders/:id/confirm` | 确认付款(触发发货) |
|
||
|
||
### 收藏夹(需登录)
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/api/wishlist` | 获取收藏商品 ID 列表 |
|
||
| POST | `/api/wishlist` | 添加收藏 |
|
||
| DELETE | `/api/wishlist/:id` | 取消收藏 |
|
||
|
||
### 聊天(需登录)
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/api/chat/messages` | 获取自己的聊天记录 |
|
||
| POST | `/api/chat/messages` | 发送消息(1 秒频率限制) |
|
||
|
||
### 管理员接口(需 `?token=xxx` 或 `Authorization: <token>`)
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/api/admin/token` | 获取令牌(用于验证) |
|
||
| GET | `/api/admin/products` | 获取全部商品(含卡密) |
|
||
| POST | `/api/admin/products` | 创建商品 |
|
||
| PUT | `/api/admin/products/:id` | 编辑商品 |
|
||
| PATCH | `/api/admin/products/:id/status` | 切换上下架 |
|
||
| DELETE | `/api/admin/products/:id` | 删除商品 |
|
||
| POST | `/api/admin/site/maintenance` | 设置维护模式 |
|
||
| GET | `/api/admin/orders` | 获取全部订单 |
|
||
| DELETE | `/api/admin/orders/:id` | 删除订单 |
|
||
| GET | `/api/admin/chat` | 获取全部用户对话 |
|
||
| GET | `/api/admin/chat/:account` | 获取指定用户对话 |
|
||
| POST | `/api/admin/chat/:account` | 管理员回复 |
|
||
| DELETE | `/api/admin/chat/:account` | 清除对话 |
|
||
|
||
## 数据库表结构
|
||
|
||
### products
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | varchar(36) | UUID 主键 |
|
||
| name | varchar(255) | 商品名称 |
|
||
| price | double | 原价 |
|
||
| discount_price | double | 折扣价(0 = 无折扣)|
|
||
| tags | json | 标签数组 |
|
||
| cover_url | varchar(500) | 封面图 URL |
|
||
| screenshot_urls | json | 截图 URL 数组(最多 5 张)|
|
||
| verification_url | varchar(500) | 验证链接 |
|
||
| description | text | Markdown 描述 |
|
||
| active | tinyint(1) | 是否上架 |
|
||
| require_login | tinyint(1) | 是否必须登录购买 |
|
||
| max_per_account | bigint | 每账户最大购买数(0=不限)|
|
||
| total_sold | bigint | 累计销量 |
|
||
| view_count | bigint | 累计浏览量 |
|
||
| delivery_mode | varchar(20) | 发货模式:`auto` / `manual` |
|
||
| show_note | tinyint(1) | 下单时显示备注输入框 |
|
||
| show_contact | tinyint(1) | 下单时显示联系方式输入框 |
|
||
| created_at | datetime(3) | 创建时间 |
|
||
|
||
### product_codes
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | bigint unsigned | 自增主键 |
|
||
| product_id | varchar(36) | 关联商品 ID(索引)|
|
||
| code | text | 卡密内容 |
|
||
|
||
### orders
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | varchar(36) | UUID 主键 |
|
||
| product_id | varchar(36) | 商品 ID(索引)|
|
||
| product_name | varchar(255) | 商品名称快照 |
|
||
| user_account | varchar(255) | 用户账号(可空,匿名)|
|
||
| user_name | varchar(255) | 用户昵称 |
|
||
| quantity | bigint | 购买数量 |
|
||
| delivered_codes | json | 已发放卡密 |
|
||
| status | varchar(20) | `pending` / `completed` |
|
||
| delivery_mode | varchar(20) | `auto` / `manual` |
|
||
| note | text | 用户备注 |
|
||
| contact_phone | varchar(50) | 联系手机号 |
|
||
| contact_email | varchar(255) | 联系邮箱 |
|
||
| created_at | datetime(3) | 下单时间 |
|
||
|
||
### site_settings
|
||
|
||
键值对存储,当前使用的键:
|
||
|
||
| Key | 说明 |
|
||
|-----|------|
|
||
| `totalVisits` | 总访问量 |
|
||
| `maintenance` | 维护模式(`true` / `false`)|
|
||
| `maintenanceReason` | 维护原因文本 |
|
||
|
||
### wishlists
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | bigint unsigned | 自增主键 |
|
||
| account_id | varchar(255) | 用户账号(唯一索引)|
|
||
| product_id | varchar(36) | 商品 ID(联合唯一)|
|
||
|
||
### chat_messages
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | varchar(36) | UUID 主键 |
|
||
| account_id | varchar(255) | 用户账号(索引)|
|
||
| account_name | varchar(255) | 用户昵称 |
|
||
| content | text | 消息内容 |
|
||
| sent_at | datetime(3) | 发送时间 |
|
||
| from_admin | tinyint(1) | 是否来自管理员 |
|
||
|
||
## 配置文件
|
||
|
||
`data/json/settings.json`:
|
||
|
||
```json
|
||
{
|
||
"adminToken": "你的管理员令牌",
|
||
"authApiUrl": "https://auth.api.shumengya.top",
|
||
"databaseDsn": ""
|
||
}
|
||
```
|
||
|
||
`databaseDsn` 为空时自动使用测试数据库。也可以通过环境变量 `DATABASE_DSN` 覆盖。
|
||
|
||
## 发货逻辑
|
||
|
||
### 自动发货(`deliveryMode = "auto"`)
|
||
|
||
1. `POST /api/checkout` → 从 `product_codes` 提取指定数量的卡密
|
||
2. 商品 `quantity` 减少,卡密从数据库删除
|
||
3. 卡密保存到订单 `delivered_codes`
|
||
4. 用户 `POST /api/orders/:id/confirm` 确认付款后,订单状态变为 `completed`,响应中返回卡密内容
|
||
5. 同时调用 `IncrementSold` 增加销量统计
|
||
|
||
### 手动发货(`deliveryMode = "manual"`)
|
||
|
||
1. `POST /api/checkout` → 创建订单,不提取卡密
|
||
2. 用户 `POST /api/orders/:id/confirm` 后,订单变为 `completed`,但 `delivered_codes` 为空
|
||
3. 管理员在后台查看订单的备注、手机号、邮箱后手动发货
|
||
|
||
## 本地开发
|
||
|
||
```bash
|
||
go run . # 启动服务(默认 :8080)
|
||
go build -o mengyastore-backend.exe . # 构建可执行文件
|
||
go run ./cmd/migrate/main.go # 迁移旧 JSON 数据到数据库
|
||
```
|
||
|
||
### 切换数据库
|
||
|
||
```bash
|
||
# 测试库(默认)
|
||
# host: 10.1.1.100:3306 / db: mengyastore-test
|
||
|
||
# 生产库
|
||
set DATABASE_DSN=mengyastore:mengyastore@tcp(192.168.1.100:3306)/mengyastore?charset=utf8mb4&parseTime=True&loc=Local
|
||
./mengyastore-backend.exe
|
||
```
|
||
|
||
## 认证说明
|
||
|
||
### 用户认证
|
||
|
||
通过 SproutGate OAuth 服务验证 Bearer Token:
|
||
|
||
```go
|
||
result, err := authClient.VerifyToken(token)
|
||
// result.Valid, result.User.Account, result.User.Username
|
||
```
|
||
|
||
### 管理员认证
|
||
|
||
管理员令牌通过查询参数或 Authorization 头传入:
|
||
|
||
```
|
||
GET /api/admin/products?token=xxx
|
||
Authorization: xxx
|
||
```
|
||
|
||
令牌与 `settings.json` 中的 `adminToken` 比对。
|