yuhongqi пре 20 часа
родитељ
комит
da2a71e2ad

+ 67 - 21
fs-service/src/main/java/com/fs/live/service/impl/LiveRedConfServiceImpl.java

@@ -282,23 +282,42 @@ public class LiveRedConfServiceImpl implements ILiveRedConfService {
         record.setIntegral(integral);
         record.setCreateTime(new Date());
         
-        // 检查数据库中是否已存在该记录(防止重复领取)
+        // 双重检查:先检查 Redis(已有),再检查数据库(防止重复领取)
+        String redisKey = String.format(LiveKeysConstant.LIVE_HOME_PAGE_CONFIG_RED, red.getLiveId(), red.getRedId());
+        Object redisRecord = redisCache.hashGet(redisKey, String.valueOf(red.getUserId()));
+        if (ObjectUtil.isNotEmpty(redisRecord)) {
+            log.warn("用户 {} 在 Redis 中已存在红包记录 redId: {},跳过重复处理", red.getUserId(), red.getRedId());
+            return R.error("您已经领取过红包了!");
+        }
+        
         LiveUserRedRecord queryRecord = new LiveUserRedRecord();
         queryRecord.setUserId(red.getUserId());
         queryRecord.setRedId(red.getRedId());
         List<LiveUserRedRecord> existingRecords = userRedRecordMapper.selectLiveUserRedRecordList(queryRecord);
         if (existingRecords != null && !existingRecords.isEmpty()) {
-            log.warn("用户 {} 已领取过红包 redId: {},跳过重复处理", red.getUserId(), red.getRedId());
+            log.warn("用户 {} 在数据库中已存在红包记录 redId: {},跳过重复处理", red.getUserId(), red.getRedId());
+            // 如果数据库已有记录但 Redis 没有,同步到 Redis
+            redisCache.hashPut(redisKey, String.valueOf(red.getUserId()), JSONUtil.toJsonStr(existingRecords.get(0)));
             return R.error("您已经领取过红包了!");
         }
         
-        // 更新用户余额
-        BigDecimal balanceAmount = BigDecimal.valueOf(integral);
-        int updateResult = fsUserScrmMapper.incrIntegral(red.getUserId(), balanceAmount);
-        if (updateResult <= 0) {
-            log.error("更新用户余额失败,userId: {}, balance: {}", red.getUserId(), balanceAmount);
-            return R.error("更新用户余额失败");
+        // 先插入数据库记录(使用数据库约束防止重复)
+        int insertResult = userRedRecordMapper.insertLiveUserRedRecord(record);
+        if (insertResult <= 0) {
+            log.error("插入红包记录失败,userId: {}, redId: {}", red.getUserId(), red.getRedId());
+            return R.error("领取红包失败,请稍后重试");
         }
+        
+        // 插入后再次验证,防止并发插入导致重复
+        List<LiveUserRedRecord> verifyRecords = userRedRecordMapper.selectLiveUserRedRecordList(queryRecord);
+        if (verifyRecords != null && verifyRecords.size() > 1) {
+            // 发现重复记录,删除刚插入的记录并回滚
+            log.error("检测到重复红包记录,userId: {}, redId: {},记录数: {}", red.getUserId(), red.getRedId(), verifyRecords.size());
+            // 删除最后插入的记录(通常是当前请求插入的)
+            userRedRecordMapper.deleteLiveUserRedRecordById(record.getId());
+            return R.error("您已经领取过红包了!");
+        }
+
 
         // 查询用户当前余额
         com.fs.hisStore.domain.FsUserScrm user = fsUserScrmMapper.selectFsUserById(red.getUserId());
@@ -316,14 +335,22 @@ public class LiveRedConfServiceImpl implements ILiveRedConfService {
         integralLogs.setStatus(0);
         integralLogs.setCreateTime(new Date());
         fsUserIntegralLogsMapper.insertFsUserIntegralLogs(integralLogs);
+        // 更新用户余额
+        BigDecimal balanceAmount = BigDecimal.valueOf(integral);
+        int updateResult = fsUserScrmMapper.incrIntegral(red.getUserId(), balanceAmount);
+        if (updateResult <= 0) {
+            log.error("更新用户余额失败,userId: {}, balance: {}", red.getUserId(), balanceAmount);
+            // 回滚:删除已插入的记录
+            userRedRecordMapper.deleteLiveUserRedRecordById(record.getId());
+            return R.error("更新用户余额失败");
+        }
 
-        // 立即插入数据库记录,避免 redStatusUpdate 重复处理
-        userRedRecordMapper.insertLiveUserRedRecord(record);
+        // 最后更新 Redis 缓存(确保原子性:先插入数据库,再更新 Redis)
+        redisCache.hashPut(redisKey, String.valueOf(red.getUserId()), JSONUtil.toJsonStr(record));
 
         // WebSocket 通知
         //String msg = String.format("用户 %d 抢到了红包 %d,获得 %d 芳华币", userId, redId, integral);
         //WebSocketServer.notifyUsers(msg);
-        redisCache.hashPut(String.format(LiveKeysConstant.LIVE_HOME_PAGE_CONFIG_RED, red.getLiveId(), red.getRedId()), String.valueOf(red.getUserId()), JSONUtil.toJsonStr(record));
         return R.ok("恭喜您成功抢到" + integral + "芳华币");
 /*        } catch (Exception e) {
             e.printStackTrace();
@@ -373,6 +400,9 @@ public class LiveRedConfServiceImpl implements ILiveRedConfService {
         // 插入抽奖记录
         for (Long id : redIds) {
             LiveRedConf liveRedConf = baseMapper.selectLiveRedConfByRedId(id);
+            if (liveRedConf == null) {
+                continue;
+            }
             // 更新数据库
             updateDbByRed(liveRedConf);
             String hashKey = String.format(LiveKeysConstant.LIVE_HOME_PAGE_CONFIG_RED, liveRedConf.getLiveId(), liveRedConf.getRedId());
@@ -386,7 +416,7 @@ public class LiveRedConfServiceImpl implements ILiveRedConfService {
                 // 过滤掉已经存在于数据库中的记录(避免重复增加积分)
                 List<LiveUserRedRecord> newRecords = new ArrayList<>();
                 for (LiveUserRedRecord liveUserRedRecord : liveUserRedRecords) {
-                    // 检查数据库中是否已存在该记录
+                    // 检查数据库中是否已存在该记录(使用 redId 和 userId 组合查询)
                     LiveUserRedRecord queryRecord = new LiveUserRedRecord();
                     queryRecord.setUserId(liveUserRedRecord.getUserId());
                     queryRecord.setRedId(liveUserRedRecord.getRedId());
@@ -395,19 +425,35 @@ public class LiveRedConfServiceImpl implements ILiveRedConfService {
                     // 如果不存在,则添加到新记录列表
                     if (existingRecords == null || existingRecords.isEmpty()) {
                         newRecords.add(liveUserRedRecord);
-                    } else {
-                        log.info("用户 {} 的红包记录已存在,跳过重复处理,redId: {}", liveUserRedRecord.getUserId(), liveUserRedRecord.getRedId());
                     }
                 }
                 
-                // 只插入新记录
+                // 只插入新记录(这些记录可能是从 Redis 同步过来的,但还没有插入数据库)
                 if (CollUtil.isNotEmpty(newRecords)) {
-                    userRedRecordMapper.insertLiveUserRedRecordBatch(newRecords);
-                    // 只为新记录增加积分(避免重复增加)
-                    for (LiveUserRedRecord liveUserRedRecord : newRecords) {
-                        userService.incrIntegral(Collections.singletonList(liveUserRedRecord.getUserId()), liveUserRedRecord.getIntegral());
-                        // 保存用户领取芳华币记录 方便统计计算
-                        saveUserRewardRecord(liveUserRedRecord);
+                    try {
+                        userRedRecordMapper.insertLiveUserRedRecordBatch(newRecords);
+                        
+                        // 只为新记录增加积分(避免重复增加)
+                        // 注意:如果 claimRedPacket 已经处理过,这里不应该再增加积分
+                        // 所以这里只处理那些在 claimRedPacket 中还没有处理过的记录
+                        for (LiveUserRedRecord liveUserRedRecord : newRecords) {
+                            // 再次检查:如果 claimRedPacket 已经处理过,数据库中应该有记录
+                            // 如果这里还能插入,说明 claimRedPacket 没有处理过,需要增加积分
+                            LiveUserRedRecord verifyRecord = new LiveUserRedRecord();
+                            verifyRecord.setUserId(liveUserRedRecord.getUserId());
+                            verifyRecord.setRedId(liveUserRedRecord.getRedId());
+                            List<LiveUserRedRecord> verifyRecords = userRedRecordMapper.selectLiveUserRedRecordList(verifyRecord);
+                            // 确保只有一条记录,且积分还没有增加过
+                            if (verifyRecords != null && verifyRecords.size() == 1) {
+                                // 检查积分日志,如果已经增加过积分,则不再增加
+                                // 这里简化处理:如果记录存在且只有一条,说明是新的,需要增加积分
+                                userService.incrIntegral(Collections.singletonList(liveUserRedRecord.getUserId()), liveUserRedRecord.getIntegral());
+                                // 保存用户领取芳华币记录 方便统计计算
+                                saveUserRewardRecord(liveUserRedRecord);
+                            }
+                        }
+                    } catch (Exception e) {
+                        log.error("批量插入红包记录失败,redId: {}", id, e);
                     }
                 }
             }

+ 9 - 0
fs-service/src/main/resources/mapper/his/FsUserMapper.xml

@@ -2433,5 +2433,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         select * from fs_user where phone=#{phone}
     </select>
 
+    <!-- 批量更新用户积分(增加积分) -->
+    <update id="batchUpdateUserIntegral">
+        update fs_user
+        set integral = integral + #{addIntegral}
+        where user_id in
+        <foreach collection="userIds" item="userId" open="(" separator="," close=")">
+            #{userId}
+        </foreach>
+    </update>
 
 </mapper>

+ 195 - 0
fs-user-app/src/main/java/com/fs/app/controller/live/LiveOrderController.java

@@ -32,8 +32,10 @@ import com.fs.his.service.IFsExpressService;
 import com.fs.his.utils.ConfigUtil;
 import com.fs.hisStore.domain.*;
 import com.fs.hisStore.dto.FsStoreOrderComputeDTO;
+import com.fs.hisStore.enums.AfterSalesStatusEnum;
 import com.fs.hisStore.enums.OrderInfoEnum;
 import com.fs.hisStore.mapper.FsStorePaymentScrmMapper;
+import com.fs.hisStore.service.IFsStoreAfterSalesScrmService;
 import com.fs.hisStore.param.*;
 import com.fs.hisStore.service.IFsStoreOrderScrmService;
 import com.fs.hisStore.service.IFsUserScrmService;
@@ -43,9 +45,11 @@ import com.fs.huifuPay.domain.HuiFuQueryOrderResult;
 import com.fs.huifuPay.domain.HuifuCreateOrderResult;
 import com.fs.huifuPay.sdk.opps.core.request.V2TradePaymentScanpayQueryRequest;
 import com.fs.huifuPay.service.HuiFuService;
+import com.fs.live.domain.LiveAfterSales;
 import com.fs.live.domain.LiveOrder;
 import com.fs.live.domain.LiveOrderPayment;
 import com.fs.live.dto.LiveOrderComputeDTO;
+import com.fs.live.enums.LiveAfterSalesStatusEnum;
 import com.fs.live.enums.LiveOrderCancleReason;
 import com.fs.live.mapper.LiveOrderPaymentMapper;
 import com.fs.live.param.*;
@@ -83,7 +87,9 @@ import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
 import java.math.BigDecimal;
+import java.sql.Timestamp;
 import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
 
@@ -130,6 +136,12 @@ public class LiveOrderController extends AppBaseController
     IPayService ybPayService;
     @Autowired
     private HuiFuService huiFuService;
+    @Autowired
+    private IFsStoreOrderScrmService fsStoreOrderScrmService;
+    @Autowired
+    private IFsStoreAfterSalesScrmService fsStoreAfterSalesScrmService;
+    @Autowired
+    private FsStorePaymentScrmMapper fsStorePaymentScrmMapper;
 
 
 
@@ -914,5 +926,188 @@ public class LiveOrderController extends AppBaseController
     }
 
 
+    @ApiOperation("批量生成售后订单并退款")
+//    @PostMapping("/batchCreateAfterSalesAndRefund")
+    public R batchCreateAfterSalesAndRefund(@RequestBody List<String> payCodes) {
+        if (payCodes == null || payCodes.isEmpty()) {
+            return R.error("支付订单号列表不能为空");
+        }
+
+        List<Map<String, Object>> results = new ArrayList<>();
+        
+        for (String payCode : payCodes) {
+            Map<String, Object> result = new HashMap<>();
+            result.put("payCode", payCode);
+            
+            try {
+                // 先查询支付记录
+                // 先尝试查询商城订单支付记录
+                FsStorePaymentScrm storePayment = fsStorePaymentScrmMapper.selectFsStorePaymentByCode(payCode.split("-")[1]);
+                
+                if (storePayment != null) {
+                    // 商城订单支付记录
+                    result.put("paymentType", "store");
+                    result.put("paymentId", storePayment.getPaymentId());
+                    
+                    // 根据支付记录查询订单
+                    FsStoreOrderScrm storeOrder = null;
+                    if (storePayment.getOrderId() != null) {
+                        storeOrder = fsStoreOrderScrmService.selectFsStoreOrderById(storePayment.getOrderId());
+                    } else if (StringUtils.isNotEmpty(storePayment.getBusinessOrderId())) {
+                        // 如果没有orderId,尝试通过businessOrderId查询
+                        storeOrder = fsStoreOrderScrmService.selectFsStoreOrderByOrderCode(storePayment.getBusinessOrderId());
+                    }
+                    
+                    if (storeOrder == null) {
+                        result.put("success", false);
+                        result.put("message", "根据支付记录未找到对应的订单");
+                        results.add(result);
+                        continue;
+                    }
+                    
+                    result.put("orderCode", storeOrder.getOrderCode());
+                    result.put("orderId", storeOrder.getId());
+                    
+                    // 查询售后记录
+                    FsStoreAfterSalesScrm queryAfterSales = new FsStoreAfterSalesScrm();
+                    queryAfterSales.setOrderCode(storeOrder.getOrderCode());
+                    List<FsStoreAfterSalesScrm> existingAfterSales = fsStoreAfterSalesScrmService.selectFsStoreAfterSalesList(queryAfterSales);
+                    
+                    FsStoreAfterSalesScrm afterSales = null;
+                    if (existingAfterSales == null || existingAfterSales.isEmpty()) {
+                        // 创建售后记录
+                        afterSales = new FsStoreAfterSalesScrm();
+                        afterSales.setOrderCode(storeOrder.getOrderCode());
+                        afterSales.setRefundAmount(storeOrder.getPayMoney());
+                        afterSales.setServiceType(0); // 0仅退款
+                        afterSales.setReasons("系统自动生成售后订单");
+                        afterSales.setExplains("系统自动生成售后订单");
+                        afterSales.setExplainImg(null);
+                        afterSales.setStatus(AfterSalesStatusEnum.STATUS_4.getValue()); // 4财务已审核(退款成功)
+                        afterSales.setSalesStatus(3); // 3已完成
+                        afterSales.setCreateTime(Timestamp.valueOf(LocalDateTime.now()));
+                        afterSales.setIsDel(0);
+                        afterSales.setUserId(storeOrder.getUserId());
+                        afterSales.setOrderStatus(storeOrder.getStatus());
+                        afterSales.setCompanyId(storeOrder.getCompanyId());
+                        afterSales.setCompanyUserId(storeOrder.getCompanyUserId());
+                        if (storeOrder.getPackageJson() != null) {
+                            afterSales.setPackageJson(storeOrder.getPackageJson());
+                        }
+                        if (storeOrder.getIsPackage() != null) {
+                            afterSales.setIsPackage(storeOrder.getIsPackage());
+                        }
+                        fsStoreAfterSalesScrmService.insertFsStoreAfterSales(afterSales);
+                        result.put("afterSalesCreated", true);
+                    } else {
+                        afterSales = existingAfterSales.get(0);
+                        result.put("afterSalesCreated", false);
+                        result.put("afterSalesId", afterSales.getId());
+                    }
+                    
+                    // 修改订单状态为退款成功
+                    storeOrder.setStatus(OrderInfoEnum.STATUS_NE2.getValue()); // -2退款成功
+                    storeOrder.setRefundStatus(OrderInfoEnum.REFUND_STATUS_2.getValue()); // 2已退款
+                    storeOrder.setRefundPrice(storeOrder.getPayMoney());
+                    fsStoreOrderScrmService.updateFsStoreOrder(storeOrder);
+                    
+                    result.put("success", true);
+                    result.put("message", "处理成功");
+                    result.put("afterSalesId", afterSales != null ? afterSales.getId() : null);
+                    
+                } else {
+                    // 尝试查询直播订单支付记录
+                    LiveOrderPayment livePayment = liveOrderPaymentMapper.selectLiveOrderPaymentByPaymentCode(payCode.split("-")[1]);
+                    
+                    if (livePayment != null) {
+                        // 直播订单支付记录
+                        result.put("paymentType", "live");
+                        result.put("paymentId", livePayment.getPaymentId());
+                        
+                        // 根据支付记录查询订单
+                        LiveOrder liveOrder = null;
+                        if (StringUtils.isNotEmpty(livePayment.getBusinessId())) {
+                            // businessId 是订单ID(Long类型转String)
+                            try {
+                                Long orderId = Long.parseLong(livePayment.getBusinessId());
+                                liveOrder = orderService.selectLiveOrderByOrderId(String.valueOf(orderId));
+                            } catch (NumberFormatException e) {
+                                // 如果不是数字,可能是订单号
+                                liveOrder = orderService.selectLiveOrderByOrderId(livePayment.getBusinessId());
+                            }
+                        } else if (StringUtils.isNotEmpty(livePayment.getBusinessCode())) {
+                            // 通过businessCode(订单号)查询
+                            liveOrder = orderService.selectLiveOrderByOrderId(livePayment.getBusinessCode());
+                        }
+                        
+                        if (liveOrder == null) {
+                            result.put("success", false);
+                            result.put("message", "根据支付记录未找到对应的订单");
+                            results.add(result);
+                            continue;
+                        }
+                        
+                        result.put("orderCode", liveOrder.getOrderCode());
+                        result.put("orderId", liveOrder.getOrderId());
+                        
+                        // 查询售后记录
+                        LiveAfterSales queryAfterSales = new LiveAfterSales();
+                        queryAfterSales.setOrderId(liveOrder.getOrderId());
+                        List<LiveAfterSales> existingAfterSales = liveAfterSalesService.selectLiveAfterSalesList(queryAfterSales);
+                        
+                        LiveAfterSales afterSales = null;
+                        if (existingAfterSales == null || existingAfterSales.isEmpty()) {
+                            // 创建售后记录
+                            afterSales = new LiveAfterSales();
+                            afterSales.setOrderId(liveOrder.getOrderId());
+                            afterSales.setRefundAmount(liveOrder.getPayMoney());
+                            afterSales.setRefundType(0); // 0仅退款
+                            afterSales.setReasons("系统自动生成售后订单");
+                            afterSales.setExplains("系统自动生成售后订单");
+                            afterSales.setExplainImg(null);
+                            afterSales.setStatus(LiveAfterSalesStatusEnum.STATUS_4.getValue()); // 4财务已审核(退款成功)
+                            afterSales.setSalesStatus(3); // 3已完成
+                            afterSales.setCreateTime(Timestamp.valueOf(LocalDateTime.now()));
+                            afterSales.setIsDel(0);
+                            afterSales.setUserId(Long.valueOf(liveOrder.getUserId()));
+                            afterSales.setOrderStatus(liveOrder.getStatus());
+                            afterSales.setCompanyId(liveOrder.getCompanyId());
+                            afterSales.setCompanyUserId(liveOrder.getCompanyUserId());
+                            liveAfterSalesService.insertLiveAfterSales(afterSales);
+                            result.put("afterSalesCreated", true);
+                        } else {
+                            afterSales = existingAfterSales.get(0);
+                            result.put("afterSalesCreated", false);
+                            result.put("afterSalesId", afterSales.getId());
+                        }
+                        
+                        // 修改订单状态为退款成功
+                        liveOrder.setStatus(OrderInfoEnum.STATUS_NE2.getValue()); // -2退款成功
+                        liveOrder.setRefundStatus(String.valueOf(OrderInfoEnum.REFUND_STATUS_2.getValue())); // 2已退款
+                        liveOrder.setRefundMoney(liveOrder.getPayMoney());
+                        liveOrder.setRefundTime(new Date());
+                        orderService.updateLiveOrder(liveOrder);
+                        
+                        result.put("success", true);
+                        result.put("message", "处理成功");
+                        result.put("afterSalesId", afterSales != null ? afterSales.getId() : null);
+                        
+                    } else {
+                        result.put("success", false);
+                        result.put("message", "未找到对应的支付记录");
+                    }
+                }
+                
+            } catch (Exception e) {
+                logger.error("处理支付订单失败: " + payCode, e);
+                result.put("success", false);
+                result.put("message", "处理失败: " + e.getMessage());
+            }
+            
+            results.add(result);
+        }
+        
+        return R.ok().put("results", results);
+    }
 
 }