From 3f45e8fdfa31d7b764d60a7c0cb5dd11944ed418 Mon Sep 17 00:00:00 2001
From: 刘帅 <rr.iii@qq.com>
Date: 星期一, 21 九月 2026 23:38:59 +0800
Subject: [PATCH] bug:统计数据修正

---
 cloud-server-account/src/main/java/com/dsh/account/service/impl/TAppUserServiceImpl.java |   73 ++++++++++++++++++++++++++++++------
 1 files changed, 60 insertions(+), 13 deletions(-)

diff --git a/cloud-server-account/src/main/java/com/dsh/account/service/impl/TAppUserServiceImpl.java b/cloud-server-account/src/main/java/com/dsh/account/service/impl/TAppUserServiceImpl.java
index b208819..f33edaf 100644
--- a/cloud-server-account/src/main/java/com/dsh/account/service/impl/TAppUserServiceImpl.java
+++ b/cloud-server-account/src/main/java/com/dsh/account/service/impl/TAppUserServiceImpl.java
@@ -1481,6 +1481,10 @@
     @Override
     @Transactional
     public synchronized ResultUtil productRedemptionOperation(Integer userIdFormRedis, GoodsExchangeVo exchangeType) {
+        // 兼容前端历史参数 chooseCouponId,内部统一使用 couponId。
+        if (exchangeType.getCouponId() == null && exchangeType.getChooseCouponId() != null) {
+            exchangeType.setCouponId(exchangeType.getChooseCouponId());
+        }
         ReturnModel returnModel = new ReturnModel();
         Long returnId = null;
         //如果是兑换优惠卷
@@ -1575,6 +1579,8 @@
             }
 
             BigDecimal cashAmount = merchandise.getCash() == null ? BigDecimal.ZERO : merchandise.getCash();
+            // 门票优惠后的订单现金应付总额;支付参数必须使用该金额,不能再使用商品原价。
+            BigDecimal ticketPayableCashAmount = null;
             UserCoupon usedCoupon = null;
             if (exchangeType.getGoodsType() == 3 && exchangeType.getCouponId() != null && exchangeType.getCouponId() != 0) {
                 if (exchangeType.getExchangeType() == 1) {
@@ -1605,10 +1611,12 @@
                             .divide(BigDecimal.valueOf(exchangeType.getNums() == null ? 1 : exchangeType.getNums()), 2, java.math.RoundingMode.HALF_UP);
                 } else if (Integer.valueOf(2).equals(coupon.getType())) {
                     BigDecimal deduction = rule.getBigDecimal("conditionalAmount");
-                    if (deduction == null) {
+                    if (deduction == null || deduction.compareTo(BigDecimal.ZERO) <= 0) {
                         return ResultUtil.error("该优惠券无法使用");
                     }
-                    cashAmount = orderCash.subtract(deduction).max(BigDecimal.ZERO)
+                    // 代金券可覆盖全部订单金额,超出订单金额的部分不找零。
+                    ticketPayableCashAmount = orderCash.subtract(deduction).max(BigDecimal.ZERO);
+                    cashAmount = ticketPayableCashAmount
                             .divide(BigDecimal.valueOf(exchangeType.getNums() == null ? 1 : exchangeType.getNums()), 2, java.math.RoundingMode.HALF_UP);
                 } else {
                     return ResultUtil.error("该优惠券不支持购买门票");
@@ -1639,6 +1647,9 @@
             } else {
                 goodsNums = exchangeType.getNums();
             }
+            BigDecimal cashPaymentAmount = ticketPayableCashAmount == null
+                    ? cashAmount.multiply(BigDecimal.valueOf(goodsNums))
+                    : ticketPayableCashAmount;
 
             TAppUser user = appUserService.getById(userIdFormRedis);
             if (merchandise.getIntegral() != null) {
@@ -1675,6 +1686,10 @@
             if (exchangeType.getExchangeType() == 1) {
                 pointsMerchandise.setPayStatus(2);
                 pointsMerchandise.setPaymentTime(new Date());
+            } else if (cashPaymentAmount.compareTo(BigDecimal.ZERO) == 0) {
+                // 优惠券将现金部分完全抵扣时,不能向第三方支付发起 0 元或原价支付。
+                pointsMerchandise.setPayStatus(2);
+                pointsMerchandise.setPaymentTime(new Date());
             } else {
                 pointsMerchandise.setPayStatus(1);
             }
@@ -1694,7 +1709,7 @@
                 pointsMerchandise.setIntegral(merchandise.getIntegral() * goodsNums);
             }
             if (exchangeType.getExchangeType() == 2 || exchangeType.getExchangeType() == 3) {
-                pointsMerchandise.setCash(cashAmount);
+                pointsMerchandise.setCash(exchangeType.getGoodsType() == 3 ? cashPaymentAmount : cashAmount);
                 pointsMerchandise.setCashPayType(exchangeType.getPayType());
             }
 
@@ -1716,6 +1731,10 @@
                     BeanUtils.copyProperties(pointsMerchandise, userPointsMerchandise);
                     // 一笔订单只能关联一次优惠券,避免拆分门票后重复计入优惠金额。
                     userPointsMerchandise.setUserCouponId(null);
+                    if (exchangeType.getGoodsType() == 3) {
+                        // 门票拆单后仅首条保留订单总实付金额,避免支付/收入统计重复累加。
+                        userPointsMerchandise.setCash(BigDecimal.ZERO);
+                    }
                     userPointsMerchandises.add(userPointsMerchandise);
                 }
                 System.err.println("新增额外购买记录"+userPointsMerchandises);
@@ -1727,8 +1746,16 @@
                 }
 
             }
