# Plan: 余额支付退款重复退款优化 ## 背景 余额支付订单退款当前允许同一订单产生多条钱包进账流水,这是合理的:客户投诉、人工补退、重算补退等场景都可能需要追加退款。 本次优化不采用“一单只能插一次”的唯一约束,而是改为累计金额控制: - 同一订单余额退款可以多次发生。 - 累计退款金额不能超过该订单余额支付金额。 - 自动结算重复执行时,只能退到订单当前目标退款金额,不能重复按全量退款。 - 钱包余额更新失败时,不能继续插入钱包流水。 ## 风险点 ### 风险 1:余额退款按全量重算 `balancePaymentOrderRefund` 和 `balancePaymentOrderRefundV2` 当前会按订单支付记录与消费金额重新计算本次退款金额。 如果同一订单已经存在部分退款流水,再次执行时没有按“目标退款金额 - 已退金额”计算差额,存在重复退款风险。 ### 风险 2:钱包更新失败后仍可能插流水 `MemberBasicInfoServiceImpl.updateMemberBalance` 使用 `version` 更新钱包余额,但当更新返回 `0` 时只打印日志,后续仍可能插入 `member_wallet_log`。 这会造成余额与流水不一致,也会影响后续已退款金额判断。 ### 风险 3:balancePaymentOrderRefundV2 无幂等校验 `OrderBasicInfoServiceImpl.balancePaymentOrderRefundV2` 没有已退金额校验,也没有累计退款上限。 重复调用时可能持续向会员钱包退款。 ## 优化原则 1. 不限制同一订单只能插入一条退款流水。 2. 同一订单累计余额退款总额不能超过余额支付总额。 3. 自动结算退款以 `order_basic_info.refund_amount` 作为当前目标退款金额;如果需要客户投诉补退,应先把目标退款金额调整到新的业务目标,且不能超过支付总额。 4. 本金与赠送金分别受各自支付金额上限约束。 5. 钱包余额更新与钱包流水必须保持事务一致。 ## 子任务 ### BR-001 - 优先级:P0 - 状态:done - 目标:补 `balancePaymentOrderRefundV2` 累计退款上限与差额退款。 - 设计: - 查询订单已退本金、已退赠送金。 - 订单目标退款金额取 `min(order.refundAmount, balancePayTotal)`。 - 本次退款金额取 `目标退款金额 - 已退总额` 范围内的金额。 - 本金累计退款不能超过本金支付金额,赠送金累计退款不能超过赠送金支付金额。 - 验收: - 同一订单重复调用 V2,不会超过当前目标退款金额。 - 如果目标退款金额被业务调整变大,可以继续补退,但累计不超过余额支付总额。 ### BR-002 - 优先级:P1 - 状态:done - 目标:统一新旧余额退款逻辑。 - 设计: - 在 `OrderBasicInfoService` 提供统一的余额退款额度裁剪方法。 - `DelayMerchantProgramLogic.balancePaymentOrderRefund`、`NotDelayMerchantProgramLogic.balancePaymentOrderRefund`、`OrderBasicInfoServiceImpl.balancePaymentOrderRefundV2` 都复用同一套累计上限判断。 - 验收: - 三条余额支付退款路径的已退金额口径一致。 ### BR-003 - 优先级:P2 - 状态:done - 目标:修复钱包更新事务一致性。 - 设计: - `updateMemberBalance` 增加事务。 - `memberBasicInfoMapper.updateMemberBalance(...)` 返回 `0` 时抛异常。 - 钱包余额更新失败时不插入 `member_wallet_log`。 - 验收: - 乐观锁失败时不会产生钱包流水。 ### BR-004 - 优先级:P3 - 状态:done - 目标:补充验证。 - 设计: - 编译受影响模块。 - 对重复调用、目标退款金额调整、钱包乐观锁失败做回归验证。 - 验收: - 编译通过,关键路径验证结果记录到本文档。 - 当前进展: - 使用 JDK 8 执行 `mvn -pl jsowell-pile -am compile -DskipTests` 通过。 - 当前默认 JDK 21 执行 Maven 会在 `jsowell-common` 编译阶段触发老 Lombok/javac 兼容性错误,未进入本次改动编译。 ## 执行日志 - 2026-06-15:创建优化方案文档,开始执行 BR-001。 - 2026-06-15:BR-001 已完成,`balancePaymentOrderRefundV2` 接入累计退款额度裁剪。 - 2026-06-15:开始执行 BR-002,统一新旧余额退款路径的累计校验口径。 - 2026-06-15:BR-002 已完成,延迟、非延迟和 V2 余额退款路径复用同一套额度裁剪逻辑。 - 2026-06-15:BR-003 已完成,`updateMemberBalance` 增加事务,钱包余额更新失败时抛异常并阻止插入流水。 - 2026-06-15:开始执行 BR-004,进行编译检查。 - 2026-06-15:BR-004 已完成,JDK 8 环境下受影响模块编译通过。