|
@@ -0,0 +1,226 @@
|
|
|
+package com.zhongshu.reward.server.core.service;
|
|
|
+
|
|
|
+import cn.hutool.core.bean.BeanUtil;
|
|
|
+import cn.hutool.core.lang.Snowflake;
|
|
|
+import com.github.microservice.auth.client.content.ResultContent;
|
|
|
+import com.github.microservice.auth.client.content.ResultState;
|
|
|
+import com.wechat.pay.java.service.transferbatch.model.InitiateBatchTransferResponse;
|
|
|
+import com.wechat.pay.java.service.transferbatch.model.TransferBatchEntity;
|
|
|
+import com.wechat.pay.java.service.transferbatch.model.TransferDetailInput;
|
|
|
+import com.zhongshu.reward.client.model.param.WalletTransferParam;
|
|
|
+import com.zhongshu.reward.client.model.wallet.TransferModel;
|
|
|
+import com.zhongshu.reward.client.model.wallet.TransferStatusModel;
|
|
|
+import com.zhongshu.reward.client.model.wallet.WxTransferBatchModel;
|
|
|
+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.dao.TransferRulerDao;
|
|
|
+import com.zhongshu.reward.server.core.dao.WalletDao;
|
|
|
+import com.zhongshu.reward.server.core.dao.WxTransferBatchDao;
|
|
|
+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.util.DateUtils;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.lang3.ObjectUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.data.mongodb.core.aggregation.DateOperators;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.time.temporal.TemporalAdjuster;
|
|
|
+import java.time.temporal.TemporalAdjusters;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Calendar;
|
|
|
+import java.util.List;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @author wjf
|
|
|
+ * @date 2024/8/5
|
|
|
+ */
|
|
|
+@Service
|
|
|
+@Slf4j
|
|
|
+public class WxTransferService {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ WalletDao walletDao;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ ChatTransferBatchService wechatService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ Snowflake snowflake;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ WxTransferBatchDao wxTransferBatchDao;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ TransferRulerDao transferRulerDao;
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发起提现
|
|
|
+ * @param param
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ public Object transfer(WalletTransferParam param){
|
|
|
+ Wallet wallet = walletDao.findTop1ById(param.getWalletId());
|
|
|
+ //校验提现规则
|
|
|
+ validTransfer(param.getTotal(), wallet);
|
|
|
+
|
|
|
+ String outBatchNo = snowflake.nextIdStr();
|
|
|
+ String outDetailNo = snowflake.nextIdStr();
|
|
|
+
|
|
|
+ TransferModel transferModel = new TransferModel();
|
|
|
+ transferModel.setBatchName("佣金/返利发放");
|
|
|
+ transferModel.setBatchRemark("佣金/返利发放");
|
|
|
+ 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);
|
|
|
+ transferModel.setTotalNum(detailList.size());
|
|
|
+ transferModel.setTransferDetailList(detailList);
|
|
|
+
|
|
|
+ InitiateBatchTransferResponse response = wechatService.initiateBatchTransfer(transferModel);
|
|
|
+ if (response==null){
|
|
|
+ return ResultContent.build(ResultState.Fail);
|
|
|
+ }
|
|
|
+
|
|
|
+ WxTransferBatch wxTransferBatch = new WxTransferBatch();
|
|
|
+ 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.setAmount(wallet.getAmount().subtract(param.getTotal()));
|
|
|
+ wallet.setTodayTransferAmount(wallet.getTodayTransferAmount().add(param.getTotal()));
|
|
|
+ walletDao.save(wallet);
|
|
|
+ return ResultContent.build(ResultState.Success);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ public Object queryTransfer(String walletId, Integer year, Integer month){
|
|
|
+ Long monthStartTime = DateUtils.getMonthStartTime(year, month);
|
|
|
+ Long monthEndTime = DateUtils.getMonthEndTime(year, month);
|
|
|
+ List<WxTransferBatch> list = wxTransferBatchDao.list(walletId, monthStartTime, monthEndTime);
|
|
|
+ return ResultContent.buildContent(list.stream().map(this::toModel).collect(Collectors.toList()));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional
|
|
|
+ public Object updateTransferStatus(String transferId){
|
|
|
+ WxTransferBatch wxTransferBatch = wxTransferBatchDao.findTop1ById(transferId);
|
|
|
+ if (ObjectUtils.isEmpty(wxTransferBatch)){
|
|
|
+ return ResultContent.build(ResultState.Fail, "提现订单不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ TransferStatus transferStatus = wxTransferBatch.getTransferStatus();
|
|
|
+ if (!transferStatus.equals(TransferStatus.PROCESSING)){
|
|
|
+ return ResultContent.build(ResultState.Success);
|
|
|
+ }
|
|
|
+
|
|
|
+ TransferStatusModel transferStatusModel = new TransferStatusModel();
|
|
|
+ transferStatusModel.setBatchId(wxTransferBatch.getWxBatchId());
|
|
|
+ transferStatusModel.setNeedQueryDetail(true);
|
|
|
+ transferStatusModel.setDetailStatus("ALL");
|
|
|
+ TransferBatchEntity transferBatchByNo = wechatService.getTransferBatchByNo(transferStatusModel);
|
|
|
+
|
|
|
+ String batchStatus = transferBatchByNo.getTransferBatch().getBatchStatus();
|
|
|
+ String detailStatus = transferBatchByNo.getTransferDetailList().get(0).getDetailStatus();
|
|
|
+
|
|
|
+ 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);
|
|
|
+ }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);
|
|
|
+ }
|
|
|
+ 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){
|
|
|
+ WxTransferBatchModel model = new WxTransferBatchModel();
|
|
|
+ if (null != wxTransferBatch){
|
|
|
+ BeanUtil.copyProperties(wxTransferBatch, model, "beforeWalletInfo", "wallet");
|
|
|
+ model.setWalletId(wxTransferBatch.getWallet().getId());
|
|
|
+ }
|
|
|
+ return model;
|
|
|
+ }
|
|
|
+
|
|
|
+ void 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, "管理员未设置提现规则");
|
|
|
+ }
|
|
|
+ TransferRuler transferRuler = list.get(0);
|
|
|
+ //提现时间
|
|
|
+ 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, "当前不处于提现时间段");
|
|
|
+ }
|
|
|
+ size = wxTransferBatchDao.countByTime(wallet.getId(), dayOfMonthStartTime, dayOfMonthEndTime).intValue();
|
|
|
+ }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, "当前不处于提现时间段");
|
|
|
+ }
|
|
|
+ size = wxTransferBatchDao.countByTime(wallet.getId(), hourMinuteStartTime, hourMinuteEndTime).intValue();
|
|
|
+ }
|
|
|
+ //单笔金额
|
|
|
+ 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, "可提现余额不足");
|
|
|
+ }
|
|
|
+ //提现次数
|
|
|
+ if (transferRuler.getSize() >= size){
|
|
|
+ throw new CommentException(com.zhongshu.reward.client.ret.ResultState.Exception, "超过可提现次数");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|