-            if ((m * goodsNums) == 0 && pointsMerchandise.getPayStatus() == 2) {
+            if (pointsMerchandise.getPayStatus() == 2 && exchangeType.getExchangeType() != 1
+                    && cashPaymentAmount.compareTo(BigDecimal.ZERO) == 0) {
+                // 积分+现金商品被优惠券抵扣为零元时,仍需扣除积分;不等待支付回调。
+                if (exchangeType.getExchangeType() == 2 && merchandise.getIntegral() != null
+                        && merchandise.getIntegral() > 0
+                        && !dealAppUserIntegral(userIdFormRedis, tAppUser, merchandise.getIntegral() * goodsNums)) {
+                    return ResultUtil.error("用户积分不足!");
+                }
                 returnModel.setReturnId(returnId);
+                returnModel.setPaySuccess(true);
                 return ResultUtil.success(returnModel);
             }
 
@@ -1830,7 +1857,7 @@
                                 } else if (merchandise.getType() == 1) {
                                     return WechatPayment(merchandise.getType(), cashAmount.multiply(new BigDecimal(goodsNums)), code, merchandise.getId());
                                 } else if (merchandise.getType() == 3) {
-                                    return WechatPayment(merchandise.getType(), cashAmount.multiply(new BigDecimal(goodsNums)), code, merchandise.getId());
+                                    return WechatPayment(merchandise.getType(), cashPaymentAmount, code, merchandise.getId());
                                 }
                             } catch (Exception e) {
                                 return ResultUtil.runErr();
@@ -1838,6 +1865,8 @@
                         case 2:
                             if (merchandise.getType() == 2) {
                                 return AlipayPayment(merchandise.getType(), cashAmount.multiply(new BigDecimal(exchangeType.getStuIds().size())), code, merchandise.getId());
+                            } else if (merchandise.getType() == 3) {
+                                return AlipayPayment(merchandise.getType(), cashPaymentAmount, code, merchandise.getId());
                             } else {
                                 return AlipayPayment(merchandise.getType(), cashAmount.multiply(new BigDecimal(goodsNums)), code, merchandise.getId());
                             }
@@ -1851,6 +1880,8 @@
                             try {
                                 if (merchandise.getType() == 2) {
                                     return WechatPayment(merchandise.getType(), cashAmount.multiply(new BigDecimal(exchangeType.getStuIds().size())), code, merchandise.getId());
+                                } else if (merchandise.getType() == 3) {
+                                    return WechatPayment(merchandise.getType(), cashPaymentAmount, code, merchandise.getId());
                                 } else {
                                     return WechatPayment(merchandise.getType(), cashAmount.multiply(new BigDecimal(goodsNums)), code, merchandise.getId());
                                 }
@@ -1860,6 +1891,8 @@
                         case 2:
                             if (merchandise.getType() == 2) {
                                 return AlipayPayment(merchandise.getType(), cashAmount.multiply(new BigDecimal(exchangeType.getStuIds().size())), code, merchandise.getId());
+                            } else if (merchandise.getType() == 3) {
+                                return AlipayPayment(merchandise.getType(), cashPaymentAmount, code, merchandise.getId());
                             } else {
                                 return AlipayPayment(merchandise.getType(), cashAmount.multiply(new BigDecimal(goodsNums)), code, merchandise.getId());
                             }
@@ -1872,6 +1905,7 @@
             }
 
             returnModel.setReturnId(returnId);
+            returnModel.setPaySuccess(pointsMerchandise.getPayStatus() == 2);
             return ResultUtil.success(returnModel);
         } catch (Exception e) {
             e.printStackTrace();
@@ -2226,7 +2260,20 @@
                 }
             }).start();
         }
