Pārlūkot izejas kodu

Merge remote-tracking branch 'origin/master'

wujiefeng 11 mēneši atpakaļ
vecāks
revīzija
60bfe72c67
23 mainītis faili ar 266 papildinājumiem un 126 dzēšanām
  1. 2 2
      FullCardClient/src/main/java/com/zhongshu/card/client/model/payment/CreateOrderParam.java
  2. 22 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/config/RedisConfiguration.java
  3. 7 1
      FullCardServer/src/main/java/com/zhongshu/card/server/core/controller/org/TestController.java
  4. 2 2
      FullCardServer/src/main/java/com/zhongshu/card/server/core/dao/payment/impl/ExpenseFlowDaoImpl.java
  5. 0 12
      FullCardServer/src/main/java/com/zhongshu/card/server/core/dao/projectAbout/impl/ProjectMainPaySettingDaoImpl.java
  6. 1 1
      FullCardServer/src/main/java/com/zhongshu/card/server/core/dataConfig/OrderConfig.java
  7. 6 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/domain/base/SuperMain.java
  8. 0 3
      FullCardServer/src/main/java/com/zhongshu/card/server/core/domain/devices/DeviceUseRecords.java
  9. 0 6
      FullCardServer/src/main/java/com/zhongshu/card/server/core/domain/paySetting/ProjectMainPaySetting.java
  10. 5 3
      FullCardServer/src/main/java/com/zhongshu/card/server/core/domain/payment/ExpenseFlow.java
  11. 0 6
      FullCardServer/src/main/java/com/zhongshu/card/server/core/domain/schedule/ScheduleTaskConfig.java
  12. 1 53
      FullCardServer/src/main/java/com/zhongshu/card/server/core/httpRequest/ApiRequestService.java
  13. 0 21
      FullCardServer/src/main/java/com/zhongshu/card/server/core/httpRequest/conf/IotCenterConf.java
  14. 4 1
      FullCardServer/src/main/java/com/zhongshu/card/server/core/listener/OrganizationEventListener.java
  15. 39 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/listener/RedisKeyExpirationListener.java
  16. 32 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/base/CommonService.java
  17. 11 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/keyExpire/KeyExpire.java
  18. 66 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/keyExpire/impl/OrderKeyExpire.java
  19. 59 1
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/payment/ExpenseFlowServiceImpl.java
  20. 4 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/payment/PayCallService.java
  21. 0 8
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/user/ForgotPassWordService.java
  22. 3 1
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/user/UserAccountServiceImpl.java
  23. 2 5
      FullCardServer/src/main/resources/application-dev.yml

+ 2 - 2
FullCardClient/src/main/java/com/zhongshu/card/client/model/payment/CreateOrderParam.java

@@ -1,7 +1,7 @@
 package com.zhongshu.card.client.model.payment;
 
-import com.github.microservice.types.deviceUse.OrderFromType;
 import com.github.microservice.types.OrderModeType;
+import com.github.microservice.types.deviceUse.OrderFromType;
 import com.github.microservice.types.payment.ChargeableType;
 import com.github.microservice.types.payment.PaymentDeviceType;
 import com.github.microservice.types.payment.PaymentType;
@@ -67,7 +67,7 @@ public class CreateOrderParam {
     @Schema(description = "消费类型,如:餐饮消费、水费、电费 等等")
     private String payType;
 
-    @Schema(description = "订单支付有效期时间,毫秒")
+    @Schema(description = "订单支付有效期时间,毫秒,如:30分钟")
     private Long expirationTime;
 
     @Schema(description = "微信小程序的openId")

+ 22 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/config/RedisConfiguration.java

@@ -0,0 +1,22 @@
+package com.zhongshu.card.server.core.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.listener.RedisMessageListenerContainer;
+
+/**
+ * @author TRX
+ * @date 2024/12/23
+ */
+@Configuration
+public class RedisConfiguration {
+
+    @Bean
+    RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory connectionFactory) {
+        final RedisMessageListenerContainer container = new RedisMessageListenerContainer();
+        container.setConnectionFactory(connectionFactory);
+        return container;
+    }
+
+}

