|
|
@@ -6,12 +6,12 @@ import java.util.*;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
-import cn.hutool.core.util.ObjectUtil;
|
|
|
import cn.hutool.json.JSONUtil;
|
|
|
import com.alibaba.fastjson.JSON;
|
|
|
import com.fs.common.constant.FsConstants;
|
|
|
import com.fs.common.core.domain.R;
|
|
|
import com.fs.common.core.redis.RedisCache;
|
|
|
+import com.fs.common.exception.CustomException;
|
|
|
import com.fs.common.utils.DateUtils;
|
|
|
import com.fs.common.utils.SecurityUtils;
|
|
|
import com.fs.common.utils.StringUtils;
|
|
|
@@ -19,11 +19,13 @@ import com.fs.company.domain.*;
|
|
|
import com.fs.company.mapper.*;
|
|
|
import com.fs.company.param.CompanyLiveShowParam;
|
|
|
import com.fs.company.param.CompanyParam;
|
|
|
-import com.fs.company.service.ICompanyMiniappService;
|
|
|
-import com.fs.company.service.ICompanyProfitService;
|
|
|
-import com.fs.company.service.ICompanyRoleService;
|
|
|
+import com.fs.company.service.*;
|
|
|
import com.fs.company.vo.*;
|
|
|
+import com.fs.course.config.CourseConfig;
|
|
|
+import com.fs.course.config.RedPacketConfig;
|
|
|
+import com.fs.course.domain.FsCourseRedPacketLog;
|
|
|
import com.fs.course.mapper.FsCourseRedPacketLogMapper;
|
|
|
+import com.fs.course.service.IFsCourseRedPacketLogService;
|
|
|
import com.fs.his.config.StoreConfig;
|
|
|
import com.fs.his.domain.FsInquiryOrder;
|
|
|
import com.fs.his.domain.FsStoreOrder;
|
|
|
@@ -41,18 +43,25 @@ import com.fs.store.config.CompanyMenuConfig;
|
|
|
import com.fs.system.domain.SysConfig;
|
|
|
import com.fs.system.mapper.SysConfigMapper;
|
|
|
import com.fs.system.service.ISysConfigService;
|
|
|
+import com.github.binarywang.wxpay.bean.transfer.QueryTransferBatchesRequest;
|
|
|
+import com.github.binarywang.wxpay.bean.transfer.QueryTransferBatchesResult;
|
|
|
+import com.github.binarywang.wxpay.bean.transfer.TransferBillsGetResult;
|
|
|
+import com.github.binarywang.wxpay.config.WxPayConfig;
|
|
|
+import com.github.binarywang.wxpay.exception.WxPayException;
|
|
|
+import com.github.binarywang.wxpay.service.TransferService;
|
|
|
+import com.github.binarywang.wxpay.service.WxPayService;
|
|
|
+import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
|
|
|
import com.github.pagehelper.PageHelper;
|
|
|
import com.google.gson.Gson;
|
|
|
import org.apache.commons.collections4.CollectionUtils;
|
|
|
-import org.apache.commons.lang3.ObjectUtils;
|
|
|
import org.redisson.api.RLock;
|
|
|
import org.redisson.api.RedissonClient;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.beans.BeanUtils;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.scheduling.annotation.Async;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
-import com.fs.company.service.ICompanyService;
|
|
|
import org.springframework.transaction.annotation.Propagation;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
import org.springframework.transaction.support.TransactionTemplate;
|
|
|
@@ -127,6 +136,12 @@ public class CompanyServiceImpl implements ICompanyService
|
|
|
@Autowired
|
|
|
private CompanyRedPacketBalanceLogsMapper companyRedPacketBalanceLogsMapper;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private ICompanyConfigService companyConfigService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IFsCourseRedPacketLogService redPacketLogService;
|
|
|
+
|
|
|
|
|
|
@Override
|
|
|
public List<CompanyVO> liveShowList(CompanyParam param) {
|
|
|
@@ -184,6 +199,80 @@ public class CompanyServiceImpl implements ICompanyService
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public String checkMchTransferStatus(String outBatchNo,Long companyId) {
|
|
|
+
|
|
|
+ // 查看红包发送配置
|
|
|
+ String json = configService.selectConfigByKey("course.config");
|
|
|
+ CourseConfig courseConfig = JSONUtil.toBean(json, CourseConfig.class);
|
|
|
+ RedPacketConfig config;
|
|
|
+ switch (courseConfig.getRedPacketMode()){// 1-总配置 2- 分公司配置
|
|
|
+ case 1:
|
|
|
+ json = configService.selectConfigByKey("redPacket.config");
|
|
|
+ config = JSONUtil.toBean(json, RedPacketConfig.class);
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ json = companyConfigService.selectRedPacketConfigByKey(companyId);
|
|
|
+ //如果分公司配置为空就走总后台的配置
|
|
|
+ if (StringUtils.isEmpty(json)){
|
|
|
+ json = configService.selectConfigByKey("redPacket.config");
|
|
|
+ }
|
|
|
+ config = JSONUtil.toBean(json, RedPacketConfig.class);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ throw new UnsupportedOperationException("当前红包模式不支持!");
|
|
|
+ }
|
|
|
+
|
|
|
+ WxPayConfig payConfig = new WxPayConfig();
|
|
|
+ BeanUtils.copyProperties(config, payConfig);
|
|
|
+
|
|
|
+ WxPayService wxPayService = new WxPayServiceImpl();
|
|
|
+ wxPayService.setConfig(payConfig);
|
|
|
+
|
|
|
+ TransferService transferService = wxPayService.getTransferService();
|
|
|
+
|
|
|
+ if (Objects.isNull(config.getIsNew()) || !Arrays.asList(0,1).contains(config.getIsNew())) {
|
|
|
+ logger.error("红包配置错误 isNew is err");
|
|
|
+ throw new CustomException("红包配置错误 isNew is err ");
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ if (config.getIsNew() == 0) {
|
|
|
+ QueryTransferBatchesRequest request = new QueryTransferBatchesRequest();
|
|
|
+ request.setOutBatchNo(outBatchNo);
|
|
|
+ request.setNeedQueryDetail(true);
|
|
|
+ request.setOffset(0);
|
|
|
+ request.setLimit(20);
|
|
|
+ request.setDetailStatus("ALL");
|
|
|
+ QueryTransferBatchesResult result = transferService.transferBatchesOutBatchNo(request);
|
|
|
+ List<QueryTransferBatchesResult.TransferDetail> detailList = result.getTransferDetailList();
|
|
|
+ boolean isSuccess = detailList.stream().anyMatch(d -> "SUCCESS".equals(d.getDetailStatus()));
|
|
|
+ if (isSuccess) {
|
|
|
+ return result.getTransferBatch().getBatchId();
|
|
|
+ }
|
|
|
+
|
|
|
+ boolean isFail = detailList.stream().anyMatch(d -> "FAIL".equals(d.getDetailStatus()));
|
|
|
+ if (isFail) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ TransferBillsGetResult result = transferService.getBillsByOutBillNo(outBatchNo);
|
|
|
+ if ("SUCCESS".equals(result.getState())) {
|
|
|
+ return result.getTransferBillNo();
|
|
|
+ } else if ("FAIL".equals(result.getState())) {
|
|
|
+ return "";
|
|
|
+ } else if ("CANCELLED".equals(result.getState())) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (WxPayException e) {
|
|
|
+ logger.error("查询转账单失败 err: {}", e.getMessage(), e);
|
|
|
+ throw new CustomException("查询转账单失败:" + e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ throw new CustomException("转账处理中");
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public List<OptionsVO> selectAllCompanyList(Long deptId) {
|
|
|
return companyMapper.selectAllCompanyList(deptId);
|
|
|
@@ -1447,7 +1536,7 @@ public class CompanyServiceImpl implements ICompanyService
|
|
|
// 记录余额变更日志
|
|
|
String remark = "同步公司余额,差额: " + amount+"(正数为增加,负数为扣减)";
|
|
|
// 实际不发生交易只是从缓存同步金额到数据库中 交易金额登记为0,备注清楚同步的金额
|
|
|
- asyncRecordBalanceLog(company.getCompanyId(),new BigDecimal(0),17,redisMoney,remark);
|
|
|
+ asyncRecordBalanceLog(company.getCompanyId(),new BigDecimal(0),17,redisMoney,remark, null);
|
|
|
}
|
|
|
}
|
|
|
return null;
|
|
|
@@ -1500,7 +1589,7 @@ public class CompanyServiceImpl implements ICompanyService
|
|
|
redisCache.setCacheObject(companyMoneyKey, newMoney.toString());
|
|
|
|
|
|
// 异步登记余额添加日志
|
|
|
- asyncRecordBalanceLog(companyId,money,16,newMoney,"红包充值(负数为扣款)");
|
|
|
+ asyncRecordBalanceLog(companyId,money,16,newMoney,"红包充值(负数为扣款)", null);
|
|
|
|
|
|
} else {
|
|
|
logger.error("获取redis锁失败,异常请求参数companyId:{},money:{},type:{}",companyId,money, type);
|
|
|
@@ -1526,15 +1615,17 @@ public class CompanyServiceImpl implements ICompanyService
|
|
|
|
|
|
/**
|
|
|
* 异步登记余额添加日志 xgb
|
|
|
+ *
|
|
|
* @param companyId 公司ID
|
|
|
- * @param money 变更金额
|
|
|
- * @param balance 当前余额
|
|
|
- * @param remark 备注信息
|
|
|
- * @param logType 16-红包余额充值 15-红包余额扣除 17-同步公司余额
|
|
|
+ * @param money 变更金额
|
|
|
+ * @param logType 16-红包余额充值 15-红包余额扣除 17-同步公司余额
|
|
|
+ * @param balance 当前余额
|
|
|
+ * @param remark 备注信息
|
|
|
+ * @param logId
|
|
|
*/
|
|
|
@Async
|
|
|
@Override
|
|
|
- public void asyncRecordBalanceLog(Long companyId, BigDecimal money,Integer logType, BigDecimal balance, String remark) {
|
|
|
+ public void asyncRecordBalanceLog(Long companyId, BigDecimal money, Integer logType, BigDecimal balance, String remark, Long logId) {
|
|
|
try {
|
|
|
CompanyRedPacketBalanceLogs log = new CompanyRedPacketBalanceLogs();
|
|
|
log.setCompanyId(companyId);
|
|
|
@@ -1543,6 +1634,7 @@ public class CompanyServiceImpl implements ICompanyService
|
|
|
log.setLogsType(logType); // 同步余额
|
|
|
log.setBalance(balance);
|
|
|
log.setCreateTime(new Date());
|
|
|
+ log.setRedPacketId(logId);
|
|
|
companyRedPacketBalanceLogsMapper.insertCompanyRedPacketBalanceLogs(log);
|
|
|
} catch (Exception e) {
|
|
|
logger.error("异步登记红包余额日志失败 - 公司ID: {}, 金额: {}, 余额: {}, 备注: {}",
|
|
|
@@ -1573,7 +1665,7 @@ public class CompanyServiceImpl implements ICompanyService
|
|
|
// 实际不发生交易只是从缓存获取当天余额报错25小时 交易金额登记为0,备注清楚同步的金额
|
|
|
String remark = "时间:" + time +",当前公司余额,金额: " + moneyStr;
|
|
|
BigDecimal money = new BigDecimal(moneyStr);
|
|
|
- asyncRecordBalanceLog(company.getCompanyId(),new BigDecimal(0),18,money,remark);
|
|
|
+ asyncRecordBalanceLog(company.getCompanyId(),new BigDecimal(0),18,money,remark, null);
|
|
|
}
|
|
|
return null;
|
|
|
});
|
|
|
@@ -1597,18 +1689,100 @@ public class CompanyServiceImpl implements ICompanyService
|
|
|
* @Author xgb
|
|
|
* @Date 2025/11/7 9:53
|
|
|
*/
|
|
|
+// @Override
|
|
|
+// public void rollbackRedPacketMoney() {
|
|
|
+// List<RedPacketMoneyVO> redPacketMoneyVOS = fsCourseRedPacketLogMapper.selectFsCourseAddRedPacketLogByCompany();
|
|
|
+// for(RedPacketMoneyVO company:redPacketMoneyVOS){
|
|
|
+// logger.info("红包余额回滚开始:{}",company);
|
|
|
+// }
|
|
|
+// Optional.ofNullable(redPacketMoneyVOS).ifPresent(list -> list.forEach(company -> {
|
|
|
+//
|
|
|
+// if(company.getCompanyId()==null){
|
|
|
+// logger.error("红包记录表中存在公司id为null的异常数据");
|
|
|
+// return;
|
|
|
+// }
|
|
|
+// String companyMoneyKey = FsConstants.COMPANY_MONEY_KEY + company.getCompanyId();
|
|
|
+// // 加锁,与看课发放红包的加锁保持一致
|
|
|
+// RLock lock = redissonClient.getLock(FsConstants.COMPANY_MONEY_LOCK + company.getCompanyId());
|
|
|
+// boolean lockAcquired = false;
|
|
|
+// try {
|
|
|
+// lockAcquired = lock.tryLock(3, 10, TimeUnit.SECONDS);
|
|
|
+// if (lockAcquired) {
|
|
|
+// BigDecimal redisMoney;
|
|
|
+// // 获取当前余额
|
|
|
+// String moneyStr = redisCache.getCacheObject(companyMoneyKey);
|
|
|
+// if (StringUtils.isNotEmpty(moneyStr)) {
|
|
|
+// redisMoney = new BigDecimal(moneyStr);
|
|
|
+// }else {
|
|
|
+// logger.error("缓存公司id:{}的余额不存在,回滚金额{}",company.getCompanyId(),company.getMoney());
|
|
|
+// return;
|
|
|
+// }
|
|
|
+// BigDecimal newMoney = redisMoney.add(company.getMoney());
|
|
|
+// redisCache.setCacheObject(companyMoneyKey, newMoney.toString());
|
|
|
+//
|
|
|
+// String remark = "执行时间:"+DateUtils.getTime()+",T2天客户未领取红包退回,金额: " + company.getMoney();
|
|
|
+// asyncRecordBalanceLog(company.getCompanyId(),company.getMoney(),16,newMoney,remark, null);
|
|
|
+// }
|
|
|
+// } catch (Exception e) {
|
|
|
+// logger.error("退回的红包同步增加到缓存和数据表,参数错误,请求异常,异常信息:{}", e.getMessage(), e);
|
|
|
+// } finally {
|
|
|
+// if (lockAcquired && lock.isHeldByCurrentThread()) {
|
|
|
+// try {
|
|
|
+// lock.unlock();
|
|
|
+// } catch (IllegalMonitorStateException e) {
|
|
|
+// logger.warn("尝试释放非当前线程持有的锁: companyId:{}", company.getCompanyId());
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }));
|
|
|
+// }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @Description: 红包余额回滚(回滚的是客户没领取的红包),红包记录表中,两天没领取的记录不会再发送
|
|
|
+ * @Param:
|
|
|
+ * @Return:
|
|
|
+ * @Author xgb
|
|
|
+ * @Date 2025/12/25 9:32
|
|
|
+ */
|
|
|
@Override
|
|
|
- public void rollbackRedPacketMoney() {
|
|
|
- List<RedPacketMoneyVO> redPacketMoneyVOS = fsCourseRedPacketLogMapper.selectFsCourseAddRedPacketLogByCompany();
|
|
|
- for(RedPacketMoneyVO company:redPacketMoneyVOS){
|
|
|
- logger.info("红包余额回滚开始:{}",company);
|
|
|
- }
|
|
|
- Optional.ofNullable(redPacketMoneyVOS).ifPresent(list -> list.forEach(company -> {
|
|
|
+ public void rollbackRedPacketMoney(String createSTime, String createETime) {
|
|
|
+ // 回滚前查询一下红包记录
|
|
|
+ List<CompanyRedPacketBalanceLogs> companyRedPacketBalanceLogsList = companyRedPacketBalanceLogsMapper.selectCompanyRedPacketBalanceLogsListByStatus(createSTime, createETime);
|
|
|
+
|
|
|
+// List<RedPacketMoneyVO> redPacketMoneyVOS = fsCourseRedPacketLogMapper.selectFsCourseAddRedPacketLogByCompany();
|
|
|
+// for(RedPacketMoneyVO company:redPacketMoneyVOS){
|
|
|
+// logger.info("红包余额回滚开始:{}",company);
|
|
|
+// }
|
|
|
+ Optional.ofNullable(companyRedPacketBalanceLogsList).ifPresent(list -> list.forEach(company -> {
|
|
|
+
|
|
|
+ // 查询红包记录
|
|
|
+ FsCourseRedPacketLog redLogs = fsCourseRedPacketLogMapper.selectFsCourseRedPacketLogByLogId(company.getRedPacketId());
|
|
|
+ if(redLogs==null){
|
|
|
+ logger.error("未查询到红包记录,流水{}",company.getLogsId());
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
if(company.getCompanyId()==null){
|
|
|
- logger.error("红包记录表中存在公司id为null的异常数据");
|
|
|
+ logger.error("红包记录表中存在公司id为null的异常数据,流水{}",company.getLogsId());
|
|
|
return;
|
|
|
}
|
|
|
+
|
|
|
+ if(StringUtils.isEmpty(redLogs.getOutBatchNo())){
|
|
|
+ String batchId=checkMchTransferStatus(redLogs.getOutBatchNo(),redLogs.getCompanyId());
|
|
|
+ if (StringUtils.isNotBlank(batchId)) {
|
|
|
+ redPacketLogService.syncRedPacket(redLogs.getOutBatchNo(),batchId);
|
|
|
+ return;
|
|
|
+ }else {
|
|
|
+ logger.error("未查询到商户转账批次号,进行退款,流水{}",company.getLogsId());
|
|
|
+ // 更新支付状态
|
|
|
+ updateBalanceStatus(company.getLogsId(), 2,company.getRemark()+";退回经销商"); // 更新为已退款
|
|
|
+ }
|
|
|
+ logger.error("未查询到OutBatchNo,进行退款,流水{}",company.getLogsId());
|
|
|
+ // 更新支付状态
|
|
|
+ updateBalanceStatus(company.getLogsId(), 2,company.getRemark()+";退回经销商"); // 更新为已退款
|
|
|
+ }
|
|
|
+
|
|
|
String companyMoneyKey = FsConstants.COMPANY_MONEY_KEY + company.getCompanyId();
|
|
|
// 加锁,与看课发放红包的加锁保持一致
|
|
|
RLock lock = redissonClient.getLock(FsConstants.COMPANY_MONEY_LOCK + company.getCompanyId());
|
|
|
@@ -1622,14 +1796,14 @@ public class CompanyServiceImpl implements ICompanyService
|
|
|
if (StringUtils.isNotEmpty(moneyStr)) {
|
|
|
redisMoney = new BigDecimal(moneyStr);
|
|
|
}else {
|
|
|
- logger.error("缓存公司id:{}的余额不存在,回滚金额{}",company.getCompanyId(),company.getMoney());
|
|
|
+ logger.error("缓存公司id:{}的余额不存在,回滚金额{}",company.getCompanyId(),redLogs.getAmount());
|
|
|
return;
|
|
|
}
|
|
|
- BigDecimal newMoney = redisMoney.add(company.getMoney());
|
|
|
+ BigDecimal newMoney = redisMoney.add(redLogs.getAmount());
|
|
|
redisCache.setCacheObject(companyMoneyKey, newMoney.toString());
|
|
|
|
|
|
- String remark = "执行时间:"+DateUtils.getTime()+",T2天客户未领取红包退回,金额: " + company.getMoney();
|
|
|
- asyncRecordBalanceLog(company.getCompanyId(),company.getMoney(),16,newMoney,remark);
|
|
|
+ String remark = "执行时间:"+DateUtils.getTime()+",T2天客户未领取红包退回,金额: " + redLogs.getAmount();
|
|
|
+ asyncRecordBalanceLog(company.getCompanyId(),redLogs.getAmount(),16,newMoney,remark, redLogs.getLogId());
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
logger.error("退回的红包同步增加到缓存和数据表,参数错误,请求异常,异常信息:{}", e.getMessage(), e);
|
|
|
@@ -1645,4 +1819,13 @@ public class CompanyServiceImpl implements ICompanyService
|
|
|
}));
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ private void updateBalanceStatus(Long logsId, Integer status,String remark){
|
|
|
+ FsCourseRedPacketLog redLogs = new FsCourseRedPacketLog();
|
|
|
+ redLogs.setLogId(logsId);
|
|
|
+ redLogs.setStatus(status);
|
|
|
+ redLogs.setRemark(remark);
|
|
|
+ fsCourseRedPacketLogMapper.updateFsCourseRedPacketLog(redLogs);
|
|
|
+ }
|
|
|
+
|
|
|
}
|