# JD Cookie 订单管理模块

## 📁 文件结构

```
jd_cookie/
├── account.go          # Cookie 账户管理
├── history.go          # 历史记录管理
├── index.go            # 服务注册
├── order_create.go     # 订单创建逻辑（带重试机制）
├── order_query.go      # 订单查询逻辑
├── order_jd.go         # 京东订单管理逻辑
├── order_utils.go      # 订单工具方法
├── order_test.go       # 测试文件
└── rotation.go         # Cookie 轮询
```

## 🎯 核心功能

### 1. 订单创建（带重试机制）

**文件**：[order_create.go](order_create.go)

**主要方法**：

- `CreateOrder()` - 创建订单主入口
- `createNewJdOrderWithRetry()` - 带重试的京东订单创建

**流程**：

```
1. 检查订单是否已存在 → 已存在返回支付链接
2. 尝试复用现有京东订单
   ├─ 支付链接未过期 → 直接复用
   ├─ 支付链接已过期 → 尝试刷新
   │  ├─ 刷新成功 → 使用新链接
   │  └─ 刷新失败 → 标记失效，创建新订单
   └─ 无可复用订单 → 创建新订单
3. 创建新订单时启用重试机制
   ├─ 最多重试 10 次
   ├─ 每次失败自动切换 Cookie
   └─ 记录所有尝试过的 Cookie
```

**重试机制详解**：

```go
// 示例：创建订单时的重试流程
orderId := "ORDER123"
amount := 100.0
category := consts.ProductCategoryApple

// 调用创建订单
createOrderReq := &model.CreateOrderReq{
    UserOrderId: orderId,
    Amount:      amount,
    Category:    category,
}
result, err := service.CreateOrder(ctx, createOrderReq)
if err != nil {
    // 所有 Cookie 都失败，返回错误
    // 错误信息会包含：已尝试的 Cookie 数量
    return err
}
wxPayUrl := result.WxPayUrl
jdOrderId := result.JdOrderId

// 成功返回支付链接
```

**内部重试逻辑**：

```go
func createNewJdOrderWithRetry(...) {
    const maxRetryCount = 10
    var triedCookies []string
    
    for retryCount := 0; retryCount < maxRetryCount; retryCount++ {
        // 1. 获取可用 Cookie
        cookieId, err := GetAvailableCookie(ctx)
        if err != nil {
            break // 无可用 Cookie，停止重试
        }
        
        // 2. 检查是否已尝试过
        if hasCookieBeenTried(triedCookies, cookieId) {
            continue
        }
        
        // 3. 记录已尝试
        triedCookies = append(triedCookies, cookieId)
        
        // 4. 调用京东下单
        jdOrderId, payId, wxPayUrl, err := callJdCreateOrder(ctx, cookieId, amount, category)
        if err != nil {
            // 失败：更新 Cookie 状态，继续下一次重试
            handleCookieFailure(ctx, cookieId, orderId)
            continue
        }
        
        // 5. 成功：创建订单记录并返回
        createJdOrderRecord(...)
        return jdOrderId, cookieId, wxPayUrl, nil
    }
    
    // 所有重试失败
    return "", "", "", error
}
```

### 2. 订单查询

**文件**：[order_query.go](order_query.go)

**主要方法**：

- `GetOrder()` - 获取单个订单
- `ListOrder()` - 订单列表查询
- `GetOrderStatus()` - 查询订单状态
- `GetPaymentUrl()` - 获取支付链接

**示例**：

```go
// 获取订单信息
order, err := service.GetOrder(ctx, "ORDER123")
if err != nil {
    return err
}

// 获取支付链接
wxPayUrl, expireTime, jdOrderId, err := service.GetPaymentUrl(ctx, "ORDER123")
```

### 3. 京东订单管理

**文件**：[order_jd.go](order_jd.go)

**主要方法**：

- `GetJdOrder()` - 获取京东订单
- `ListJdOrder()` - 京东订单列表
- `CheckJdOrderPayment()` - 检查支付状态
- `ExtractCardInfo()` - 提取卡密信息
- `BatchCheckPaymentStatus()` - 批量检查支付状态（定时任务）
- `CleanupExpiredOrders()` - 清理过期订单（定时任务）
- `ReleaseExpiredJdOrders()` - 释放过期订单关联（定时任务）

**定时任务**：

```go
// 批量检查支付状态（建议每 5 分钟执行）
err := service.BatchCheckPaymentStatus(ctx)

// 清理过期订单（建议每小时执行）
err := service.CleanupExpiredOrders(ctx)

// 释放过期订单关联（建议每 10 分钟执行）
err := service.ReleaseExpiredJdOrders(ctx)
```

