Explorar o código

添加邀请逻辑

wujiefeng hai 9 meses
pai
achega
3a2dec6bc0
Modificáronse 31 ficheiros con 1105 adicións e 586 borrados
  1. 6 0
      RewardServer/pom.xml
  2. 15 0
      RewardServer/src/main/java/com/zhongshu/reward/server/core/config/BatchConfig.java
  3. 2 1
      RewardServer/src/main/java/com/zhongshu/reward/server/core/config/MongoConfig.java
  4. 33 22
      RewardServer/src/main/java/com/zhongshu/reward/server/core/controller/TestController.java
  5. 0 6
      RewardServer/src/main/java/com/zhongshu/reward/server/core/controller/wallet/WalletController.java
  6. 14 6
      RewardServer/src/main/java/com/zhongshu/reward/server/core/dao/Impl/WalletDaoImpl.java
  7. 15 0
      RewardServer/src/main/java/com/zhongshu/reward/server/core/dao/Impl/WalletReceiptsDaoImpl.java
  8. 22 0
      RewardServer/src/main/java/com/zhongshu/reward/server/core/dao/Impl/WxTransferBatchDaoImpl.java
  9. 2 0
      RewardServer/src/main/java/com/zhongshu/reward/server/core/dao/WalletReceiptsDao.java
  10. 6 1
      RewardServer/src/main/java/com/zhongshu/reward/server/core/dao/extend/WalletDaoExtend.java
  11. 2 0
      RewardServer/src/main/java/com/zhongshu/reward/server/core/dao/extend/WalletReceiptsDaoExtend.java
  12. 2 0
      RewardServer/src/main/java/com/zhongshu/reward/server/core/dao/extend/WxTransferBatchDaoExtend.java
  13. 13 0
      RewardServer/src/main/java/com/zhongshu/reward/server/core/domain/TransferRuler.java
  14. 3 0
      RewardServer/src/main/java/com/zhongshu/reward/server/core/domain/Wallet.java
  15. 17 1
      RewardServer/src/main/java/com/zhongshu/reward/server/core/domain/WalletReceipts.java
  16. 127 0
      RewardServer/src/main/java/com/zhongshu/reward/server/core/helper/RedisHelper.java
  17. 96 0
      RewardServer/src/main/java/com/zhongshu/reward/server/core/service/GoodsReceiptsService.java
  18. 0 73
      RewardServer/src/main/java/com/zhongshu/reward/server/core/service/InviteReceiptsRulerService.java
  19. 320 0
      RewardServer/src/main/java/com/zhongshu/reward/server/core/service/InviteReceiptsService.java
  20. 11 251
      RewardServer/src/main/java/com/zhongshu/reward/server/core/service/WalletReceiptsService.java
  21. 136 86
      RewardServer/src/main/java/com/zhongshu/reward/server/core/service/WxTransferService.java
  22. 15 0
      RewardServer/src/main/java/com/zhongshu/reward/server/core/stream/OrderStream.java
  23. 5 2
      RewardServer/src/main/java/com/zhongshu/reward/server/core/stream/VipUserStream.java
  24. 126 0
      RewardServer/src/main/java/com/zhongshu/reward/server/core/timer/TransferStatusTimer.java
  25. 29 23
      RewardServer/src/main/java/com/zhongshu/reward/server/core/timer/WalletTimer.java
  26. 13 0
      RewardServer/src/main/java/com/zhongshu/reward/server/core/util/DateUtils.java
  27. 51 38
      RewardServer/src/main/java/com/zhongshu/reward/server/core/util/JedisUtil.java
  28. 0 74
      RewardServer/src/main/java/com/zhongshu/reward/server/core/util/RedisDistributedLock.java
  29. 19 0
      RewardServer/src/main/java/com/zhongshu/reward/server/core/util/wx/BusinessUtil.java
  30. 1 1
      RewardServer/src/main/resources/application-dev.yml
  31. 4 1
      RewardServer/src/main/resources/application.yml

+ 6 - 0
RewardServer/pom.xml

@@ -110,6 +110,12 @@
 			<version>4.4.2</version>
 		</dependency>
 
+		<dependency>
+			<groupId>com.zswl.cloud.SpringBatchService</groupId>
+			<artifactId>SpringBatchServiceClient</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+
 <!--		<dependency>-->
 <!--			<groupId>org.redisson</groupId>-->
 <!--			<artifactId>redisson-spring-boot-starter</artifactId>-->

+ 15 - 0
RewardServer/src/main/java/com/zhongshu/reward/server/core/config/BatchConfig.java

@@ -0,0 +1,15 @@
+package com.zhongshu.reward.server.core.config;
+
+import com.zhongshu.vip.client.config.VipCenterClientConfiguration;
+import com.zswl.cloud.springBatch.client.config.BatchClientConfiguration;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+/**
+ * @author wjf
+ * @date 2024/8/22
+ */
+@Configuration
+@Import(BatchClientConfiguration.class)
+public class BatchConfig {
+}

+ 2 - 1
RewardServer/src/main/java/com/zhongshu/reward/server/core/config/MongoConfig.java

@@ -2,12 +2,13 @@ package com.zhongshu.reward.server.core.config;
 
 
 import com.github.microservice.components.data.mongo.mongo.config.MongoConfiguration;
+import com.github.microservice.components.data.mongo.token.config.ResourceTokenConfiguration;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
 import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
 
 @Configuration
-@Import(MongoConfiguration.class)
+@Import({MongoConfiguration.class, ResourceTokenConfiguration.class})
 @EnableMongoRepositories("com.zhongshu.reward.server.core.dao")
 public class MongoConfig {
 }

+ 33 - 22
RewardServer/src/main/java/com/zhongshu/reward/server/core/controller/TestController.java

@@ -3,10 +3,13 @@ package com.zhongshu.reward.server.core.controller;
 import com.zhongshu.reward.client.model.param.TestSettleParam;
 import com.zhongshu.reward.client.ret.ResultContent;
 import com.zhongshu.reward.server.core.dao.VipUserRecordDao;
+import com.zhongshu.reward.server.core.dao.WalletDao;
 import com.zhongshu.reward.server.core.dao.WalletReceiptsDao;
 import com.zhongshu.reward.server.core.domain.VipUserRecord;
+import com.zhongshu.reward.server.core.domain.Wallet;
 import com.zhongshu.reward.server.core.domain.WalletReceipts;
 import com.zhongshu.reward.server.core.service.Impl.InviteRecordFeignServiceImpl;
+import com.zhongshu.reward.server.core.service.InviteReceiptsService;
 import com.zhongshu.reward.server.core.service.WalletReceiptsService;
 import com.zhongshu.reward.server.core.util.DateUtils;
 import io.swagger.annotations.Api;
@@ -14,9 +17,11 @@ import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
 
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 import redis.clients.jedis.Jedis;
 
+import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.util.Calendar;
 import java.util.Date;
@@ -44,6 +49,12 @@ public class TestController {
     @Autowired
     VipUserRecordDao vipUserRecordDao;
 
+    @Autowired
+    WalletDao walletDao;
+
+    @Autowired
+    InviteReceiptsService inviteReceiptsService;
+
 //    @ApiOperation("会员消息")
 //    @PostMapping("vipUser")
 //    public Object vipUser(@RequestBody VipUserParam param){
@@ -90,7 +101,7 @@ public class TestController {
     @ApiOperation("结算")
     @PostMapping("test")
     public Object test(@RequestParam("day") Integer day){
-        walletReceiptsService.settle(day);
+        inviteReceiptsService.settle(day);
         return ResultContent.buildSuccess();
     }
 
@@ -126,32 +137,32 @@ public class TestController {
     @PostMapping("autoReceipts")
     public Object autoReceipts(@RequestParam("month") Integer month){
 
-        walletReceiptsService.testAutoReceipts(month);
+        inviteReceiptsService.testAutoReceipts(month);
         return ResultContent.buildSuccess();
     }
 
 
 
 
-//    @PostMapping("testLock")
-//    public void testLock(){
-//        boolean lock = jedisUtil.lock("user_1001", 1000);
-////        RedisDistributedLock lock = new RedisDistributedLock(jedis, "user_1001", 1000);
-//
-//        try {
-//            if (lock) {
-//                // 执行业务逻辑
-//                System.out.println("执行业务逻辑...");
-//                // 模拟耗时操作
-//                Thread.sleep(2000);
-//            } else {
-//                System.out.println("未获取到锁,其他实例可能正在操作...");
-//            }
-//        } catch (InterruptedException e) {
-//            e.printStackTrace();
-//        } finally {
-//            jedisUtil.unlock("user_1001");
-////            jedisUtil.del()
+    @PostMapping("testUpdate")
+    @Transactional
+    public void testUpdate(@RequestParam("walletId") String walletId, @RequestParam("total") BigDecimal total){
+//        if (total.compareTo(BigDecimal.ZERO) < 0){
+//            total = total.negate();
 //        }
-//    }
+        log.info("修改金额:{}", total);
+        log.info("当前时间为:{}", System.currentTimeMillis());
+        walletDao.updateIncWaitAmount(walletId, total);
+    }
+
+    @PostMapping("testUpdateTotal")
+    @Transactional
+    public void testUpdateTotal(@RequestParam("walletId") String walletId, @RequestParam("total") BigDecimal total){
+//        if (total.compareTo(BigDecimal.ZERO) < 0){
+//            total = total.negate();
+//        }
+        log.info("修改金额:{}", total);
+        log.info("当前时间为:{}", System.currentTimeMillis());
+        walletDao.updateIncWaitAmount(walletId, total);
+    }
 }

+ 0 - 6
RewardServer/src/main/java/com/zhongshu/reward/server/core/controller/wallet/WalletController.java

@@ -77,12 +77,6 @@ public class WalletController {
     }
 
 
-    @Operation(summary = "发起提现lock", description = "发起提现")
-    @ResourceAuth(value = "user", type = AuthType.User)
-    @PostMapping (value = "transferLock", consumes = MediaType.APPLICATION_JSON_VALUE)
-    public Object transferLock(@RequestBody WalletTransferParam param){
-        return wxTransferService.transferLock(param);
-    }
 
     @Operation(summary = "查询提现列表", description = "查询提现列表")
     @ResourceAuth(value = "user", type = AuthType.User)

+ 14 - 6
RewardServer/src/main/java/com/zhongshu/reward/server/core/dao/Impl/WalletDaoImpl.java

@@ -24,13 +24,21 @@ public class WalletDaoImpl implements WalletDaoExtend {
     MongoTemplate mongoTemplate;
 
     @Override
-    public boolean resetTodayAmount() {
-        Query query = Query.query(Criteria.where("todayTransferAmount").ne(BigDecimal.ZERO));
+    public boolean updateIncAmount(String walletId, BigDecimal total) {
+        Criteria criteria = Criteria.where("_id").is(walletId);
+        Query query = Query.query(criteria);
         Update update = new Update();
-        update.set("todayTransferAmount", BigDecimal.ZERO);
+        update.inc("amount", total);
         this.dbHelper.updateTime(update);
-        return this.mongoTemplate.updateMulti(
-                query, update, Wallet.class
-        ).getModifiedCount() > 0;
+        return this.mongoTemplate.updateFirst(query, update, Wallet.class).getModifiedCount()>0;
+    }
+
+    public boolean updateIncWaitAmount(String walletId, BigDecimal total) {
+
+        Query query = Query.query(Criteria.where("_id").is(walletId));
+        Update update = new Update();
+        update.inc("waitAmount", total);
+        this.dbHelper.updateTime(update);
+        return this.mongoTemplate.updateFirst(query, update, Wallet.class).getModifiedCount()>0;
     }
 }

+ 15 - 0
RewardServer/src/main/java/com/zhongshu/reward/server/core/dao/Impl/WalletReceiptsDaoImpl.java

@@ -1,5 +1,6 @@
 package com.zhongshu.reward.server.core.dao.Impl;
 
+import com.github.microservice.components.data.mongo.mongo.helper.DBHelper;
 import com.zhongshu.reward.client.model.InviteSuccessModel;
 import com.zhongshu.reward.client.model.TotalStatisticsModel;
 import com.zhongshu.reward.client.type.ReceiptsStatus;
@@ -100,4 +101,18 @@ public class WalletReceiptsDaoImpl implements WalletReceiptsDaoExtend {
         query.with(Sort.by(Sort.Order.asc("createTime")));
         return mongoTemplate.find(query, WalletReceipts.class);
     }
+
+    @Override
+    public WalletReceipts findNoCancelByCreateTime(String userId, Long startTime, Long endTime) {
+        Criteria criteria = new Criteria();
+        criteria.and("userId").is(userId);
+        criteria.andOperator(Criteria.where("createTime").gte(startTime),Criteria.where("createTime").lte(endTime));
+        criteria.and("receiptsType").is(ReceiptsType.COMMISSION);
+        criteria.and("status").ne(ReceiptsStatus.CANCEL);
+
+        Query query = Query.query(criteria);
+        query.with(Sort.by(Sort.Order.asc("createTime")));
+
+        return mongoTemplate.findOne(query, WalletReceipts.class);
+    }
 }

+ 22 - 0
RewardServer/src/main/java/com/zhongshu/reward/server/core/dao/Impl/WxTransferBatchDaoImpl.java

@@ -8,6 +8,7 @@ import com.zhongshu.reward.server.core.domain.WxTransferBatch;
 import org.apache.commons.lang3.ObjectUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 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.aggregation.Aggregation;
 import org.springframework.data.mongodb.core.aggregation.AggregationResults;
@@ -108,4 +109,25 @@ public class WxTransferBatchDaoImpl implements WxTransferBatchDaoExtend {
         return groupList.getMappedResults().get(0).getTotalAmount();
     }
 
+    @Override
+    public List<WxTransferBatch> findNeedUpdateStatus(TransferStatus transferStatus) {
+        Criteria criteria = new Criteria("transferStatus").is(TransferStatus.PROCESSING);
+
+        Query query = new Query(criteria);
+        query.with(Sort.by(Sort.Direction.ASC, "createTime"));
+
+        Update update = new Update();
+        update.set("heartbeatTime", dbHelper.getTime());
+        dbHelper.updateTime(update);
+
+//        //取出当前的第一个任务,且心跳大于超时时间,其余返回空 ,保证不会被并发
+//        BuildModePushChunk buildModePushChunk = this.mongoTemplate.findAndModify(query, update, FindAndModifyOptions.options().returnNew(true), BuildModePushChunk.class);
+//        if (buildModePushChunk == null) {
+//            return null;
+//        } else if (buildModePushChunk.getHeartbeatTime() > dbHelper.getTime()) {
+//            return null;
+//        }
+        return  null;
+    }
+
 }

+ 2 - 0
RewardServer/src/main/java/com/zhongshu/reward/server/core/dao/WalletReceiptsDao.java

@@ -20,4 +20,6 @@ public interface WalletReceiptsDao extends MongoDao<WalletReceipts>, WalletRecei
     WalletReceipts findTop1ById(String id);
 
     WalletReceipts findTop1ByVipUserRecord_IdAndVipUserRecord_First(String vipUserRecordId, boolean first);
+
+    List<WalletReceipts> findByOutTradeNoAndGoodsIdInAndStatus(String outTradeNo, List<String> goodsIds, ReceiptsStatus status);
 }

