# 订单支付系统功能总结

## 概述

add-order-payment 提案实现了完整的订单和支付流程，核心是"强充"机制：用户不能直接给钱包充值，必须通过购买套餐来充值。这样每笔充值都有对应的套餐购买记录，便于佣金计算和业务追踪。

## 核心功能

### 1. 订单管理

**新增模型**：
- `Order`：订单模型，记录套餐购买信息
- `OrderItem`：订单明细（支持一个订单购买多个套餐）

**订单字段**：
- 订单号、订单类型（单卡购买/设备购买）
- 买家信息（个人客户/代理店铺）
- 关联的卡/设备 ID
- 支付金额、支付状态、支付方式
- 佣金计算状态

**业务流程**：
1. 用户选择套餐，创建订单
2. 用户支付（微信/支付宝/钱包余额）
3. 支付成功后，套餐生效，流量额度增加
4. 触发佣金计算（Phase 5）

### 2. API 端点

**后台管理端** (`/api/admin/orders`):
- `POST /orders` - 创建订单
- `GET /orders` - 获取订单列表（支持分页和筛选）
- `GET /orders/:id` - 获取订单详情
- `POST /orders/:id/cancel` - 取消订单

**H5 端** (`/api/h5/orders`):
- `POST /orders` - 创建订单
- `GET /orders` - 获取订单列表
- `GET /orders/:id` - 获取订单详情
- `POST /orders/:id/wallet-pay` - 钱包支付

**支付回调** (`/api/callback`):
- `POST /wechat-pay` - 微信支付回调
- `POST /alipay` - 支付宝回调

### 3. 业务规则

**购买限制**：
- 只能购买卡/设备关联的套餐系列下的套餐
- 只能购买已上架且启用的套餐
- 设备购买时，套餐分配给设备下所有卡（流量共享）
- 订单金额 = 套餐零售价（代理设置的售价）

**支付流程**：
- 钱包支付：事务扣减余额 → 更新订单状态 → 激活套餐 → 更新销售统计
- 第三方支付：验证签名 → 幂等处理 → 激活套餐 → 更新销售统计

**套餐激活**：
- 创建 PackageUsage 记录
- 更新 ShopSeriesCommissionStats（销售统计）
- 快照佣金配置版本

## 数据库设计

### 表结构

**tb_order**（订单表）：
- `id`, `created_at`, `updated_at`, `deleted_at`
- `creator`, `updater`
- `order_no`（订单号，唯一）
- `order_type`（订单类型：1=单卡购买，2=设备购买）
- `buyer_type`（买家类型：1=个人客户，2=代理店铺）
- `buyer_id`（买家 ID）
- `iot_card_id`（IoT 卡 ID）
- `device_id`（设备 ID）
- `total_amount`（总金额，分）
- `payment_method`（支付方式：1=钱包，2=微信，3=支付宝）
- `payment_status`（支付状态：1=待支付，2=已支付，3=已取消）
- `paid_at`（支付时间）
- `commission_status`（佣金状态：1=未计算，2=已计算）
- `commission_config_version`（佣金配置快照版本）

**tb_order_item**（订单明细表）：
- `id`, `created_at`, `updated_at`, `deleted_at`
- `order_id`（订单 ID）
- `package_id`（套餐 ID）
- `package_name`（套餐名称）
- `quantity`（数量）
- `unit_price`（单价，分）
- `amount`（小计金额，分）

### 索引设计

```sql
-- tb_order
CREATE UNIQUE INDEX idx_order_no ON tb_order(order_no);
CREATE INDEX idx_buyer ON tb_order(buyer_type, buyer_id);
CREATE INDEX idx_payment_status ON tb_order(payment_status);
CREATE INDEX idx_iot_card ON tb_order(iot_card_id);
CREATE INDEX idx_device ON tb_order(device_id);

-- tb_order_item
CREATE INDEX idx_order_id ON tb_order_item(order_id);
CREATE INDEX idx_package_id ON tb_order_item(package_id);
```

## 代码结构

### Store 层

**OrderStore** (`internal/store/postgres/order_store.go`):
- `Create(ctx, order) error` - 创建订单
- `GetByID(ctx, id) (*Order, error)` - 按 ID 查询
- `GetByIDWithItems(ctx, id) (*Order, []OrderItem, error)` - 查询订单及明细
- `GetByOrderNo(ctx, orderNo) (*Order, error)` - 按订单号查询
- `Update(ctx, order) error` - 更新订单
- `UpdatePaymentStatus(ctx, id, status, paidAt) error` - 更新支付状态
- `List(ctx, req) ([]Order, int64, error)` - 分页查询
- `GenerateOrderNo() string` - 生成订单号

**OrderItemStore** (`internal/store/postgres/order_item_store.go`):
- `BatchCreate(ctx, items) error` - 批量创建明细
- `ListByOrderID(ctx, orderID) ([]OrderItem, error)` - 查询订单明细

### Service 层

**PurchaseValidationService** (`internal/service/purchase_validation/service.go`):
- `ValidateCardPurchase(ctx, cardID, packageID) error` - 验证卡购买权限
- `ValidateDevicePurchase(ctx, deviceID, packageID) error` - 验证设备购买权限
- `ValidatePackageStatus(ctx, packageID) error` - 验证套餐状态
- `GetPurchasePrice(ctx, packageID, buyerType, buyerID) (int64, error)` - 获取购买价格

