Browse Source

Merge remote-tracking branch 'origin/master'

xiari 11 months ago
parent
commit
63564f42c5

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

@@ -22,11 +22,13 @@ import org.dromara.common.core.enums.ConsumeRecordTypeEnum;
 import org.dromara.common.core.enums.CreditTypeEnum;
 import org.dromara.common.core.enums.ResultCodeEnum;
 import org.dromara.common.core.enums.SystemUseTypeEnum;
+import org.dromara.common.core.utils.SpringUtils;
 import org.dromara.common.json.utils.JsonUtils;
 import org.dromara.server.common.domain.consume.bo.ConsumptionBo;
 import org.dromara.server.consume.domain.vo.PtBagVo;
 import org.dromara.server.consume.domain.vo.XfConsumeDetailOriginalVo;
 import org.dromara.server.consume.domain.vo.XfTermVo;
+import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 
 import java.text.MessageFormat;
@@ -269,4 +271,16 @@ public class ConsumeBusiness {
         doMessage.forEach(System.out::println);
         return R.ok(MessageFormat.format("[同步消费完成]-[待处理:{0}条,成功:{1}条,失败:{2}条]", total, success.get(), fail.get()));
     }
+
+    @Async
+    public void postOrderAsync(ConsumptionBo bo, String mac, String xfPwd) {
+        R<ErrorInfo> result = SpringUtils.getAopProxy(this).postOrder(bo, mac, xfPwd);
+        if (R.isSuccess(result)) {
+            // 发送消息
+            if (ObjectUtil.equals(defaultConfig.getLocationFlag(), DefaultConstants.LOCAL_FLAG)) {
+                ThreadUtil.execAsync(() -> baseBusiness.sendCloudConsume(bo));
+            }
+        }
+        log.info("[上传交易结果完成]");
+    }
 }

+ 46 - 36
ruoyi-server/ruoyi-server-consume/src/main/java/org/dromara/server/consume/business/TermBusiness.java

