diff --git a/electripper-admin/src/main/java/com/ruoyi/web/controller/app/AppController.java b/electripper-admin/src/main/java/com/ruoyi/web/controller/app/AppController.java index ab6f156..76e2a00 100644 --- a/electripper-admin/src/main/java/com/ruoyi/web/controller/app/AppController.java +++ b/electripper-admin/src/main/java/com/ruoyi/web/controller/app/AppController.java @@ -7,6 +7,10 @@ import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.utils.CommonUtil; import com.ruoyi.system.domain.*; import com.ruoyi.system.service.*; +import com.wechat.pay.java.service.payments.model.Transaction; +import com.wechat.pay.java.service.refund.RefundService; +import com.wechat.pay.java.service.refund.model.QueryByOutRefundNoRequest; +import com.wechat.pay.java.service.refund.model.Refund; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @@ -39,6 +43,9 @@ public class AppController extends BaseController @Autowired private IEtOrderService etOrderService; + @Autowired + private IWxPayService wxPayService; + /** @@ -287,4 +294,26 @@ public class AppController extends BaseController return AjaxResult.success("操作成功", address); } + /** + * 查询退款是否成功 + */ + @GetMapping("/queryByOutRefundNo") + public AjaxResult queryByOutRefundNo(String outRefundNo) + { + logger.info("查询退款是否成功:【outRefundNo="+outRefundNo+"】"); + Refund refund = wxPayService.queryByOutRefundNo(outRefundNo); + return AjaxResult.success(refund); + } + + /** + * 通过商户订单号查询订单信息 + */ + @GetMapping("/queryOrderByOutTradeNo") + public AjaxResult queryOrderByOutTradeNo(String outTradeNo) + { + logger.info("查询支付订单信息:【outTradeNo="+outTradeNo+"】"); + Transaction transaction = wxPayService.queryOrderByOutTradeNo(outTradeNo); + return AjaxResult.success(transaction); + } + } diff --git a/electripper-admin/src/main/resources/application.yml b/electripper-admin/src/main/resources/application.yml index 7ca29f3..e8d230b 100644 --- a/electripper-admin/src/main/resources/application.yml +++ b/electripper-admin/src/main/resources/application.yml @@ -133,7 +133,7 @@ xss: # 过滤开关 enabled: true # 排除链接(多个用逗号分隔) - excludes: /system/notice + excludes: /system/notice,/system/area # 匹配链接 urlPatterns: /system/*,/monitor/*,/tool/* # 阿里云短信 diff --git a/electripper-common/src/main/java/com/ruoyi/common/utils/DateUtils.java b/electripper-common/src/main/java/com/ruoyi/common/utils/DateUtils.java index c7c9350..1deb6b7 100644 --- a/electripper-common/src/main/java/com/ruoyi/common/utils/DateUtils.java +++ b/electripper-common/src/main/java/com/ruoyi/common/utils/DateUtils.java @@ -199,6 +199,23 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils return day + "天" + hour + "小时" + min + "分钟"; } + /** + * 计算时间差(只返回小时数) + * + * @param endDate 结束时间 + * @param startTime 开始时间 + * @return 时间差(小时) + */ + public static int timeDifferenceInHours(Date endDate, Date startTime) { + // 获得两个时间的毫秒时间差异 + long diff = endDate.getTime() - startTime.getTime(); + + // 直接计算差多少小时 + int hours = (int) Math.abs(diff / (1000 * 60 * 60)); + + return hours; + } + /** * 计算时间差(只返回分钟数) * diff --git a/electripper-system/src/main/java/com/ruoyi/system/mapper/EtOrderMapper.java b/electripper-system/src/main/java/com/ruoyi/system/mapper/EtOrderMapper.java index 6b0bd52..30a5d10 100644 --- a/electripper-system/src/main/java/com/ruoyi/system/mapper/EtOrderMapper.java +++ b/electripper-system/src/main/java/com/ruoyi/system/mapper/EtOrderMapper.java @@ -212,4 +212,19 @@ public interface EtOrderMapper * 预约未完成订单处理 */ List selectAppointmentUnfinished(); + + /** + * 押金未退还订单处理 + */ + List selectUnrefundableDepositOrder(); + + /** + * 已完成订单的用户列表 + */ + List selectUserListFinishOrder(); + + /** + * 待结算订单 + */ + List selectNeedDividendOrder(); } diff --git a/electripper-system/src/main/java/com/ruoyi/system/service/CallbackService.java b/electripper-system/src/main/java/com/ruoyi/system/service/CallbackService.java index 6fb8637..e31f2e1 100644 --- a/electripper-system/src/main/java/com/ruoyi/system/service/CallbackService.java +++ b/electripper-system/src/main/java/com/ruoyi/system/service/CallbackService.java @@ -1,5 +1,8 @@ package com.ruoyi.system.service; +import com.ruoyi.system.domain.EtOperatingArea; +import com.ruoyi.system.domain.EtOrder; + import javax.servlet.http.HttpServletRequest; /** @@ -21,4 +24,22 @@ public interface CallbackService { */ void weChatRefund(HttpServletRequest request); + /** + * 新增资金流水记录 + * @param order 订单 + * @param type 类型 + * @param busType 业务类型 + * @return void + */ + public void capitalFlowRecords(EtOrder order, String type, String busType); + + /** + * 分红处理 + * @param transactionId 订单号 + * @param order 订单 + * @param area 运营区域 + * @return boolean + */ + public boolean dividendHandle(String transactionId, EtOrder order, EtOperatingArea area); + } diff --git a/electripper-system/src/main/java/com/ruoyi/system/service/IEtDividendDetailService.java b/electripper-system/src/main/java/com/ruoyi/system/service/IEtDividendDetailService.java index 9b9f344..b4c8b51 100644 --- a/electripper-system/src/main/java/com/ruoyi/system/service/IEtDividendDetailService.java +++ b/electripper-system/src/main/java/com/ruoyi/system/service/IEtDividendDetailService.java @@ -74,4 +74,12 @@ public interface IEtDividendDetailService * @return 结果 */ boolean isDividendComputed(String date); + + /** + * 根据订单号判断是否已经计算过分账结果 + * + * @param orderNo 订单号 + * @return 结果 + */ + boolean isDividendComputedByOrderNo(String orderNo); } diff --git a/electripper-system/src/main/java/com/ruoyi/system/service/IWxPayService.java b/electripper-system/src/main/java/com/ruoyi/system/service/IWxPayService.java index 8341ce6..e126d8b 100644 --- a/electripper-system/src/main/java/com/ruoyi/system/service/IWxPayService.java +++ b/electripper-system/src/main/java/com/ruoyi/system/service/IWxPayService.java @@ -41,11 +41,11 @@ public interface IWxPayService { Transaction queryOrderById(String prePayId); /** - * 通过订单编号查询订单信息 - * @param billNo 订单编号 + * 通过商户订单号查询订单信息 + * @param outTradeNo 商户订单号 * @return 订单信息 */ - Transaction queryOrderByOutTradeNo(String billNo); + Transaction queryOrderByOutTradeNo(String outTradeNo); /** * 退款 @@ -55,6 +55,12 @@ public interface IWxPayService { */ Refund refund(EtOrder etOrder, String reason, BigDecimal amount); + /** + * 根据退款单号查询退款信息 + * @param outRefundNo 退款单号 + */ + Refund queryByOutRefundNo(String outRefundNo); + /** * 请求分账API diff --git a/electripper-system/src/main/java/com/ruoyi/system/service/impl/CallbackServiceImpl.java b/electripper-system/src/main/java/com/ruoyi/system/service/impl/CallbackServiceImpl.java index f4c720c..11f4418 100644 --- a/electripper-system/src/main/java/com/ruoyi/system/service/impl/CallbackServiceImpl.java +++ b/electripper-system/src/main/java/com/ruoyi/system/service/impl/CallbackServiceImpl.java @@ -160,13 +160,17 @@ public class CallbackServiceImpl implements CallbackService { // 新增资金流水记录 capitalFlowRecords(order,ServiceConstants.FLOW_TYPE_INCOME,ServiceConstants.ORDER_TYPE_RIDING); + // 还车结算___小时后自动退押金---创建一个定时器TimerTask,计算出退还时间后,执行退款操作 EtOperatingArea area = etOperatingAreaService.selectEtOperatingAreaByAreaId(order.getAreaId()); // 退还押金处理 refundDeposit(area.getDeposit(), order, asUser); - // 请求分账处理 - if (dividendHandle(transactionId, order, area)) return; + // 24小时后发起分账 + scheduledExecutorService.schedule(() -> { + // 请求分账处理 + if (dividendHandle(transactionId, order, area)) return; + }, 24 , TimeUnit.HOURS); }else if(attachVo.getType().equals(ServiceConstants.BUSINESS_TYPE_APPOINTMENT)){ logger.info("【微信支付回调】取消预约支付"); @@ -219,12 +223,19 @@ public class CallbackServiceImpl implements CallbackService { } } - private boolean dividendHandle(String transactionId, EtOrder order, EtOperatingArea area) { + /** + * 分账处理 + * 1.根据订单号查询分账记录,如果有记录直接返回 + * 2.根据区域id查询合伙人列表,根据合伙人分红比例分账,保存分账明细表 + * 3.请求分账 + */ + @Override + public boolean dividendHandle(String transactionId, EtOrder order, EtOperatingArea area) { List etDividendDetails = dividendDetailService.selectEtDividendDetailByOrderNo(order.getOrderNo()); if(ObjectUtil.isNotNull(etDividendDetails) && etDividendDetails.size()>0){ return true; } - logger.info("=================【微信支付回调】开始请求分账=================="); + logger.info("=================【微信支付回调】24小时后开始请求分账=================="); logger.info("区域对象====="+JSON.toJSONString(area)); logger.info("订单对象====="+JSON.toJSONString(order)); // 请求分账 @@ -355,7 +366,8 @@ public class CallbackServiceImpl implements CallbackService { /** * 资金流水记录 * */ - private void capitalFlowRecords(EtOrder order,String type,String busType) { + @Override + public void capitalFlowRecords(EtOrder order,String type,String busType) { if(ObjectUtil.isNotNull(etCapitalFlowService.selectEtCapitalFlowByOutTradeNo(order.getOutTradeNo()))){ return; } @@ -399,6 +411,8 @@ public class CallbackServiceImpl implements CallbackService { int i = etCapitalFlowService.insertEtCapitalFlow(capitalFlow); if(i==0){ throw new ServiceException("保存资金流水记录失败"); + }else { + logger.info("【微信支付回调】保存资金流水记录成功"); } } diff --git a/electripper-system/src/main/java/com/ruoyi/system/service/impl/EtDividendDetailServiceImpl.java b/electripper-system/src/main/java/com/ruoyi/system/service/impl/EtDividendDetailServiceImpl.java index c35e286..cdd6951 100644 --- a/electripper-system/src/main/java/com/ruoyi/system/service/impl/EtDividendDetailServiceImpl.java +++ b/electripper-system/src/main/java/com/ruoyi/system/service/impl/EtDividendDetailServiceImpl.java @@ -1,6 +1,8 @@ package com.ruoyi.system.service.impl; import java.util.List; + +import cn.hutool.core.util.ObjectUtil; import com.ruoyi.common.utils.DateUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -8,6 +10,8 @@ import com.ruoyi.system.mapper.EtDividendDetailMapper; import com.ruoyi.system.domain.EtDividendDetail; import com.ruoyi.system.service.IEtDividendDetailService; +import javax.annotation.Resource; + /** * 分账明细Service业务层处理 * @@ -17,7 +21,7 @@ import com.ruoyi.system.service.IEtDividendDetailService; @Service public class EtDividendDetailServiceImpl implements IEtDividendDetailService { - @Autowired + @Resource private EtDividendDetailMapper etDividendDetailMapper; /** @@ -111,5 +115,19 @@ public class EtDividendDetailServiceImpl implements IEtDividendDetailService return false; } + /** + * 判断是否已经计算过 + * @param orderNo + * @return + */ + @Override + public boolean isDividendComputedByOrderNo(String orderNo) { + List etDividendDetails = etDividendDetailMapper.selectEtDividendDetailByOrderNo(orderNo); + if(ObjectUtil.isNotNull(etDividendDetails) && etDividendDetails.size() > 0){ + return true; + } + return false; + } + } diff --git a/electripper-system/src/main/java/com/ruoyi/system/service/impl/EtOrderServiceImpl.java b/electripper-system/src/main/java/com/ruoyi/system/service/impl/EtOrderServiceImpl.java index 6123cc7..a9a363b 100644 --- a/electripper-system/src/main/java/com/ruoyi/system/service/impl/EtOrderServiceImpl.java +++ b/electripper-system/src/main/java/com/ruoyi/system/service/impl/EtOrderServiceImpl.java @@ -64,9 +64,6 @@ public class EtOrderServiceImpl implements IEtOrderService @Autowired private IAsDeviceService deviceService; - @Autowired - private ISysConfigService sysConfigService; - @Autowired private IEtFeeRuleService etFeeRuleService; @@ -76,9 +73,6 @@ public class EtOrderServiceImpl implements IEtOrderService @Autowired private IAsDeviceService asDeviceService; - @Autowired - private TransactionTemplate transactionTemplate; - @Autowired private IEtRefundService etRefundService; @@ -86,16 +80,10 @@ public class EtOrderServiceImpl implements IEtOrderService private IEtTripLogService etTripLogService; @Autowired - private RedisCache redisCache; - -// @Autowired -// private TokenService tokenService; - - // 令牌有效期(默认30分钟) - @Value("${token.expireTime}") - private int expireTime; - + private IEtDividendDetailService dividendDetailService; + @Autowired + private CallbackService callbackService; /** * 查询订单 @@ -689,6 +677,9 @@ public class EtOrderServiceImpl implements IEtOrderService if(ServiceConstants.ORDER_PAY_STATUS_NON_PAYMENT.equals(etOrder1.getPaid())){ throw new ServiceException("订单未支付,不能退款"); } + if(dividendDetailService.isDividendComputedByOrderNo(etOrder.getOrderNo())){ + throw new ServiceException("订单【{}】已经分账,不能退款"); + } /** 1.退款*/ //退款金额 BigDecimal refundAmount = new BigDecimal("0"); @@ -716,6 +707,8 @@ public class EtOrderServiceImpl implements IEtOrderService if(i>0){ log.info("保存退款对象成功"); } + // 新增资金流水记录 + callbackService.capitalFlowRecords(etOrder1,ServiceConstants.FLOW_TYPE_DISBURSE,ServiceConstants.ORDER_TYPE_RIDING_REFUND); return i; } diff --git a/electripper-system/src/main/java/com/ruoyi/system/service/impl/WxPayService.java b/electripper-system/src/main/java/com/ruoyi/system/service/impl/WxPayService.java index 01de147..79d52ab 100644 --- a/electripper-system/src/main/java/com/ruoyi/system/service/impl/WxPayService.java +++ b/electripper-system/src/main/java/com/ruoyi/system/service/impl/WxPayService.java @@ -28,6 +28,7 @@ import com.wechat.pay.java.service.profitsharing.model.*; import com.wechat.pay.java.service.refund.RefundService; import com.wechat.pay.java.service.refund.model.AmountReq; import com.wechat.pay.java.service.refund.model.CreateRequest; +import com.wechat.pay.java.service.refund.model.QueryByOutRefundNoRequest; import com.wechat.pay.java.service.refund.model.Refund; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -142,11 +143,16 @@ public class WxPayService implements IWxPayService { return jsapiService.queryOrderById(request); } + /** + * 根据订单号查询订单 + * @param outTradeNo 商户订单号 + * @return + */ @Override - public Transaction queryOrderByOutTradeNo(String billNo) { + public Transaction queryOrderByOutTradeNo(String outTradeNo) { QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest(); request.setMchid(wxPayConfig.getMerchantId()); - request.setOutTradeNo(billNo); + request.setOutTradeNo(outTradeNo); return jsapiService.queryOrderByOutTradeNo(request); } @@ -170,6 +176,13 @@ public class WxPayService implements IWxPayService { return refund; } + @Override + public Refund queryByOutRefundNo(String outRefundNo) { + QueryByOutRefundNoRequest request = new QueryByOutRefundNoRequest(); + request.setOutRefundNo(outRefundNo); + return refundService2.queryByOutRefundNo(request); + } + /** 请求分账API */ public OrdersEntity createOrder(String transactionId,List receivers) { CreateOrderRequest request = new CreateOrderRequest(); @@ -177,7 +190,7 @@ public class WxPayService implements IWxPayService { request.setTransactionId(transactionId);// 微信订单号 request.setOutOrderNo(IdUtils.getOrderNo("fz"));// 商户系统内部分账单号 request.setReceivers(receivers); - request.setUnfreezeUnsplit(false); + request.setUnfreezeUnsplit(true); return profitsharingService.createOrder(request); } diff --git a/electripper-system/src/main/java/com/ruoyi/system/task/EtTask.java b/electripper-system/src/main/java/com/ruoyi/system/task/EtTask.java index 0b6d1b2..01bef20 100644 --- a/electripper-system/src/main/java/com/ruoyi/system/task/EtTask.java +++ b/electripper-system/src/main/java/com/ruoyi/system/task/EtTask.java @@ -1,33 +1,35 @@ package com.ruoyi.system.task; +import cn.hutool.core.util.ObjectUtil; import com.alibaba.fastjson2.JSON; +import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.ServiceConstants; +import com.ruoyi.common.core.domain.entity.AsUser; import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.system.domain.AsDevice; -import com.ruoyi.system.domain.EtDividendDetail; -import com.ruoyi.system.domain.EtOperatingArea; -import com.ruoyi.system.domain.EtOrder; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.system.domain.*; import com.ruoyi.system.mapper.AsDeviceMapper; +import com.ruoyi.system.mapper.AsUserMapper; import com.ruoyi.system.mapper.EtOrderMapper; import com.ruoyi.system.mapper.SysUserMapper; -import com.ruoyi.system.service.IEtDividendDetailService; -import com.ruoyi.system.service.IEtOperatingAreaService; -import com.ruoyi.system.service.IEtOrderService; -import com.ruoyi.system.service.ISysUserService; +import com.ruoyi.system.service.*; +import com.wechat.pay.java.service.payments.model.Transaction; +import com.wechat.pay.java.service.refund.model.Refund; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.math.BigDecimal; import java.time.LocalDate; import java.time.format.DateTimeFormatter; -import java.util.Date; -import java.util.List; +import java.util.*; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.stream.IntStream; @@ -62,15 +64,176 @@ public class EtTask { @Resource private AsDeviceMapper asDeviceMapper; + @Autowired + private IWxPayService wxPayService; + + @Autowired + private IEtFeeRuleService etFeeRuleService; + + @Autowired + private IEtRefundService etRefundService; + + @Autowired + private RedisCache redisCache; + + @Resource + private AsUserMapper asUserMapper; + + @Autowired + private CallbackService callbackService; + /** * 1.启动时判断是否有未取消预约的订单 * 2.判断已完成的订单未退还押金的 + * 3.启动时判断是否分账 */ + @Transactional @PostConstruct public void init() { - log.info("=========启动时判断是否有未取消预约的订单、已完成的订单未退还押金的=========="); + log.info("=========================启动业务处理========================="); + log.info("=========================开始========================="); + /** 1.启动时判断是否有未取消预约的订单*/ + uncancelledAppointmentHandle(); + + /** 2.判断已完成的订单未退还押金的(根据et_refund表中的refund_result结果判断是否已经退款) */ + /** ①找出所有已完成的订单 status=4 type = 1 r.refund_result IS NULL + * ②根据用户查询最后一次押金充值记录 + */ + List orders = etOrderMapper.selectUserListFinishOrder(); + for(EtOrder order:orders){ + EtFeeRule rule = etFeeRuleService.selectEtFeeRuleByRuleId(order.getRuleId()); + if(ObjectUtil.isNull(rule)){ + throw new ServiceException("骑行订单:【"+order.getOrderNo()+"】未找到该套餐【"+order.getRuleId()+"】"); + } + EtOperatingArea area = etOperatingAreaService.selectEtOperatingAreaByAreaId(order.getAreaId()); + AsUser asUser = asUserMapper.selectUserById(order.getUserId()); + Integer autoRefundDeposit = rule.getAutoRefundDeposit(); + + // 根据用户查询最后一次押金充值订单 + EtOrder etOrder = new EtOrder(); + etOrder.setUserId(order.getUserId()); + etOrder.setPaid(ServiceConstants.ORDER_PAY_STATUS_PAID); + etOrder.setType(ServiceConstants.ORDER_TYPE_DEPOSIT); + etOrder.setStatus(ServiceConstants.ORDER_STATUS_ORDER_END); + List etOrders = etOrderMapper.selectEtOrderList(etOrder); + if (etOrders.size() > 0 || ObjectUtil.isNotNull(etOrders) ) { + Optional latestOrderOptional = etOrders.stream() + .max(Comparator.comparing(EtOrder::getPayTime)); + if (latestOrderOptional.isPresent()) { + EtOrder lastOrder = latestOrderOptional.get(); + log.info("【系统启动】用户【{}】最后一次押金充值订单 : " + JSON.toJSONString(lastOrder),asUser.getUserId()); + if(lastOrder.getTotalFee().compareTo(new BigDecimal(area.getDeposit()))!=0){ + log.info("【系统启动】最后一次押金充值记录 金额与押金不一致,订单押金:【{}】,区域押金:【{}】",lastOrder.getTotalFee(),area.getDeposit()); + }else{ + // 根据最新的订单号,查询是否有退款记录 + EtRefund etRefund = etRefundService.selectEtRefundByOrderNo(lastOrder.getOrderNo()); + // 没有退款记录,发起退款 + if(ObjectUtil.isNull(etRefund)){ + // 根据订单支付时间 autoRefundDeposit个小时后退押金 + String reason = autoRefundDeposit + "个小时后自动退押金"; + Date payTime = order.getPayTime(); + Date refundDepositTime = DateUtils.getTimeAfterXHours(payTime, autoRefundDeposit); + Date nowDate = DateUtils.getNowDate(); + if (nowDate.after(refundDepositTime)) { + log.info("【系统启动】用户【{}】押金充值订单【{}】已过期,开始自动退押金",asUser.getUserId(),lastOrder.getOrderNo()); + refundDeposit(asUser, lastOrder, reason); + }else{ + int timeDifferenceInMinutes = DateUtils.timeDifferenceInMinutes(payTime, nowDate); + int i = autoRefundDeposit * 60; + int delay = i - timeDifferenceInMinutes; + log.info("【系统启动】用户【{}】押金充值订单【{}】未过期,【{}】分钟后退押金",asUser.getUserId(),lastOrder.getOrderNo(),delay); + scheduledExecutorService.schedule(() -> { + refundDeposit(asUser, lastOrder, reason); + }, delay, TimeUnit.MINUTES); + } + }else{ + // 有退款记录,判断是否成功 + if(!Constants.SUCCESS2.equals(etRefund.getRefundResult())){ + log.info("【系统启动】押金退款未成功回调,退款单号:【{}】",etRefund.getRefundNo()); + // 根据退款单号查询退款信息 + Refund refund = wxPayService.queryByOutRefundNo(etRefund.getRefundNo()); + if(ObjectUtil.isNotNull(refund) && Constants.SUCCESS2.equals(refund.getStatus().name())){ + // 更新退款记录 + etRefund.setRefundResult(Constants.SUCCESS2); + etRefund.setUpdateTime(new Date()); + etRefundService.updateEtRefund(etRefund); + log.info("【系统启动】更新押金退款回调成功,退款单号:【{}】",refund.getOutRefundNo()); + } + } + } + } + } + } + } + + /** 3.启动时判断是否分账(根据订单号查询分账明细表是否有记录来判断是否分账) */ + /** ①找出所有已完成的骑行订单 status=4 type = 1 r.refund_result IS NULL + * ②根据订单号查询分账明细表是否有记录 + * 有记录则已经分账过 + * 没值代表还未分账 + * 判断是否已过分账时间 + * 未过,计算出多少小时后分账 + * 已过,直接分账(记录分账明细表) + */ + // 查询所有待分账的订单 + List needDividendOrders = etOrderMapper.selectNeedDividendOrder(); + for(EtOrder order: needDividendOrders){ + log.info("【系统启动】待分账订单:【{}】",order.getOrderNo()); + EtOperatingArea area = etOperatingAreaService.selectEtOperatingAreaByAreaId(order.getAreaId()); + if(dividendDetailService.isDividendComputedByOrderNo(order.getOrderNo())){ + log.info("订单【{}】已经分账",order.getOrderNo()); + break; + } + log.info("【系统启动】骑行订单【{}】未分账,开始分账",order.getOrderNo()); + Date payTime = order.getPayTime(); + Date dividendTime = DateUtils.getTimeAfterXHours(payTime, 24);//分账时间 + Date nowDate = DateUtils.getNowDate(); + if (nowDate.after(dividendTime)) { + log.info("【系统启动】骑行订单【{}】已过分账时间,开始分账",order.getOrderNo()); + // 请求分账处理 + Transaction transaction = wxPayService.queryOrderByOutTradeNo(order.getOrderNo()); + if (callbackService.dividendHandle(transaction.getTransactionId(), order, area)) break; + }else{ + int timeDifferenceInHours = DateUtils.timeDifferenceInHours(payTime, nowDate); + int delay = 24 - timeDifferenceInHours; + log.info("【系统启动】骑行订单【{}】未过分账时间,【{}】小时后开始分账",order.getOrderNo(),delay); + // 24小时后发起分账 + scheduledExecutorService.schedule(() -> { + // 请求分账处理 + Transaction transaction = wxPayService.queryOrderByOutTradeNo(order.getOrderNo()); + if (callbackService.dividendHandle(transaction.getTransactionId(), order, area)) return; + }, delay , TimeUnit.HOURS); + } + } + log.info("=========================结束========================="); + } + + + private void refundDeposit(AsUser asUser, EtOrder lastOrder, String reason) { + Refund refund = wxPayService.refund(lastOrder, reason, lastOrder.getTotalFee()); + lastOrder.setReason(reason); + EtRefund refund1= etOrderService.createRefund(lastOrder, lastOrder.getTotalFee(), null, null, null, null, refund,ServiceConstants.REFUND_TYPE_DEPOSIT); + if(etRefundService.insertEtRefund(refund1)>0){ + log.info("【自动退款】保存退款对象成功"); + // 新增资金流水记录 + callbackService.capitalFlowRecords(lastOrder,ServiceConstants.FLOW_TYPE_DISBURSE,ServiceConstants.ORDER_TYPE_DEPOSIT_REFUND); + // 更新用户信息,清除缓存 + asUser.setBalance(BigDecimal.ZERO); + int updateUser = asUserMapper.updateUser(asUser); + if(updateUser>0){ + Collection keys = SpringUtils.getBean(RedisCache.class).keys(CacheConstants.LOGIN_TOKEN_KEY + "*"); + redisCache.deleteObject(keys); + log.info("【系统启动】退还押金,更新用户余额成功!"); + } + log.info("=================【系统启动】退还押金定时任务结束!!!=================="); + }else{ + throw new ServiceException("【系统启动】保存退款对象失败"); + } + } + + private void uncancelledAppointmentHandle() { List orders= etOrderMapper.selectAppointmentUnfinished(); log.info("预约未完成的订单 = " + JSON.toJSONString(orders)); for (EtOrder order:orders) { diff --git a/electripper-system/src/main/resources/mapper/system/EtOperatingAreaMapper.xml b/electripper-system/src/main/resources/mapper/system/EtOperatingAreaMapper.xml index d3375c8..2cda30f 100644 --- a/electripper-system/src/main/resources/mapper/system/EtOperatingAreaMapper.xml +++ b/electripper-system/src/main/resources/mapper/system/EtOperatingAreaMapper.xml @@ -47,7 +47,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" boundary_str, longitude, latitude, create_by, create_time, contact, phone, status, area_time, service_phone, slogan, province,city, county, area_out_outage, parking_out_dispatch, area_out_dispatch, - no_riding_outage, authentication, msg_switch, undercharge, error, agreement, deposit, + no_riding_outage, authentication, msg_switch, undercharge, error, cast(agreement as char) as agreement, deposit, outage, appointment_service_fee, dispatch_fee, vehicle_management_fee, timeout_minutes, auto_replacement_order, area_time_start, area_time_end from et_operating_area diff --git a/electripper-system/src/main/resources/mapper/system/EtOrderMapper.xml b/electripper-system/src/main/resources/mapper/system/EtOrderMapper.xml index d8559a5..935c25d 100644 --- a/electripper-system/src/main/resources/mapper/system/EtOrderMapper.xml +++ b/electripper-system/src/main/resources/mapper/system/EtOrderMapper.xml @@ -299,6 +299,30 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" select * from et_order where appointment_start_time is not null and appointment_start_time != '' AND appointment_end_time IS NULL + + + + + insert into et_order