1. 启动时判断是否分账
2. 判断已完成的订单未退还押金的
This commit is contained in:
parent
a4b28c47dd
commit
6a4c3baf94
|
@ -7,6 +7,10 @@ import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
import com.ruoyi.common.utils.CommonUtil;
|
import com.ruoyi.common.utils.CommonUtil;
|
||||||
import com.ruoyi.system.domain.*;
|
import com.ruoyi.system.domain.*;
|
||||||
import com.ruoyi.system.service.*;
|
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.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
@ -39,6 +43,9 @@ public class AppController extends BaseController
|
||||||
@Autowired
|
@Autowired
|
||||||
private IEtOrderService etOrderService;
|
private IEtOrderService etOrderService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IWxPayService wxPayService;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -287,4 +294,26 @@ public class AppController extends BaseController
|
||||||
return AjaxResult.success("操作成功", address);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,7 +133,7 @@ xss:
|
||||||
# 过滤开关
|
# 过滤开关
|
||||||
enabled: true
|
enabled: true
|
||||||
# 排除链接(多个用逗号分隔)
|
# 排除链接(多个用逗号分隔)
|
||||||
excludes: /system/notice
|
excludes: /system/notice,/system/area
|
||||||
# 匹配链接
|
# 匹配链接
|
||||||
urlPatterns: /system/*,/monitor/*,/tool/*
|
urlPatterns: /system/*,/monitor/*,/tool/*
|
||||||
# 阿里云短信
|
# 阿里云短信
|
||||||
|
|
|
@ -199,6 +199,23 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
|
||||||
return day + "天" + hour + "小时" + min + "分钟";
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 计算时间差(只返回分钟数)
|
* 计算时间差(只返回分钟数)
|
||||||
*
|
*
|
||||||
|
|
|
@ -212,4 +212,19 @@ public interface EtOrderMapper
|
||||||
* 预约未完成订单处理
|
* 预约未完成订单处理
|
||||||
*/
|
*/
|
||||||
List<EtOrder> selectAppointmentUnfinished();
|
List<EtOrder> selectAppointmentUnfinished();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 押金未退还订单处理
|
||||||
|
*/
|
||||||
|
List<EtOrder> selectUnrefundableDepositOrder();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已完成订单的用户列表
|
||||||
|
*/
|
||||||
|
List<EtOrder> selectUserListFinishOrder();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 待结算订单
|
||||||
|
*/
|
||||||
|
List<EtOrder> selectNeedDividendOrder();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
package com.ruoyi.system.service;
|
package com.ruoyi.system.service;
|
||||||
|
|
||||||
|
import com.ruoyi.system.domain.EtOperatingArea;
|
||||||
|
import com.ruoyi.system.domain.EtOrder;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21,4 +24,22 @@ public interface CallbackService {
|
||||||
*/
|
*/
|
||||||
void weChatRefund(HttpServletRequest request);
|
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,4 +74,12 @@ public interface IEtDividendDetailService
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
boolean isDividendComputed(String date);
|
boolean isDividendComputed(String date);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据订单号判断是否已经计算过分账结果
|
||||||
|
*
|
||||||
|
* @param orderNo 订单号
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
boolean isDividendComputedByOrderNo(String orderNo);
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,11 +41,11 @@ public interface IWxPayService {
|
||||||
Transaction queryOrderById(String prePayId);
|
Transaction queryOrderById(String prePayId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过订单编号查询订单信息
|
* 通过商户订单号查询订单信息
|
||||||
* @param billNo 订单编号
|
* @param outTradeNo 商户订单号
|
||||||
* @return 订单信息
|
* @return 订单信息
|
||||||
*/
|
*/
|
||||||
Transaction queryOrderByOutTradeNo(String billNo);
|
Transaction queryOrderByOutTradeNo(String outTradeNo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 退款
|
* 退款
|
||||||
|
@ -55,6 +55,12 @@ public interface IWxPayService {
|
||||||
*/
|
*/
|
||||||
Refund refund(EtOrder etOrder, String reason, BigDecimal amount);
|
Refund refund(EtOrder etOrder, String reason, BigDecimal amount);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据退款单号查询退款信息
|
||||||
|
* @param outRefundNo 退款单号
|
||||||
|
*/
|
||||||
|
Refund queryByOutRefundNo(String outRefundNo);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 请求分账API
|
* 请求分账API
|
||||||
|
|
|
@ -160,13 +160,17 @@ public class CallbackServiceImpl implements CallbackService {
|
||||||
|
|
||||||
// 新增资金流水记录
|
// 新增资金流水记录
|
||||||
capitalFlowRecords(order,ServiceConstants.FLOW_TYPE_INCOME,ServiceConstants.ORDER_TYPE_RIDING);
|
capitalFlowRecords(order,ServiceConstants.FLOW_TYPE_INCOME,ServiceConstants.ORDER_TYPE_RIDING);
|
||||||
|
|
||||||
// 还车结算___小时后自动退押金---创建一个定时器TimerTask,计算出退还时间后,执行退款操作
|
// 还车结算___小时后自动退押金---创建一个定时器TimerTask,计算出退还时间后,执行退款操作
|
||||||
EtOperatingArea area = etOperatingAreaService.selectEtOperatingAreaByAreaId(order.getAreaId());
|
EtOperatingArea area = etOperatingAreaService.selectEtOperatingAreaByAreaId(order.getAreaId());
|
||||||
// 退还押金处理
|
// 退还押金处理
|
||||||
refundDeposit(area.getDeposit(), order, asUser);
|
refundDeposit(area.getDeposit(), order, asUser);
|
||||||
|
|
||||||
// 请求分账处理
|
// 24小时后发起分账
|
||||||
if (dividendHandle(transactionId, order, area)) return;
|
scheduledExecutorService.schedule(() -> {
|
||||||
|
// 请求分账处理
|
||||||
|
if (dividendHandle(transactionId, order, area)) return;
|
||||||
|
}, 24 , TimeUnit.HOURS);
|
||||||
|
|
||||||
}else if(attachVo.getType().equals(ServiceConstants.BUSINESS_TYPE_APPOINTMENT)){
|
}else if(attachVo.getType().equals(ServiceConstants.BUSINESS_TYPE_APPOINTMENT)){
|
||||||
logger.info("【微信支付回调】取消预约支付");
|
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<EtDividendDetail> etDividendDetails = dividendDetailService.selectEtDividendDetailByOrderNo(order.getOrderNo());
|
List<EtDividendDetail> etDividendDetails = dividendDetailService.selectEtDividendDetailByOrderNo(order.getOrderNo());
|
||||||
if(ObjectUtil.isNotNull(etDividendDetails) && etDividendDetails.size()>0){
|
if(ObjectUtil.isNotNull(etDividendDetails) && etDividendDetails.size()>0){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
logger.info("=================【微信支付回调】开始请求分账==================");
|
logger.info("=================【微信支付回调】24小时后开始请求分账==================");
|
||||||
logger.info("区域对象====="+JSON.toJSONString(area));
|
logger.info("区域对象====="+JSON.toJSONString(area));
|
||||||
logger.info("订单对象====="+JSON.toJSONString(order));
|
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()))){
|
if(ObjectUtil.isNotNull(etCapitalFlowService.selectEtCapitalFlowByOutTradeNo(order.getOutTradeNo()))){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -399,6 +411,8 @@ public class CallbackServiceImpl implements CallbackService {
|
||||||
int i = etCapitalFlowService.insertEtCapitalFlow(capitalFlow);
|
int i = etCapitalFlowService.insertEtCapitalFlow(capitalFlow);
|
||||||
if(i==0){
|
if(i==0){
|
||||||
throw new ServiceException("保存资金流水记录失败");
|
throw new ServiceException("保存资金流水记录失败");
|
||||||
|
}else {
|
||||||
|
logger.info("【微信支付回调】保存资金流水记录成功");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package com.ruoyi.system.service.impl;
|
package com.ruoyi.system.service.impl;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import com.ruoyi.common.utils.DateUtils;
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
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.domain.EtDividendDetail;
|
||||||
import com.ruoyi.system.service.IEtDividendDetailService;
|
import com.ruoyi.system.service.IEtDividendDetailService;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分账明细Service业务层处理
|
* 分账明细Service业务层处理
|
||||||
*
|
*
|
||||||
|
@ -17,7 +21,7 @@ import com.ruoyi.system.service.IEtDividendDetailService;
|
||||||
@Service
|
@Service
|
||||||
public class EtDividendDetailServiceImpl implements IEtDividendDetailService
|
public class EtDividendDetailServiceImpl implements IEtDividendDetailService
|
||||||
{
|
{
|
||||||
@Autowired
|
@Resource
|
||||||
private EtDividendDetailMapper etDividendDetailMapper;
|
private EtDividendDetailMapper etDividendDetailMapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -111,5 +115,19 @@ public class EtDividendDetailServiceImpl implements IEtDividendDetailService
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否已经计算过
|
||||||
|
* @param orderNo
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isDividendComputedByOrderNo(String orderNo) {
|
||||||
|
List<EtDividendDetail> etDividendDetails = etDividendDetailMapper.selectEtDividendDetailByOrderNo(orderNo);
|
||||||
|
if(ObjectUtil.isNotNull(etDividendDetails) && etDividendDetails.size() > 0){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,9 +64,6 @@ public class EtOrderServiceImpl implements IEtOrderService
|
||||||
@Autowired
|
@Autowired
|
||||||
private IAsDeviceService deviceService;
|
private IAsDeviceService deviceService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ISysConfigService sysConfigService;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IEtFeeRuleService etFeeRuleService;
|
private IEtFeeRuleService etFeeRuleService;
|
||||||
|
|
||||||
|
@ -76,9 +73,6 @@ public class EtOrderServiceImpl implements IEtOrderService
|
||||||
@Autowired
|
@Autowired
|
||||||
private IAsDeviceService asDeviceService;
|
private IAsDeviceService asDeviceService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private TransactionTemplate transactionTemplate;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IEtRefundService etRefundService;
|
private IEtRefundService etRefundService;
|
||||||
|
|
||||||
|
@ -86,16 +80,10 @@ public class EtOrderServiceImpl implements IEtOrderService
|
||||||
private IEtTripLogService etTripLogService;
|
private IEtTripLogService etTripLogService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedisCache redisCache;
|
private IEtDividendDetailService dividendDetailService;
|
||||||
|
|
||||||
// @Autowired
|
|
||||||
// private TokenService tokenService;
|
|
||||||
|
|
||||||
// 令牌有效期(默认30分钟)
|
|
||||||
@Value("${token.expireTime}")
|
|
||||||
private int expireTime;
|
|
||||||
|
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CallbackService callbackService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询订单
|
* 查询订单
|
||||||
|
@ -689,6 +677,9 @@ public class EtOrderServiceImpl implements IEtOrderService
|
||||||
if(ServiceConstants.ORDER_PAY_STATUS_NON_PAYMENT.equals(etOrder1.getPaid())){
|
if(ServiceConstants.ORDER_PAY_STATUS_NON_PAYMENT.equals(etOrder1.getPaid())){
|
||||||
throw new ServiceException("订单未支付,不能退款");
|
throw new ServiceException("订单未支付,不能退款");
|
||||||
}
|
}
|
||||||
|
if(dividendDetailService.isDividendComputedByOrderNo(etOrder.getOrderNo())){
|
||||||
|
throw new ServiceException("订单【{}】已经分账,不能退款");
|
||||||
|
}
|
||||||
/** 1.退款*/
|
/** 1.退款*/
|
||||||
//退款金额
|
//退款金额
|
||||||
BigDecimal refundAmount = new BigDecimal("0");
|
BigDecimal refundAmount = new BigDecimal("0");
|
||||||
|
@ -716,6 +707,8 @@ public class EtOrderServiceImpl implements IEtOrderService
|
||||||
if(i>0){
|
if(i>0){
|
||||||
log.info("保存退款对象成功");
|
log.info("保存退款对象成功");
|
||||||
}
|
}
|
||||||
|
// 新增资金流水记录
|
||||||
|
callbackService.capitalFlowRecords(etOrder1,ServiceConstants.FLOW_TYPE_DISBURSE,ServiceConstants.ORDER_TYPE_RIDING_REFUND);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.RefundService;
|
||||||
import com.wechat.pay.java.service.refund.model.AmountReq;
|
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.CreateRequest;
|
||||||
|
import com.wechat.pay.java.service.refund.model.QueryByOutRefundNoRequest;
|
||||||
import com.wechat.pay.java.service.refund.model.Refund;
|
import com.wechat.pay.java.service.refund.model.Refund;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
@ -142,11 +143,16 @@ public class WxPayService implements IWxPayService {
|
||||||
return jsapiService.queryOrderById(request);
|
return jsapiService.queryOrderById(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据订单号查询订单
|
||||||
|
* @param outTradeNo 商户订单号
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Transaction queryOrderByOutTradeNo(String billNo) {
|
public Transaction queryOrderByOutTradeNo(String outTradeNo) {
|
||||||
QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
|
QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
|
||||||
request.setMchid(wxPayConfig.getMerchantId());
|
request.setMchid(wxPayConfig.getMerchantId());
|
||||||
request.setOutTradeNo(billNo);
|
request.setOutTradeNo(outTradeNo);
|
||||||
return jsapiService.queryOrderByOutTradeNo(request);
|
return jsapiService.queryOrderByOutTradeNo(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,6 +176,13 @@ public class WxPayService implements IWxPayService {
|
||||||
return refund;
|
return refund;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Refund queryByOutRefundNo(String outRefundNo) {
|
||||||
|
QueryByOutRefundNoRequest request = new QueryByOutRefundNoRequest();
|
||||||
|
request.setOutRefundNo(outRefundNo);
|
||||||
|
return refundService2.queryByOutRefundNo(request);
|
||||||
|
}
|
||||||
|
|
||||||
/** 请求分账API */
|
/** 请求分账API */
|
||||||
public OrdersEntity createOrder(String transactionId,List<CreateOrderReceiver> receivers) {
|
public OrdersEntity createOrder(String transactionId,List<CreateOrderReceiver> receivers) {
|
||||||
CreateOrderRequest request = new CreateOrderRequest();
|
CreateOrderRequest request = new CreateOrderRequest();
|
||||||
|
@ -177,7 +190,7 @@ public class WxPayService implements IWxPayService {
|
||||||
request.setTransactionId(transactionId);// 微信订单号
|
request.setTransactionId(transactionId);// 微信订单号
|
||||||
request.setOutOrderNo(IdUtils.getOrderNo("fz"));// 商户系统内部分账单号
|
request.setOutOrderNo(IdUtils.getOrderNo("fz"));// 商户系统内部分账单号
|
||||||
request.setReceivers(receivers);
|
request.setReceivers(receivers);
|
||||||
request.setUnfreezeUnsplit(false);
|
request.setUnfreezeUnsplit(true);
|
||||||
return profitsharingService.createOrder(request);
|
return profitsharingService.createOrder(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,33 +1,35 @@
|
||||||
package com.ruoyi.system.task;
|
package com.ruoyi.system.task;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.ruoyi.common.constant.CacheConstants;
|
||||||
import com.ruoyi.common.constant.Constants;
|
import com.ruoyi.common.constant.Constants;
|
||||||
import com.ruoyi.common.constant.ServiceConstants;
|
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.domain.entity.SysUser;
|
||||||
|
import com.ruoyi.common.core.redis.RedisCache;
|
||||||
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
import com.ruoyi.common.utils.DateUtils;
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
import com.ruoyi.system.domain.AsDevice;
|
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||||
import com.ruoyi.system.domain.EtDividendDetail;
|
import com.ruoyi.system.domain.*;
|
||||||
import com.ruoyi.system.domain.EtOperatingArea;
|
|
||||||
import com.ruoyi.system.domain.EtOrder;
|
|
||||||
import com.ruoyi.system.mapper.AsDeviceMapper;
|
import com.ruoyi.system.mapper.AsDeviceMapper;
|
||||||
|
import com.ruoyi.system.mapper.AsUserMapper;
|
||||||
import com.ruoyi.system.mapper.EtOrderMapper;
|
import com.ruoyi.system.mapper.EtOrderMapper;
|
||||||
import com.ruoyi.system.mapper.SysUserMapper;
|
import com.ruoyi.system.mapper.SysUserMapper;
|
||||||
import com.ruoyi.system.service.IEtDividendDetailService;
|
import com.ruoyi.system.service.*;
|
||||||
import com.ruoyi.system.service.IEtOperatingAreaService;
|
import com.wechat.pay.java.service.payments.model.Transaction;
|
||||||
import com.ruoyi.system.service.IEtOrderService;
|
import com.wechat.pay.java.service.refund.model.Refund;
|
||||||
import com.ruoyi.system.service.ISysUserService;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.Date;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
|
@ -62,15 +64,176 @@ public class EtTask {
|
||||||
@Resource
|
@Resource
|
||||||
private AsDeviceMapper asDeviceMapper;
|
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.启动时判断是否有未取消预约的订单
|
* 1.启动时判断是否有未取消预约的订单
|
||||||
* 2.判断已完成的订单未退还押金的
|
* 2.判断已完成的订单未退还押金的
|
||||||
|
* 3.启动时判断是否分账
|
||||||
*/
|
*/
|
||||||
|
@Transactional
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void init() {
|
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<EtOrder> 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<EtOrder> etOrders = etOrderMapper.selectEtOrderList(etOrder);
|
||||||
|
if (etOrders.size() > 0 || ObjectUtil.isNotNull(etOrders) ) {
|
||||||
|
Optional<EtOrder> 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<EtOrder> 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<String> 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<EtOrder> orders= etOrderMapper.selectAppointmentUnfinished();
|
List<EtOrder> orders= etOrderMapper.selectAppointmentUnfinished();
|
||||||
log.info("预约未完成的订单 = " + JSON.toJSONString(orders));
|
log.info("预约未完成的订单 = " + JSON.toJSONString(orders));
|
||||||
for (EtOrder order:orders) {
|
for (EtOrder order:orders) {
|
||||||
|
|
|
@ -47,7 +47,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
boundary_str, longitude, latitude, create_by, create_time,
|
boundary_str, longitude, latitude, create_by, create_time,
|
||||||
contact, phone, status, area_time, service_phone, slogan, province,city,
|
contact, phone, status, area_time, service_phone, slogan, province,city,
|
||||||
county, area_out_outage, parking_out_dispatch, area_out_dispatch,
|
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,
|
outage, appointment_service_fee, dispatch_fee, vehicle_management_fee, timeout_minutes,
|
||||||
auto_replacement_order, area_time_start, area_time_end from et_operating_area
|
auto_replacement_order, area_time_start, area_time_end from et_operating_area
|
||||||
</sql>
|
</sql>
|
||||||
|
|
|
@ -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
|
select * from et_order where appointment_start_time is not null and appointment_start_time != '' AND appointment_end_time IS NULL
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectUnrefundableDepositOrder" resultMap="EtOrderResult">
|
||||||
|
select * from et_order o
|
||||||
|
left JOIN et_refund r on r.order_no = o.order_no
|
||||||
|
where o.status ='4' and o.paid = '1' and o.type = 2 and r.refund_result IS NULL
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectUserListFinishOrder" resultMap="EtOrderResult">
|
||||||
|
select * from et_order o
|
||||||
|
where o.status ='4' and o.paid = '1' and o.type = 1
|
||||||
|
GROUP BY o.user_id
|
||||||
|
</select>
|
||||||
|
<select id="selectNeedDividendOrder" resultType="com.ruoyi.system.domain.EtOrder">
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
et_order o
|
||||||
|
WHERE
|
||||||
|
o.STATUS = '4'
|
||||||
|
AND o.paid = '1'
|
||||||
|
AND o.type = 1
|
||||||
|
AND o.pay_type != 'sys'
|
||||||
|
AND o.total_fee != 0
|
||||||
|
</select>
|
||||||
|
|
||||||
<insert id="insertEtOrder" parameterType="EtOrder" useGeneratedKeys="true" keyProperty="orderId">
|
<insert id="insertEtOrder" parameterType="EtOrder" useGeneratedKeys="true" keyProperty="orderId">
|
||||||
insert into et_order
|
insert into et_order
|
||||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||||
|
|
Loading…
Reference in New Issue
Block a user