Files
mengyastore/mengyastore-backend/README.md

257 lines
8.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 萌芽小店 · 后端
基于 **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` 比对。