feat: 实现代理钱包订单创建和订单角色追踪功能
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m0s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m0s
新增功能: - 代理在后台使用 wallet 支付时,订单直接完成(扣款 + 激活套餐) - 支持代理自购和代理代购场景 - 新增订单角色追踪字段(operator_id、operator_type、actual_paid_amount、purchase_role) - 订单查询支持 OR 逻辑(buyer_id 或 operator_id) - 钱包流水记录交易子类型和关联店铺 - 佣金逻辑调整:代理代购不产生佣金 数据库变更: - 订单表新增 4 个字段和 2 个索引 - 钱包流水表新增 2 个字段 - 包含迁移脚本和回滚脚本 文档: - 功能总结文档 - 部署指南 - OpenAPI 文档更新 - Specs 同步(新增 agent-order-role-tracking capability) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
538
docs/fix-agent-wallet-order-creation/部署指南.md
Normal file
538
docs/fix-agent-wallet-order-creation/部署指南.md
Normal file
@@ -0,0 +1,538 @@
|
||||
# 代理钱包订单创建功能部署指南
|
||||
|
||||
## 部署前检查清单
|
||||
|
||||
### 代码检查
|
||||
|
||||
- [x] 编译通过:`go build ./...`
|
||||
- [x] OpenAPI 文档更新:`go run cmd/gendocs/main.go`
|
||||
- [ ] 测试环境验证通过
|
||||
- [ ] Code Review 通过
|
||||
|
||||
### 数据库准备
|
||||
|
||||
- [ ] 测试环境迁移脚本执行成功
|
||||
- [ ] 生产环境数据库备份完成
|
||||
- [ ] 回滚脚本准备完毕
|
||||
|
||||
---
|
||||
|
||||
## 数据库迁移
|
||||
|
||||
### 迁移脚本清单
|
||||
|
||||
**脚本位置**:`migrations/`
|
||||
|
||||
| 序号 | 文件名 | 说明 | 执行时间 |
|
||||
|------|--------|------|----------|
|
||||
| 000067 | `add_operator_fields_to_orders.up.sql` | 订单表新增字段和索引 | < 5 秒 |
|
||||
| 000068 | `add_transaction_subtype_to_wallet_transaction.up.sql` | 钱包流水表新增字段 | < 1 秒 |
|
||||
|
||||
**回滚脚本**:
|
||||
| 序号 | 文件名 | 说明 |
|
||||
|------|--------|------|
|
||||
| 000067 | `add_operator_fields_to_orders.down.sql` | 删除订单表字段和索引 |
|
||||
| 000068 | `add_transaction_subtype_to_wallet_transaction.down.sql` | 删除钱包流水表字段 |
|
||||
|
||||
---
|
||||
|
||||
### 迁移执行步骤
|
||||
|
||||
#### 步骤 1:备份数据库
|
||||
|
||||
```bash
|
||||
# 生产环境数据库备份
|
||||
pg_dump -h <host> -U <user> -d junhong_cmp -F c -b -v -f "backup_$(date +%Y%m%d_%H%M%S).dump"
|
||||
```
|
||||
|
||||
**验证备份**:
|
||||
```bash
|
||||
pg_restore --list backup_*.dump | head -20
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 步骤 2:执行迁移(测试环境)
|
||||
|
||||
**使用 migrate 工具**:
|
||||
```bash
|
||||
# 切换到项目目录
|
||||
cd /path/to/junhong_cmp_fiber
|
||||
|
||||
# 执行迁移
|
||||
migrate -path migrations -database "postgresql://<user>:<password>@<host>:<port>/junhong_cmp?sslmode=disable" up
|
||||
|
||||
# 验证迁移版本
|
||||
migrate -path migrations -database "postgresql://<user>:<password>@<host>:<port>/junhong_cmp?sslmode=disable" version
|
||||
```
|
||||
|
||||
**手动执行(可选)**:
|
||||
```bash
|
||||
# 连接数据库
|
||||
psql -h <host> -U <user> -d junhong_cmp
|
||||
|
||||
# 执行迁移脚本
|
||||
\i migrations/000067_add_operator_fields_to_orders.up.sql
|
||||
\i migrations/000068_add_transaction_subtype_to_wallet_transaction.up.sql
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 步骤 3:验证迁移结果
|
||||
|
||||
**检查字段**:
|
||||
```sql
|
||||
-- 验证订单表字段
|
||||
\d tb_order
|
||||
|
||||
-- 预期输出包含:
|
||||
-- operator_id | integer | | |
|
||||
-- operator_type | character varying(20) | | |
|
||||
-- actual_paid_amount | bigint | | |
|
||||
-- purchase_role | character varying(50) | | |
|
||||
```
|
||||
|
||||
**检查索引**:
|
||||
```sql
|
||||
-- 验证索引
|
||||
SELECT indexname, indexdef
|
||||
FROM pg_indexes
|
||||
WHERE tablename = 'tb_order'
|
||||
AND indexname IN ('idx_orders_operator_id', 'idx_orders_purchase_role');
|
||||
|
||||
-- 预期输出:
|
||||
-- idx_orders_operator_id | CREATE INDEX idx_orders_operator_id ON public.tb_order USING btree (operator_id)
|
||||
-- idx_orders_purchase_role | CREATE INDEX idx_orders_purchase_role ON public.tb_order USING btree (purchase_role)
|
||||
```
|
||||
|
||||
**检查钱包流水表**:
|
||||
```sql
|
||||
-- 验证钱包流水表字段
|
||||
\d tb_agent_wallet_transaction
|
||||
|
||||
-- 预期输出包含:
|
||||
-- transaction_subtype | character varying(50) | | |
|
||||
-- related_shop_id | integer | | |
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 步骤 4:数据回填(可选)
|
||||
|
||||
**回填历史订单**:
|
||||
```bash
|
||||
psql -h <host> -U <user> -d junhong_cmp -f migrations/backfill_order_purchase_role.sql
|
||||
```
|
||||
|
||||
**验证回填结果**:
|
||||
```sql
|
||||
SELECT purchase_role, operator_type, COUNT(*) as count
|
||||
FROM tb_order
|
||||
WHERE purchase_role IS NOT NULL
|
||||
GROUP BY purchase_role, operator_type;
|
||||
|
||||
-- 预期输出示例:
|
||||
-- purchased_by_platform | platform | 1234
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 步骤 5:执行迁移(生产环境)
|
||||
|
||||
**时间窗口**:选择低峰期(凌晨 2:00 - 4:00)
|
||||
|
||||
**执行命令**(与测试环境相同):
|
||||
```bash
|
||||
migrate -path migrations -database "postgresql://<prod_host>:<prod_port>/<db>?sslmode=require" up
|
||||
```
|
||||
|
||||
**监控指标**:
|
||||
- 迁移执行时间
|
||||
- 索引创建时间(CONCURRENTLY,不锁表)
|
||||
- 数据库连接数
|
||||
- 慢查询日志
|
||||
|
||||
---
|
||||
|
||||
### 回滚步骤
|
||||
|
||||
**场景**:迁移失败或发现严重 Bug
|
||||
|
||||
#### 步骤 1:停止应用
|
||||
|
||||
```bash
|
||||
# 停止应用服务
|
||||
systemctl stop junhong-cmp-api
|
||||
```
|
||||
|
||||
#### 步骤 2:执行回滚
|
||||
|
||||
```bash
|
||||
# 回滚到上一版本
|
||||
migrate -path migrations -database "postgresql://<host>:<port>/<db>?sslmode=disable" down 2
|
||||
```
|
||||
|
||||
**或手动执行回滚脚本**:
|
||||
```bash
|
||||
psql -h <host> -U <user> -d junhong_cmp <<EOF
|
||||
\i migrations/000068_add_transaction_subtype_to_wallet_transaction.down.sql
|
||||
\i migrations/000067_add_operator_fields_to_orders.down.sql
|
||||
EOF
|
||||
```
|
||||
|
||||
#### 步骤 3:验证回滚
|
||||
|
||||
```sql
|
||||
-- 验证字段已删除
|
||||
\d tb_order
|
||||
\d tb_agent_wallet_transaction
|
||||
|
||||
-- 验证索引已删除
|
||||
SELECT indexname FROM pg_indexes WHERE tablename = 'tb_order';
|
||||
```
|
||||
|
||||
#### 步骤 4:恢复应用(旧版本代码)
|
||||
|
||||
```bash
|
||||
# 回滚代码到上一版本
|
||||
git checkout <previous_commit>
|
||||
|
||||
# 重新编译
|
||||
go build -o api cmd/api/main.go
|
||||
|
||||
# 启动应用
|
||||
systemctl start junhong-cmp-api
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 代码部署
|
||||
|
||||
### 灰度发布计划
|
||||
|
||||
**阶段 1:灰度服务器(10% 流量)**
|
||||
|
||||
**时间**:低峰期(周一至周五 02:00 - 04:00)
|
||||
|
||||
**步骤**:
|
||||
1. 部署代码到灰度服务器
|
||||
2. 切换 10% 流量到灰度服务器
|
||||
3. 观察 2 小时,监控关键指标
|
||||
4. 手工测试代理自购、代理代购场景
|
||||
|
||||
**验证项**:
|
||||
- [ ] 应用启动成功
|
||||
- [ ] 健康检查通过:`curl http://localhost:8080/health`
|
||||
- [ ] 订单创建成功率 > 95%
|
||||
- [ ] 钱包扣款成功率 > 99%
|
||||
- [ ] 无严重错误日志
|
||||
|
||||
---
|
||||
|
||||
**阶段 2:全量发布(100% 流量)**
|
||||
|
||||
**时间**:灰度验证通过后 24 小时
|
||||
|
||||
**步骤**:
|
||||
1. 部署代码到所有服务器
|
||||
2. 逐步切换流量(20% → 50% → 100%)
|
||||
3. 持续监控 24 小时
|
||||
|
||||
**验证项**:
|
||||
- [ ] 所有服务器应用启动成功
|
||||
- [ ] 订单创建成功率 > 95%
|
||||
- [ ] 钱包扣款成功率 > 99%
|
||||
- [ ] 错误日志无异常峰值
|
||||
- [ ] 用户反馈无异常
|
||||
|
||||
---
|
||||
|
||||
### 发布命令
|
||||
|
||||
**构建**:
|
||||
```bash
|
||||
# 构建二进制文件
|
||||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o api cmd/api/main.go
|
||||
|
||||
# 验证版本
|
||||
./api --version
|
||||
```
|
||||
|
||||
**部署**:
|
||||
```bash
|
||||
# 停止服务
|
||||
systemctl stop junhong-cmp-api
|
||||
|
||||
# 备份旧版本
|
||||
cp /opt/junhong-cmp/api /opt/junhong-cmp/api.backup
|
||||
|
||||
# 替换新版本
|
||||
cp api /opt/junhong-cmp/api
|
||||
|
||||
# 启动服务
|
||||
systemctl start junhong-cmp-api
|
||||
|
||||
# 检查状态
|
||||
systemctl status junhong-cmp-api
|
||||
```
|
||||
|
||||
**验证**:
|
||||
```bash
|
||||
# 健康检查
|
||||
curl http://localhost:8080/health
|
||||
|
||||
# 查看日志
|
||||
journalctl -u junhong-cmp-api -f
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 监控指标
|
||||
|
||||
### 关键业务指标
|
||||
|
||||
**订单创建**:
|
||||
- 订单创建成功率(总体)
|
||||
- 订单创建成功率(按 payment_method 分组)
|
||||
- 订单创建耗时(P50、P95、P99)
|
||||
- 订单创建 QPS
|
||||
|
||||
**钱包扣款**:
|
||||
- 钱包扣款成功率
|
||||
- 钱包扣款失败原因分布(余额不足、并发冲突、其他)
|
||||
- 钱包余额不足次数
|
||||
|
||||
**订单查询**:
|
||||
- 订单列表查询耗时(P95)
|
||||
- OR 查询性能(慢查询日志)
|
||||
|
||||
---
|
||||
|
||||
### 错误日志监控
|
||||
|
||||
**关键错误**:
|
||||
```bash
|
||||
# 余额不足
|
||||
grep "余额不足" /var/log/junhong-cmp/app.log | wc -l
|
||||
|
||||
# 并发冲突
|
||||
grep "并发冲突" /var/log/junhong-cmp/app.log | wc -l
|
||||
|
||||
# 套餐激活失败
|
||||
grep "套餐激活失败" /var/log/junhong-cmp/app.log | wc -l
|
||||
|
||||
# 成本价查询失败
|
||||
grep "店铺没有该套餐的分配配置" /var/log/junhong-cmp/app.log | wc -l
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 数据库性能监控
|
||||
|
||||
**慢查询**:
|
||||
```sql
|
||||
-- 查看慢查询
|
||||
SELECT query, calls, total_time, mean_time
|
||||
FROM pg_stat_statements
|
||||
WHERE query LIKE '%tb_order%'
|
||||
AND mean_time > 100
|
||||
ORDER BY mean_time DESC
|
||||
LIMIT 10;
|
||||
```
|
||||
|
||||
**索引使用率**:
|
||||
```sql
|
||||
-- 检查新索引是否被使用
|
||||
SELECT schemaname, tablename, indexname, idx_scan, idx_tup_read, idx_tup_fetch
|
||||
FROM pg_stat_user_indexes
|
||||
WHERE indexname IN ('idx_orders_operator_id', 'idx_orders_purchase_role');
|
||||
```
|
||||
|
||||
**OR 查询性能**:
|
||||
```sql
|
||||
-- EXPLAIN 分析
|
||||
EXPLAIN ANALYZE
|
||||
SELECT * FROM tb_order
|
||||
WHERE (buyer_type = 'agent' AND buyer_id = 10) OR operator_id = 10
|
||||
LIMIT 20;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 告警规则
|
||||
|
||||
**业务告警**:
|
||||
| 指标 | 阈值 | 级别 |
|
||||
|------|------|------|
|
||||
| 订单创建成功率 | < 95% | P1 |
|
||||
| 钱包扣款成功率 | < 99% | P1 |
|
||||
| 订单创建耗时 P99 | > 1000ms | P2 |
|
||||
| 并发冲突次数 | > 100/分钟 | P2 |
|
||||
| 余额不足次数 | > 500/小时 | P3 |
|
||||
|
||||
**系统告警**:
|
||||
| 指标 | 阈值 | 级别 |
|
||||
|------|------|------|
|
||||
| 应用进程退出 | - | P0 |
|
||||
| 数据库连接数 | > 80% | P1 |
|
||||
| 慢查询(订单相关) | > 1000ms | P2 |
|
||||
|
||||
---
|
||||
|
||||
## 验证测试
|
||||
|
||||
### 功能验证清单
|
||||
|
||||
**代理自购**:
|
||||
- [ ] 创建订单成功
|
||||
- [ ] 钱包余额正确扣减
|
||||
- [ ] 订单状态为已支付
|
||||
- [ ] 套餐已激活
|
||||
- [ ] 钱包流水记录正确(transaction_subtype = "self_purchase")
|
||||
- [ ] 订单响应字段完整(operator_id、purchase_role 等)
|
||||
|
||||
**代理代购**:
|
||||
- [ ] 创建订单成功
|
||||
- [ ] 钱包余额按操作者成本价扣减
|
||||
- [ ] 订单金额显示买家成本价
|
||||
- [ ] actual_paid_amount 为操作者成本价
|
||||
- [ ] 套餐已激活
|
||||
- [ ] 钱包流水记录正确(transaction_subtype = "purchase_for_subordinate"、related_shop_id、remark 包含店铺名称)
|
||||
- [ ] 未产生佣金记录
|
||||
|
||||
**平台代购**:
|
||||
- [ ] 创建订单成功
|
||||
- [ ] 钱包余额未扣减
|
||||
- [ ] 订单状态为已支付
|
||||
- [ ] 套餐已激活
|
||||
- [ ] 产生佣金记录
|
||||
- [ ] purchase_role = "purchased_by_platform"
|
||||
|
||||
**订单查询**:
|
||||
- [ ] 代理可查询作为买家或操作者的订单
|
||||
- [ ] purchase_role 筛选生效
|
||||
- [ ] 订单列表响应包含新字段
|
||||
|
||||
**边界场景**:
|
||||
- [ ] 余额不足时返回明确错误
|
||||
- [ ] 并发扣款时乐观锁生效
|
||||
- [ ] 幂等性检查防止重复创建
|
||||
- [ ] H5 端 wallet 订单不受影响(仍为待支付)
|
||||
|
||||
---
|
||||
|
||||
### 性能验证
|
||||
|
||||
**压力测试**(可选):
|
||||
```bash
|
||||
# 订单创建并发测试
|
||||
ab -n 1000 -c 50 -H "Authorization: Bearer <token>" \
|
||||
-p order_request.json \
|
||||
-T "application/json" \
|
||||
http://localhost:8080/api/admin/orders
|
||||
|
||||
# 订单列表查询性能测试
|
||||
ab -n 5000 -c 100 -H "Authorization: Bearer <token>" \
|
||||
http://localhost:8080/api/admin/orders?page=1&page_size=20
|
||||
```
|
||||
|
||||
**预期结果**:
|
||||
- 订单创建 QPS > 50
|
||||
- 订单创建 P95 < 200ms
|
||||
- 订单列表查询 P95 < 100ms
|
||||
|
||||
---
|
||||
|
||||
## 回滚预案
|
||||
|
||||
### 回滚触发条件
|
||||
|
||||
满足以下任一条件时立即回滚:
|
||||
- 订单创建成功率 < 90%(持续 5 分钟)
|
||||
- 钱包扣款成功率 < 95%(持续 5 分钟)
|
||||
- 发现严重 Bug(如:重复扣款、金额计算错误、数据丢失)
|
||||
- 用户投诉量激增
|
||||
|
||||
---
|
||||
|
||||
### 快速回滚步骤
|
||||
|
||||
**步骤 1:立即回滚代码**(< 5 分钟)
|
||||
|
||||
```bash
|
||||
# 停止服务
|
||||
systemctl stop junhong-cmp-api
|
||||
|
||||
# 恢复旧版本
|
||||
cp /opt/junhong-cmp/api.backup /opt/junhong-cmp/api
|
||||
|
||||
# 启动服务
|
||||
systemctl start junhong-cmp-api
|
||||
```
|
||||
|
||||
**步骤 2:回滚数据库**(可选,< 10 分钟)
|
||||
|
||||
仅当数据异常时执行:
|
||||
```bash
|
||||
# 执行回滚脚本
|
||||
migrate -path migrations -database "..." down 2
|
||||
```
|
||||
|
||||
**步骤 3:验证回滚成功**
|
||||
|
||||
- [ ] 应用启动成功
|
||||
- [ ] 健康检查通过
|
||||
- [ ] 订单创建成功率恢复
|
||||
- [ ] 用户反馈恢复正常
|
||||
|
||||
---
|
||||
|
||||
## 上线后观察
|
||||
|
||||
### 观察期(7 天)
|
||||
|
||||
**每日检查**:
|
||||
- [ ] 订单创建成功率
|
||||
- [ ] 钱包扣款成功率
|
||||
- [ ] 错误日志无异常
|
||||
- [ ] 用户反馈无异常
|
||||
- [ ] 数据库慢查询无新增
|
||||
|
||||
**周报总结**:
|
||||
- 订单创建总量、成功率
|
||||
- 钱包扣款总量、成功率
|
||||
- 代理自购 vs 代理代购占比
|
||||
- 错误类型分布
|
||||
- 性能指标趋势
|
||||
|
||||
---
|
||||
|
||||
## 联系人
|
||||
|
||||
**技术负责人**:[姓名]
|
||||
**运维负责人**:[姓名]
|
||||
**产品负责人**:[姓名]
|
||||
|
||||
**紧急联系方式**:
|
||||
- 技术值班电话:[电话]
|
||||
- 运维值班电话:[电话]
|
||||
|
||||
---
|
||||
|
||||
## 附录
|
||||
|
||||
### 相关文档
|
||||
|
||||
- [功能总结](./功能总结.md)
|
||||
- [提案文档](../../openspec/changes/fix-agent-wallet-order-creation/proposal.md)
|
||||
- [设计文档](../../openspec/changes/fix-agent-wallet-order-creation/design.md)
|
||||
- [任务清单](../../openspec/changes/fix-agent-wallet-order-creation/tasks.md)
|
||||
|
||||
### 迁移脚本内容
|
||||
|
||||
详见 `migrations/` 目录:
|
||||
- `000067_add_operator_fields_to_orders.up.sql`
|
||||
- `000067_add_operator_fields_to_orders.down.sql`
|
||||
- `000068_add_transaction_subtype_to_wallet_transaction.up.sql`
|
||||
- `000068_add_transaction_subtype_to_wallet_transaction.down.sql`
|
||||
- `backfill_order_purchase_role.sql`
|
||||
Reference in New Issue
Block a user