## 现状与审计结论 - 积分存储:`user_points` 余额、`user_points_ledger` 流水;订单字段 `orders.points_amount`(分)存在但未在支付链路写入。 - 转换比率存在两套并存: - 1元=10积分:`internal/api/user/points_redeem_product_app.go:55-60`、`internal/api/user/points_redeem_coupon_app.go:55-61`、展示与调度退款部分。 - 1元=100积分:退款按比例恢复:`internal/api/admin/pay_refund_admin.go:133-167`;以及金额退款流水:`internal/api/admin/pay_refund_admin.go:158-167` 与 `internal/api/admin/lottery_admin.go:131`。 - 统一配置已存在但未全面使用:`points_exchange_per_cent`(每分对应的积分),在资产兑换中生效:`internal/service/user/address_share.go:137-147,175-183,198-199`。 - 支付回调未联动积分:`internal/api/pay/wechat_notify.go:133-141` 仅更新订单与券,不处理 `points_amount/points_ledger_id`。 - 管理端订单详情积分展示按 /10:`internal/api/admin/pay_orders_admin.go:366-372`。 - 调度器退款按 /10 恢复:`internal/service/activity/scheduler.go:80-83`。 ## 目标与边界 - 统一换算:严格执行“1元=100积分”,即“分→积分除以100”,或统一通过 `points_exchange_per_cent`(默认1)控制,所有入口使用同一来源。 - 钱支付为主,积分是权益之一:支持订单使用积分抵扣(记录为 `orders.points_amount`),并在退款按比例恢复所扣积分;支持支付成功后按配置返积分(可选)。 - 保持幂等与数据一致性,避免对历史数据造成破坏。 ## 变更设计 - 转换率收敛 - 将积分兑换商品/优惠券的“分/10”改为统一转换: - 商品:`internal/api/user/points_redeem_product_app.go` 使用 `needPoints := price_in_cents / 100` 或 `price_in_cents * points_exchange_per_cent`。 - 优惠券:`internal/api/user/points_redeem_coupon_app.go` 使用同一逻辑。 - 管理端展示:`PointsUsed := points_amount / 100`,修改 `internal/api/admin/pay_orders_admin.go`。 - 调度器退款恢复:`refundPts := points_amount / 100`,修改 `internal/service/activity/scheduler.go`。 - 提供共用转换函数(服务层):`centsToPoints(cents, rate)`,所有入口统一调用,来源于 `system_configs.points_exchange_per_cent`。 - 订单积分抵扣接入 - 下单/支付前:新增“使用积分抵扣”选项,调用 `user.ConsumePointsFor` 扣减;将抵扣金额写入 `orders.points_amount`(单位分),并写入 `user_points_ledger`(ref_table=`orders`、ref_id=order_no)。 - 幂等:重复请求不重复扣减;取消/超时需恢复。 - 支付成功联动 - 微信回调:`internal/api/pay/wechat_notify.go` 在订单转“已支付”后: - 若订单已有 `points_amount>0`,确保对应扣积分流水存在(幂等校验)。 - 可选:读取 `system_configs.points_reward_per_cent`(默认0),按“每分奖励多少积分”为用户发放支付返积分(流水 action=`pay_reward`)。 - 退款联动一致性 - 管理端退款与调度器统一按 `points_amount/100` 计算需恢复积分,流水 action=`refund_restore`;金额退款流水 `refund_amount := amount_refund/100` 保持不变。 - 退款比例恢复公式保持:`restorePointsTarget = (points_amount * refunded_cents / total_paid_cents) / 100`。 - 文档与配置 - Swagger注释与说明文本改为“1元=100积分”。 - 系统配置:确保存在并默认 `points_exchange_per_cent=1`;新增可选 `points_reward_per_cent=0`。 ## 实现清单(按模块) 1) 统一转换入口 - 修改 `internal/api/user/points_redeem_product_app.go:55-60`、`internal/api/user/points_redeem_coupon_app.go:55-61`。 - 增加服务层转换工具并替换硬编码。 2) 展示与调度一致 - 修改 `internal/api/admin/pay_orders_admin.go:366-372`。 - 修改 `internal/service/activity/scheduler.go:80-83`。 3) 订单积分抵扣 - 下单接口/订单生成逻辑:写入 `orders.points_amount`(分)与积分扣减流水。 - 回调幂等校验:`wechat_notify.go` 保证一致。 4) 退款一致性 - 保持 `admin/pay_refund_admin.go` 公式不变; - 修正调度器恢复逻辑为 `/100`,并保证只在 `points_amount>0` 场景生效。 5) 支付返积分(可选) - 新增读取 `points_reward_per_cent`,在 `wechat_notify.go` 进行奖励入账与流水。 6) 测试与验收 - 单元测试: - 转换函数:分↔积分在不同 `points_exchange_per_cent` 下正确。 - 订单使用积分:扣减、写入订单、退款部分恢复。 - 回调奖励:开启/关闭奖励配置的行为。 - 集成测试: - 正常支付→即时开奖→虚拟发货链路无回归。 - 调度不足参与→全额退款→金额与积分恢复一致。 - 管理端与APP展示:`points_used=points_amount/100` 一致。 ## 风险与数据兼容 - 历史数据可能基于/10:提供一次性校验脚本(仅统计差异,不强制修复),新数据全走统一入口避免继续漂移。 - 幂等与重复扣减:以 `user_points_ledger` + `ref_table/ref_id` 作为幂等键。 ## 交付物 - 代码改动(API、服务、调度)。 - 配置项说明与默认值。 - Swagger与README更新。 - 测试报告(单元+集成)。 请确认按此方案执行。我将按上述顺序推进并提交具体改动与测试结果。