+ 7 - 1
FullCardServer/src/main/java/com/zhongshu/card/server/core/controller/org/TestController.java

@@ -6,6 +6,7 @@ import com.zhongshu.card.client.model.test.TestUserParam;
 import com.zhongshu.card.client.utils.DateUtils;
 import com.zhongshu.card.server.core.service.TestService;
 import com.zhongshu.card.server.core.service.devices.DeviceInfoServiceImpl;
+import com.zhongshu.card.server.core.service.keyExpire.impl.OrderKeyExpire;
 import com.zhongshu.card.server.core.service.openAPI.OpenAPIRegisterService;
 import com.zhongshu.card.server.core.service.payment.PayCallService;
 import io.swagger.v3.oas.annotations.Operation;
@@ -39,6 +40,9 @@ public class TestController {
     @Autowired
     private PayCallService payCallService;
 
+    @Autowired
+    private OrderKeyExpire orderKeyExpire;
+
     @Operation(summary = "测试接口", description = "测试接口")
     @RequestMapping(value = "text", method = {RequestMethod.GET})
     public ResultContent text() {
@@ -61,7 +65,9 @@ public class TestController {
     @Operation(summary = "测试用户同步(From)", description = "测试隐患同步")
     @RequestMapping(value = "testAddUser1", method = {RequestMethod.POST})
     public ResultContent testAddUser1(@Parameter TestUserInfoParam param) {
-        log.info("testAddUser1... {}", param.getNickname());
+//        log.info("testAddUser1... {}", param.getNickname());
+        orderKeyExpire.saveKey("2025032115212400002", 5000L);
+
         return ResultContent.buildSuccess();
     }
 

+ 2 - 2
FullCardServer/src/main/java/com/zhongshu/card/server/core/dao/payment/impl/ExpenseFlowDaoImpl.java

@@ -545,8 +545,8 @@ public class ExpenseFlowDaoImpl extends BaseImpl implements ExpenseFlowDaoExtend
     public ExpenseFlow init(String mqttDataId, String token) {
         ExpenseFlow doc = null;
         try {
-            Query query = Query.query(Criteria.where("mqttDataId").is(mqttDataId).and("token").isNull());
-            Update update = new Update().set("token", token).set("createTime", System.currentTimeMillis());
+            Query query = Query.query(Criteria.where("mqttDataId").is(mqttDataId).and("createToken").isNull());
+            Update update = new Update().set("createToken", token).set("createTime", System.currentTimeMillis());
             FindAndModifyOptions options = new FindAndModifyOptions().upsert(true).returnNew(true);
             doc = mongoTemplate.findAndModify(query, update, options, ExpenseFlow.class);
         } catch (Exception e) {

+ 0 - 12
FullCardServer/src/main/java/com/zhongshu/card/server/core/dao/projectAbout/impl/ProjectMainPaySettingDaoImpl.java

@@ -2,28 +2,16 @@ package com.zhongshu.card.server.core.dao.projectAbout.impl;
 
 import com.github.microservice.components.data.mongo.mongo.helper.DBHelper;
 import com.github.microservice.core.util.token.TokenUtil;
-import com.zhongshu.card.client.model.projectAbout.PayChannelConfigSearch;
 import com.zhongshu.card.server.core.dao.BaseImpl;
-import com.zhongshu.card.server.core.dao.projectAbout.extend.PayChannelConfigDaoExtend;
 import com.zhongshu.card.server.core.dao.projectAbout.extend.ProjectMainPaySettingDaoExtend;
-import com.zhongshu.card.server.core.domain.paySetting.PayChannelConfig;
 import com.zhongshu.card.server.core.domain.paySetting.ProjectMainPaySetting;
-import org.apache.commons.lang3.ObjectUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.Pageable;
-import org.springframework.data.domain.Sort;
 import org.springframework.data.mongodb.core.FindAndModifyOptions;
 import org.springframework.data.mongodb.core.MongoTemplate;
 import org.springframework.data.mongodb.core.query.Criteria;
 import org.springframework.data.mongodb.core.query.Query;
 import org.springframework.data.mongodb.core.query.Update;
-import org.springframework.util.CollectionUtils;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.regex.Pattern;
 
 /**
  * @Author TRX

+ 1 - 1
FullCardServer/src/main/java/com/zhongshu/card/server/core/dataConfig/OrderConfig.java

@@ -7,7 +7,7 @@ package com.zhongshu.card.server.core.dataConfig;
 public class OrderConfig {
 
     // 订单最大有效时间 (默认设置)
-    public static final Long orderExpirationTime = 5 * 60 * 1000L;
+    public static final Long orderExpirationTime = 10 * 60 * 1000L;
 
     // 订单微信支付 回调的数据key
     public static final String wxSurePaymentTypeOrderPay = "initWxSurePaymentTypeOrderPay";

+ 6 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/domain/base/SuperMain.java

@@ -56,4 +56,10 @@ public class SuperMain extends SuperEntity {
 
     @Schema(description = "添加用户电话", hidden = true)
     private String updatePhone;
+
+    @Schema(description = "")
+    private String token;
+
+    @Schema(description = "锁过期时间")
+    private Long expireAt;
 }

+ 0 - 3
FullCardServer/src/main/java/com/zhongshu/card/server/core/domain/devices/DeviceUseRecords.java

@@ -37,9 +37,6 @@ public class DeviceUseRecords extends SuperMain {
     @Schema(description = "mqtt推送生成的业务数据ID")
     private String mqttDataId;
 
-    @Schema(description = "token")
-    private String token;
-
     @Schema(description = "关联的项目名称")
     private String projectName;
 

+ 0 - 6
FullCardServer/src/main/java/com/zhongshu/card/server/core/domain/paySetting/ProjectMainPaySetting.java

@@ -110,10 +110,4 @@ public class ProjectMainPaySetting extends SuperMain {
     @Schema(description = "全局机构分账比例,0-100")
     private BigDecimal orgScale = BigDecimal.ZERO;
 
-    @Schema(description = "锁过期时间")
-    private Long expireAt;
-
-    @Schema(description = "锁token")
-    private String token;
-
 }

+ 5 - 3
FullCardServer/src/main/java/com/zhongshu/card/server/core/domain/payment/ExpenseFlow.java

@@ -51,8 +51,7 @@ public class ExpenseFlow extends SuperMain {
     @Schema(description = "mqtt推送生成的业务数据ID")
     private String mqttDataId;
 
-    @Schema(description = "")
-    private String token;
+    private String createToken;
 
     @Indexed
     @Schema(description = "订单的总体状态,待付款、支付中、已支付、已退款")
@@ -83,9 +82,12 @@ public class ExpenseFlow extends SuperMain {
     @Schema(description = "订单生效时间")
     private Long startTime;
 
-    @Schema(description = "订单支付失效时间, (不会为空,有默认值)")
+    @Schema(description = "订单支付失效时间,时间毫秒数,(不会为空,有默认值)")
     private Long expirationTime;
 
+    @Schema(description = "设置的过期时间,过期时间值,如: 2000 毫秒 = 2秒")
+    private Long expireTime;
+
     @Schema(description = "消费金额(单位:分)")
     @Indexed
     private BigDecimal payAmount;

+ 0 - 6
FullCardServer/src/main/java/com/zhongshu/card/server/core/domain/schedule/ScheduleTaskConfig.java

@@ -42,10 +42,4 @@ public class ScheduleTaskConfig extends SuperMain {
     @Schema(description = "执行状态 1.正在执行 0.等待执行")
     private Integer executeStatus = 0;
 
-    @Schema(description = "中心token")
-    private String token;
-
-    @Schema(description = "过期时间")
-    private Long expireAt;
-
 }

+ 1 - 53
FullCardServer/src/main/java/com/zhongshu/card/server/core/httpRequest/ApiRequestService.java

@@ -11,13 +11,9 @@ import com.github.microservice.core.util.net.apache.ResponseModel;
 import com.github.microservice.http.APIResponseModel;
 import com.github.microservice.http.ApiConfParam;
 import com.github.microservice.models.hxz.WxPayResult;
-import com.zhongshu.card.server.core.httpRequest.conf.IotCenterAPIConfig;
-import com.zhongshu.card.server.core.httpRequest.conf.IotCenterConf;
 import com.zhongshu.card.server.core.service.base.SuperService;
 import com.zhongshu.card.server.core.service.payment.RequestInfoService;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.ObjectUtils;
-import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -30,55 +26,7 @@ import org.springframework.stereotype.Service;
 public class ApiRequestService extends SuperService {
 
     @Autowired
-    IotCenterConf iotCenterConf;
-
-    @Autowired
-    RequestInfoService requestInfoService;
-
-    /**
-     * 发送请求
-     *
-     * @param apiName
-     * @param data
-     * @return
-     */
-    public APIResponseModel sendIotCenterAPI(String apiName, Object data) {
-        APIResponseModel responseModel = new APIResponseModel();
-        responseModel.setRequestData(data);
-        if (StringUtils.isEmpty(iotCenterConf.getUrl())) {
-            responseModel.setIsFailed("未配置物联网平台URL");
-            return responseModel;
-        }
-        ApiConfParam apiConfParam = IotCenterAPIConfig.getApiConfParam(apiName);
-        if (ObjectUtils.isEmpty(apiConfParam)) {
-            responseModel.setIsFailed("未找到API配置");
-            return responseModel;
-        }
-        StopWatch stopWatch = new StopWatch();
-        stopWatch.start();
-        try {
-            String url = iotCenterConf.getUrl() + iotCenterConf.getIotserverName() + apiConfParam.getApiName();
-            ResponseModel request = HttpClientUtil.request(HttpModel.builder().url(url).method(
-                    MethodType.Json).charset("utf-8").body(data).build());
-            if (request.getCode() == 200) {
-                responseModel = BeanUtil.copyProperties(request.getBody(), APIResponseModel.class);
-            } else {
-                responseModel = BeanUtil.copyProperties(request.getBody(), APIResponseModel.class);
-            }
-            // 请求API参数
-            responseModel.setParam(apiConfParam);
-        } catch (Exception e) {
-            e.printStackTrace();
-            responseModel.setIsFailed(String.format("请求出错:%s", e.getMessage()));
-            return responseModel;
-        }
-        stopWatch.stop();
-        // 请求时间:毫秒
-        responseModel.setMillis(stopWatch.getTotalTimeMillis());
-        // 请求日志
-        requestInfoService.addIotRequestInfo(data, responseModel);
-        return responseModel;
-    }
+    private RequestInfoService requestInfoService;
 
     /**
      * 访问地址

+ 0 - 21
FullCardServer/src/main/java/com/zhongshu/card/server/core/httpRequest/conf/IotCenterConf.java

@@ -1,21 +0,0 @@
-package com.zhongshu.card.server.core.httpRequest.conf;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.stereotype.Component;
-
-@Data
-@Component
-@NoArgsConstructor
-@AllArgsConstructor
-@ConfigurationProperties(prefix = "iotcenter")
-public class IotCenterConf {
-    /**
-     * 物联网平台地址配置
-     */
-    private String url = "";
-
-    private String iotserverName = "";
-}

+ 4 - 1
FullCardServer/src/main/java/com/zhongshu/card/server/core/listener/OrganizationEventListener.java

@@ -6,6 +6,9 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.context.ApplicationListener;
 import org.springframework.stereotype.Component;
 
+/**
+ * 机构添加/编辑的事件
+ */
 @Slf4j
 @Component
 public class OrganizationEventListener implements ApplicationListener<OrganizationApplicationEvent> {
@@ -16,7 +19,7 @@ public class OrganizationEventListener implements ApplicationListener<Organizati
         AuthEventType eventType = event.getStreamModel().getParameter().getEventType();
         log.info("OrganizationEventListener {} {}", epId, eventType);
         // 初始
-        if(eventType == AuthEventType.Add) {
+        if (eventType == AuthEventType.Add) {
 
         }
     }

+ 39 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/listener/RedisKeyExpirationListener.java

@@ -0,0 +1,39 @@
+package com.zhongshu.card.server.core.listener;
+
+import com.zhongshu.card.server.core.service.keyExpire.KeyExpire;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.data.redis.connection.Message;
+import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
+import org.springframework.data.redis.listener.RedisMessageListenerContainer;
+import org.springframework.stereotype.Component;
+
+/**
+ * redis 过期的key
+ * @author TRX
+ * @date 2024/12/23
+ */
+@Component
+@Slf4j
+public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
+
+    @Autowired
+    private ApplicationContext applicationContext;
+
+    public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
+        super(listenerContainer);
+    }
+
+    @Override
+    public void onMessage(Message message, byte[] pattern) {
+        // 获取到过期的键
+        String expiredKey = message.toString();
+        log.info("redis expired: {}", expiredKey);
+        this.applicationContext.getBeansOfType(KeyExpire.class).values().forEach(it -> {
+            if (it.isAccessKey(expiredKey)) {
+                it.handle(expiredKey);
+            }
+        });
+    }
+}

+ 32 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/base/CommonService.java

@@ -2,18 +2,22 @@ package com.zhongshu.card.server.core.service.base;
 
 import com.github.microservice.auth.security.type.AuthType;
 import com.github.microservice.core.util.net.HttpClient;
+import com.github.microservice.core.util.token.TokenUtil;
 import com.github.microservice.models.common.EnumListModel;
 import com.github.microservice.net.ResultContent;
 import com.github.microservice.types.common.CommonEnum;
 import com.mongodb.client.result.UpdateResult;
 import com.zhongshu.card.client.type.OrganizationState;
 import com.zhongshu.card.server.core.dao.org.OrganizationDao;
+import com.zhongshu.card.server.core.domain.base.SuperMain;
 import com.zhongshu.card.server.core.domain.org.Organization;
+import com.zhongshu.card.server.core.domain.paySetting.ProjectMainPaySetting;
 import com.zhongshu.card.server.core.util.CommonUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.ObjectUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.FindAndModifyOptions;
 import org.springframework.data.mongodb.core.MongoTemplate;
 import org.springframework.data.mongodb.core.query.Criteria;
 import org.springframework.data.mongodb.core.query.Query;
@@ -188,4 +192,32 @@ public class CommonService {
         return base64;
     }
 
+    public String acquire(String id, Long expiration, SuperMain superMain) {
+        Query query = Query.query(Criteria.where("_id").is(id).and("token").isNull());
+        String token = TokenUtil.create();
+        Update update = new Update().set("expireAt", System.currentTimeMillis() + expiration).set("token", token);
+
+        FindAndModifyOptions options = new FindAndModifyOptions().upsert(false).returnNew(true);
+        SuperMain doc = mongoTemplate.findAndModify(query, update, options, superMain.getClass());
+        if (doc == null) {
+            SuperMain lockObj = mongoTemplate.findOne(Query.query(Criteria.where("_id").is(id)), ProjectMainPaySetting.class);
+            doc = lockObj;
+        }
+        boolean locked = doc != null && doc.getToken() != null && doc.getToken().equals(token);
+
+        if (!locked && doc != null && doc.getExpireAt() < System.currentTimeMillis()) {
+            release(id, superMain);
+            return this.acquire(id, expiration, superMain);
+        }
+        return locked ? token : null;
+    }
+
+    public boolean release(String id, SuperMain superMain) {
+        Query releaseQuery = Query.query(Criteria.where("_id").is(id));
+        Update releaseUpdate = new Update().set("expireAt", null).set("token", null);
+        FindAndModifyOptions releaseOptions = new FindAndModifyOptions().upsert(true).returnNew(true);
+        SuperMain flowDisposition = mongoTemplate.findAndModify(releaseQuery, releaseUpdate, releaseOptions, superMain.getClass());
+        return StringUtils.isEmpty(flowDisposition.getToken());
+    }
+
 }

+ 11 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/keyExpire/KeyExpire.java

@@ -0,0 +1,11 @@
+package com.zhongshu.card.server.core.service.keyExpire;
+
+import com.github.microservice.net.ResultContent;
+
+public interface KeyExpire {
+
+    boolean isAccessKey(String key);
+
+    ResultContent<Object> handle(String key);
+
+}

+ 66 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/keyExpire/impl/OrderKeyExpire.java

@@ -0,0 +1,66 @@
+package com.zhongshu.card.server.core.service.keyExpire.impl;
+
+import com.github.microservice.net.ResultContent;
+import com.zhongshu.card.server.core.dataConfig.OrderConfig;
+import com.zhongshu.card.server.core.service.base.RedisService;
+import com.zhongshu.card.server.core.service.keyExpire.KeyExpire;
+import com.zhongshu.card.server.core.service.payment.ExpenseFlowServiceImpl;
+import com.zhongshu.card.server.core.util.CommonUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ *
+ * @author TRX
+ * @date 2025/3/28
+ */
+@Slf4j
+@Component
+public class OrderKeyExpire implements KeyExpire {
+
+    @Autowired
+    private ExpenseFlowServiceImpl expenseFlowService;
+
+    @Autowired
+    private RedisService redisService;
+
+    private String keyStart() {
+        return "order_";
+    }
+
+    private String buildKey(String orderNo) {
+        return String.format("%s%s", keyStart(), orderNo);
+    }
+
+    public void saveKey(String orderNo, Long time) {
+        if (CommonUtil.longIsEmpty(time)) {
+            time = OrderConfig.orderExpirationTime;
+        }
+        redisService.setValue(buildKey(orderNo), orderNo, time);
+    }
+
+    public void deleteKey(String orderNo) {
+        redisService.removeValue(buildKey(orderNo));
+    }
+
+    @Override
+    public boolean isAccessKey(String key) {
+        if (StringUtils.isEmpty(key)) {
+            return false;
+        }
+        return key.startsWith(keyStart());
+    }
+
+    @Override
+    public ResultContent<Object> handle(String key) {
+        if (StringUtils.isEmpty(key)) {
+            return ResultContent.buildFail("key is empty");
+        }
+        String orderNo = key.replaceAll(keyStart(), "");
+        log.info("orderNo:{}", orderNo);
+        expenseFlowService.handleDelayedTask(orderNo);
+        return ResultContent.buildSuccess();
+    }
+}

+ 59 - 1
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/payment/ExpenseFlowServiceImpl.java

@@ -55,6 +55,7 @@ import com.zhongshu.card.server.core.httpRequest.ApiRequestService;
 import com.zhongshu.card.server.core.service.base.CommonService;
 import com.zhongshu.card.server.core.service.base.SuperService;
 import com.zhongshu.card.server.core.service.devices.DeviceInfoServiceImpl;
+import com.zhongshu.card.server.core.service.keyExpire.impl.OrderKeyExpire;
 import com.zhongshu.card.server.core.service.mqtt.MqttServiceImpl;
 import com.zhongshu.card.server.core.service.org.OrganizationServiceImpl;
 import com.zhongshu.card.server.core.service.org.OrganizationUserServiceImpl;
@@ -132,8 +133,11 @@ public class ExpenseFlowServiceImpl extends SuperService implements ExpenseFlowS
     @Autowired
     private OrganizationUserServiceImpl organizationUserService;
 
+    @Autowired
+    private OrderKeyExpire orderKeyExpire;
+
     /**
-     * 创建流水
+     * 创建流水/订单记录
      *
      * @param mqttDataId
      * @return
@@ -217,9 +221,12 @@ public class ExpenseFlowServiceImpl extends SuperService implements ExpenseFlowS
             expirationTime = OrderConfig.orderExpirationTime;
         }
         expenseFlow.setExpirationTime(System.currentTimeMillis() + expirationTime);
+        expenseFlow.setExpireTime(expirationTime);
 
         // 验证参数、填充数据
         commonVerifyExpenseFlow(expenseFlow);
+        // 开始计时订单过期时间
+        delayedTimeout(expenseFlow);
         return ResultContent.buildSuccess(expenseFlow);
     }
 
@@ -525,7 +532,10 @@ public class ExpenseFlowServiceImpl extends SuperService implements ExpenseFlowS
             sendMessageModel.setUserId(userId);
             log.info("mq topic : {}", topic);
             mqttService.sendMessage(sendMessageModel);
+            // 记录设备使用记录数据
             payCallService.buildDeviceUseRecord(expenseFlow);
+            // 取消定时任务
+            clearDelayedTimeout(expenseFlow);
         } else {
             log.error("wxSurePaymentTypeOrderPayCallSuccess 订单为空: {}", orderNo);
         }
@@ -582,6 +592,7 @@ public class ExpenseFlowServiceImpl extends SuperService implements ExpenseFlowS
             entity.setPaymentType(PaymentType.UserWallet);
             expenseFlowDao.save(entity);
         }
+        // 添加设备使用记录
         payCallService.buildDeviceUseRecord(entity);
         return ResultContent.buildSuccess();
     }
@@ -1131,7 +1142,54 @@ public class ExpenseFlowServiceImpl extends SuperService implements ExpenseFlowS
             Map<String, Object> standardData = new HashMap<>();
             standardData.put("orderState", OrderState.Expired);
             standardData.put("payRemark", "超时关闭");
+
+            standardData.put("isClosed", Boolean.TRUE);
+            standardData.put("closeUserId", "");
+            standardData.put("closeReason", "超时关闭");
+            standardData.put("closeTime", System.currentTimeMillis());
+
             commonService.updateData(entity.getId(), standardData, ExpenseFlow.class.getSimpleName());
+            clearDelayedTimeout(entity);
+        }
+    }
+
+    /**
+     * 把新创建的订单加入延时
+     */
+    public void delayedTimeout(ExpenseFlow order) {
+        if (ObjectUtils.isEmpty(order)) {
+            return;
+        }
+        orderKeyExpire.saveKey(order.getOrderNo(), order.getExpireTime());
+    }
+
+    public void clearDelayedTimeout(ExpenseFlow order) {
+        if (ObjectUtils.isEmpty(order)) {
+            return;
+        }
+        orderKeyExpire.deleteKey(order.getOrderNo());
+    }
+
+    public void handleDelayedTask(String orderNo) {
+        ExpenseFlow expenseFlow = expenseFlowDao.findTopByOrderNoOrderByCreateTimeDesc(orderNo);
+        if (ObjectUtils.isEmpty(expenseFlow)) {
+            return;
+        }
+        String id = expenseFlow.getId();
+        try {
+            String lockKey = commonService.acquire(id, 5000L, expenseFlow);
+            log.info("lockKey: {}", lockKey);
+            if (StringUtils.isNotEmpty(lockKey)) {
+                if (expenseFlow.getOrderState() == OrderState.WAIT_PAYMENT
+                        && expenseFlow.getExpirationTime() <= System.currentTimeMillis()) {
+                    // 为待支付并且支付时间已过
+                    markOrderTimeOut(expenseFlow);
+                }
+            }
+        } catch (Exception e) {
+            log.info(e.getMessage());
+        } finally {
+            commonService.release(id, expenseFlow);
         }
     }
 

+ 4 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/payment/PayCallService.java

@@ -117,6 +117,9 @@ public class PayCallService extends SuperService {
     @Autowired
     private OrganizationUserServiceImpl organizationUserService;
 
+    @Autowired
+    private ExpenseFlowServiceImpl expenseFlowService;
+
     /**
      * 统一调用支付服务 (无感方式,直接后台 扣款)
      *
@@ -205,6 +208,7 @@ public class PayCallService extends SuperService {
             // 支付成功
             if (entity.getIsPaySuccess() != null && entity.getIsPaySuccess()) {
                 b = true;
+                expenseFlowService.clearDelayedTimeout(entity);
                 break;
             }
         }

+ 0 - 8
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/user/ForgotPassWordService.java

@@ -9,10 +9,8 @@ import com.zhongshu.card.client.model.forgotPassword.ValidateUserParam;
 import com.zhongshu.card.server.core.dao.org.UserCountDao;
 import com.zhongshu.card.server.core.domain.org.UserAccount;
 import com.zhongshu.card.server.core.domain.projectAbout.ProjectCommonConfig;
-import com.zhongshu.card.server.core.service.base.CommonService;
 import com.zhongshu.card.server.core.service.base.RedisService;
 import com.zhongshu.card.server.core.service.base.SuperService;
-import com.zhongshu.card.server.core.service.org.OrganizationUserServiceImpl;
 import com.zhongshu.card.server.core.service.projectAbout.ProjectCommonConfigService;
 import com.zhongshu.card.server.core.util.CommonUtil;
 import com.zhongshu.card.server.core.util.ValidateResult;
@@ -33,9 +31,6 @@ import org.springframework.web.multipart.MultipartFile;
 @Slf4j
 public class ForgotPassWordService extends SuperService {
 
-    @Autowired
-    private OrganizationUserServiceImpl organizationUserService;
-
     @Autowired
     private UserCountDao userCountDao;
 
@@ -54,9 +49,6 @@ public class ForgotPassWordService extends SuperService {
     @Autowired
     private UserFaceService userFaceService;
 
-    @Autowired
-    private CommonService commonService;
-
     // 随机key存储的时间 10 分钟
     private final Long keyTime = 60 * 10L;
 

+ 3 - 1
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/user/UserAccountServiceImpl.java

@@ -664,6 +664,7 @@ public class UserAccountServiceImpl extends SuperService implements UserAccountS
         if (StringUtils.isEmpty(oid)) {
             oid = getCurrentOid();
         }
+        // 查询用户基本信息
         Page<UserAccount> page = userCountDao.page(pageable, param);
 
         List<UserCountAboutRoleModel> models = new ArrayList<>();
@@ -725,7 +726,8 @@ public class UserAccountServiceImpl extends SuperService implements UserAccountS
         if (ObjectUtils.isNotEmpty(entity)) {
             model = new UserCountAboutRoleModel();
             BeanUtils.copyProperties(entity, model);
-            // 角色
+
+            // 角色(指定机构上角色信息)
             if (StringUtils.isNotEmpty(oid)) {
                 OrganizationUser organizationUser = organizationUserDao.findTopByUserIdAndOid(entity.getUserId(), oid);
                 if (ObjectUtils.isNotEmpty(organizationUser)) {

+ 2 - 5
FullCardServer/src/main/resources/application-dev.yml

@@ -34,6 +34,8 @@ spring:
           max-idle: 16   # 最大空闲连接
           min-idle: 8   # 最小空闲连接
           max-wait: 100ms # 连接等待时间
+      key-value-store:
+        notify-keyspace-events: Ex
 
 # c端的小程序配置 (学生端)
 cwechat:
@@ -82,11 +84,6 @@ oss:
   accessKeySecret: Vbt3NiZfi6f47vU8QcfqQIsjiFo6vH
   arn: acs:ram::1540890773231210:role/oss
 
-# 物联网平台的配置
-iotcenter:
-  url: http://172.24.50.53:9101
-  iotserverName: # 服务名称
-
 #logging:
 #  level:
 #    org: