wujiefeng 9 месяцев назад
Родитель
Сommit
b40a305313

+ 3 - 0
RewardClient/src/main/java/com/zhongshu/reward/client/model/param/WalletTransferParam.java

@@ -22,4 +22,7 @@ public class WalletTransferParam {
     @Schema(name = "openid", description = "微信openid")
     private String openid;
 
+    @Schema(name = "appid", description = "appid")
+    private String appid;
+
 }

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

@@ -0,0 +1,42 @@
+package com.zhongshu.reward.server.core.dao.Impl;
+
+import com.zhongshu.reward.server.core.dao.extend.VipUserRecordDaoExtend;
+import com.zhongshu.reward.server.core.domain.VipUserRecord;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+
+import java.util.List;
+
+/**
+ * @author wjf
+ * @date 2024/8/13
+ */
+public class VipUserRecordDaoImpl implements VipUserRecordDaoExtend {
+
+    @Autowired
+    MongoTemplate mongoTemplate;
+
+    @Override
+    public VipUserRecord findTopOneByOperateTime(String userId, Long startTime, Long endTime) {
+
+        Criteria criteria = new Criteria();
+
+        criteria.and("operateTime").gte(startTime);
+
+        criteria.and("operateTime").lte(endTime);
+
+
+        criteria.and("cpId").is(userId);
+
+        Query query = Query.query(criteria);
+        query.with(Sort.by(Sort.Order.desc("operateTime")));
+        List<VipUserRecord> vipUserRecords = mongoTemplate.find(query, VipUserRecord.class);
+        if (vipUserRecords.isEmpty()){
+            return null;
+        }
+        return vipUserRecords.get(0);
+    }
+}

+ 2 - 1
RewardServer/src/main/java/com/zhongshu/reward/server/core/dao/VipUserRecordDao.java

@@ -1,6 +1,7 @@
 package com.zhongshu.reward.server.core.dao;
 
 import com.github.microservice.components.data.mongo.mongo.dao.MongoDao;
+import com.zhongshu.reward.server.core.dao.extend.VipUserRecordDaoExtend;
 import com.zhongshu.reward.server.core.domain.VipUserRecord;
 
 import java.util.List;
@@ -9,7 +10,7 @@ import java.util.List;
  * @author wjf
  * @date 2024/8/8
  */
