Explorar el Código

refactor(消费服务): 优化消费记录上传与缓存逻辑

1. 修改异步上传日志信息,调整为更准确的描述。
2. 增加消费记录重复上传校验逻辑,通过缓存存储和校验`detailId`,避免重复处理。
3. 调整缓存过期时间,将`XF_ORIGINAL_ID`和`XF_DETAIL_ID`的过期时间延长至20小时。
4. 新增`XF_DETAIL_ID`缓存常量定义,用于存储消费记录标识。
5. 优化代码格式和日志输出风格,提升可读性与一致性。
autumnal_wind hace 11 meses
padre
commit
695ca360f7

+ 1 - 0
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CacheNames.java

@@ -191,4 +191,5 @@ public interface CacheNames {
     String PT_MEAL_TYPE_LIST = "pt_meal_type_list";
 
     String XF_ORIGINAL_ID = "xf_original_id";
+    String XF_DETAIL_ID = "xf_detail_id";
 }

+ 1 - 1
ruoyi-server/ruoyi-server-consume/src/main/java/org/dromara/server/consume/business/ConsumeBusiness.java

@@ -184,7 +184,7 @@ public class ConsumeBusiness {
     @Async
     public void postOrderAsync(ConsumptionBo bo, String mac, String xfPwd) {
         R<ErrorInfo> result = SpringUtils.getAopProxy(this).postOrder(bo, mac, xfPwd);
-        log.info("[上传交易结果完成]");
+        log.info("[上传交异步处理完成]");
     }
 
     //region 云端消费对账

+ 1 - 1
ruoyi-server/ruoyi-server-consume/src/main/java/org/dromara/server/consume/check/CommonCheck.java

@@ -505,7 +505,7 @@ public class CommonCheck {
         // 将当笔原始消费记录标识放入缓存,1天过期
         Set<String> originalId = Collections.singleton(bo.getOriginalId());
         RedisUtils.setCacheSet(CacheNames.XF_ORIGINAL_ID, originalId);
-        RedisUtils.expire(CacheNames.XF_ORIGINAL_ID, Duration.ofHours(6));
+        RedisUtils.expire(CacheNames.XF_ORIGINAL_ID, Duration.ofHours(20));
 
         if (ObjectUtil.equals(currentDateStr, consumeDateStr)) {
             // 重置卡天当日消费数据

+ 26 - 15
ruoyi-server/ruoyi-server-consume/src/main/java/org/dromara/server/consume/check/ConsumeUploadCheck.java

@@ -8,10 +8,12 @@ import lombok.extern.slf4j.Slf4j;
 import org.dromara.backstage.api.domain.vo.RemoteMealTypeVo;
 import org.dromara.backstage.api.domain.vo.RemoteUserAccountVo;
 import org.dromara.common.core.constant.ApiErrorTypeConstants;
+import org.dromara.common.core.constant.CacheNames;
 import org.dromara.common.core.domain.R;
 import org.dromara.common.core.domain.model.ErrorInfo;
 import org.dromara.common.core.enums.BagNameEnum;
 import org.dromara.common.core.utils.RecordIdUtils;
+import org.dromara.common.redis.utils.RedisUtils;
 import org.dromara.server.common.domain.consume.bo.ConsumptionBo;
 import org.dromara.server.consume.business.BaseBusiness;
 import org.dromara.server.consume.domain.convert.RemoteVoConvert;
@@ -26,10 +28,8 @@ import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
 import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
+import java.time.Duration;
+import java.util.*;
 
 /**
  * 消费记录上传业务处理类
@@ -62,6 +62,17 @@ public class ConsumeUploadCheck {
      */
     public R<ErrorInfo> checkBill(ConsumptionBo bo, RemoteUserAccountVo userAccountVo,
                                   XfTermVo useTermVo, List<PtBagVo> bagVoList, RemoteMealTypeVo mealTypeVo) {
+        // 检验之前先检查这条记录是否上传过,如果上传过则返回已上传的错误,如未上传,将记录Id存入缓存
+        String detailId = RecordIdUtils.getRecordId(bo.getConsumeDate(), bo.getTermNo().shortValue(),
+            bo.getTermRecordId().shortValue(), bo.getUserNo().intValue(), 0);
+        Set<String> detailIdSet = RedisUtils.getCacheSet(CacheNames.XF_DETAIL_ID);
+        if (detailIdSet.contains(detailId)) {
+            return commonCheck.createErrorResponse(400, ApiErrorTypeConstants.CONSUME_CHECK_FAIL, "消费记录已上传",
+                MessageFormat.format("消费记录已上传:{0}", detailId));
+        }
+        RedisUtils.setCacheSet(CacheNames.XF_DETAIL_ID, Collections.singleton(detailId));
+        RedisUtils.expire(CacheNames.XF_DETAIL_ID, Duration.ofHours(20));
+
         R<ErrorInfo> result = checkOriginalRecord(bo, userAccountVo);
         if (R.isError(result)) {
             return result;
@@ -90,7 +101,7 @@ public class ConsumeUploadCheck {
 
     private R<ErrorInfo> checkOriginalRecord(ConsumptionBo bo, RemoteUserAccountVo userAccountVo) {
         String originalId = RecordIdUtils.getRecordId(bo.getConsumeDate(), bo.getTermNo().shortValue(),
-                                                      bo.getTermRecordId().shortValue(), bo.getUserNo().intValue(), 0);
+            bo.getTermRecordId().shortValue(), bo.getUserNo().intValue(), 0);
         //  补偿性措施:防止消费时间错乱问题(在线模式)
         int recordType = bo.getRecordStatus().intValue();
         long uniqueRecordId = bo.getRecordId();
@@ -114,7 +125,7 @@ public class ConsumeUploadCheck {
                 if (!checkFlag) {
                     // 根据卡流水号、机号、机器流水号和消费金额查询
                     originalVo = consumeDetailOriginalService.queryByConsumeMoney(bo.getCardNo(), bo.getTermNo(), bo.getTermRecordId(),
-                                                                                  bo.getConsumeMoney());
+                        bo.getConsumeMoney());
                     if (ObjectUtil.isEmpty(originalVo)) {
                         bo.setRecordStatus(108L);
                         // 判断脱机消费
@@ -141,7 +152,7 @@ public class ConsumeUploadCheck {
         if (ObjectUtil.isNotEmpty(consumeDetailVo)) {
             // 认为是重复上传,不再入账
             return R.fail(new ErrorInfo(400, ApiErrorTypeConstants.RECORD_IS_EXISTS, "原始消费记录已处理",
-                                        MessageFormat.format("标识为[{0}]的原始消费记录已处理", bo.getRecordId())));
+                MessageFormat.format("标识为[{0}]的原始消费记录已处理", bo.getRecordId())));
         }
         return R.ok();
     }
@@ -152,8 +163,8 @@ public class ConsumeUploadCheck {
         String consumeType = termVo.getConsumeType();
         // 分解扣费钱包,设置为可能有空值 ""或" ",要过滤掉
         List<String> bagCodes = StrUtil.split(consumeType, ",").stream()
-                                        .filter(s -> s != null && !s.trim().isEmpty())
-                                        .toList();
+            .filter(s -> s != null && !s.trim().isEmpty())
+            .toList();
         Long userId = userAccountVo.getUserId();
         // 可能会在处理过程中更改实际的消费金额,因此先取出来
         BigDecimal consumeMoney = bo.getConsumeMoney();
@@ -182,7 +193,7 @@ public class ConsumeUploadCheck {
                 sb.append(BagNameEnum.getMessage(Integer.valueOf(bagCode)));
                 doBagVos.add(bagVo);
                 log.warn("[上传交易]-[扣费钱包]-[钱包代码:{},钱包余额:{},消费金额:{},扣款金额:{},姓名:{}]", bagCode, balance, consumeMoney, doMoney,
-                         userAccountVo.getRealName());
+                    userAccountVo.getRealName());
                 break;
             } else {
                 // 如果消费金额>0,则可能会需要多钱包扣费
@@ -195,7 +206,7 @@ public class ConsumeUploadCheck {
                         sb.append(BagNameEnum.getMessage(Integer.parseInt(bagCode)));
                         doBagVos.add(bagVo);
                         log.warn("[上传交易]-[扣费钱包]-[钱包代码:{},钱包余额:{},消费金额:{},扣款金额:{},姓名:{}]", bagCode, balance, consumeMoney,
-                                 doMoney, userAccountVo.getRealName());
+                            doMoney, userAccountVo.getRealName());
                         break;
                     } else {
                         // 将钱包扣费为0,剩余待扣金额=消费金额-原钱包余额
@@ -205,7 +216,7 @@ public class ConsumeUploadCheck {
                         sb.append(BagNameEnum.getMessage(Integer.parseInt(bagCode)));
                         doBagVos.add(bagVo);
                         log.warn("[上传交易]-[扣费钱包]-[钱包代码:{},钱包余额:{},消费金额:{},扣款金额:{},姓名:{}]", bagCode, balance, balance,
-                                 doMoney, userAccountVo.getRealName());
+                            doMoney, userAccountVo.getRealName());
                     }
                 }
             }
@@ -235,7 +246,7 @@ public class ConsumeUploadCheck {
             if (RecordId == 0 && (recordStatus == 106 || recordStatus == 108 || recordStatus == 110 || recordStatus == 111)) {
                 if (recordStatus == 110 || recordStatus == 111) {
                     vo = consumeDetailOriginalService.queryByConsumeMoney(bo.getCardNo(), bo.getTermNo(), bo.getTermRecordId(),
-                                                                          bo.getOperatorMoney());
+                        bo.getOperatorMoney());
                     if (ObjectUtil.isNotEmpty(vo)) {
                         resetBoByOfflineResult(bo, vo);
                     }
@@ -252,7 +263,7 @@ public class ConsumeUploadCheck {
                     if (bo.getConsumeDate().getTime() > currentDate.getTime()) {
                         bo.setConsumeDate(currentDate);
                         originalId = RecordIdUtils.getRecordId(bo.getConsumeDate(), bo.getTermNo().shortValue(),
-                                                               bo.getTermRecordId().shortValue(), bo.getUserNo().intValue(), 0);
+                            bo.getTermRecordId().shortValue(), bo.getUserNo().intValue(), 0);
                         bo.setOriginalId(originalId);
                     }
                     vo = new XfConsumeDetailOriginalVo();
@@ -270,7 +281,7 @@ public class ConsumeUploadCheck {
         } catch (Exception e) {
             log.error("[处理脱机记录错误]-[{}]-[{}]", e.getMessage(), Arrays.toString(e.getStackTrace()));
             return R.fail(new ErrorInfo(400, ApiErrorTypeConstants.RECORD_IS_EXISTS, "处理脱机记录错误",
-                                        MessageFormat.format("错误消息:{0}", e.getMessage())));
+                MessageFormat.format("错误消息:{0}", e.getMessage())));
         }
     }