**OrderService** (`internal/service/order/service.go`):
- `Create(ctx, req) (*Order, error)` - 创建订单
- `Get(ctx, id) (*OrderResponse, error)` - 获取订单详情
- `List(ctx, req) ([]OrderResponse, int64, error)` - 获取订单列表
- `Cancel(ctx, id) error` - 取消订单
- `WalletPay(ctx, id, req) error` - 钱包支付
- `HandlePaymentCallback(ctx, orderNo, paymentMethod) error` - 处理支付回调

### Handler 层

**AdminOrderHandler** (`internal/handler/admin/order.go`):
- `Create(c)` - 创建订单
- `Get(c)` - 获取订单详情
- `List(c)` - 获取订单列表
- `Cancel(c)` - 取消订单

**H5OrderHandler** (`internal/handler/h5/order.go`):
- `Create(c)` - 创建订单
- `Get(c)` - 获取订单详情
- `List(c)` - 获取订单列表
- `WalletPay(c)` - 钱包支付

**PaymentCallbackHandler** (`internal/handler/callback/payment.go`):
- `WechatPayCallback(c)` - 微信支付回调
- `AlipayCallback(c)` - 支付宝回调

## 测试覆盖

### 单元测试

**OrderStore 测试** (`order_store_test.go`):
- ✅ 创建订单
- ✅ 按 ID 查询
- ✅ 按 ID 查询（含明细）
- ✅ 按订单号查询
- ✅ 更新订单
- ✅ 更新支付状态
- ✅ 分页查询
- ✅ 生成订单号

**OrderItemStore 测试** (`order_item_store_test.go`):
- ✅ 批量创建明细
- ✅ 查询订单明细

**PurchaseValidationService 测试** (`service_test.go`):
- ✅ 验证卡购买（成功/卡不存在/套餐系列不匹配/套餐未上架）
- ✅ 验证设备购买（成功/设备不存在/套餐系列不匹配）
- ✅ 获取购买价格（个人客户零售价/代理成本价）

**OrderService 测试** (`service_test.go`):
- ✅ 创建单卡订单
- ✅ 创建设备订单
- ✅ 获取订单详情
- ✅ 获取订单列表
- ✅ 取消订单
- ✅ 钱包支付（成功/订单不存在/无权操作/重复支付）

### 集成测试

- ✅ 编译验证：`go build ./...`
- ✅ 服务启动验证
- ✅ OpenAPI 文档生成验证

## 验证结果

### 编译验证
```bash
✅ go build ./... 编译通过
```

### 服务启动
```bash
✅ ./api 启动成功
✅ /health 健康检查通过
```

### OpenAPI 文档
```yaml
✅ /api/admin/orders 路由已生成
✅ /api/h5/orders 路由已生成
✅ /api/callback/wechat-pay 路由已生成
✅ /api/callback/alipay 路由已生成
```

### 测试通过率
```bash
✅ OrderStore 单元测试：8/8 通过
✅ OrderItemStore 单元测试：4/4 通过
✅ PurchaseValidationService 测试：3/3 通过
✅ OrderService 测试：6/6 通过
```

## 使用指南

### 创建订单（单卡购买）

**请求**：
```http
POST /api/h5/orders
Authorization: Bearer {token}
Content-Type: application/json

{
  "order_type": 1,
  "iot_card_id": 101,
  "package_ids": [201, 202]
}
```

**响应**：
```json
{
  "code": 0,
  "data": {
    "id": 1001,
    "order_no": "ORD202601281234567890",
    "order_type": 1,
    "buyer_type": 1,
    "buyer_id": 301,
    "iot_card_id": 101,
    "total_amount": 39900,
    "payment_status": 1,
    "items": [
      {
        "id": 2001,
        "package_id": 201,
        "package_name": "月套餐 3000G",
        "quantity": 1,
        "unit_price": 19900,
        "amount": 19900
      }
    ]
  },
  "msg": "success"
}
```

### 钱包支付

**请求**：
```http
POST /api/h5/orders/1001/wallet-pay
Authorization: Bearer {token}
Content-Type: application/json

{
  "payment_method": 1
}
```

**响应**：
```json
{
  "code": 0,
  "msg": "支付成功"
}
```

### 查询订单列表

**请求**：
```http
GET /api/h5/orders?payment_status=2&page=1&page_size=20
Authorization: Bearer {token}
```

**响应**：
```json
{
  "code": 0,
  "data": {
    "list": [...],
    "total": 100
  },
  "msg": "success"
}
```

## 依赖关系

**依赖**：
- Phase 3（add-card-device-series-binding）- 卡/设备套餐系列关联
- Wallet 模型 - 钱包余额管理

**被依赖**：
- Phase 5（add-one-time-commission）- 一次性佣金计算

## 后续优化

1. **支付集成**：完成微信支付、支付宝支付的真实对接
2. **订单超时**：实现订单超时自动取消机制
3. **支付重试**：处理支付失败的重试逻辑
4. **退款流程**：实现订单退款功能
5. **发票管理**：支持开具电子发票

## 相关文档

- [提案文档](../../openspec/changes/add-order-payment/proposal.md)
- [设计文档](../../openspec/changes/add-order-payment/design.md)
- [任务清单](../../openspec/changes/add-order-payment/tasks.md)
- [项目规范](../../AGENTS.md)