-public interface VipUserRecordDao extends MongoDao<VipUserRecord> {
+public interface VipUserRecordDao extends MongoDao<VipUserRecord>, VipUserRecordDaoExtend {
 
     boolean existsByCpIdAndSucIn(String cpId, List<Integer> suc);
     VipUserRecord findTop1ByCpIdAndSucOrderByOperateTime(String cpId, Integer suc);

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

@@ -0,0 +1,14 @@
+package com.zhongshu.reward.server.core.dao.extend;
+
+import com.zhongshu.reward.server.core.domain.VipUserRecord;
+
+import java.util.List;
+
+/**
+ * @author wjf
+ * @date 2024/8/13
+ */
+public interface VipUserRecordDaoExtend {
+
+    VipUserRecord findTopOneByOperateTime(String userId, Long startTime, Long endTime);
+}

+ 4 - 3
RewardServer/src/main/java/com/zhongshu/reward/server/core/service/ChatTransferBatchService.java

@@ -41,7 +41,7 @@ public class ChatTransferBatchService {
                         .merchantId(weChatConfig.getMerchantId())
                         // 使用 com.wechat.pay.java.core.util
                         // 中的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名
-                        .privateKey(weChatConfig.getPrivateKey())
+                        .privateKey(Thread.currentThread().getContextClassLoader().getResource("").getPath() + weChatConfig.getPrivateKey())
                         .merchantSerialNumber(weChatConfig.getMerchantSerialNumber())
                         .apiV3Key(weChatConfig.getApiV3Key())
                         .build();
@@ -74,15 +74,16 @@ public class ChatTransferBatchService {
     /**
      * 发起商家转账
      */
-    public InitiateBatchTransferResponse initiateBatchTransfer(TransferModel transferModel) {
+    public InitiateBatchTransferResponse initiateBatchTransfer(TransferModel transferModel, String appid) {
         Config config = RSAAutoCertificateConfig();
         // 初始化服务
         service = new TransferBatchService.Builder().config(config).build();
         try {
             InitiateBatchTransferRequest request = new InitiateBatchTransferRequest();
             BeanUtils.copyProperties(transferModel,request);
-            request.setAppid(weChatConfig.getAppid());
+            request.setAppid(appid);
             request.setTransferSceneId(transferModel.getTransferSceneId());
+            request.setTransferSceneId(weChatConfig.getTransferSceneId());
             return service.initiateBatchTransfer(request);
         } catch (HttpException e) { // 发送HTTP请求失败
             // 调用e.getHttpRequest()获取请求打印日志或上报监控,更多方法见HttpException定义

+ 58 - 5
RewardServer/src/main/java/com/zhongshu/reward/server/core/service/WalletReceiptsService.java

@@ -29,6 +29,8 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 import java.util.Objects;
 import java.util.stream.Collectors;
@@ -130,11 +132,62 @@ public class WalletReceiptsService {
         Long endTime = DateUtils.lastMonthEndTime();
         List<WalletReceipts> list = walletReceiptsDao.listMonth(startTime, endTime);
 
-        for (WalletReceipts walletReceipts : list){
-            String inviteUserId = walletReceipts.getInviteUserId();
-            String userId = walletReceipts.getUserId();
-        }
-        return;
+        List<WalletReceipts> receipts = new ArrayList<>();
+        List<Wallet> wallets = new ArrayList<>();
+
+        //首次订购
+        list.forEach(it -> {
+            if (it.getVipUserRecord().isFirst()) {
+                addAmount(receipts, wallets, it);
+            }
+        });
+
+        //持续订购
+        List<WalletReceipts> keep  = list.stream().map(it -> {
+            if (!it.getVipUserRecord().isFirst()) {
+                return it;
+            }
+            return null;
+        }).collect(Collectors.toList());
+
+        keep.forEach(it->{
+            boolean cancel = vipUserRecordDao.existsByCpIdAndSucIn(it.getUserId(), List.of(-1, 5));
+            if (!cancel){//无退订消息
+                addAmount(receipts, wallets, 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(receipts, wallets, it);
+                }else {
+                    cancel(receipts, wallets, it);
+                }
+            }
+        });
+        walletDao.saveAll(wallets);
+        walletReceiptsDao.saveAll(receipts);
+    }
+
+    public void autoReceipts(){
+//        inviteReceiptsRoleFeignService.getOne()
+    }
+
+    private static void addAmount(List<WalletReceipts> receipts, List<Wallet> wallets, 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()));
+        receipts.add(it);
+        wallets.add(wallet);
+    }
+
+    private static void cancel(List<WalletReceipts> receipts, List<Wallet> wallets, WalletReceipts it){
+        it.setStatus(ReceiptsStatus.CANCEL);
+        Wallet wallet = it.getWallet();
+        wallet.setWaitAmount(wallet.getWaitAmount().subtract(it.getTotal()));
+        receipts.add(it);
+        wallets.add(wallet);
     }
 
     /**

+ 5 - 1
RewardServer/src/main/java/com/zhongshu/reward/server/core/service/WxTransferService.java

@@ -15,6 +15,7 @@ import com.zhongshu.reward.client.ret.CommentException;
 import com.zhongshu.reward.client.type.TimeUnitType;
 import com.zhongshu.reward.client.type.TransferChannel;
 import com.zhongshu.reward.client.type.TransferStatus;
+import com.zhongshu.reward.server.core.config.WeChatConfig;
 import com.zhongshu.reward.server.core.dao.TransferRulerDao;
 import com.zhongshu.reward.server.core.dao.WalletDao;
 import com.zhongshu.reward.server.core.dao.WxTransferBatchDao;
@@ -61,6 +62,9 @@ public class WxTransferService {
     @Autowired
     TransferRulerDao transferRulerDao;
 
+    @Autowired
+    WeChatConfig weChatConfig;
+
 
     /**
      * 发起提现
@@ -92,7 +96,7 @@ public class WxTransferService {
         transferModel.setTotalNum(detailList.size());
         transferModel.setTransferDetailList(detailList);
 
-        InitiateBatchTransferResponse response = wechatService.initiateBatchTransfer(transferModel);
+        InitiateBatchTransferResponse response = wechatService.initiateBatchTransfer(transferModel, param.getAppid());
         if (response==null){
             return ResultContent.build(ResultState.Fail);
         }

+ 33 - 11
RewardServer/src/main/java/com/zhongshu/reward/server/core/timer/WalletTimer.java

@@ -5,6 +5,7 @@ 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.WalletReceiptsService;
 import com.zhongshu.reward.server.core.service.WxTransferService;
 import lombok.extern.log4j.Log4j2;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -30,17 +31,20 @@ public class WalletTimer {
     @Autowired
     WxTransferService wxTransferService;
 
-    /**
-     * 重置每日提现额度
-     */
-    @Scheduled(cron = "0 0 0 * * ?")
-    public void resetTodayAmount(){
-        try {
-            walletDao.resetTodayAmount();
-        }catch (Exception e){
-            e.printStackTrace();
-        }
-    }
+    @Autowired
+    WalletReceiptsService walletReceiptsService;
+
+//    /**
+//     * 重置每日提现额度
+//     */
+//    @Scheduled(cron = "0 0 0 * * ?")
+//    public void resetTodayAmount(){
+//        try {
+//            walletDao.resetTodayAmount();
+//        }catch (Exception e){
+//            e.printStackTrace();
+//        }
+//    }
 
     @Scheduled(fixedRate = 5000)
     public void updateTransferStatus(){
@@ -53,4 +57,22 @@ public class WalletTimer {
             e.printStackTrace();
         }
     }
+
+    @Scheduled(cron = "0 0 0 25 * ?")
+    public void settle(){
+        try {
+            walletReceiptsService.settle();
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+    }
+
+    @Scheduled(cron = "0 0 0 1 * ?")
+    public void autoReceipts(){
+        try {
+            walletReceiptsService.settle();
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+    }
 }

+ 28 - 1
RewardServer/src/main/java/com/zhongshu/reward/server/core/util/DateUtils.java

@@ -3,11 +3,13 @@ package com.zhongshu.reward.server.core.util;
 import cn.hutool.log.Log;
 import lombok.extern.slf4j.Slf4j;
 
+import java.security.SecureRandom;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
 import java.time.ZoneId;
+import java.util.Base64;
 import java.util.Calendar;
 import java.util.Date;
 
@@ -78,6 +80,26 @@ public class DateUtils {
         return c.getTimeInMillis();
     }
 
+    /**
+     * 次月指定日开始时间
+     *
+     * @return
+     */
+    public static Long lastMonthDayStartTime(Integer day) {
+        Calendar c = Calendar.getInstance();
+        c.add(Calendar.MONTH, -1);
+
+        if (day >c.getActualMaximum(Calendar.DAY_OF_MONTH)){
+            c.set(Calendar.DATE, c.getActualMaximum(Calendar.DAY_OF_MONTH));
+        }else {
+            c.set(Calendar.DATE, day);
+        }
+        c.set(Calendar.HOUR_OF_DAY, 0);
+        c.set(Calendar.MINUTE, 0);
+        c.set(Calendar.SECOND, 0);
+        return c.getTimeInMillis();
+    }
+
     /**
      * 上月开始时间
      *
@@ -226,7 +248,12 @@ public class DateUtils {
     }
 
     public static void main(String[] args) {
-        log.info(paresTime(lastMonthStartTime(), FORMAT_LONG));
+        SecureRandom secureRandom = new SecureRandom();
+        byte[] key = new byte[32];
+        secureRandom.nextBytes(key);
+        ;
+        log.info("密钥:{}", Base64.getEncoder().encodeToString(key).substring(0, key.length));
+        log.info(paresTime(lastMonthDayStartTime(2), FORMAT_LONG));
         log.info(paresTime(lastMonthEndTime(), FORMAT_LONG));
     }
 }

+ 28 - 0
RewardServer/src/main/resources/apiclientkey/apiclient_key.pem

@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDObdQ0TjgDt+hZ
+v/4bXSI2PutVImiEXJGkjjTj9SsdZUuc+/oqq9ngx9oRtL85Jfv+cCzHt1PSzzBA
+CUCAhvhAEHuJiJ4/QC4i99VgNAPVoYNQ93fpbeu575gZhOSVEsvNWPzpistxl9+g
+V+KuH8b+pwv/Gq0ZS5QEyZlsaA263MbGECNXYsqKwfRqgUr4cC6mXaDjkxkt1WNi
+ul+uru/GDHMaNaJtH4HpjBvxvC5jbHrBWx/8nAmJe9CbBucOH+mYwXlTZtUxMBDA
+gOG0tBVD7YLjSemm0i+Zcv3I//4S+p7CTeUT39JHT+lUxlQM0MF191JAOH54FVWe
+OxAUzxinAgMBAAECggEAecjB0Ln0wfzVz109hNdFP8uO+wL5tl0Gb5aWDYaukQEZ
+wtvFkzcfq0U8mgWQax7FtC5pvMmjYlNpm93Zd/ooq2MN/u3irl4m2epsr/z/5iEL
+X9EfpU98Ko33pdaJJImaQuOlEgMYU0POYsJ2sVN+Cu5yXWZXiPzVrp1hLluU/hAC
+1AWDnzs2UfU1MeFu5Yazqk24GzmgFPz/sJBeWmy3FMiyWjgv16x8cdBZ4nwCuqe+
+1R4dfDYGpS8Cx+oL4rM3qp464yezhJj3KenxVq8GkAe0tODzytgJTi5gw73XXtUu
+aDlpvnAIublntJjVbttsMU7VEnk8gtWGPDdP3+A4QQKBgQDnuWHDBnOEQCFVFywJ
+ftMQUI+WxcXcJ55aYSLlAWPexdRw5pFeoj3F/xiS3MG9FgxH4W7sR0O83ucUzODr
+arpwPyqD0gEt9VPYbDS0IyBwZYdms3iIETlPKFz3QmIHQ45dR+lxnxZNDDOWQ1uj
+wxRmNb6oTZwtAgQKiDUDr6zUqwKBgQDkDg5b1dePg34ysRj4wVmTLbKxBBmmp2tk
+BfzejuvsfsN7bcj1c7gFIWbMYxGbytfmMjQ5CvkKwF3pJ2wkVxLhIYJe2hpyIViR
+FihL3OV/5wtXsZuc8AsNAChpq4u427wLrbiAAsknuopU/PeSu7hB9AgaEyUXYUpH
+8wb5ixyz9QKBgBNLc2F62wmLEXt1V3xe7BIysxIZ27TOM7hQ2Ef7SqaVEHBqMnaP
+ydb/u7sW2Kb2/ATMN6FC+dfzM4ie2qeflnCcQd0CEokSIW4m7GiHeD8DpTefAA1M
+ado2gS8xftod/O+1ejG0znWR64W6jBnht4QfO4XmGHgC7/U0jD2HVjvLAoGBAMqU
+UdzyEBHD1I5jErOlzVQX++uSoNaRUawARafNfXUPBcbWtvSSXpzwFsjoF/Q0M6Sg
+ZBNn0+HhD4rVIhMF5hdmFND9HRDU3j/DVvhMuPDs4/56HqlB8g8SXNPBNtR3HIuj
+PYk48EcCRW9JZwJJDlxH0gqXhxNFsR5Im6GAGXchAoGAfBRRc03Qfy1PNwBfpuf4
+3sqFMpa1NOHv5yjftFXWz3qbQyhKeZWZ8raC4dbrZA1UfOV21/9DVY73+ebhqHE4
+IfKt4I1lzDvhsw1uaGU7jmzlfeeuN/bAeCHWDnumDEhUEo/1/YN1DDlOdIOkyQcF
+ESYd5NpmCQRJjBRxbCJhxKg=
+-----END PRIVATE KEY-----

+ 5 - 5
RewardServer/src/main/resources/application.yml

@@ -48,12 +48,12 @@ spring:
 
 
 wechat:
-  merchantId: 111
-  privateKey: 1212
-  merchantSerialNumber: 111
-  apiV3Key: 1111
+  merchantId: 1682408108
+  privateKey: apiclientkey/apiclient_key.pem
+  merchantSerialNumber: 4A635020A23CDE38953A74CEC5DE903596165236
+  apiV3Key: ExrdXlCSbr9R61pU2iacmz0T5JxuLHhL
   appid: 1111
-  transferSceneId: 1111
+  transferSceneId: 1000