@@ -61,55 +61,41 @@ public class TermBusiness {
     private final IXfTermService termService;
     private final TokenManager tokenManager;
     private final DefaultConfig defaultConfig;
-
+    // 常量定义(2000-01-01 00:00:00+8 的固定时间戳)
+    private static final long MIN_TIME = LocalDateTime.of(2000, 1, 1, 0, 0, 0)
+        .toInstant(ZoneOffset.of("+8")).toEpochMilli();
+    private static final long TOKEN_EXPIRE_HOURS = 2;
+    private static final long TOKEN_EXPIRE_MS = TOKEN_EXPIRE_HOURS * 3600000;
     public R<TermToken> getTermToken(Long termNo, String admin, String pwd) {
-        // XfTermVo termVo = termService.queryVoOneByNo(termNo);
         RemoteXfTermVo remoteVo = remoteTermService.queryByNo(termNo, defaultConfig.getTenantId());
         if (ObjectUtil.isEmpty(remoteVo)) {
             return R.fail(MessageFormat.format("机号为[{0}]的设备不存在", termNo), null);
         }
-        RemoteUserVo userVo = remoteUserService.selectUserVoByUserName(admin, defaultConfig.getTenantId());
-        if (ObjectUtil.isEmpty(userVo)) {
-            return R.fail(MessageFormat.format("用户为[{0}]的用户不存在", admin), null);
-        }
-        TermToken termToken = null;
-        synchronized (locker) {
-            String strTermNo = String.valueOf(termNo);
-            termToken = tokenManager.getTermToken().get(strTermNo);
-            if (ObjectUtil.isEmpty(termToken)) {
-                LocalDateTime ldt = LocalDateTime.of(2000, 1, 1, 0, 0, 0);
-                Date minDate = Date.from(ldt.toInstant(ZoneOffset.of("+8")));
-
-                LocalDateTime now = LocalDateTime.now();
-                LocalDateTime expireTime = now.plusHours(2);
-                // termToken = new TermToken(strTermNo, UUID.randomUUID().toString(), admin, new Date().getTime(), minDate.getTime(),
-                //     Date.from(expireTime.toInstant(ZoneOffset.of("+8"))).getTime());
+        //RemoteUserVo userVo = remoteUserService.selectUserVoByUserName(admin, defaultConfig.getTenantId());
+        //if (ObjectUtil.isEmpty(userVo)) {
+        //    return R.fail(MessageFormat.format("用户为[{0}]的用户不存在", admin), null);
+        //}
+        final String strTermNo = String.valueOf(termNo);
+        final String roomName = remoteVo.getRoomName();
 
-                termToken = new TermToken(strTermNo, UUID.randomUUID().toString(), admin, new Date().getTime(), minDate.getTime(),
-                                          Date.from(expireTime.toInstant(ZoneOffset.of("+8"))).getTime(), remoteVo.getRoomName());
+        // 使用termNo字符串作为锁对象,减小锁粒度
+        synchronized (strTermNo.intern()) {
+            Map<String, TermToken> tokenMap = tokenManager.getTermToken();
+            TermToken termToken = tokenMap.get(strTermNo);
 
-                tokenManager.getTermToken().put(strTermNo, termToken);
+            if (ObjectUtil.isEmpty(termToken)) {
+                termToken = createNewTermToken(strTermNo, admin, roomName);
+                tokenMap.put(strTermNo, termToken);
             } else {
-                if (termToken.getExpireTime() < new Date().getTime()) {
-                    LocalDateTime ldt = LocalDateTime.of(2000, 1, 1, 0, 0, 0);
-                    Date minDate = Date.from(ldt.toInstant(ZoneOffset.of("+8")));
-
-                    LocalDateTime now = LocalDateTime.now();
-                    LocalDateTime expireTime = now.plusHours(2);
-                    Date expireDate = Date.from(expireTime.toInstant(ZoneOffset.of("+8")));
-
-                    termToken.setAdmin(admin);
-                    termToken.setToken(UUID.randomUUID().toString());
-                    termToken.setDateTime(DateUtil.date().getTime());
-                    termToken.setAuthTime(minDate.getTime());
-                    termToken.setExpireTime(expireDate.getTime());
-                    termToken.setRoomName(remoteVo.getRoomName());
+                long currentTime = System.currentTimeMillis();
+                if (termToken.getExpireTime() < currentTime) {
+                    resetTermToken(termToken, admin, roomName);
                 } else {
                     termToken.setAdmin(admin);
                 }
             }
+            return R.ok(MessageFormat.format("获取token成功,设备编号[{0}],账号[{1}]", termNo, admin), termToken);
         }
-        return R.ok(MessageFormat.format("获取token成功,设备编号[{0}],账号[{1}]", termNo, admin), termToken);
     }
 
     public R<TermToken> getTermTokenNew(Long termNo, String admin, String pwd){
@@ -302,5 +288,29 @@ public class TermBusiness {
         RedisUtils.setCacheObject(cacheName, newToken, Duration.ofHours(4));
         return newToken;
     }
+    // 创建新令牌
+    private TermToken createNewTermToken(String termNo, String admin, String roomName) {
+        long currentTime = System.currentTimeMillis();
+        return new TermToken(
+            termNo,
+            UUID.randomUUID().toString(),
+            admin,
+            currentTime,
+            MIN_TIME,
+            currentTime + TOKEN_EXPIRE_MS,
+            roomName
+        );
+    }
+
+    // 重置过期令牌
+    private void resetTermToken(TermToken token, String admin, String roomName) {
+        long currentTime = System.currentTimeMillis();
+        token.setToken(UUID.randomUUID().toString());
+        token.setAdmin(admin);
+        token.setDateTime(currentTime);
+        token.setAuthTime(MIN_TIME);
+        token.setExpireTime(currentTime + TOKEN_EXPIRE_MS);
+        token.setRoomName(roomName);
+    }
 
 }

+ 2 - 2
ruoyi-server/ruoyi-server-consume/src/main/java/org/dromara/server/consume/controller/v1/AuthController.java

@@ -35,8 +35,8 @@ public class AuthController {
         if (ObjectUtil.isEmpty(pwd)) {
             pwd = "123456";
         }
-        // R<TermToken> mapResult = termBusiness.getTermToken(termId, admin, pwd);
-        R<TermToken> mapResult = termBusiness.getTermTokenNew(termId, admin, pwd);
+         R<TermToken> mapResult = termBusiness.getTermToken(termId, admin, pwd);
+        //R<TermToken> mapResult = termBusiness.getTermTokenNew(termId, admin, pwd);
 
         if (R.isError(mapResult)) {
             ErrorResult result = new ErrorResult();

+ 7 - 3
ruoyi-server/ruoyi-server-consume/src/main/java/org/dromara/server/consume/controller/v1/ConsumeController.java

@@ -22,6 +22,7 @@ import org.dromara.server.consume.convert.strategy.RecordConvertStrategyContent;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
@@ -48,6 +49,7 @@ public class ConsumeController {
     private final ConsumeBusiness consumeBusiness;
     private final BaseBusiness baseBusiness;
     private final DefaultConfig defaultConfig;
+    private final ThreadPoolTaskExecutor threadPoolTaskExecutor;
 
     /**
      * 请求消费(校园码)
@@ -68,7 +70,7 @@ public class ConsumeController {
         Object redisQrCode = RedisUtils.getCacheMapValue(CacheNames.SCHOOL_CODE, Long.toString(userNo));
         if (ObjectUtil.equals(qrcode, redisQrCode)) {
             ErrorResult result = ErrorResult.instance(HttpStatus.FORBIDDEN, "处理失败", 1, "PARAM_ERROR", "二维码失效",
-                                                      "请勿重复使用相同的二维码消费。");
+                "请勿重复使用相同的二维码消费。");
             return new ResponseEntity<Object>(result, null, HttpStatus.FORBIDDEN);
         }
         RedisUtils.setCacheMapValue(CacheNames.SCHOOL_CODE, Long.toString(userNo), qrcode);
@@ -169,7 +171,7 @@ public class ConsumeController {
     private Object doRecordData(Object record, String type, String mac, String xfPwd) {
         if (ObjectUtil.length(record) == 0) {
             ErrorResult result = ErrorResult.instance(HttpStatus.FORBIDDEN, "处理失败", 1, "PARAM_ERROR", "参数错误",
-                                                      "json字符串无法还原为对象,可能原因是格式不正确。");
+                "json字符串无法还原为对象,可能原因是格式不正确。");
             return new ResponseEntity<Object>(result, null, HttpStatus.FORBIDDEN);
         }
         ConsumptionBo bo = recordConvertStrategy.convert(record, "YC");
@@ -179,7 +181,9 @@ public class ConsumeController {
         if (Objects.equals(type, "requestConsume")) {
             errorInfo = consumeBusiness.createOrder(bo, mac, xfPwd);
         } else if (Objects.equals(type, "uploadRecord")) {
-            errorInfo = consumeBusiness.postOrder(bo, mac, xfPwd);
+            threadPoolTaskExecutor.submit(() -> consumeBusiness.postOrderAsync(bo, mac, xfPwd));
+            errorInfo = R.ok();
+            //errorInfo = consumeBusiness.postOrder(bo, mac, xfPwd);
         } else {
             errorInfo = consumeBusiness.fullOrder(bo, mac, xfPwd);
         }

+ 3 - 0
ruoyi-server/ruoyi-server-consume/src/main/java/org/dromara/server/consume/convert/strategy/impl/YcRecordConvertStrategyImpl.java

@@ -70,6 +70,9 @@ public class YcRecordConvertStrategyImpl implements IRecordConvertStrategy {
             }else{
                 consumptionBo.setCreditType(CreditTypeEnum.TERM_CONSUME.code());
             }
+            //金额精确到两位小数
+            String balance =ObjectUtil.isEmpty(yc.get("cardValue")) ? "0.00": yc.get("cardValue").toString();
+            consumptionBo.setBalance(new BigDecimal(balance).setScale(2, RoundingMode.HALF_UP));
 
             return consumptionBo;
         }