+ 6 - 1
RewardServer/src/main/java/com/zhongshu/reward/server/core/dao/extend/WalletDaoExtend.java

@@ -1,10 +1,15 @@
 package com.zhongshu.reward.server.core.dao.extend;
 
+import java.math.BigDecimal;
+
 /**
  * @author wjf
  * @date 2024/8/5
  */
 public interface WalletDaoExtend {
 
-    boolean resetTodayAmount();
+
+    boolean updateIncAmount(String walletId, BigDecimal total);
+
+    boolean updateIncWaitAmount(String walletId, BigDecimal total);
 }

+ 2 - 0
RewardServer/src/main/java/com/zhongshu/reward/server/core/dao/extend/WalletReceiptsDaoExtend.java

@@ -18,4 +18,6 @@ public interface WalletReceiptsDaoExtend {
     List<InviteSuccessModel> myInvite(String userId);
 
     List<WalletReceipts> listMonthBySetMealCode(Long startTime, Long endTime, List<String> setMealCodeList);
+
+    WalletReceipts findNoCancelByCreateTime(String userId, Long startTime, Long endTime);
 }

+ 2 - 0
RewardServer/src/main/java/com/zhongshu/reward/server/core/dao/extend/WxTransferBatchDaoExtend.java

@@ -19,4 +19,6 @@ public interface WxTransferBatchDaoExtend {
     Integer countByTime(String walletId, Long startTime, Long endTime);
 
     Integer sumDayTotal(String walletId, Long startTime, Long endTime);
+
+    List<WxTransferBatch> findNeedUpdateStatus(TransferStatus transferStatus);
 }

+ 13 - 0
RewardServer/src/main/java/com/zhongshu/reward/server/core/domain/TransferRuler.java

@@ -7,6 +7,7 @@ import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
 import lombok.NoArgsConstructor;
+import org.springframework.data.mongodb.core.index.Indexed;
 import org.springframework.data.mongodb.core.mapping.Document;
 
 import java.math.BigDecimal;
@@ -26,61 +27,73 @@ public class TransferRuler extends SuperEntity {
     /**
      * 单笔最小提现金额
      */
+    @Indexed
     private BigDecimal minTotal = BigDecimal.ZERO;
 
     /**
      * 单笔最大提现金额
      */
+    @Indexed
     private BigDecimal maxTotal = BigDecimal.ZERO;
 
     /**
      * 单日最大转账金额
      */
+    @Indexed
     private BigDecimal dayMaxTotal = BigDecimal.ZERO;
 
     /**
      * 提现手续费
      */
+    @Indexed
     private BigDecimal commission = BigDecimal.ZERO;
 
     /**
      * 提现次数
      */
+    @Indexed
     private Integer size;
 
     /**
      * 时间单位
      */
+    @Indexed
     private TimeUnitType timeUnit;
 
     /**
      * 每月开始号数
      */
+    @Indexed
     private Integer startDay;
 
     /**
      * 每月结束号数
      */
+    @Indexed
     private Integer endDay;
 
     /**
      * 每日开始时
      */
+    @Indexed
     private Integer startHour;
 
     /**
      * 每日开始分
      */
+    @Indexed
     private Integer startMinute;
 
     /**
      * 每日结束时
      */
+    @Indexed
     private Integer endHour;
 
     /**
      * 每日结束分
      */
+    @Indexed
     private Integer endMinute;
 
 }

+ 3 - 0
RewardServer/src/main/java/com/zhongshu/reward/server/core/domain/Wallet.java

@@ -39,11 +39,13 @@ public class Wallet extends SuperEntity {
     /**
      * 账户余额(可提现金额)
      */
+    @Indexed
     private BigDecimal amount = BigDecimal.ZERO;
 
     /**
      * 未结算金额
      */
+    @Indexed
     private BigDecimal waitAmount = BigDecimal.ZERO;
 
     /**
@@ -54,6 +56,7 @@ public class Wallet extends SuperEntity {
     /**
      * 钱包状态
      */
+    @Indexed
     private DataState dataState;
 
 }

+ 17 - 1
RewardServer/src/main/java/com/zhongshu/reward/server/core/domain/WalletReceipts.java

@@ -8,6 +8,7 @@ import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
 import lombok.NoArgsConstructor;
+import org.springframework.data.mongodb.core.index.Indexed;
 import org.springframework.data.mongodb.core.mapping.DBRef;
 import org.springframework.data.mongodb.core.mapping.Document;
 
@@ -34,26 +35,31 @@ public class WalletReceipts extends SuperEntity {
     /**
      * 邀请人id
      */
+    @Indexed
     private String inviteUserId;
 
     /**
      * 被邀请人id
      */
+    @Indexed
     private String userId;
 
     /**
      * 预计到账时间
      */
+    @Indexed
     private Long estimatedTime;
 
     /**
      * 实际到账时间
      */
+    @Indexed
     private Long receiptsTime;
 
     /**
      * 到账类型
      */
+    @Indexed
     private ReceiptsType receiptsType;
 
     /**
@@ -64,21 +70,31 @@ public class WalletReceipts extends SuperEntity {
     /**
      * 状态
      */
+    @Indexed
     private ReceiptsStatus status;
 
     /**
-     * 外部订单号
+     * 外部订单号(邀请返利:套餐code, 商品返利:订单号)
      */
+    @Indexed
     private String outTradeNo;
 
+    /**
+     * 外部订单号(商品返利:商品id)
+     */
+    @Indexed
+    private String goodsId;
+
     /**
      * 产生入账的订阅消息
      */
+    @Indexed
     private VipUserRecord vipUserRecord;
 
     /**
      * 产生入账是匹配的规则
      */
+    @Indexed
     private InviteReceiptsRoleVo ruler;
 
     /**

+ 127 - 0
RewardServer/src/main/java/com/zhongshu/reward/server/core/helper/RedisHelper.java

@@ -0,0 +1,127 @@
+package com.zhongshu.reward.server.core.helper;
+
+import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.ValueOperations;
+import org.springframework.stereotype.Component;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+@Component
+@Log4j2
+public class RedisHelper {
+
+    @Autowired
+    RedisTemplate<String, Object> redisTemplate;
+
+    @Autowired
+    RedisTemplate<String, String> redisString;
+
+
+
+    public boolean cacheValue(String key, Object value, long time) {
+        try {
+            ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
+            valueOperations.set(key, value);
+            if (time > 0) {
+                // 如果有设置超时时间的话
+                redisTemplate.expire(key, time, TimeUnit.SECONDS);
+            }
+            return true;
+        } catch (Throwable e) {
+            log.error("缓存[" + key + "]失败, value[" + value + "] " + e.getMessage());
+        }
+        return false;
+    }
+
+    public boolean distributedLock(String key, Object value, long time){
+        try {
+            Boolean ret = redisTemplate.opsForValue().setIfAbsent(key, value);
+            if (null == ret){
+                return false;
+            }
+            return ret;
+        } catch (Throwable e) {
+            log.error("缓存[" + key + "]失败, value[" + value + "] " + e.getMessage());
+        }
+        return false;
+    }
+
+    /**
+     * 缓存value,没有设置超时时间
+     *
+     * @param key
+     * @param value
+     * @return
+     */
+    public boolean cacheValue(String key, Object value) {
+        return cacheValue(key, value, -1);
+    }
+
+    /**
+     * 判断缓存是否存在
+     *
+     * @param key
+     * @return
+     */
+    public boolean containsKey(String key) {
+        try {
+            return redisTemplate.hasKey(key);
+        } catch (Throwable e) {
+            log.error("判断缓存是否存在时失败key[" + key + "]", "err[" + e.getMessage() + "]");
+        }
+        return false;
+    }
+
+    /**
+     * 根据key,获取缓存
+     *
+     * @param key
+     * @return
+     */
+    public Object getValue(String key) {
+        try {
+            ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
+            return valueOperations.get(key);
+        } catch (Throwable e) {
+            log.error("获取缓存时失败key[" + key + "]", "err[" + e.getMessage() + "]");
+        }
+        return null;
+    }
+
+    /**
+     * 移除缓存
+     *
+     * @param key
+     * @return
+     */
+    public boolean removeValue(String key) {
+        try {
+            redisTemplate.delete(key);
+            return true;
+        } catch (Throwable e) {
+            log.error("移除缓存时失败key[" + key + "]", "err[" + e.getMessage() + "]");
+        }
+        return false;
+    }
+
+    /**
+     * 根据前缀移除所有以传入前缀开头的key-value
+     *
+     * @param pattern
+     * @return
+     */
+    public boolean removeKeys(String pattern) {
+        try {
+            Set<String> keySet = redisTemplate.keys(pattern + "*");
+            redisTemplate.delete(keySet);
+            return true;
+        } catch (Throwable e) {
+            log.error("移除key[" + pattern + "]前缀的缓存时失败", "err[" + e.getMessage() + "]");
+        }
+        return false;
+    }
+
+}

+ 96 - 0
RewardServer/src/main/java/com/zhongshu/reward/server/core/service/GoodsReceiptsService.java