### 4. 工具方法

**文件**：[order_utils.go](order_utils.go)

**内部方法**（不对外暴露）：

- 数据库查询：`getOrderByOrderId()`, `getJdOrderByJdOrderId()`, `getCookieById()`
- 数据库更新：`createJdOrderRecord()`, `createOrderRecord()`, `updateOrderLastRequest()`
- 京东接口：`callJdCreateOrder()`, `refreshPaymentUrl()`, `callJdCheckPayment()`
- Cookie 处理：`handleCookieFailure()`

## 🔧 配置常量

在 `internal/consts/jd_cookie.go` 中定义：

```go
const (
    JdCookieMaxFailureCount = 3    // Cookie 最大失败次数
    JdCookieSuspendDuration = 10   // Cookie 暂停时长（分钟）
    JdOrderExpireDuration   = 24   // 京东订单过期时间（小时）
    WxPayUrlExpireDuration  = 3    // 微信支付链接过期时间（分钟）
    JdOrderReuseTimeout     = 30   // 京东订单复用超时时间（分钟）
)
```

## 📊 状态流转

### Cookie 状态

```
创建 → 正常 ⇄ 暂停 → 失效
              ↓
            删除
```

### 京东订单状态

```
待支付 → 已支付 → 已发货
  ↓
已过期/已取消
```

### 用户订单状态

```
待支付 → 已支付
  ↓
已过期/已取消
```

## 🚨 错误处理

### Cookie 失败处理

```go
// 自动处理流程：
1. 失败次数 +1
2. 失败次数 < 3 → 状态改为"暂停"，10 分钟后自动恢复
3. 失败次数 >= 3 → 状态改为"失效"
4. 记录失败历史
```

### 订单创建失败

```go
// 重试机制：
1. 尝试 Cookie 1 → 失败 → 暂停 Cookie 1
2. 尝试 Cookie 2 → 失败 → 暂停 Cookie 2
3. ...
4. 尝试 Cookie 10 → 失败 → 返回错误
```

## 📝 历史记录

所有重要操作都会记录历史：

### Cookie 变更历史

- 创建 (create)
- 使用 (use)
- 暂停 (suspend)
- 恢复 (resume)
- 失败 (fail)
- **刷新失败 (refresh_fail)** - 新增
- **被替换 (replaced)** - 新增
- 删除 (delete)
- 更新 (update)

### 京东订单变更历史

- 创建 (create)
- 绑定 (bind)
- 解绑 (unbind)
- 支付 (pay)
- 过期 (expire)
- **失效 (invalid)** - 新增
- 替换 (replace)

### 用户订单变更历史

- 创建 (create)
- 绑定 (bind)
- 支付 (pay)
- 过期 (expire)
- 重新绑定 (rebind)

## 🧪 测试

运行测试：

```bash
go test ./internal/logic/jd_cookie/... -v
```

测试覆盖：

- ✅ 卡密提取判断逻辑
- ✅ 批量检查配置验证
- ✅ 缓存键生成

## 🔍 日志示例

### 订单创建成功

```
[INFO] 复用现有京东订单 {"orderId":"ORDER123","jdOrderId":"JD456","cookieId":"COOKIE789"}
[INFO] 创建订单记录成功 {"orderId":"ORDER123","amount":100,"jdOrderId":"JD456"}
```

### 刷新支付链接失败

```
[WARN] 刷新支付链接失败，将创建新订单 {"jdOrderId":"JD456","error":"刷新失败"}
[INFO] 创建京东订单成功 {"orderId":"ORDER123","jdOrderId":"JD789","cookieId":"COOKIE999","retryCount":1}
```

### Cookie 重试

```
[WARN] 京东下单失败，尝试切换Cookie重试 {"orderId":"ORDER123","cookieId":"COOKIE1","retryCount":0,"error":"下单失败"}
[WARN] 京东下单失败，尝试切换Cookie重试 {"orderId":"ORDER123","cookieId":"COOKIE2","retryCount":1,"error":"下单失败"}
[INFO] 创建京东订单成功 {"orderId":"ORDER123","jdOrderId":"JD789","cookieId":"COOKIE3","retryCount":2}
```

## 📚 相关文档

- [重构报告](../../JD_ORDER_CREATE_REFACTOR_REPORT.md) - 详细的重构说明
- [重构总结](../../ORDER_REFACTOR_SUMMARY.md) - 重构总结
- [项目架构](../../README.md) - 整体项目架构

---

**最后更新**：2025-10-11
