From 90559cff06b5ede9479ae4ed044a8747e7e84991 Mon Sep 17 00:00:00 2001 From: zhangli <123879394@qq.com> Date: Fri, 26 Sep 2025 18:20:44 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=8D=E6=8A=BC=E4=B8=8B=E5=8D=95=E5=92=8C?= =?UTF-8?q?=E5=85=8D=E6=8A=BC=E6=94=AF=E4=BB=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ClientOrderController.java | 12 ++ .../java/com/sczx/order/po/OrderSubPO.java | 3 + .../com/sczx/order/service/OrderService.java | 7 ++ .../com/sczx/order/service/PayService.java | 10 ++ .../order/service/impl/OrderServiceImpl.java | 115 ++++++++++++++---- .../order/service/impl/PayServiceImpl.java | 19 ++- .../java/com/sczx/order/utils/OrderUtil.java | 2 + 7 files changed, 138 insertions(+), 30 deletions(-) diff --git a/src/main/java/com/sczx/order/controller/ClientOrderController.java b/src/main/java/com/sczx/order/controller/ClientOrderController.java index 37744a2..8741930 100644 --- a/src/main/java/com/sczx/order/controller/ClientOrderController.java +++ b/src/main/java/com/sczx/order/controller/ClientOrderController.java @@ -53,6 +53,18 @@ public class ClientOrderController { return Result.ok(orderService.submitRentCarOrder(rentCarOrderReq)); } + @ApiOperation(value = "免押生成租车订单") + @PostMapping("/depositFreeSubmitRentCarOrder") + public Result depositFreeSubmitRentCarOrder(@Valid @RequestBody RentCarOrderReq rentCarOrderReq){ + return Result.ok(orderService.depositFreeSubmitRentCarOrder(rentCarOrderReq)); + } + + @ApiOperation(value = "免押支付") + @PostMapping("/depositFreePayRentCarOrder") + public Result depositFreePayRentCarOrder(@Valid @RequestBody RentCarOrderReq rentCarOrderReq){ + return Result.ok(orderService.depositFreePayRentCarOrder(rentCarOrderReq)); + } + @ApiOperation(value = "续租车") @PostMapping("/reRentalCarOrder") public Result reRentalCarOrder(@Valid @RequestBody ReRentCarReq rentCarOrderReq){ diff --git a/src/main/java/com/sczx/order/po/OrderSubPO.java b/src/main/java/com/sczx/order/po/OrderSubPO.java index ce2a052..cd4ba80 100644 --- a/src/main/java/com/sczx/order/po/OrderSubPO.java +++ b/src/main/java/com/sczx/order/po/OrderSubPO.java @@ -74,6 +74,9 @@ public class OrderSubPO implements Serializable { @ApiModelProperty("备注") private String remark; + @ApiModelProperty("平台流水号") + private String transactionId; + @ApiModelProperty("删除标志(0代表存在 2代表删除)") private String delFlag; diff --git a/src/main/java/com/sczx/order/service/OrderService.java b/src/main/java/com/sczx/order/service/OrderService.java index 6cbc576..4b614bd 100644 --- a/src/main/java/com/sczx/order/service/OrderService.java +++ b/src/main/java/com/sczx/order/service/OrderService.java @@ -29,6 +29,13 @@ public interface OrderService { */ RentCarOrderResultDTO depositFreeSubmitRentCarOrder(RentCarOrderReq rentCarOrderReq); + /** + * 免押支付 + * @param rentCarOrderReq + * @return + */ + RentCarOrderResultDTO depositFreePayRentCarOrder(RentCarOrderReq rentCarOrderReq); + /** * 续租车 * @param rentCarOrderReq diff --git a/src/main/java/com/sczx/order/service/PayService.java b/src/main/java/com/sczx/order/service/PayService.java index 2f7718f..b306395 100644 --- a/src/main/java/com/sczx/order/service/PayService.java +++ b/src/main/java/com/sczx/order/service/PayService.java @@ -28,4 +28,14 @@ public interface PayService { * @param refundFee */ String refundOrder(String payType,Long companyId,String outTradeNo, BigDecimal totalFee, BigDecimal refundFee); + + + /** + * 冻结 + * @param companyId + * @param outOrderNo + * @param freezeFee + * @return + */ + UnifiedPaymentInfoDTO freezeOrder(Long companyId,String outOrderNo, BigDecimal freezeFee); } diff --git a/src/main/java/com/sczx/order/service/impl/OrderServiceImpl.java b/src/main/java/com/sczx/order/service/impl/OrderServiceImpl.java index 3fe186b..6f3db08 100644 --- a/src/main/java/com/sczx/order/service/impl/OrderServiceImpl.java +++ b/src/main/java/com/sczx/order/service/impl/OrderServiceImpl.java @@ -19,6 +19,7 @@ import com.sczx.order.service.PayService; import com.sczx.order.thirdpart.dto.*; import com.sczx.order.thirdpart.dto.req.AlipayCloseRequest; import com.sczx.order.thirdpart.dto.req.AlipayFundFreezeRequest; +import com.sczx.order.thirdpart.dto.req.AlipayQueryFreezeRequest; import com.sczx.order.thirdpart.dto.req.CarQueryConditionReq; import com.sczx.order.thirdpart.integration.CarInteg; import com.sczx.order.thirdpart.integration.PayInteg; @@ -239,6 +240,7 @@ public class OrderServiceImpl implements OrderService { @Override public RentCarOrderResultDTO depositFreeSubmitRentCarOrder(RentCarOrderReq rentCarOrderReq) { + log.info("开始发起免押 : {}", rentCarOrderReq); SimpleUserInfoDTO userInfoDTO = jwtUtil.getUserInfoFromToken(); if(!(rentCarOrderReq.getIsDepositFree() && StringUtils.equalsIgnoreCase(userInfoDTO.getMiniProgramType(), MiniProgramTypeEnum.ALIPAY.getType()))){ throw new BizException("不满足支付宝免押条件"); @@ -301,13 +303,17 @@ public class OrderServiceImpl implements OrderService { List orderSubPOList = new ArrayList<>(); //生成免押订单 - OrderSubPO depositOrder = new OrderSubPO(); - depositOrder.setSuborderNo(OrderUtil.generateSubOrderNo(OrderUtil.MY_PREFIX)); - depositOrder.setSuborderType(SubOrderTypeEnum.NO_DEPOSIT.getCode()); - depositOrder.setAmount(orderMainPO.getDepositPrice()); - depositOrder.setCreatedAt(LocalDateTime.now()); - depositOrder.setPaymentMethod(paymentType); - orderSubPOList.add(depositOrder); + OrderSubPO noDepositOrder = new OrderSubPO(); + noDepositOrder.setSuborderNo(OrderUtil.generateSubOrderNo(OrderUtil.MY_PREFIX)); + noDepositOrder.setPaymentId(OrderUtil.generateSubOrderNo(OrderUtil.FZ_PREFIX)); + noDepositOrder.setSuborderType(SubOrderTypeEnum.NO_DEPOSIT.getCode()); + noDepositOrder.setAmount(orderMainPO.getDepositPrice()); + noDepositOrder.setCreatedAt(LocalDateTime.now()); + noDepositOrder.setPaymentMethod(paymentType); + noDepositOrder.setPayStatus(PayStatusEnum.USERPAYING.getCode()); + orderSubPOList.add(noDepositOrder); + + String paymentId = OrderUtil.generateSubOrderNo(OrderUtil.ZF_PREFIX); //如果选择了租电套餐,则还需要生成租电子订单 if(rentBatteyRuleDTO!=null){ rentBatteyRuleDTO = carInteg.getRentBatteyRuleByBatteyRuleId(rentCarOrderReq.getRentBatteyRuleId()); @@ -317,6 +323,8 @@ public class OrderServiceImpl implements OrderService { rentBatteyRuleOrder.setAmount(rentBatteyRuleDTO.getRentPrice()); rentBatteyRuleOrder.setCreatedAt(LocalDateTime.now()); rentBatteyRuleOrder.setPaymentMethod(paymentType); + rentBatteyRuleOrder.setPayStatus(PayStatusEnum.INIT.getCode()); + rentBatteyRuleOrder.setPaymentId(paymentId); orderSubPOList.add(rentBatteyRuleOrder); } //生成租车订单 @@ -328,29 +336,19 @@ public class OrderServiceImpl implements OrderService { rentOrder.setCreatedAt(LocalDateTime.now()); rentOrder.setPaymentMethod(paymentType); rentOrder.setReturnTime(endRentTime); + rentOrder.setPayStatus(PayStatusEnum.INIT.getCode()); + rentOrder.setPaymentId(paymentId); orderSubPOList.add(rentOrder); - BigDecimal orderAmount = orderSubPOList.stream().map(OrderSubPO::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add); + //计算订单金额除开免押订单的金额 + BigDecimal orderAmount = orderSubPOList.stream().filter(x->!StringUtils.equalsIgnoreCase(x.getSuborderType(),SubOrderTypeEnum.NO_DEPOSIT.getCode())).map(OrderSubPO::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add); orderMainPO.setOrderAmount(orderAmount); //发起支付返回预支付信息 - String paymentId = OrderUtil.generateSubOrderNo(OrderUtil.ZF_PREFIX); - UnifiedPaymentInfoDTO unifiedPaymentInfoDTO = payService.prepayOrder(paymentType,rentCarRuleDTO.getRuleName(),Long.valueOf(companyStoreDTO.getOperatingCompanyId()),paymentId,userInfoDTO - ,orderMainPO.getOrderAmount()); - - for(OrderSubPO orderSubPO : orderSubPOList){ - orderSubPO.setPaymentId(paymentId); - //发起免押冻结后,免押订单状态设置为待支付,其他子订单都为初始状态,等待支付 - if(StringUtils.equalsIgnoreCase(orderSubPO.getSuborderType(), SubOrderTypeEnum.NO_DEPOSIT.getCode())){ - orderSubPO.setPayStatus(PayStatusEnum.USERPAYING.getCode()); - } else { - orderSubPO.setPayStatus(PayStatusEnum.INIT.getCode()); - } - - } + UnifiedPaymentInfoDTO unifiedPaymentInfoDTO = payService.freezeOrder(Long.valueOf(companyStoreDTO.getOperatingCompanyId()),noDepositOrder.getPaymentId(),noDepositOrder.getAmount()); + //保存订单 orderMainRepo.save(orderMainPO); - orderSubPOList.forEach(orderSubPO -> { orderSubPO.setOrderId(orderMainPO.getOrderId()); }); @@ -369,18 +367,83 @@ public class OrderServiceImpl implements OrderService { return rentCarOrderResultDTO; }catch (Exception e){ - log.warn("下单失败", e); + log.warn("免押下单失败", e); throw e; } finally { redisUtil.deleteRedisLock(redisLockKey); } } else { - log.warn("下单失败,锁已被占用"); - throw new InnerException("服务器正在处理,请稍后再试"); + log.warn("免押失败,锁已被占用"); + throw new InnerException("免押失败,请稍后再试"); } } + @Override + public RentCarOrderResultDTO depositFreePayRentCarOrder(RentCarOrderReq rentCarOrderReq) { + SimpleUserInfoDTO userInfoDTO = jwtUtil.getUserInfoFromToken(); + OrderMainPO orderMainPO = queryOrderMainPoByOrderNo(rentCarOrderReq.getOrderNo(), "0"); + if(orderMainPO == null || OrderStatusEnum.WAIT_PAY.getCode().equals(orderMainPO.getOrderStatus())){ + throw new BizException("订单不存在或订单状态不正确"); + } + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(OrderSubPO::getOrderId, orderMainPO.getOrderId()).eq(OrderSubPO::getDelFlag, "0"); + List orderSubPOList = orderSubRepo.list(queryWrapper); + OrderSubPO noDepositOrder = orderSubPOList.stream().filter(x->StringUtils.equalsIgnoreCase(x.getSuborderType(),SubOrderTypeEnum.NO_DEPOSIT.getCode())).findFirst().orElse(null); + if(noDepositOrder == null){ + throw new BizException("未做免押,支付失败"); + } + String redisLockKey = RedisKeyConstants.ORDER_SUB_KEY + userInfoDTO.getUserId(); + if(redisUtil.getRedisLock(redisLockKey, "免押支付")) { + try{ + if(PayStatusEnum.USERPAYING.getCode().equals(noDepositOrder.getPayStatus())){ + log.info("查询支付宝冻结订单结果,并更新状态"); + AlipayQueryFreezeRequest alipayQueryFreezeRequest = new AlipayQueryFreezeRequest(); + alipayQueryFreezeRequest.setOutOrderNo(noDepositOrder.getPaymentId()); + alipayQueryFreezeRequest.setOperationType("FREEZE"); + alipayQueryFreezeRequest.setCompanyId(orderMainPO.getOperatorId().toString()); + AlipayQueryFreezeResponse queryFreezeResponse = payInteg.queryFundFreeze(alipayQueryFreezeRequest); + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(OrderSubPO::getSuborderId, noDepositOrder.getSuborderId()) + .set(OrderSubPO::getPayStatus, PayStatusEnum.SUCCESS.getCode()) + .set(OrderSubPO::getTransactionId, queryFreezeResponse.getAuthNo()); + orderSubRepo.update(updateWrapper); + } + OrderSubPO rentCarOrder = orderSubPOList.stream().filter(x->StringUtils.equalsIgnoreCase(x.getSuborderType(),SubOrderTypeEnum.RENTCAR.getCode())).findFirst().orElse(null); + if(rentCarOrder == null){ + throw new BizException("无租车待支付单,支付失败"); + } + //开始发起支付 + UnifiedPaymentInfoDTO unifiedPaymentInfoDTO = payService.prepayOrder(rentCarOrder.getPaymentMethod(),orderMainPO.getRentCarRuleId().toString(),orderMainPO.getOperatorId(),rentCarOrder.getPaymentId(),userInfoDTO + ,orderMainPO.getOrderAmount()); + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(OrderSubPO::getSuborderId, noDepositOrder.getSuborderId()) + .eq(OrderSubPO::getDelFlag, "0") + .in(OrderSubPO::getSuborderType, Arrays.asList(SubOrderTypeEnum.RENTCAR.getCode(), SubOrderTypeEnum.RENTBATTEY.getCode())) + .in(OrderSubPO::getPayStatus, PayStatusEnum.INIT.getCode()) + .set(OrderSubPO::getPayStatus, PayStatusEnum.USERPAYING.getCode()); + orderSubRepo.update(updateWrapper); + //返回订单信息 + OrderDTO orderDTO = OrderConvert.INSTANCE.poToDto(orderMainPO); + RentCarOrderResultDTO rentCarOrderResultDTO = new RentCarOrderResultDTO(); + rentCarOrderResultDTO.setOrderMainInfo(orderDTO); + rentCarOrderResultDTO.setUnifiedPaymentInfo(unifiedPaymentInfoDTO); + + return rentCarOrderResultDTO; + }catch (Exception e){ + log.warn("免押支付失败", e); + throw e; + } finally { + redisUtil.deleteRedisLock(redisLockKey); + } + } else { + log.warn("免押支付失败,锁已被占用"); + throw new InnerException("免押支付失败,请稍后再试"); + } + + + } + @Transactional(rollbackFor = Exception.class) @Override diff --git a/src/main/java/com/sczx/order/service/impl/PayServiceImpl.java b/src/main/java/com/sczx/order/service/impl/PayServiceImpl.java index 7581e7c..ad7d018 100644 --- a/src/main/java/com/sczx/order/service/impl/PayServiceImpl.java +++ b/src/main/java/com/sczx/order/service/impl/PayServiceImpl.java @@ -3,11 +3,9 @@ package com.sczx.order.service.impl; import com.sczx.order.common.enums.PaymentTypeEnum; import com.sczx.order.dto.SimpleUserInfoDTO; import com.sczx.order.service.PayService; +import com.sczx.order.thirdpart.dto.AlipayFundFreezeResponse; import com.sczx.order.thirdpart.dto.UnifiedPaymentInfoDTO; -import com.sczx.order.thirdpart.dto.req.AlipayCreateRequest; -import com.sczx.order.thirdpart.dto.req.AlipayRefundRequest; -import com.sczx.order.thirdpart.dto.req.PaymentRequest; -import com.sczx.order.thirdpart.dto.req.RefundRequest; +import com.sczx.order.thirdpart.dto.req.*; import com.sczx.order.thirdpart.integration.PayInteg; import com.sczx.order.utils.OrderUtil; import lombok.extern.slf4j.Slf4j; @@ -89,4 +87,17 @@ public class PayServiceImpl implements PayService { } return null; } + + @Override + public UnifiedPaymentInfoDTO freezeOrder(Long companyId, String outOrderNo, BigDecimal freezeFee) { + AlipayFundFreezeRequest request = new AlipayFundFreezeRequest(); + request.setCompanyId(companyId.toString()); + request.setOutOrderNo(outOrderNo); + request.setTitle("租车免押"); + request.setAmount(freezeFee.toString()); + AlipayFundFreezeResponse result = payInteg.fundFreeze(request); + UnifiedPaymentInfoDTO unifiedPaymentInfoDTO = new UnifiedPaymentInfoDTO(); + unifiedPaymentInfoDTO.setOrderStr(result.getOrderStr()); + return unifiedPaymentInfoDTO; + } } diff --git a/src/main/java/com/sczx/order/utils/OrderUtil.java b/src/main/java/com/sczx/order/utils/OrderUtil.java index d907651..a050e90 100644 --- a/src/main/java/com/sczx/order/utils/OrderUtil.java +++ b/src/main/java/com/sczx/order/utils/OrderUtil.java @@ -28,6 +28,8 @@ public class OrderUtil { public static final String FD_PREFIX = "FD"; + public static final String FZ_PREFIX = "FZ"; + /** * 生成订单号的方法 * @return 唯一订单号字符串