@@ -0,0 +1,96 @@
+package com.zhongshu.reward.server.core.service;
+
+import com.zhongshu.reward.client.type.ReceiptsStatus;
+import com.zhongshu.reward.client.type.ReceiptsType;
+import com.zhongshu.reward.server.core.dao.WalletDao;
+import com.zhongshu.reward.server.core.dao.WalletReceiptsDao;
+import com.zhongshu.reward.server.core.domain.Wallet;
+import com.zhongshu.reward.server.core.domain.WalletReceipts;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author wjf
+ * @date 2024/8/23
+ */
+@Service
+@Slf4j
+public class GoodsReceiptsService {
+
+    @Autowired
+    WalletDao walletDao;
+
+    @Autowired
+    WalletService walletService;
+
+    @Autowired
+    WalletReceiptsDao walletReceiptsDao;
+
+    /**
+     * 购物返利 todo// 1、获取产品库 返利规则 2、获取订单详情、获取商品详情
+     * @param userId 用户id
+     * @param total 返利金额
+     * @param orderNo 订单号
+     * @param goodsId 商品id
+     */
+    @Transactional
+    public void receipts(String userId, BigDecimal total, String orderNo, String goodsId){
+
+        Wallet wallet = walletService.getWalletByUserId(userId);
+
+        WalletReceipts walletReceipts = new WalletReceipts();
+        walletReceipts.setWallet(wallet);
+        walletReceipts.setReceiptsType(ReceiptsType.REBATE);
+        walletReceipts.setEstimatedTime(new Date().getTime() + 2*24*60*60*1000);
+        walletReceipts.setTotal(total);
+        walletReceipts.setOutTradeNo(orderNo);
+        walletReceipts.setGoodsId(goodsId);
+        walletReceipts.setStatus(ReceiptsStatus.WAIT);
+
+        walletReceiptsDao.save(walletReceipts);
+        walletDao.updateIncWaitAmount(wallet.getId(), total);
+        log.info("购物返利入账");
+    }
+
+
+    /**
+     * 取消购物返利
+     * @param userId 用户id
+     * @param orderNo 订单号
+     * @param goodsIds 商品id
+     */
+    @Transactional
+    public void cancel(String userId, String orderNo, List<String> goodsIds){
+        BigDecimal total = BigDecimal.ZERO;
+        Wallet wallet = walletService.getWalletByUserId(userId);
+        List<WalletReceipts> walletReceiptsList = walletReceiptsDao.findByOutTradeNoAndGoodsIdInAndStatus(orderNo, goodsIds, ReceiptsStatus.WAIT);
+        for (WalletReceipts it : walletReceiptsList){
+            total = total.add(it.getTotal());
+            it.setStatus(ReceiptsStatus.CANCEL);
+        }
+        walletReceiptsDao.saveAll(walletReceiptsList);
+        walletDao.updateIncWaitAmount(wallet.getId(), total.negate());
+    }
+
+    /**
+     * 入账结算
+     */
+    @Transactional
+    public void settle(){
+        //todo 查询到期入账的订单
+        WalletReceipts walletReceipts = walletReceiptsDao.findTop1ById("");
+
+        walletReceipts.setReceiptsTime(new Date().getTime());
+        walletReceipts.setStatus(ReceiptsStatus.RECEIPTS);
+        walletReceiptsDao.save(walletReceipts);
+        walletDao.updateIncWaitAmount(walletReceipts.getWallet().getId(), walletReceipts.getTotal().negate());
+        walletDao.updateIncAmount(walletReceipts.getWallet().getId(), walletReceipts.getTotal());
+    }
+}

+ 0 - 73
RewardServer/src/main/java/com/zhongshu/reward/server/core/service/InviteReceiptsRulerService.java

@@ -1,73 +0,0 @@
-package com.zhongshu.reward.server.core.service;
-
-import com.zhongshu.reward.client.model.InviteReceiptsRoleModel;
-import com.zhongshu.reward.client.ret.ResultContent;
-import com.zhongshu.reward.server.core.dao.InviteReceiptsRoleDao;
-import com.zhongshu.reward.server.core.dao.VipUserRecordDao;
-import com.zhongshu.reward.server.core.domain.InviteReceiptsRuler;
-import org.apache.commons.lang3.ObjectUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-/**
- * 邀请返利
- * @author wjf
- * @date 2024/8/7
- */
-@Service
-public class InviteReceiptsRulerService {
-
-    @Autowired
-    InviteReceiptsRoleDao inviteReceiptsRoleDao;
-
-    @Autowired
-    VipUserRecordDao vipUserRecordDao;
-
-    @Autowired
-    WalletReceiptsService walletReceiptsService;
-
-
-
-    /**
-     * 添加推广规则
-     * @param inviteReceiptsRoleModel
-     * @return
-     */
-//    public Object add(InviteReceiptsRoleModel inviteReceiptsRoleModel){
-//        boolean existsBySetMeal= inviteReceiptsRoleDao.existsBySetMealIdAndDisable(inviteReceiptsRoleModel.getSetMealId(), false);
-//        if (existsBySetMeal){
-//            return ResultContent.buildFail("该套餐存在推广规则");
-//        }
-//        InviteReceiptsRuler inviteReceiptsRole = new InviteReceiptsRuler();
-//        BeanUtils.copyProperties(inviteReceiptsRoleModel, inviteReceiptsRole);
-//        return ResultContent.buildContent(toModel(inviteReceiptsRoleDao.save(inviteReceiptsRole)));
-//    }
-
-    public Object update(InviteReceiptsRoleModel inviteReceiptsRoleModel){
-        if (StringUtils.isEmpty(inviteReceiptsRoleModel.getId())) {//添加
-            boolean existsBySetMeal= inviteReceiptsRoleDao.existsBySetMealIdAndDisable(inviteReceiptsRoleModel.getSetMealId(), false);
-            if (existsBySetMeal){
-                return ResultContent.buildFail("该套餐存在推广规则");
-            }
-        }else if (!inviteReceiptsRoleDao.existsById(inviteReceiptsRoleModel.getId())){
-            return ResultContent.buildContent("找不到要修改的推广规则");
-        }
-
-        InviteReceiptsRuler inviteReceiptsRuler = new InviteReceiptsRuler();
-        BeanUtils.copyProperties(inviteReceiptsRoleModel, inviteReceiptsRuler);
-        return ResultContent.buildContent(toModel(inviteReceiptsRoleDao.save(inviteReceiptsRuler)));
-    }
-
-
-
-
-    InviteReceiptsRoleModel toModel(InviteReceiptsRuler inviteReceiptsRuler){
-        InviteReceiptsRoleModel model = new InviteReceiptsRoleModel();
-        if (ObjectUtils.isNotEmpty(inviteReceiptsRuler)){
-            BeanUtils.copyProperties(inviteReceiptsRuler, model);
-        }
-        return model;
-    }
-}

+ 320 - 0
RewardServer/src/main/java/com/zhongshu/reward/server/core/service/InviteReceiptsService.java

