refactor(utils): 修复密码哈希比较逻辑错误 feat(user): 新增按状态筛选优惠券接口 docs: 添加虚拟发货与任务中心相关文档 fix(wechat): 修正Code2Session上下文传递问题 test: 补充订单折扣与积分转换测试用例 build: 更新配置文件与构建脚本 style: 清理多余的空行与注释
72 lines
4.0 KiB
Markdown
72 lines
4.0 KiB
Markdown
## 执行逻辑(目标态)
|
||
|
||
### 参与下单(仅创建订单,不开奖)
|
||
- 接口:`POST /api/app/lottery/join`
|
||
- 入参:`activity_id`、`issue_id`、`count`(默认1,≤N)、可选 `client_nonce`
|
||
- 流程:
|
||
- 查询活动单价 `price_draw`;计算 `total_amount = price_draw * count`
|
||
- 查询积分余额;计算需积分 `needPts = ceil(total_amount / 10)`;实际扣减 `usePts = min(balance, needPts)`
|
||
- 写订单:`draw_count = count`、`PointsAmount = usePts * 10`、`ActualAmount = total_amount - PointsAmount`、`Status=1`
|
||
- 当 `ActualAmount == 0` → 将订单置为已支付(`Status=2`、`PaidAt=now`),但不开奖
|
||
- 返回:`order_no`、`draw_mode`、`count`、金额与抵扣细节、`queued`
|
||
|
||
### 预下单(微信 JSAPI)
|
||
- 接口:`POST /api/app/pay/wechat/jsapi/preorder`
|
||
- 校验:订单属于当前用户且 `Status=1`
|
||
- 返回:`wx.requestPayment` 参数;记录 `PaymentPreorders`
|
||
|
||
### 支付回调(入账)
|
||
- 接口:`POST /api/pay/wechat/notify`
|
||
- 行为:验签→记录交易→更新订单 `Status=2(PAID)`、`PaidAt`;幂等事件处理
|
||
- 触发:即时模式下调用 `DrawProcessor`;计划模式下等待调度
|
||
|
||
### 抽奖处理器(按订单维度执行)
|
||
- 输入:`order_id/order_no/activity_id/issue_id/draw_mode/draw_count`
|
||
- 即时模式:
|
||
- 读取已抽次数 `n = count(ActivityDrawLogs where order_id)`
|
||
- 循环 `i=n+1..draw_count`: `SelectItem`→`GrantReward`→`Create(ActivityDrawLogs{draw_index=i})`
|
||
- `completed == draw_count` → 订单标记 `SETTLED`
|
||
- 计划模式:
|
||
- 到 `scheduled_time` 统一处理;参与不足自动退款(先积分、后微信金额),保留现有逻辑
|
||
- 幂等:以上循环按“每订单已存在日志条数”补齐,事务化执行
|
||
|
||
### 统一结果轮询(基于 order_no)
|
||
- 接口:`GET /api/app/lottery/result?order_no=...`
|
||
- 返回:
|
||
- `status`: `pending|paid_waiting|settled|refunded`
|
||
- `draw_mode`、`count`、`completed`、`results[{reward_id,reward_name,level,draw_index}]`
|
||
- `receipt`:`issue_id/seed_version/timestamp/nonce/signature/algorithm`
|
||
- `nextPollMs`(建议2s-5s)
|
||
|
||
## 改造点与文件定位
|
||
- 修改 `JoinLottery`:internal/api/activity/lottery_app.go
|
||
- 增加 `count` 入参;仅下单与积分抵扣;免支付不开奖
|
||
- 保持 `WechatJSAPIPreorder` 不变:internal/api/user/pay_wechat_app.go
|
||
- 扩展回调:在 `WechatNotify` 支付入账后触发即时模式订单的 `DrawProcessor`:internal/api/pay/wechat_notify.go
|
||
- 定时调度按订单 `draw_count` 抽取或退款:internal/service/activity/scheduler.go
|
||
- 新增统一查询接口 `GET /api/app/lottery/result`:新增 handler(internal/api/activity/lottery_result_app.go),挂载到 APP 认证组(internal/router/router.go)
|
||
|
||
## 数据库变更
|
||
- `orders` 新增:`draw_count INT NOT NULL DEFAULT 1`(可选:`draw_mode` 冗余)
|
||
- `activity_draw_logs` 可选新增:`draw_index INT NULL`(记录第几次抽取)
|
||
- 迁移默认值:历史订单填充 `draw_count = 1`
|
||
|
||
## 边界与异常
|
||
- 积分充足:免支付→订单直接 `PAID`;由处理器负责开奖
|
||
- 积分不够/无积分:需支付→入账后再开奖
|
||
- 计划不足:自动退款(积分与金额),订单 `REFUNDED`
|
||
- 并发与幂等:以 `order_id` + 已有日志条数控制,所有扣减与发奖在事务中执行
|
||
|
||
## 前端调用契约
|
||
- 流程:`join` → (可选)`preorder` → 支付 → 轮询 `result` 至 `settled|refunded`
|
||
- 显示:用 `results` 数组展示 N 次抽奖结果;根据 `status` 渲染进度与状态
|
||
|
||
## 测试与验收
|
||
- 单元:积分计算(充足/不够/为0)、N 抽即时/计划模式日志与发奖一致
|
||
- 集成:支付回调幂等、计划不足退款、统一查询状态流转
|
||
- 验收:同一 `order_no` 在两模式下的查询端点返回一致结构与正确状态机;库存扣减准确;退款日志完整
|
||
|
||
## 注意事项
|
||
- `client_nonce`(可选):用于防重复参与提交的客户端幂等键;不影响支付与开奖
|
||
- 安全:JWT校验、签名凭证不泄露种子;所有金额与积分变更审计入库
|