Jelajahi Sumber

fix: 支付分补扣平账 — post_payments金额sum必须等于totalAmount

问题:DB中单价保留2位小数,乘数量再求和时产生累计四舍五入误差,
导致 sum(post_payments)≠totalAmount,微信返回 PARAM_ERROR 最终总金额计算非法。

示例: 17.85元订单,商品sum=17.86,差1分。

修复: buildPostPayments 接收 totalAmount 参数,如有差额自动调整末项抹平。

Co-Authored-By: Claude <noreply@anthropic.com>
skyline 4 hari lalu
induk
melakukan
cf6a1248c5

+ 16 - 2
haha-service/src/main/java/com/haha/service/impl/HahaCallbackServiceImpl.java

@@ -1538,7 +1538,7 @@ public class HahaCallbackServiceImpl implements HahaCallbackService {
      * 从 order_goods 表查询已保存的商品,按微信支付分智慧零售规范构建
      * name="商品信息", description=商品名, amount=单价(元), count=数量
      */
-    private List<PayScoreCreateRequest.PostPayment> buildPostPayments(Long orderId) {
+    private List<PayScoreCreateRequest.PostPayment> buildPostPayments(Long orderId, BigDecimal totalAmount) {
         List<PayScoreCreateRequest.PostPayment> payments = new ArrayList<>();
         try {
             List<OrderGoods> goodsList = orderGoodsMapper.selectList(
@@ -1572,6 +1572,20 @@ public class HahaCallbackServiceImpl implements HahaCallbackService {
                 payments.add(payment);
             }
 
+            // 修正四舍五入累计误差:确保 sum(post_payments) 严格等于 totalAmount
+            if (totalAmount != null && !payments.isEmpty()) {
+                BigDecimal sum = payments.stream()
+                        .map(PayScoreCreateRequest.PostPayment::getAmount)
+                        .reduce(BigDecimal.ZERO, BigDecimal::add);
+                BigDecimal diff = totalAmount.subtract(sum);
+                if (diff.compareTo(BigDecimal.ZERO) != 0) {
+                    PayScoreCreateRequest.PostPayment last = payments.get(payments.size() - 1);
+                    last.setAmount(last.getAmount().add(diff));
+                    log.info("post_payments余额平账: 商品sum={}, 订单total={}, 差额={}, 调整末项amount为{}",
+                            sum, totalAmount, diff, last.getAmount());
+                }
+            }
+
             log.info("构建post_payments成功 - orderId: {}, 商品数量: {}", orderId, payments.size());
         } catch (Exception e) {
             log.error("构建post_payments失败 - orderId: {}", orderId, e);
@@ -1627,7 +1641,7 @@ public class HahaCallbackServiceImpl implements HahaCallbackService {
             log.info("开始处理支付分扣费 - orderId: {}, payScoreOrderId: {}, amount: {}元",
                     order.getId(), order.getPayScoreOrderId(), totalAmount);
 
-            List<PayScoreCreateRequest.PostPayment> payments = buildPostPayments(order.getId());
+            List<PayScoreCreateRequest.PostPayment> payments = buildPostPayments(order.getId(), totalAmount);
 
             PayScoreResult result = payScoreService.completePayScoreOrder(order.getId(), totalAmount, payments);
 

+ 16 - 2
haha-service/src/main/java/com/haha/service/impl/OrderServiceImpl.java

@@ -709,7 +709,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
      * 从 order_goods 表查询已保存的商品,按微信支付分智慧零售规范构建
      * name="商品信息", description=商品名, amount=单价(元), count=数量
      */
-    private List<PayScoreCreateRequest.PostPayment> buildPostPayments(Long orderId) {
+    private List<PayScoreCreateRequest.PostPayment> buildPostPayments(Long orderId, BigDecimal totalAmount) {
         List<PayScoreCreateRequest.PostPayment> payments = new ArrayList<>();
         try {
             List<OrderGoods> goodsList = orderGoodsMapper.selectList(
@@ -743,6 +743,20 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
                 payments.add(payment);
             }
 
+            // 修正四舍五入累计误差:确保 sum(post_payments) 严格等于 totalAmount
+            if (totalAmount != null && !payments.isEmpty()) {
+                BigDecimal sum = payments.stream()
+                        .map(PayScoreCreateRequest.PostPayment::getAmount)
+                        .reduce(BigDecimal.ZERO, BigDecimal::add);
+                BigDecimal diff = totalAmount.subtract(sum);
+                if (diff.compareTo(BigDecimal.ZERO) != 0) {
+                    PayScoreCreateRequest.PostPayment last = payments.get(payments.size() - 1);
+                    last.setAmount(last.getAmount().add(diff));
+                    log.info("post_payments余额平账: 商品sum={}, 订单total={}, 差额={}, 调整末项amount为{}",
+                            sum, totalAmount, diff, last.getAmount());
+                }
+            }
+
             log.info("构建post_payments成功 - orderId: {}, 商品数量: {}", orderId, payments.size());
         } catch (Exception e) {
             log.error("构建post_payments失败 - orderId: {}", orderId, e);
@@ -798,7 +812,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
         }
 
         try {
-            List<PayScoreCreateRequest.PostPayment> payments = buildPostPayments(orderId);
+            List<PayScoreCreateRequest.PostPayment> payments = buildPostPayments(orderId, totalAmount);
             PayScoreResult result = payScoreService.completePayScoreOrder(orderId, totalAmount, payments);
 
             if (result.isSuccess()) {