@@ -0,0 +1,320 @@
+package com.zhongshu.reward.server.core.service;
+
+import com.github.microservice.auth.security.helper.AuthHelper;
+import com.zhongshu.reward.client.type.ReceiptsStatus;
+import com.zhongshu.reward.client.type.ReceiptsType;
+import com.zhongshu.reward.client.type.UserType;
+import com.zhongshu.reward.server.core.dao.InviteRecordDao;
+import com.zhongshu.reward.server.core.dao.VipUserRecordDao;
+import com.zhongshu.reward.server.core.dao.WalletDao;
+import com.zhongshu.reward.server.core.dao.WalletReceiptsDao;
+import com.zhongshu.reward.server.core.domain.InviteRecord;
+import com.zhongshu.reward.server.core.domain.VipUserRecord;
+import com.zhongshu.reward.server.core.domain.Wallet;
+import com.zhongshu.reward.server.core.domain.WalletReceipts;
+import com.zhongshu.reward.server.core.util.DateUtils;
+import com.zswl.cloud.bdb.client.service.InviteReceiptsRoleFeignService;
+import com.zswl.cloud.bdb.client.vo.InviteReceiptsRoleVo;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.ObjectUtils;
+import org.bson.types.ObjectId;
+import org.jetbrains.annotations.NotNull;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * @author wjf
+ * @date 2024/8/23
+ */
+
+@Service
+@Slf4j
+public class InviteReceiptsService {
+
+    @Autowired
+    WalletDao walletDao;
+
+    @Autowired
+    WalletService walletService;
+
+    @Autowired
+    WalletReceiptsDao walletReceiptsDao;
+
+    @Autowired
+    VipUserRecordDao vipUserRecordDao;
+
+    @Autowired
+    InviteRecordDao inviteRecordDao;
+
+    @Autowired
+    AuthHelper authHelper;
+
+    @Autowired
+    InviteReceiptsRoleFeignService inviteReceiptsRoleFeignService;
+
+    /**
+     * 邀请返利入账
+     * @param
+     * @return
+     */
+    @Transactional
+    public void receipts(VipUserRecord vipUserRecord){
+        //校验对应套餐返利规则
+        com.zswl.cloud.bdb.client.ret.ResultContent<InviteReceiptsRoleVo> rulerResultContent = inviteReceiptsRoleFeignService.getOne(vipUserRecord.getPlanningId());
+        if (rulerResultContent.getState().equals(com.zswl.cloud.bdb.client.ret.ResultState.Success)){
+            InviteReceiptsRoleVo rulerVo = rulerResultContent.getContent();
+            if (rulerVo.isFirst() && (vipUserRecord.getSuc().equals(1) || vipUserRecord.getSuc().equals(4))){
+                vipUserRecord.setFirst(false);
+                //订阅
+                //查询邀请关系
+                InviteRecord inviteRecord = inviteRecordDao.findTopByUserIdOrderByCreateTime(vipUserRecord.getCpId());
+                if (Objects.nonNull(inviteRecord) && inviteRecord.getUserType().equals(UserType.NEW)){
+                    //首次订购且订购时间小于注册时间48小时
+                    if (rulerVo.getFirstPurchaseDay()!=null && !vipUserRecordDao.existsByCpIdAndSucIn(vipUserRecord.getCpId(), List.of(1)) && Math.abs(vipUserRecord.getOperateTime() - inviteRecord.getRegisterTime()) <= 48L*60*60*1000) {
+                        vipUserRecord.setFirst(true);
+                        //订阅入账
+                        Wallet wallet = walletService.getWalletByUserId(inviteRecord.getInviteUserId());
+                        WalletReceipts walletReceipts = buildReceipts(vipUserRecord, rulerVo, inviteRecord, wallet);
+                        walletDao.updateIncWaitAmount(wallet.getId(), rulerVo.getBaseTotal());
+                        walletReceiptsDao.save(walletReceipts);
+                    }else if (rulerVo.getFirstPurchaseDay()!=null && vipUserRecordDao.existsByCpIdAndSucIn(vipUserRecord.getCpId(), List.of(1))){
+                        //不是首次订购、
+                        WalletReceipts lastMoth = walletReceiptsDao.findNoCancelByCreateTime(vipUserRecord.getCpId(), DateUtils.lastMonthStartTime(), DateUtils.lastMonthEndTime());
+
+                        if (ObjectUtils.isNotEmpty(lastMoth)){//上月有未取消返利订单
+                            WalletReceipts currentMonth = walletReceiptsDao.findNoCancelByCreateTime(vipUserRecord.getCpId(), DateUtils.getCurrentMonthStartTime(), new Date().getTime());
+
+                            if (ObjectUtils.isEmpty(currentMonth)){//本月没有未取消返利订单
+                                Wallet wallet = walletService.getWalletByUserId(inviteRecord.getInviteUserId());
+                                WalletReceipts walletReceipts = buildReceipts(vipUserRecord, rulerVo, inviteRecord, wallet);
+                                walletDao.updateIncWaitAmount(wallet.getId(), rulerVo.getBaseTotal());
+                                walletReceiptsDao.save(walletReceipts);
+                            }
+                        }
+                    }
+                }
+            }else if (vipUserRecord.getSuc().equals(-1) || vipUserRecord.getSuc().equals(5)){
+                //获取历史最新订阅消息
+                VipUserRecord lastOne = vipUserRecordDao.findTop1ByCpIdAndSucOrderByOperateTime(vipUserRecord.getCpId(), 1);
+                //上一单首购
+                if (ObjectUtils.isNotEmpty(lastOne) && lastOne.isFirst()){
+                    WalletReceipts walletReceipts = walletReceiptsDao.findTop1ByVipUserRecord_IdAndVipUserRecord_First(lastOne.getId(), true);
+                    if (ObjectUtils.isNotEmpty(walletReceipts) && Math.abs(vipUserRecord.getOperateTime() - lastOne.getOperateTime()) < 24L *60*60*1000*walletReceipts.getRuler().getFirstPurchaseDay()){
+                        walletReceipts.setStatus(ReceiptsStatus.CANCEL);
+                        Wallet wallet = walletService.getWalletByUserId(walletReceipts.getInviteUserId());
+                        walletDao.updateIncWaitAmount(wallet.getId(), rulerVo.getBaseTotal().negate());
+                        walletReceiptsDao.save(walletReceipts);
+                    }
+                }else {
+                    InviteRecord inviteRecord = inviteRecordDao.findTopByUserIdOrderByCreateTime(vipUserRecord.getCpId());
+                    if (Objects.nonNull(inviteRecord) && inviteRecord.getUserType().equals(UserType.NEW)){
+                        WalletReceipts currentMonth = walletReceiptsDao.findNoCancelByCreateTime(vipUserRecord.getCpId(), DateUtils.getCurrentMonthStartTime(), new Date().getTime());
+                        if (Objects.nonNull(currentMonth) && Math.abs(vipUserRecord.getOperateTime() - currentMonth.getCreateTime()) < 24L *60*60*1000*currentMonth.getRuler().getFirstPurchaseDay()){
+                            currentMonth.setStatus(ReceiptsStatus.CANCEL);
+                            walletReceiptsDao.save(currentMonth);
+                            Wallet wallet = walletService.getWalletByUserId(currentMonth.getInviteUserId());
+                            walletDao.updateIncWaitAmount(wallet.getId(), rulerVo.getBaseTotal().negate());
+                        }
+                    }
+                }
+            }
+        }
+        vipUserRecordDao.save(vipUserRecord);
+    }
+
+    @NotNull
+    private static WalletReceipts buildReceipts(VipUserRecord vipUserRecord, InviteReceiptsRoleVo rulerVo, InviteRecord inviteRecord, Wallet wallet) {
+        WalletReceipts walletReceipts = new WalletReceipts();
+        walletReceipts.setWallet(wallet);
+        walletReceipts.setInviteUserId(inviteRecord.getInviteUserId());
+        walletReceipts.setUserId(vipUserRecord.getCpId());
+        walletReceipts.setReceiptsType(ReceiptsType.COMMISSION);
+        walletReceipts.setOutTradeNo(vipUserRecord.getPlanningId());
+        walletReceipts.setTotal(rulerVo.getBaseTotal());
+        walletReceipts.setEstimatedTime(DateUtils.nextMonthDayStartTime(rulerVo.getDay()));
+        vipUserRecord.setId(new ObjectId().toHexString());
+        walletReceipts.setVipUserRecord(vipUserRecord);
+        walletReceipts.setRuler(rulerVo);
+        //邀请人钱包
+        walletReceipts.setStatus(ReceiptsStatus.WAIT);
+        return walletReceipts;
+    }
+
+    /**
+     * 结算邀请返利
+     * @param day
+     */
+    @Transactional
+    public void settle(Integer day){
+
+        Long startTime = DateUtils.lastMonthStartTime();
+        Long endTime = DateUtils.lastMonthEndTime();
+        List<WalletReceipts> list = walletReceiptsDao.listMonth(startTime, endTime, day);
+
+//        List<WalletReceipts> receipts = new ArrayList<>();
+//        List<Wallet> wallets = new ArrayList<>();
+
+        if (list==null || list.isEmpty()){
+            return;
+        }
+
+        //首次订购
+        list.forEach(it -> {
+            if (it.getVipUserRecord().isFirst()) {
+                addAmount(it);
+            }
+        });
+
+        //持续订购
+        List<WalletReceipts> keep  = list.stream().map(it -> {
+            if (!it.getVipUserRecord().isFirst()) {
+                return it;
+            }
+            return null;
+        }).collect(Collectors.toList());
+
+        if (keep.isEmpty()){
+            return;
+        }
+
+        keep.forEach(it->{
+            boolean cancel = vipUserRecordDao.existsByCpIdAndSucIn(it.getUserId(), List.of(-1, 5));
+            if (!cancel){//无退订消息
+                addAmount(it);
+            }else {
+                VipUserRecord cancelRecord = vipUserRecordDao.findTopOneByOperateTime(it.getUserId(), DateUtils.lastMonthDayStartTime(1), DateUtils.lastMonthDayStartTime(6));
+                if (ObjectUtils.isEmpty(cancelRecord) || cancelRecord.getSuc().equals(1) || cancelRecord.getSuc().equals(4)){
+                    //上月1-5号无退订消息或消息为订购:默认扣款成功。。。
+                    addAmount(it);
+                }else {
+                    cancel(it);
+                }
+            }
+        });
+
+    }
+
+    /**
+     * 生成持续订购返利单
+     */
+    @Transactional
+    public void autoReceipts(){
+        //获取设置持续订购返利的套餐规则
+        com.zswl.cloud.bdb.client.ret.ResultContent<List<InviteReceiptsRoleVo>> rulerResult = inviteReceiptsRoleFeignService.listKeep();
+        if (rulerResult.getState().equals(com.zswl.cloud.bdb.client.ret.ResultState.Success)){
+            List<InviteReceiptsRoleVo> rulerList = rulerResult.getContent();
+            if (rulerList.isEmpty()){
+                return;
+            }
+            List<String> setMealCodeList = rulerList.stream().map(InviteReceiptsRoleVo::getSetMealCode).collect(Collectors.toList());
+
+            //获取上月所有入帐单(待结算和已结算的)
+            Long startTime = DateUtils.lastMonthStartTime();
+            Long endTime = DateUtils.lastMonthEndTime();
+            List<WalletReceipts> walletReceiptsList = walletReceiptsDao.listMonthBySetMealCode(startTime, endTime, setMealCodeList);
+            if (walletReceiptsList.isEmpty()){
+                return;
+            }
+
+            rulerList.forEach(ruler->{
+                walletReceiptsList.forEach(walletReceipts -> {
+                    //匹配规则
+                    if (walletReceipts.getOutTradeNo().equals(ruler.getSetMealCode())){
+                        //上月最新消息
+                        VipUserRecord topOne = vipUserRecordDao.findTopOneByOperateTime(walletReceipts.getUserId(), startTime, endTime);
+                        if (Objects.isNull(topOne)){
+                            //上月无消息,生成入账
+                            insertReceipts(ruler, walletReceipts);
+                        }else if (topOne.getSuc().equals(1) || topOne.getSuc().equals(4)){
+                            //上月最后消息为订购,生成入账
+                            insertReceipts(ruler, walletReceipts);
+                        }
+                    }
+                });
+            });
+        }
+    }
+
+    public void testAutoReceipts(Integer month){
+        //获取设置持续订购返利的套餐规则
+        com.zswl.cloud.bdb.client.ret.ResultContent<List<InviteReceiptsRoleVo>> rulerResult = inviteReceiptsRoleFeignService.listKeep();
+        if (rulerResult.getState().equals(com.zswl.cloud.bdb.client.ret.ResultState.Success)){
+            List<InviteReceiptsRoleVo> rulerList = rulerResult.getContent();
+            if (rulerList.isEmpty()){
+                return;
+            }
+            List<String> setMealCodeList = rulerList.stream().map(InviteReceiptsRoleVo::getSetMealCode).collect(Collectors.toList());
+
+            //获取上月所有入帐单(待结算和已结算的)
+            Long startTime = DateUtils.getMonthStartTime(2024, month);
+            Long endTime = DateUtils.getMonthEndTime(2024, month);
+            List<WalletReceipts> walletReceiptsList = walletReceiptsDao.listMonthBySetMealCode(startTime, endTime, setMealCodeList);
+            if (walletReceiptsList.isEmpty()){
+                return;
+            }
+
+            rulerList.forEach(ruler->{
+                walletReceiptsList.forEach(walletReceipts -> {
+                    //匹配规则
+                    if (walletReceipts.getOutTradeNo().equals(ruler.getSetMealCode())){
+                        //上月最新消息
+                        VipUserRecord topOne = vipUserRecordDao.findTopOneByOperateTime(walletReceipts.getUserId(), startTime, endTime);
+                        if (Objects.isNull(topOne)){
+                            //上月无消息,生成入账
+                            insertReceipts(ruler, walletReceipts);
+                        }else if (topOne.getSuc().equals(1) || topOne.getSuc().equals(4)){
+                            //上月最后消息为订购,生成入账
+                            insertReceipts(ruler, walletReceipts);
+                        }
+                    }
+                });
+            });
+        }
+    }
+
+    private void insertReceipts(InviteReceiptsRoleVo ruler, WalletReceipts it) {
+        WalletReceipts walletReceipts = new WalletReceipts();
+        walletReceipts.setWallet(it.getWallet());
+        walletReceipts.setInviteUserId(it.getInviteUserId());
+        walletReceipts.setUserId(it.getUserId());
+        walletReceipts.setEstimatedTime(DateUtils.nextMonthDayStartTime(ruler.getDay()));
+        walletReceipts.setReceiptsType(ReceiptsType.COMMISSION);
+        walletReceipts.setTotal(ruler.getBaseTotal());
+        walletReceipts.setStatus(ReceiptsStatus.WAIT);
+        walletReceipts.setOutTradeNo(ruler.getSetMealCode());
+        walletReceipts.setRuler(ruler);
+        VipUserRecord vipUserRecord = it.getVipUserRecord();
+        vipUserRecord.setId(null);
+        vipUserRecord.setFirst(false);
+        vipUserRecord.setPlanningId(ruler.getSetMealCode());
+        walletReceipts.setVipUserRecord(vipUserRecord);
+        Wallet wallet = walletReceipts.getWallet();
+        wallet.setWaitAmount(wallet.getWaitAmount().add(ruler.getBaseTotal()));
+        walletDao.save(wallet);
+        walletReceiptsDao.save(walletReceipts);
+    }
+
+    private void addAmount(WalletReceipts it) {
+        it.setStatus(ReceiptsStatus.RECEIPTS);
+        it.setReceiptsTime(new Date().getTime());
+        Wallet wallet = it.getWallet();
+        wallet.setWaitAmount(wallet.getWaitAmount().subtract(it.getTotal()));
+        wallet.setAmount(wallet.getAmount().add(it.getTotal()));
+        walletDao.save(wallet);
+        walletReceiptsDao.save(it);
+    }
+
+    private void cancel(WalletReceipts it){
+        it.setStatus(ReceiptsStatus.CANCEL);
+        Wallet wallet = it.getWallet();
+        wallet.setWaitAmount(wallet.getWaitAmount().subtract(it.getTotal()));
+        walletDao.save(wallet);
+        walletReceiptsDao.save(it);
+    }
+}

+ 11 - 251
RewardServer/src/main/java/com/zhongshu/reward/server/core/service/WalletReceiptsService.java

