refactor(utils): 修复密码哈希比较逻辑错误 feat(user): 新增按状态筛选优惠券接口 docs: 添加虚拟发货与任务中心相关文档 fix(wechat): 修正Code2Session上下文传递问题 test: 补充订单折扣与积分转换测试用例 build: 更新配置文件与构建脚本 style: 清理多余的空行与注释
4.0 KiB
4.0 KiB
执行逻辑(目标态)
参与下单(仅创建订单,不开奖)
- 接口:
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|refundeddraw_mode、count、completed、results[{reward_id,reward_name,level,draw_index}]receipt:issue_id/seed_version/timestamp/nonce/signature/algorithmnextPollMs(建议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校验、签名凭证不泄露种子;所有金额与积分变更审计入库