-        return alipay;
+        return appendPaySuccess(alipay);
+    }
+
+    /**
+     * 支付宝、微信的成功响应仅表示已生成支付单,客户端仍需拉起第三方支付。
+     */
+    private ResultUtil appendPaySuccess(ResultUtil paymentResult) {
+        JSONObject data = paymentResult.getData() == null ? new JSONObject()
+                : JSON.parseObject(JSON.toJSONString(paymentResult.getData()));
+        if (data == null) {
+            data = new JSONObject();
+        }
+        data.put("paySuccess", false);
+        return ResultUtil.getResult(paymentResult.getCode(), paymentResult.getMsg(), data);
     }
 
 
@@ -2248,7 +2295,7 @@
                         // 平台门票
                         ResultUtil weixinpay = payMoneyUtil.weixinpay(name, "", code, cash.toString(),
                                 "/base/pointMer/exchangeGoodPaymentWeChatCallback", "APP", "");
-                        return weixinpay;
+                        return appendPaySuccess(weixinpay);
                     } else {
                         String s2 = storeClient.getmerchantNumberByOperatorId(store1.getOperatorId());
                         System.err.println("微信商户号" + s2);
@@ -2259,7 +2306,7 @@
                         ResultUtil weixinpay = payMoneyUtil.weixinpayV3(s2, name, code,
                                 "/base/pointMer/exchangeGoodPaymentWeChatCallback1",
                                 cash.toString());
-                        return weixinpay;
+                        return appendPaySuccess(weixinpay);
                     }
                 }
                 break;
@@ -2271,7 +2318,7 @@
                     // 平台课包
                     ResultUtil weixinpay = payMoneyUtil.weixinpay(name, "", code, cash.toString(),
                             "/base/pointMer/exchangeGoodPaymentWeChatCallback", "APP", "");
-                    return weixinpay;
+                    return appendPaySuccess(weixinpay);
                 } else {
                     String s2 = storeClient.getmerchantNumberByOperatorId(store.getOperatorId());
                     System.err.println("微信商户号" + s2);
@@ -2282,7 +2329,7 @@
                     ResultUtil weixinpay = payMoneyUtil.weixinpayV3(s2, name, code,
                             "/base/pointMer/exchangeGoodPaymentWeChatCallback1",
                             cash.toString());
-                    return weixinpay;
+                    return appendPaySuccess(weixinpay);
                 }
             case 3:
                 if (!integers.isEmpty()) {
@@ -2291,7 +2338,7 @@
                         // 平台门票
                         ResultUtil weixinpay = payMoneyUtil.weixinpay(name, "", code, cash.toString(),
                                 "/base/pointMer/exchangeGoodPaymentWeChatCallback", "APP", "");
-                        return weixinpay;
+                        return appendPaySuccess(weixinpay);
                     } else {
                         String s2 = storeClient.getmerchantNumberByOperatorId(store1.getOperatorId());
                         System.err.println("微信商户号" + s2);
@@ -2302,13 +2349,13 @@
                         ResultUtil weixinpay = payMoneyUtil.weixinpayV3(s2, name, code,
                                 "/base/pointMer/exchangeGoodPaymentWeChatCallback1",
                                 cash.toString());
-                        return weixinpay;
+                        return appendPaySuccess(weixinpay);
                     }
                 } else {
                     // 平台门票
                     ResultUtil weixinpay = payMoneyUtil.weixinpay(name, "", code, cash.toString(),
                             "/base/pointMer/exchangeGoodPaymentWeChatCallback", "APP", "");
-                    return weixinpay;
+                    return appendPaySuccess(weixinpay);
 
                 }
         }

--
Gitblit v1.7.1