@@ -62,259 +62,9 @@ public class WalletReceiptsService {
     @Autowired
     InviteReceiptsRoleFeignService inviteReceiptsRoleFeignService;
 
-
     /**
-     * 邀请返利入账
-     * @param
-     * @return
+     * 查询即将到账
      */
-    @Transactional
-    public void receipts(VipUserRecord vipUserRecord){
-        //校验对应套餐返利规则
-        com.zswl.cloud.bdb.client.ret.ResultContent<InviteReceiptsRoleVo> rulerResultContent = inviteReceiptsRoleFeignService.getOne(vipUserRecord.getPlanningId());
-        if (rulerResultContent.getState().equals(com.zswl.cloud.bdb.client.ret.ResultState.Success)){
-            InviteReceiptsRoleVo rulerVo = rulerResultContent.getContent();
-            if (rulerVo.isFirst() && vipUserRecord.getSuc().equals(1)){
-                vipUserRecord.setFirst(false);
-                //订阅
-                //查询邀请关系
-                InviteRecord inviteRecord = inviteRecordDao.findTopByUserIdOrderByCreateTime(vipUserRecord.getCpId());
-                if (Objects.nonNull(inviteRecord) && inviteRecord.getUserType().equals(UserType.NEW)){
-                    if (rulerVo.getFirstPurchaseDay()!=null && !vipUserRecordDao.existsByCpIdAndSucIn(vipUserRecord.getCpId(), List.of(1)) && Math.abs(vipUserRecord.getOperateTime() - inviteRecord.getRegisterTime()) <= 48L*60*60*1000) {
-                        vipUserRecord.setFirst(true);
-                        //订阅入账
-                        WalletReceipts walletReceipts = new WalletReceipts();
-                        //获取邀请人userid
-                        String inviteId = inviteRecord.getInviteUserId();
-                        Wallet wallet = walletService.getWalletByUserId(inviteId);
-                        walletReceipts.setWallet(wallet);
-                        walletReceipts.setInviteUserId(inviteId);
-                        walletReceipts.setUserId(vipUserRecord.getCpId());
-                        walletReceipts.setReceiptsType(ReceiptsType.COMMISSION);
-                        walletReceipts.setOutTradeNo(vipUserRecord.getPlanningId());
-                        walletReceipts.setTotal(rulerVo.getBaseTotal());
-                        walletReceipts.setEstimatedTime(DateUtils.nextMonthDayStartTime(rulerVo.getDay()));
-                        vipUserRecord.setId(new ObjectId().toHexString());
-                        walletReceipts.setVipUserRecord(vipUserRecord);
-                        walletReceipts.setRuler(rulerVo);
-                        //邀请人钱包
-                        walletReceipts.setStatus(ReceiptsStatus.WAIT);
-                        wallet.setWaitAmount(wallet.getWaitAmount().add(rulerVo.getBaseTotal()));
-                        walletDao.save(wallet);
-                        walletReceiptsDao.save(walletReceipts);
-                }
-            }
-        }else if (vipUserRecord.getSuc().equals(-1) || vipUserRecord.getSuc().equals(5)){
-                VipUserRecord lastOne = vipUserRecordDao.findTop1ByCpIdAndSucOrderByOperateTime(vipUserRecord.getCpId(), 1);
-                //上一单首购
-                if (ObjectUtils.isNotEmpty(lastOne) && lastOne.isFirst()){
-                    WalletReceipts walletReceipts = walletReceiptsDao.findTop1ByVipUserRecord_IdAndVipUserRecord_First(lastOne.getId(), true);
-                    if (ObjectUtils.isNotEmpty(walletReceipts) && Math.abs(vipUserRecord.getOperateTime() - lastOne.getOperateTime()) < 24L *60*60*1000*walletReceipts.getRuler().getFirstPurchaseDay()){
-                        walletReceipts.setStatus(ReceiptsStatus.CANCEL);
-                        Wallet wallet = walletService.getWalletByUserId(walletReceipts.getInviteUserId());
-                        wallet.setWaitAmount(wallet.getWaitAmount().subtract(walletReceipts.getTotal()));
-                        walletDao.save(wallet);
-                        walletReceiptsDao.save(walletReceipts);
-                    }
-                }
-            }
-        }
-        vipUserRecordDao.save(vipUserRecord);
-    }
-
-
-    /**
-     * 结算
-     */
-    public void settle(Integer day){
-
-        Long startTime = DateUtils.lastMonthStartTime();
-        Long endTime = DateUtils.lastMonthEndTime();
-        List<WalletReceipts> list = walletReceiptsDao.listMonth(startTime, endTime, day);
-
-//        List<WalletReceipts> receipts = new ArrayList<>();
-//        List<Wallet> wallets = new ArrayList<>();
-
-        if (list==null || list.isEmpty()){
-            return;
-        }
-
-        //首次订购
-        list.forEach(it -> {
-            if (it.getVipUserRecord().isFirst()) {
-                addAmount(it);
-            }
-        });
-
-        //持续订购
-        List<WalletReceipts> keep  = list.stream().map(it -> {
-            if (!it.getVipUserRecord().isFirst()) {
-                return it;
-            }
-            return null;
-        }).collect(Collectors.toList());
-
-        if (keep.isEmpty()){
-            return;
-        }
-
-        keep.forEach(it->{
-            boolean cancel = vipUserRecordDao.existsByCpIdAndSucIn(it.getUserId(), List.of(-1, 5));
-            if (!cancel){//无退订消息
-                addAmount(it);
-            }else {
-                VipUserRecord cancelRecord = vipUserRecordDao.findTopOneByOperateTime(it.getUserId(), DateUtils.lastMonthDayStartTime(1), DateUtils.lastMonthDayStartTime(6));
-                if (ObjectUtils.isEmpty(cancelRecord) || cancelRecord.getSuc().equals(1) || cancelRecord.getSuc().equals(4)){
-                    //上月1-5号无退订消息或消息为订购:默认扣款成功。。。
-                    addAmount(it);
-                }else {
-                    cancel(it);
-                }
-            }
-        });
-//        walletDao.saveAll(wallets);
-//        walletReceiptsDao.saveAll(receipts);
-
-    }
-    public void testAutoReceipts(Integer month){
-        //获取设置持续订购返利的套餐规则
-        com.zswl.cloud.bdb.client.ret.ResultContent<List<InviteReceiptsRoleVo>> rulerResult = inviteReceiptsRoleFeignService.listKeep();
-        if (rulerResult.getState().equals(com.zswl.cloud.bdb.client.ret.ResultState.Success)){
-            List<InviteReceiptsRoleVo> rulerList = rulerResult.getContent();
-            if (rulerList.isEmpty()){
-                return;
-            }
-            List<String> setMealCodeList = rulerList.stream().map(InviteReceiptsRoleVo::getSetMealCode).collect(Collectors.toList());
-
-            //获取上月所有入帐单(待结算和已结算的)
-            Long startTime = DateUtils.getMonthStartTime(2024, month);
-            Long endTime = DateUtils.getMonthEndTime(2024, month);
-            List<WalletReceipts> walletReceiptsList = walletReceiptsDao.listMonthBySetMealCode(startTime, endTime, setMealCodeList);
-            if (walletReceiptsList.isEmpty()){
-                return;
-            }
-
-            rulerList.forEach(ruler->{
-                walletReceiptsList.forEach(walletReceipts -> {
-                    //匹配规则
-                    if (walletReceipts.getOutTradeNo().equals(ruler.getSetMealCode())){
-                        //上月最新消息
-                        VipUserRecord topOne = vipUserRecordDao.findTopOneByOperateTime(walletReceipts.getUserId(), startTime, endTime);
-                        if (Objects.isNull(topOne)){
-                            //上月无消息,生成入账
-                            insertReceipts(ruler, walletReceipts);
-                        }else if (topOne.getSuc().equals(1) || topOne.getSuc().equals(4)){
-                            //上月最后消息为订购,生成入账
-                            insertReceipts(ruler, walletReceipts);
-                        }
-                    }
-                });
-            });
-        }
-    }
-
-    public void autoReceipts(){
-        //获取设置持续订购返利的套餐规则
-        com.zswl.cloud.bdb.client.ret.ResultContent<List<InviteReceiptsRoleVo>> rulerResult = inviteReceiptsRoleFeignService.listKeep();
-        if (rulerResult.getState().equals(com.zswl.cloud.bdb.client.ret.ResultState.Success)){
-            List<InviteReceiptsRoleVo> rulerList = rulerResult.getContent();
-            if (rulerList.isEmpty()){
-                return;
-            }
-            List<String> setMealCodeList = rulerList.stream().map(InviteReceiptsRoleVo::getSetMealCode).collect(Collectors.toList());
-
-            //获取上月所有入帐单(待结算和已结算的)
-            Long startTime = DateUtils.lastMonthStartTime();
-            Long endTime = DateUtils.lastMonthEndTime();
-            List<WalletReceipts> walletReceiptsList = walletReceiptsDao.listMonthBySetMealCode(startTime, endTime, setMealCodeList);
-            if (walletReceiptsList.isEmpty()){
-                return;
-            }
-
-            rulerList.forEach(ruler->{
-                walletReceiptsList.forEach(walletReceipts -> {
-                    //匹配规则
-                    if (walletReceipts.getOutTradeNo().equals(ruler.getSetMealCode())){
-                        //上月最新消息
-                        VipUserRecord topOne = vipUserRecordDao.findTopOneByOperateTime(walletReceipts.getUserId(), startTime, endTime);
-                        if (Objects.isNull(topOne)){
-                            //上月无消息,生成入账
-                            insertReceipts(ruler, walletReceipts);
-                        }else if (topOne.getSuc().equals(1) || topOne.getSuc().equals(4)){
-                            //上月最后消息为订购,生成入账
-                            insertReceipts(ruler, walletReceipts);
-                        }
-                    }
-                });
-            });
-        }
-    }
-
-
-    private void insertReceipts(InviteReceiptsRoleVo ruler, WalletReceipts it) {
-        WalletReceipts walletReceipts = new WalletReceipts();
-        walletReceipts.setWallet(it.getWallet());
-        walletReceipts.setInviteUserId(it.getInviteUserId());
-        walletReceipts.setUserId(it.getUserId());
-        walletReceipts.setEstimatedTime(DateUtils.nextMonthDayStartTime(ruler.getDay()));
-        walletReceipts.setReceiptsType(ReceiptsType.COMMISSION);
-        walletReceipts.setTotal(ruler.getBaseTotal());
-        walletReceipts.setStatus(ReceiptsStatus.WAIT);
-        walletReceipts.setOutTradeNo(ruler.getSetMealCode());
-        walletReceipts.setRuler(ruler);
-        VipUserRecord vipUserRecord = it.getVipUserRecord();
-        vipUserRecord.setId(null);
-        vipUserRecord.setFirst(false);
-        vipUserRecord.setPlanningId(ruler.getSetMealCode());
-        walletReceipts.setVipUserRecord(vipUserRecord);
-        Wallet wallet = walletReceipts.getWallet();
-        wallet.setWaitAmount(wallet.getWaitAmount().add(ruler.getBaseTotal()));
-        walletDao.save(wallet);
-        walletReceiptsDao.save(walletReceipts);
-    }
-
-    private void addAmount(WalletReceipts it) {
-        it.setStatus(ReceiptsStatus.RECEIPTS);
-        it.setReceiptsTime(new Date().getTime());
-        Wallet wallet = it.getWallet();
-        wallet.setWaitAmount(wallet.getWaitAmount().subtract(it.getTotal()));
-        wallet.setAmount(wallet.getAmount().add(it.getTotal()));
-        walletDao.save(wallet);
-        walletReceiptsDao.save(it);
-    }
-
-    private void cancel(WalletReceipts it){
-        it.setStatus(ReceiptsStatus.CANCEL);
-        Wallet wallet = it.getWallet();
-        wallet.setWaitAmount(wallet.getWaitAmount().subtract(it.getTotal()));
-        walletDao.save(wallet);
-        walletReceiptsDao.save(it);
-    }
-
-    /**
-     * 取消返利入账
-     * @param
-     * @return
-     */
-    @Transactional
-    public Object cancelReceipts(String outTradeNo){
-
-        WalletReceipts walletReceipts = walletReceiptsDao.findTopByOutTradeNo(outTradeNo);
-        if (ObjectUtils.isEmpty(walletReceipts)){
-            return ResultContent.build(ResultState.Fail,"返利订单不存在或未入账");
-        }
-        if (!walletReceipts.getStatus().equals(ReceiptsStatus.WAIT)){
-            return ResultContent.build(ResultState.Fail,"订单不处于未结算状态");
-        }
-
-        walletReceipts.setStatus(ReceiptsStatus.CANCEL);
-        walletReceiptsDao.save(walletReceipts);
-        Wallet wallet = walletDao.findTop1ById(walletReceipts.getWallet().getId());
-        wallet.setWaitAmount(wallet.getWaitAmount().subtract(walletReceipts.getTotal()));
-        walletDao.save(wallet);
-        return ResultContent.build(ResultState.Success);
-    }
-
     public Object listByWallet(){
         String userId = authHelper.getCurrentUser().getUserId();
         Wallet wallet = walletService.getWalletByUserId(userId);
@@ -322,6 +72,10 @@ public class WalletReceiptsService {
         return ResultContent.buildContent(list.stream().map(this::toModel).collect(Collectors.toList()));
     }
 
+    /**
+     * 即将到账详情
+     * @param receiptsId 账单id
+     */
     public Object receiptsDetail(String receiptsId){
         WalletReceipts walletReceipts = walletReceiptsDao.findTop1ById(receiptsId);
         if (ObjectUtils.isEmpty(walletReceipts)){
@@ -339,6 +93,12 @@ public class WalletReceiptsService {
         return ResultContent.buildContent(vipUserModel);
     }
 
+    /**
+     * 邀请奖励明细
+     * @param year 年
+     * @param month 月
+     * @return
+     */
     public Object rewardDetail(Integer year, Integer month){
         String userId = authHelper.getCurrentUser().getUserId();
         Long monthStartTime = DateUtils.getMonthStartTime(year, month);

+ 136 - 86
RewardServer/src/main/java/com/zhongshu/reward/server/core/service/WxTransferService.java

@@ -1,7 +1,9 @@
 package com.zhongshu.reward.server.core.service;
 
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.lang.Assert;
 import cn.hutool.core.lang.Snowflake;
+import com.wechat.pay.java.service.transferbatch.model.TransferDetailCompact;
 import com.zhongshu.reward.client.ret.ResultContent;
 import com.github.microservice.auth.security.helper.AuthHelper;
 import com.github.microservice.components.data.mongo.mongo.helper.DBHelper;
@@ -27,11 +29,15 @@ import com.zhongshu.reward.server.core.domain.OperateDisable;
 import com.zhongshu.reward.server.core.domain.TransferRuler;
 import com.zhongshu.reward.server.core.domain.Wallet;
 import com.zhongshu.reward.server.core.domain.WxTransferBatch;
+import com.zhongshu.reward.server.core.helper.RedisHelper;
 import com.zhongshu.reward.server.core.util.DateUtils;
 import com.zhongshu.reward.server.core.util.JedisUtil;
+import com.zhongshu.reward.server.core.util.wx.BusinessUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.ObjectUtils;
+import org.jetbrains.annotations.NotNull;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -75,22 +81,35 @@ public class WxTransferService {
     @Autowired
     DBHelper dbHelper;
 
-    @Resource
+    @Autowired
+    RedisHelper redisHelper;
+
+    @Autowired
     JedisUtil jedisUtil;
-    private static final String TRANSFER = "com:zswl:reward:wxtransfer";
+
+
 
     public ResultContent transferLock(WalletTransferParam param){
         String userId = authHelper.getCurrentUser().getUserId();
-        if (jedisUtil.lock(userId + TRANSFER, 30L)){
-            log.info("发起提现");
-            return transfer(param);
-        }else {
-            log.info("获取锁失败");
-            return ResultContent.buildFail("请勿重复操作");
+        String key = BusinessUtil.WXTRANSFER + ":" + userId;
+        String requestId = "";
+        try {
+            requestId = snowflake.nextIdStr();
+            boolean ret = false;
+            ret = jedisUtil.distributedLock(key, requestId, 30);
+            if (ret){
+                return transfer(param);
+            }else {
+                return ResultContent.buildFail("操作频繁,请稍后再试");
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+            return ResultContent.buildFail("系统异常,请联系管理员");
+        } finally {
+            jedisUtil.assignDb(BusinessUtil.REDIS_DB).releaseDistributedLock(key, requestId);
         }
     }
 
-
     /**
      * 发起提现
      * @param param
@@ -98,17 +117,21 @@ public class WxTransferService {
      */
     public ResultContent transfer(WalletTransferParam param){
         String userId = authHelper.getCurrentUser().getUserId();
-        OperateDisable operateDisable = operateDisableDao.findTopByUserIdAndType(userId, OperateType.TRANSFER);
-        if (ObjectUtils.isNotEmpty(operateDisable)){
-            if (new Date().getTime() < operateDisable.getTTL().getTime()){
-                return ResultContent.build(ResultState.Fail, "系统异常,请"+ DateUtils.paresTime(operateDisable.getTTL().getTime(), DateUtils.patternyyyyMis) + "后重试");
-            }else {
-                operateDisableDao.delete(operateDisable);
-            }
+        //校验提现操作是否被禁用
+        OperateDisable operateDisable = checkOperateDisable(userId, OperateType.TRANSFER);
+        if (null != operateDisable){
+            return ResultContent.build(ResultState.Fail, "系统异常,请"+ DateUtils.paresTime(operateDisable.getTTL().getTime(), DateUtils.patternyyyyMis) + "后重试");
+        }
+
+        Wallet wallet = walletDao.findByUserId(userId);
+        if (ObjectUtils.isEmpty(wallet)){
+            return ResultContent.buildFail("钱包暂未开通");
         }
-        Wallet wallet = walletDao.findTop1ById(param.getWalletId());
         //校验提现规则
-        validTransfer(param.getTotal(), wallet);
+        ResultContent validResult = validTransfer(param.getTotal(), wallet);
+        if (validResult.isFailed()){
+            return validResult;
+        }
 
         String outBatchNo = snowflake.nextIdStr();
         String outDetailNo = snowflake.nextIdStr();
@@ -119,17 +142,51 @@ public class WxTransferService {
         transferModel.setTotalAmount(param.getTotal().longValue());
         transferModel.setOutBatchNo(outBatchNo);
 
-        List<TransferDetailInput> detailList = new ArrayList<>();
-        TransferDetailInput detail = new TransferDetailInput();
-        detail.setTransferAmount(param.getTotal().longValue());
-        detail.setTransferRemark("佣金/返利发放");
-        detail.setOpenid(param.getOpenid());
-        detail.setOutDetailNo(outDetailNo);
-        detailList.add(detail);
+        List<TransferDetailInput> detailList = getTransferDetailInputs(param, outDetailNo);
         transferModel.setTotalNum(detailList.size());
         transferModel.setTransferDetailList(detailList);
 
         //初始化提现单
+        WxTransferBatch wxTransferBatch = getWxTransferBatch(param, wallet, outBatchNo, outDetailNo);
+
+        InitiateBatchTransferResponse firstResponse = wechatService.initiateBatchTransfer(transferModel, param.getAppid());
+        if (firstResponse==null){
+            //失败做一次补偿
+            firstResponse = wechatService.initiateBatchTransfer(transferModel, param.getAppid());
+            if (firstResponse == null){
+                //禁用1小时
+                disableTransfer(userId);
+                wxTransferBatch.setTransferStatus(TransferStatus.FAIL);
+                wxTransferBatch.setFailReason("提现失败请一小时后再次尝试");
+                wxTransferBatchDao.save(wxTransferBatch);
+                return ResultContent.buildFail("提现失败请一小时后再次尝试");
+            }
+        }
+
+        wxTransferBatch.setBatchStatus(firstResponse.getBatchStatus());
+        wxTransferBatch.setWxBatchId(firstResponse.getBatchId());
+        wxTransferBatch.setTransferStatus(TransferStatus.PROCESSING);
+        wxTransferBatchDao.save(wxTransferBatch);
+
+//        Wallet currentWallet = walletDao.findTop1ById(param.getWalletId());
+//        wallet.setAmount(currentWallet.getAmount().subtract(param.getTotal()));
+//        wallet.setTodayTransferAmount(currentWallet.getTodayTransferAmount().add(param.getTotal()));
+//        walletDao.save(wallet);
+        BigDecimal negateTotal = param.getTotal().negate();
+        walletDao.updateIncAmount(wallet.getId(), negateTotal);
+        return ResultContent.build(ResultState.Success);
+    }
+
+    private void disableTransfer(String userId) {
+        OperateDisable newDisable = new OperateDisable();
+        newDisable.setUserId(userId);
+        newDisable.setType(OperateType.TRANSFER);
+        newDisable.setTTL(new Date(this.dbHelper.getTime() + 60*60 * 1000L));
+        operateDisableDao.save(newDisable);
+    }
+
+    @NotNull
+    private static WxTransferBatch getWxTransferBatch(WalletTransferParam param, Wallet wallet, String outBatchNo, String outDetailNo) {
         WxTransferBatch wxTransferBatch = new WxTransferBatch();
         wxTransferBatch.setBatchNo(outBatchNo);
         wxTransferBatch.setDetailNo(outDetailNo);
@@ -138,38 +195,32 @@ public class WxTransferService {
         wxTransferBatch.setChannel(TransferChannel.WeChat);
         wxTransferBatch.setBeforeWalletInfo(wallet);
         wxTransferBatch.setWechatName(param.getWechatName());
+        return wxTransferBatch;
+    }
 
-        InitiateBatchTransferResponse response = wechatService.initiateBatchTransfer(transferModel, param.getAppid());
-        if (response==null){
-            OperateDisable newDisable = new OperateDisable();
-            newDisable.setUserId(userId);
-            newDisable.setType(OperateType.TRANSFER);
-            newDisable.setTTL(new Date(this.dbHelper.getTime() + 60*60 * 1000L));
-            operateDisableDao.save(newDisable);
-            wxTransferBatch.setTransferStatus(TransferStatus.FAIL);
-            wxTransferBatch.setFailReason("提现失败请一小时后再次尝试");
-            wxTransferBatchDao.save(wxTransferBatch);
-            //失败做一次补偿
-            return ResultContent.build(ResultState.Fail);
-        }
-//        wxTransferBatch.setBatchNo(outBatchNo);
-//        wxTransferBatch.setDetailNo(outDetailNo);
-//        wxTransferBatch.setWallet(wallet);
-//        wxTransferBatch.setTotal(param.getTotal());
-//        wxTransferBatch.setChannel(TransferChannel.WeChat);
-//        wxTransferBatch.setBeforeWalletInfo(wallet);
-        wxTransferBatch.setBatchStatus(response.getBatchStatus());
-        wxTransferBatch.setWxBatchId(response.getBatchId());
-        wxTransferBatch.setTransferStatus(TransferStatus.PROCESSING);
-        wxTransferBatchDao.save(wxTransferBatch);
-
-        Wallet currentWallet = walletDao.findTop1ById(param.getWalletId());
-        wallet.setAmount(currentWallet.getAmount().subtract(param.getTotal()));
-        wallet.setTodayTransferAmount(currentWallet.getTodayTransferAmount().add(param.getTotal()));
-        walletDao.save(wallet);
-        return ResultContent.build(ResultState.Success);
+    @NotNull
+    private static List<TransferDetailInput> getTransferDetailInputs(WalletTransferParam param, String outDetailNo) {
+        List<TransferDetailInput> detailList = new ArrayList<>();
+        TransferDetailInput detail = new TransferDetailInput();
+        detail.setTransferAmount(param.getTotal().longValue());
+        detail.setTransferRemark("佣金/返利发放");
+        detail.setOpenid(param.getOpenid());
+        detail.setOutDetailNo(outDetailNo);
+        detailList.add(detail);
+        return detailList;
     }
 
+    public OperateDisable checkOperateDisable(String userId, OperateType operateType){
+        OperateDisable operateDisable = operateDisableDao.findTopByUserIdAndType(userId, operateType);
+        if (ObjectUtils.isEmpty(operateDisable)){
+            return null;
+        }else if (new Date().getTime() < operateDisable.getTTL().getTime()){
+            return operateDisable;
+        }else {
+            operateDisableDao.delete(operateDisable);
+            return null;
+        }
+    }
 
 
     public Object queryTransfer(String walletId, Integer year, Integer month){
@@ -180,15 +231,15 @@ public class WxTransferService {
     }
 
 
-    public Object updateTransferStatus(String transferId){
+    public void updateTransferStatus(String transferId){
         WxTransferBatch wxTransferBatch = wxTransferBatchDao.findTop1ById(transferId);
         if (ObjectUtils.isEmpty(wxTransferBatch)){
-            return ResultContent.build(ResultState.Fail, "提现订单不存在");
+            return;
         }
 
         TransferStatus transferStatus = wxTransferBatch.getTransferStatus();
         if (!transferStatus.equals(TransferStatus.PROCESSING)){
-            return ResultContent.build(ResultState.Success);
+           return;
         }
 
         TransferStatusModel transferStatusModel = new TransferStatusModel();
@@ -198,26 +249,26 @@ public class WxTransferService {
         TransferBatchEntity transferBatchByNo = wechatService.getTransferBatchByNo(transferStatusModel);
 
         String batchStatus = transferBatchByNo.getTransferBatch().getBatchStatus();
-        String detailStatus = transferBatchByNo.getTransferDetailList().get(0).getDetailStatus();
+        String detailStatus = "INIT";
+        List<TransferDetailCompact> transferDetailList = transferBatchByNo.getTransferDetailList();
+        if (null != transferDetailList && !transferDetailList.isEmpty()){
+            detailStatus = transferBatchByNo.getTransferDetailList().get(0).getDetailStatus();
+        }
+
+        String walletId = wxTransferBatch.getWallet().getId();
+        BigDecimal total = wxTransferBatch.getTotal();
 
         if(batchStatus.equals("FINISHED") && detailStatus.equals("SUCCESS")){
             transferStatus = TransferStatus.SUCCESS;
         }else if(batchStatus.equals("CLOSED")){
             transferStatus = TransferStatus.CLOSE;
-            Wallet wallet = walletDao.findTop1ById(wxTransferBatch.getWallet().getId());
-            wallet.setAmount(wallet.getAmount().add(wxTransferBatch.getTotal()));
-            wallet.setTodayTransferAmount(wallet.getTodayTransferAmount().subtract(wxTransferBatch.getTotal()));
-            walletDao.save(wallet);
+            walletDao.updateIncAmount(walletId, total);
         }else if (detailStatus.equals("FAIL")){
             transferStatus = TransferStatus.FAIL;
-            Wallet wallet = walletDao.findTop1ById(wxTransferBatch.getWallet().getId());
-            wallet.setAmount(wallet.getAmount().add(wxTransferBatch.getTotal()));
-            wallet.setTodayTransferAmount(wallet.getTodayTransferAmount().subtract(wxTransferBatch.getTotal()));
-            walletDao.save(wallet);
+            walletDao.updateIncAmount(walletId, total);
         }
         boolean update = wxTransferBatchDao.updateStatus(transferId, batchStatus, detailStatus, transferStatus);
         log.info("更新微信转账批次状态:结果:{}, id:{}, batchStatus:{}, detailStatus: {}, transferStatus: {}",update, transferId, batchStatus, detailStatus, transferStatus);
-        return ResultContent.build(update);
     }
 
     WxTransferBatchModel toModel(WxTransferBatch wxTransferBatch){
@@ -229,52 +280,51 @@ public class WxTransferService {
         return model;
     }
 
-    void validTransfer(BigDecimal total, Wallet wallet){
+    public ResultContent validTransfer(BigDecimal total, Wallet wallet){
         long currentTime = System.currentTimeMillis();
         Integer size = 0;
         List<TransferRuler> list = transferRulerDao.findAll();
         if (list.isEmpty()){
-            throw new CommentException(com.zhongshu.reward.client.ret.ResultState.Exception, "管理员未设置提现规则");
+            return ResultContent.buildFail("管理员未设置提现规则");
         }
         TransferRuler transferRuler = list.get(0);
+
+        //判断可提现金额是否足够
+        if (total.compareTo(wallet.getAmount()) > 0){
+            return ResultContent.build(ResultState.Fail, "可提现余额不足");
+        }
+        //单笔金额
+        if (total.compareTo(transferRuler.getMinTotal()) < 0){
+            return ResultContent.buildFail("单笔提现金额低于最小值");
+        }else if (total.compareTo(transferRuler.getMaxTotal()) > 0){
+            return ResultContent.buildFail("单笔提现金额超出最大值");
+        }
         //提现时间
         if (transferRuler.getTimeUnit().equals(TimeUnitType.MONTH)){//每月
             Long dayOfMonthStartTime = DateUtils.getDayOfMonthStartTime(transferRuler.getStartDay());
             Long dayOfMonthEndTime = DateUtils.getDayOfMonthEndTime(transferRuler.getEndDay());
             if (currentTime < dayOfMonthStartTime || currentTime > dayOfMonthEndTime){
-                throw new CommentException(com.zhongshu.reward.client.ret.ResultState.Exception, "当前不处于提现时间段");
+                return ResultContent.buildFail("当前不处于提现时间段");
             }
             size = wxTransferBatchDao.countByTime(wallet.getId(), dayOfMonthStartTime, dayOfMonthEndTime);
         }else if (transferRuler.getTimeUnit().equals(TimeUnitType.DAY)){
             Long hourMinuteStartTime = DateUtils.getHourMinuteStartTime(transferRuler.getStartHour(), transferRuler.getStartMinute());
             Long hourMinuteEndTime = DateUtils.getHourMinuteEndTime(transferRuler.getEndHour(), transferRuler.getEndMinute());
             if (currentTime < hourMinuteStartTime || currentTime > hourMinuteEndTime){
-                throw new CommentException(com.zhongshu.reward.client.ret.ResultState.Exception, "当前不处于提现时间段");
+                return ResultContent.buildFail("当前不处于提现时间段");
             }
             size = wxTransferBatchDao.countByTime(wallet.getId(), hourMinuteStartTime, hourMinuteEndTime);
         }
-        //单笔金额
-        if (total.compareTo(transferRuler.getMinTotal()) < 0){
-            throw new CommentException(com.zhongshu.reward.client.ret.ResultState.Exception, "单笔提现金额低于最小值");
-        }else if (total.compareTo(transferRuler.getMaxTotal()) > 0){
-            throw new CommentException(com.zhongshu.reward.client.ret.ResultState.Exception, "单笔提现金额超出最大值");
-        }
-
         //判断提现额度是否超出每日上限
         Integer sumDayTotal = wxTransferBatchDao.sumDayTotal(wallet.getId(), DateUtils.getCurrentDayStartTime().getTime(), DateUtils.getCurrentDayEndTime().getTime());
         if (total.add(BigDecimal.valueOf(sumDayTotal)).compareTo(transferRuler.getDayMaxTotal()) > 0){
-            throw new CommentException(com.zhongshu.reward.client.ret.ResultState.Exception, "超出每日提现金额上限");
-//            return ResultContent.build(ResultState.Fail, "超出每日提现金额上限");
-        }
-        //判断可提现金额是否足够
-        if (total.compareTo(wallet.getAmount()) > 0){
-            throw new CommentException(com.zhongshu.reward.client.ret.ResultState.Exception, "可提现余额不足");
-//            return ResultContent.build(ResultState.Fail, "可提现余额不足");
+            return ResultContent.build(ResultState.Fail, "超出每日提现金额上限");
         }
         //提现次数
         if (size >= transferRuler.getSize()){
-            throw new CommentException(com.zhongshu.reward.client.ret.ResultState.Exception, "超过可提现次数");
+            return ResultContent.build(ResultState.Fail, "超过可提现次数");
         }
+        return ResultContent.buildSuccess();
     }
 
 

+ 15 - 0
RewardServer/src/main/java/com/zhongshu/reward/server/core/stream/OrderStream.java

@@ -0,0 +1,15 @@
+package com.zhongshu.reward.server.core.stream;
+
+import com.github.microservice.app.stream.StreamConsumer;
+import com.zhongshu.payment.client.model.order.v2.OrderStremModel;
+
+/**
+ * @author wjf
+ * @date 2024/8/22
+ */
+public class OrderStream extends StreamConsumer<OrderStremModel> {
+    @Override
+    public void accept(OrderStremModel orderStremModel) {
+        
+    }
+}

+ 5 - 2
RewardServer/src/main/java/com/zhongshu/reward/server/core/stream/VipUserStream.java

@@ -3,7 +3,7 @@ package com.zhongshu.reward.server.core.stream;
 import com.github.microservice.app.stream.StreamConsumer;
 import com.zhongshu.reward.server.core.dao.VipUserRecordDao;
 import com.zhongshu.reward.server.core.domain.VipUserRecord;
-import com.zhongshu.reward.server.core.service.InviteReceiptsRulerService;
+import com.zhongshu.reward.server.core.service.InviteReceiptsService;
 import com.zhongshu.reward.server.core.service.WalletReceiptsService;
 import com.zhongshu.reward.server.core.util.DateUtils;
 import com.zhongshu.vip.client.model.param.VipUserParam;
@@ -19,6 +19,9 @@ public class VipUserStream extends StreamConsumer<VipUserParam> {
     @Autowired
     WalletReceiptsService walletReceiptsService;
 
+    @Autowired
+    InviteReceiptsService inviteReceiptsService;
+
     @Autowired
     VipUserRecordDao vipUserRecordDao;
 
@@ -28,6 +31,6 @@ public class VipUserStream extends StreamConsumer<VipUserParam> {
         VipUserRecord vipUserRecord = new VipUserRecord();
         BeanUtils.copyProperties(vipUserParam, vipUserRecord, "createTime");
         vipUserRecord.setOperateTime(DateUtils.timeToLong(vipUserParam.getCreateTime(), DateUtils.FORMAT_LONG));
-        walletReceiptsService.receipts(vipUserRecord);
+        inviteReceiptsService.receipts(vipUserRecord);
     }
 }

+ 126 - 0
RewardServer/src/main/java/com/zhongshu/reward/server/core/timer/TransferStatusTimer.java

@@ -0,0 +1,126 @@
+package com.zhongshu.reward.server.core.timer;
+
+import com.github.microservice.components.data.mongo.token.service.ResourceTokenService;
+import com.zhongshu.reward.client.type.TransferStatus;
+import com.zhongshu.reward.server.core.dao.WxTransferBatchDao;
+import com.zhongshu.reward.server.core.domain.WxTransferBatch;
+import com.zhongshu.reward.server.core.service.WxTransferService;
+import lombok.Cleanup;
+import lombok.Setter;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.context.ApplicationContext;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * @author wjf
+ * @date 2024/8/22
+ */
+@Slf4j
+@Component
+@EnableScheduling
+public class TransferStatusTimer implements ApplicationRunner {
+
+    @Autowired
+    WxTransferBatchDao wxTransferBatchDao;
+
+    @Autowired
+    private ResourceTokenService resourceTokenService;
+
+    @Autowired
+    private WxTransferService wxTransferService;
+
+    private Timer transferStatusTimer = new Timer();
+
+    private AtomicBoolean isRunTransferStatusTimer = new AtomicBoolean(false);
+
+    private AtomicReference<ResourceTokenService.Token> token = new AtomicReference<>();
+    @Override
+    public void run(ApplicationArguments args) throws Exception {
+        transferStatusTimer.schedule(new TimerTask() {
+            @Override
+            public void run() {
+                if (isRunTransferStatusTimer.get()){
+                    return;
+                }
+                isRunTransferStatusTimer.set(true);
+                try {
+                    //
+                    updateTransferStatus();
+                }catch (Exception e){
+                    e.printStackTrace();
+                }finally {
+                    isRunTransferStatusTimer.set(false);
+                }
+            }
+        }, 3000, 3000);
+
+    }
+
+    @Autowired
+    private void init(ApplicationContext applicationContext) {
+        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
+            Optional.ofNullable(token.get()).ifPresent((it) -> {
+                it.close();
+            });
+        }));
+
+    }
+
+    @SneakyThrows
+    public synchronized void updateTransferStatus(){
+        @Cleanup ResourceTokenService.Token token = resourceTokenService.token("updateTransferStatusToken");
+        try {
+
+            List<WxTransferBatch> byTransferStatus = wxTransferBatchDao.findByTransferStatus(TransferStatus.PROCESSING);
+            if (null == byTransferStatus || byTransferStatus.isEmpty()){
+                return;
+            }
+            for (WxTransferBatch wxTransferBatch : byTransferStatus){
+                @Cleanup TaskExecutor taskExecutor = new TaskExecutor();
+                taskExecutor.setWxTransferBatch(wxTransferBatch);
+                taskExecutor.start();
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+    }
+
+
+    private class TaskExecutor{
+        @Setter
+        private WxTransferBatch wxTransferBatch;
+
+        private Timer timer = new Timer();
+
+        public void start() {
+            timer.scheduleAtFixedRate(new TimerTask() {
+                @Override
+                public void run() {
+
+                }
+            }, 5000L, 1000L);
+
+            wxTransferService.updateTransferStatus(wxTransferBatch.getId());
+        }
+
+        public void close() {
+            timer.cancel();
+        }
+    }
+
+    private void findAndUpdateTask(){
+        List<WxTransferBatch> byTransferStatus = wxTransferBatchDao.findByTransferStatus(TransferStatus.PROCESSING);
+    }
+}

+ 29 - 23
RewardServer/src/main/java/com/zhongshu/reward/server/core/timer/WalletTimer.java

@@ -1,13 +1,16 @@
 package com.zhongshu.reward.server.core.timer;
 
 
+import com.github.microservice.components.data.mongo.token.service.ResourceTokenService;
 import com.zhongshu.reward.client.type.TransferStatus;
 import com.zhongshu.reward.server.core.dao.WalletDao;
 import com.zhongshu.reward.server.core.dao.WxTransferBatchDao;
 import com.zhongshu.reward.server.core.domain.WxTransferBatch;
+import com.zhongshu.reward.server.core.service.InviteReceiptsService;
 import com.zhongshu.reward.server.core.service.WalletReceiptsService;
 import com.zhongshu.reward.server.core.service.WxTransferService;
 import com.zhongshu.reward.server.core.util.DateUtils;
+import lombok.Cleanup;
 import lombok.extern.log4j.Log4j2;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Scheduled;
@@ -36,50 +39,53 @@ public class WalletTimer {
     @Autowired
     WalletReceiptsService walletReceiptsService;
 
-//    /**
-//     * 重置每日提现额度
-//     */
-//    @Scheduled(cron = "0 0 0 * * ?")
-//    public void resetTodayAmount(){
+    @Autowired
+    InviteReceiptsService inviteReceiptsService;
+
+    @Autowired
+    ResourceTokenService resourceTokenService;
+
+
+//    @Scheduled(fixedRate = 5000)
+//    public void updateTransferStatus(){
 //        try {
-//            walletDao.resetTodayAmount();
+//            List<WxTransferBatch> byTransferStatus = wxTransferBatchDao.findByTransferStatus(TransferStatus.PROCESSING);
+//            for (WxTransferBatch wxTransferBatch : byTransferStatus){
+//                wxTransferService.updateTransferStatus(wxTransferBatch.getId());
+//            }
 //        }catch (Exception e){
 //            e.printStackTrace();
 //        }
 //    }
 
-    @Scheduled(fixedRate = 5000)
-    public void updateTransferStatus(){
-        try {
-            List<WxTransferBatch> byTransferStatus = wxTransferBatchDao.findByTransferStatus(TransferStatus.PROCESSING);
-            for (WxTransferBatch wxTransferBatch : byTransferStatus){
-                wxTransferService.updateTransferStatus(wxTransferBatch.getId());
-            }
-        }catch (Exception e){
-            e.printStackTrace();
-        }
-    }
-
-    @Scheduled(cron = "0 0 1 * * ?")
+    /**
+     * 定时结算邀请返利
+     */
+    @Scheduled(cron = "0 0 3 * * ?")
     public void settle(){
+        @Cleanup ResourceTokenService.Token token =  resourceTokenService.token("settleInviteReceipts");
         try {
             LocalDate now = LocalDate.now();
 
             if (DateUtils.checkLastDayOfMonth() &&  now.getMonthValue() == 2){
                 for (int i = now.getDayOfMonth(); i <= 31; i++) {
-                    walletReceiptsService.settle(i);
+                    inviteReceiptsService.settle(i);
                 }
             }
-            walletReceiptsService.settle(now.getDayOfMonth());
+            inviteReceiptsService.settle(now.getDayOfMonth());
         }catch (Exception e){
             e.printStackTrace();
         }
     }
 
-    @Scheduled(cron = "0 0 0 1 * ?")
+    /**
+     * 定时生成持续返利订单
+     */
+    @Scheduled(cron = "0 0 1 1 * ?")
     public void autoReceipts(){
+        @Cleanup ResourceTokenService.Token token =  resourceTokenService.token("autoInviteReceipts");
         try {
-            walletReceiptsService.autoReceipts();
+            inviteReceiptsService.autoReceipts();
         }catch (Exception e){
             e.printStackTrace();
         }

+ 13 - 0
RewardServer/src/main/java/com/zhongshu/reward/server/core/util/DateUtils.java

@@ -36,6 +36,19 @@ public class DateUtils {
         return null;
     }
 
+    /**
+     * 获取本月开始时间
+     */
+    public static Long getCurrentMonthStartTime(){
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(Calendar.DAY_OF_MONTH, 1); // 设置为本月的第一天
+        calendar.set(Calendar.HOUR_OF_DAY, 0); // 将小时设置为0
+        calendar.set(Calendar.MINUTE, 0); // 将分钟设置为0
+        calendar.set(Calendar.SECOND, 0); // 将秒设置为0
+        calendar.set(Calendar.MILLISECOND, 0); // 将毫秒设置为0
+        return calendar.getTimeInMillis();
+    }
+
     /**
      * 获取上月指定日期时间
      */

+ 51 - 38
RewardServer/src/main/java/com/zhongshu/reward/server/core/util/JedisUtil.java

@@ -40,36 +40,46 @@ public class JedisUtil {
     public JedisUtil(Pool<Jedis> jedisPool){
         this.jedisPool = jedisPool;
     }
-
-    public boolean lock(String lockKey, long expireTime) {
-        try (Jedis jedis = getRedisClient()){
-            long expires = System.currentTimeMillis() + expireTime + 1;
-            String expiresStr = String.valueOf(expires); // 锁到期时间
-
-            if (jedis.setnx(lockKey, expiresStr) == 1) {
-                // 获取锁成功
-                jedis.expire(lockKey, expireTime); // 设置锁的过期时间
-                return true;
-            }
-
-            String currentValueStr = jedis.get(lockKey); // Redis里面的时间
-            if (currentValueStr != null && Long.parseLong(currentValueStr) < System.currentTimeMillis()) {
-                // 锁已经存在,但已经过期,可以尝试获取锁
-                String oldValueStr = jedis.getSet(lockKey, expiresStr);
-                if (oldValueStr != null && oldValueStr.equals(currentValueStr)) {
-                    // 获取锁成功
-                    jedis.expire(lockKey, expireTime); // 设置锁的过期时间
-                    return true;
-                }
-            }
-            // 其他情况,无法获取锁
-            return false;
-        }catch (Exception e){
-            log.error("jedis执行异常......", e);
-            return false;
-        }
-
-    }
+//        public boolean distributedLock(String lockKey, String requestId, long expireTime) {
+//            try (Jedis jedis = getRedisClient()) {
+//                String script = "if redis.call('SETNX', KEY[1], ARGV[1]) >= 1 then return redis.call('EXPIRE', KEY[1], ARGV[2]) else return 0 end";
+//                Object obj = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
+//                return LOCK_SUCCESS.equals(obj);
+//            } catch (Exception e) {
+//                log.error("jedis执行异常......", e);
+//                return false;
+//            }
+//        }
+
+//    public boolean lock(String lockKey, long expireTime) {
+//        try (Jedis jedis = getRedisClient()){
+//            long expires = System.currentTimeMillis() + expireTime + 1;
+//            String expiresStr = String.valueOf(expires); // 锁到期时间
+//
+//            if (jedis.setnx(lockKey, expiresStr) == 1) {
+//                // 获取锁成功
+//                jedis.expire(lockKey, expireTime); // 设置锁的过期时间
+//                return true;
+//            }
+//
+//            String currentValueStr = jedis.get(lockKey); // Redis里面的时间
+//            if (currentValueStr != null && Long.parseLong(currentValueStr) < System.currentTimeMillis()) {
+//                // 锁已经存在,但已经过期,可以尝试获取锁
+//                String oldValueStr = jedis.getSet(lockKey, expiresStr);
+//                if (oldValueStr != null && oldValueStr.equals(currentValueStr)) {
+//                    // 获取锁成功
+//                    jedis.expire(lockKey, expireTime); // 设置锁的过期时间
+//                    return true;
+//                }
+//            }
+//            jedis.close();
+//            // 其他情况,无法获取锁
+//            return false;
+//        }catch (Exception e){
+//            log.error("jedis执行异常......", e);
+//            return false;
+//        }
+//    }
 
     public Set<String> keys(final String pattern) {
         try (Jedis jedis = getRedisClient()) {
@@ -347,7 +357,7 @@ public class JedisUtil {
 
     public boolean distributedLock(String lockKey, String requestId, long expireTime) {
         try (Jedis jedis = getRedisClient()) {
-            SetParams params = SetParams.setParams().nx().ex((int) expireTime);
+            SetParams params = SetParams.setParams().nx().ex(expireTime);
             String ret = jedis.set(lockKey, requestId, params);
             return LOCK_SUCCESS.equals(ret);
         } catch (Exception e) {
@@ -385,7 +395,7 @@ public class JedisUtil {
         }
     }
 
-    
+
     public Long incr(String key) {
         try (Jedis jedis = getRedisClient()) {
             return jedis.incr(key);
@@ -670,7 +680,7 @@ public class JedisUtil {
         }
     }
 
-    
+
     public Long geoAdd(String key, Map<String, GeoCoordinate> memberCoordinateMap) {
         try (Jedis jedis = getRedisClient()) {
             return jedis.geoadd(key, memberCoordinateMap);
@@ -680,7 +690,7 @@ public class JedisUtil {
         }
     }
 
-    
+
     public Double geoDist(String key, String member1, String member2, GeoUnit geoUnit) {
         try (Jedis jedis = getRedisClient()) {
             return jedis.geodist(key, member1, member2, geoUnit);
@@ -690,7 +700,7 @@ public class JedisUtil {
         }
     }
 
-    
+
     public List<String> geoHash(String key, String... members) {
         try (Jedis jedis = getRedisClient()) {
             return jedis.geohash(key, members);
@@ -700,7 +710,7 @@ public class JedisUtil {
         }
     }
 
-    
+
     public List<GeoCoordinate> geoPos(String key, String... members) {
         try (Jedis jedis = getRedisClient()) {
             return jedis.geopos(key, members);
@@ -710,7 +720,7 @@ public class JedisUtil {
         }
     }
 
-    
+
     public List<GeoRadiusResponseExt> geoRadius(String key, GeoCoordinate coordinate, double radius, int count) {
         try (Jedis jedis = getRedisClient()) {
             List<GeoRadiusResponse> georadius = jedis.georadius(key,
@@ -726,7 +736,7 @@ public class JedisUtil {
         }
     }
 
-    
+
     public List<GeoRadiusResponseExt> geoRadiusByMember(String key, String member, double radius) {
         try (Jedis jedis = getRedisClient()) {
             List<GeoRadiusResponse> georadius = jedis.georadiusByMember(key,
@@ -961,4 +971,7 @@ public class JedisUtil {
         return jedis;
     }
 
+
+
+
 }

+ 0 - 74
RewardServer/src/main/java/com/zhongshu/reward/server/core/util/RedisDistributedLock.java

@@ -1,74 +0,0 @@
-package com.zhongshu.reward.server.core.util;
-
-import org.springframework.stereotype.Component;
-import redis.clients.jedis.Jedis;
-
-/**
- * @author wjf
- * @date 2024/8/19
- */
-
-public class RedisDistributedLock {
-    private Jedis jedis;
-    private String lockKey;
-    private int expireTime; // 锁的超时时间
-
-    public RedisDistributedLock(Jedis jedis, String lockKey, int expireTime) {
-        this.jedis = jedis;
-        this.lockKey = lockKey;
-        this.expireTime = expireTime;
-    }
-
-    public boolean lock() {
-        long expires = System.currentTimeMillis() + expireTime + 1;
-        String expiresStr = String.valueOf(expires); // 锁到期时间
-
-        if (jedis.setnx(lockKey, expiresStr) == 1) {
-            // 获取锁成功
-            jedis.expire(lockKey, expireTime); // 设置锁的过期时间
-            return true;
-        }
-
-        String currentValueStr = jedis.get(lockKey); // Redis里面的时间
-        if (currentValueStr != null && Long.parseLong(currentValueStr) < System.currentTimeMillis()) {
-            // 锁已经存在,但已经过期,可以尝试获取锁
-            String oldValueStr = jedis.getSet(lockKey, expiresStr);
-            if (oldValueStr != null && oldValueStr.equals(currentValueStr)) {
-                // 获取锁成功
-                jedis.expire(lockKey, expireTime); // 设置锁的过期时间
-                return true;
-            }
-        }
-        // 其他情况,无法获取锁
-        return false;
-    }
-
-    public void unlock() {
-        // 确保是该用户持有的锁才能释放
-        String currentValueStr = jedis.get(lockKey);
-        if (currentValueStr != null && Long.parseLong(currentValueStr) == System.currentTimeMillis()) {
-            jedis.del(lockKey); // 释放锁
-        }
-    }
-
-    public static void main(String[] args) {
-        Jedis jedis = new Jedis("localhost");
-        RedisDistributedLock lock = new RedisDistributedLock(jedis, "user_1001", 1000);
-
-        try {
-            if (lock.lock()) {
-                // 执行业务逻辑
-                System.out.println("执行业务逻辑...");
-                // 模拟耗时操作
-                Thread.sleep(2000);
-            } else {
-                System.out.println("未获取到锁,其他实例可能正在操作...");
-            }
-        } catch (InterruptedException e) {
-            e.printStackTrace();
-        } finally {
-            lock.unlock();
-            jedis.close();
-        }
-    }
-}

+ 19 - 0
RewardServer/src/main/java/com/zhongshu/reward/server/core/util/wx/BusinessUtil.java

@@ -0,0 +1,19 @@
+package com.zhongshu.reward.server.core.util.wx;
+
+import com.zswl.cloud.shop.client.vo.es.GoodsVo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Author: wy
+ * @Date: 2023/12/5 10:10
+ */
+public class BusinessUtil {
+
+    public final static Integer REDIS_DB = 8;
+    public final static String WXTRANSFER = "reward:wxtransfer";
+
+    public final static String WXTRANSFERSTATUS = "reward:wxtransfer:status";
+
+}

+ 1 - 1
RewardServer/src/main/resources/application-dev.yml

@@ -9,7 +9,7 @@ spring:
     port: 6379
     password:
     timeout: 60000
-    database: 9
+    database: 8
     jedis:
       pool:
         max-active: 128 # 连接池最大连接数

+ 4 - 1
RewardServer/src/main/resources/application.yml

@@ -24,7 +24,7 @@ spring:
           brokers: ${Kafka.brokers}
           replication-factor: 1
       function:
-        definition: userLogStreamConsumer;vipUserStreamConsumer
+        definition: userLogStreamConsumer;vipUserStreamConsumer;orderStreamConsumer
       bindings:
         userLogStreamConsumer-in-0:
           destination: UserLogStream
@@ -32,6 +32,9 @@ spring:
         vipUserStreamConsumer-in-0:
           destination: VipUserStream
           group: ${project.artifactId}
+        orderStreamConsumer-in-0:
+          destination: OrderStream
+          group: ${project.artifactId}
     bus:
       enabled: true
   #??zipkin???????