From 323b43be530d7f0d50d62dd4ce6f0aa5ed0fee47 Mon Sep 17 00:00:00 2001 From: jsowell <123@jsowell.com> Date: Wed, 5 Aug 2026 14:08:02 +0800 Subject: [PATCH] =?UTF-8?q?update=20=E5=90=8E=E7=AE=A1=E5=8F=96=E6=B6=88?= =?UTF-8?q?=E8=AE=A2=E5=8D=95=E6=94=AF=E6=8C=81=E9=80=80=E6=AC=BE=E4=B8=8E?= =?UTF-8?q?=E7=BB=93=E7=AE=97=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/jsowell/service/OrderService.java | 187 ++++++++++++++++++ .../pile/OrderBasicInfoController.java | 7 +- 2 files changed, 191 insertions(+), 3 deletions(-) diff --git a/jsowell-admin/src/main/java/com/jsowell/service/OrderService.java b/jsowell-admin/src/main/java/com/jsowell/service/OrderService.java index 178fc615b..9dfb5cc86 100644 --- a/jsowell-admin/src/main/java/com/jsowell/service/OrderService.java +++ b/jsowell-admin/src/main/java/com/jsowell/service/OrderService.java @@ -375,6 +375,193 @@ public class OrderService { log.info("主动停止充电, orderCode:{}, transactionCode:{}, 发送停机指令成功", dto.getOrderCode(), orderInfo.getTransactionCode()); } + /** + * 后管取消订单 + * 除最终状态(订单完成/订单关闭)外,其他状态均可取消: + * - 待支付:直接关闭订单 + * - 已支付未启动充电:关闭订单并退款 + * - 充电中:发送停机指令,由充电桩返回交易记录后自动结算(结算含退款) + * - 待结算/待补缴/异常/可疑:按最近一次充电数据直接结算(结算含退款) + * + * @param orderCode 订单编号 + */ + public void cancelOrderForWeb(String orderCode) { + OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByOrderCode(orderCode); + if (orderBasicInfo == null) { + throw new BusinessException(ReturnCodeEnum.CODE_QUERY_ORDER_INFO_IS_NULL); + } + String orderStatus = orderBasicInfo.getOrderStatus(); + String payStatus = orderBasicInfo.getPayStatus(); + + // 最终状态不可取消 + if (StringUtils.equals(orderStatus, OrderStatusEnum.ORDER_COMPLETE.getValue()) + || StringUtils.equals(orderStatus, OrderStatusEnum.ORDER_CLOSE_TIMEOUT.getValue())) { + throw new BusinessException(ReturnCodeEnum.CODE_ORDER_INFO_ERROR); + } + + // 1. 待支付:直接关闭订单 + if (StringUtils.equals(payStatus, OrderPayStatusEnum.unpaid.getValue())) { + closeOrderForCancel(orderBasicInfo); + log.info("取消订单-待支付订单直接关闭, orderCode:{}", orderCode); + return; + } + + // 2. 已支付未启动充电:关闭订单并退款 + if (StringUtils.equals(orderStatus, OrderStatusEnum.NOT_START.getValue())) { + closeOrderForCancel(orderBasicInfo); + refundOrderForCancel(orderBasicInfo); + log.info("取消订单-已支付未启动订单关闭并退款, orderCode:{}", orderCode); + return; + } + + // 3. 充电中:发送停机指令,结算由桩返回交易记录后自动完成 + if (StringUtils.equals(orderStatus, OrderStatusEnum.IN_THE_CHARGING.getValue())) { + sendStopChargingCommand(orderBasicInfo); + log.info("取消订单-充电中订单发送停机指令, orderCode:{}", orderCode); + return; + } + + // 4. 待结算/待补缴/异常/可疑:直接触发结算(含退款) + settleOrderForCancel(orderBasicInfo); + log.info("取消订单-未结算订单执行结算, orderCode:{}", orderCode); + } + + /** + * 关闭订单(状态改为 7-订单关闭) + */ + private void closeOrderForCancel(OrderBasicInfo orderBasicInfo) { + orderBasicInfo.setOrderStatus(OrderStatusEnum.ORDER_CLOSE_TIMEOUT.getValue()); + orderBasicInfoService.updateOrderBasicInfo(orderBasicInfo); + } + + /** + * 已支付未启动订单退款:按实际支付金额全额退款 + */ + private void refundOrderForCancel(OrderBasicInfo orderBasicInfo) { + String orderCode = orderBasicInfo.getOrderCode(); + String payMode = orderBasicInfo.getPayMode(); + + // 白名单支付无需退款 + if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_WHITELIST.getValue())) { + log.info("取消订单退款-白名单支付不退款, orderCode:{}", orderCode); + return; + } + + // 已存在退款记录,说明已经退过,跳过 + List refundInfoList = orderBasicInfoService.getOrderRefundInfoList(orderBasicInfo); + if (CollectionUtils.isNotEmpty(refundInfoList)) { + log.info("取消订单退款-订单已存在退款记录, 跳过退款, orderCode:{}", orderCode); + return; + } + + // 退款金额取实际支付金额 + BigDecimal refundAmount = orderBasicInfo.getPayAmount() != null + ? orderBasicInfo.getPayAmount() + : orderBasicInfo.getOrderAmount(); + if (refundAmount == null || refundAmount.compareTo(BigDecimal.ZERO) <= 0) { + log.info("取消订单退款-退款金额小于等于0, 跳过退款, orderCode:{}", orderCode); + return; + } + orderBasicInfo.setRefundAmount(refundAmount); + orderBasicInfoService.updateOrderBasicInfo(orderBasicInfo); + + // 余额支付:退到会员余额 + if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_PRINCIPAL_BALANCE.getValue())) { + orderBasicInfoService.refundBalancePaymentOrder(orderBasicInfo); + return; + } + + // 在线支付:根据支付机构退款 + MemberTransactionRecord transactionRecord = memberTransactionRecordService.selectByOrderCode(orderCode, ActionTypeEnum.FORWARD.getValue()); + if (transactionRecord == null) { + log.warn("取消订单退款-未查到正向支付流水, 无法自动退款, orderCode:{}", orderCode); + return; + } + String wechatAppId = pileMerchantInfoService.queryAppIdByMerchantId(orderBasicInfo.getMerchantId()); + ApplyRefundDTO applyRefundDTO = new ApplyRefundDTO(); + applyRefundDTO.setOrderCode(orderCode); + applyRefundDTO.setRefundType(Constants.ONE); + applyRefundDTO.setRefundAmount(refundAmount); + applyRefundDTO.setWechatAppId(wechatAppId); + applyRefundDTO.setMemberId(orderBasicInfo.getMemberId()); + if (StringUtils.equals(transactionRecord.getPaymentInstitutions(), PaymentInstitutionsEnum.ADAPAY.getValue())) { + // 汇付支付:撤销/退款 + orderBasicInfoService.refundOrderWithAdapay(applyRefundDTO); + } else if (StringUtils.equals(transactionRecord.getPaymentInstitutions(), PaymentInstitutionsEnum.WECHAT_PAY.getValue())) { + // 微信支付:退款 + orderBasicInfoService.refundOrderWithWechatPay(applyRefundDTO); + } else { + log.info("取消订单退款-支付机构:{}不支持自动退款, orderCode:{}", transactionRecord.getPaymentInstitutions(), orderCode); + } + } + + /** + * 充电中订单发送停机指令(含第三方桩统一停止充电) + */ + private void sendStopChargingCommand(OrderBasicInfo orderBasicInfo) { + List list = snRelationService.selectSnRelationListByParams( + orderBasicInfo.getStationId(), orderBasicInfo.getPileSn(), null); + if (CollectionUtils.isNotEmpty(list)) { + for (ThirdPartySnRelationVO vo : list) { + ThirdPartyCommonStopChargeDTO commonStopChargeDTO = new ThirdPartyCommonStopChargeDTO(); + commonStopChargeDTO.setThirdPartyType(vo.getThirdPartyType()); + commonStopChargeDTO.setOrderBasicInfo(orderBasicInfo); + String result = commonService.commonStopCharge(commonStopChargeDTO); + log.info("取消订单-订单:{} 调用统一停止充电接口, result:{}", orderBasicInfo.getOrderCode(), result); + } + } else { + pileRemoteService.remoteStopCharging(orderBasicInfo.getPileSn(), + orderBasicInfo.getConnectorCode(), orderBasicInfo.getTransactionCode()); + } + log.info("取消订单-订单:{} 发送停机指令成功", orderBasicInfo.getOrderCode()); + } + + /** + * 待结算/待补缴/异常/可疑订单:按最近一次充电数据执行结算(结算含退款) + */ + private void settleOrderForCancel(OrderBasicInfo orderBasicInfo) { + TransactionRecordsData data = null; + // 优先取桩返回的交易记录 + List pileFeedList = pileMsgRecordService.queryPileFeedList( + orderBasicInfo.getPileSn(), "0x3B", orderBasicInfo.getTransactionCode()); + for (PileMsgRecord pileMsgRecord : pileFeedList) { + TransactionRecordsData parse = JSONObject.parseObject(pileMsgRecord.getJsonMsg(), TransactionRecordsData.class); + if (StringUtils.equals(parse.getTransactionCode(), orderBasicInfo.getTransactionCode())) { + data = parse; + data.setVinCode(""); + } + } + + // 没有交易记录时,用最后一次实时数据兜底 + if (data == null) { + data = new TransactionRecordsData(); + List chargingRealTimeData = orderBasicInfoService.getChargingRealTimeData(orderBasicInfo.getTransactionCode()); + if (CollectionUtils.isNotEmpty(chargingRealTimeData)) { + RealTimeMonitorData realTimeMonitorData = chargingRealTimeData.get(0); + data.setConsumptionAmount(realTimeMonitorData.getChargingAmount()); + data.setTotalElectricity(realTimeMonitorData.getChargingDegree()); + } else { + data.setConsumptionAmount(Constants.ZERO); + data.setTotalElectricity(Constants.ZERO); + } + data.setStopReasonMsg("后管取消订单,操作人:" + SecurityUtils.getUsername()); + } + + String mode = pileMerchantInfoService.getDelayModeByMerchantId(orderBasicInfo.getMerchantId()); + AbstractProgramLogic orderLogic = ProgramLogicFactory.getProgramLogic(mode); + if (YouDianUtils.isEBikePileSn(orderBasicInfo.getPileSn())) { + // 电单车桩 + BigDecimal chargingDegree = StringUtils.isNotBlank(data.getTotalElectricity()) + ? new BigDecimal(data.getTotalElectricity()) : BigDecimal.ZERO; + EBikeMessageCmd03 message = new EBikeMessageCmd03(chargingDegree, EBikeStopReasonEnum.EXTERNAL_OPERATION_STOPPED.getCode()); + orderLogic.settleOrderForEBike(message, orderBasicInfo); + } else { + // 汽车桩 + orderLogic.settleOrder(data, orderBasicInfo); + } + log.info("取消订单-订单:{} 结算完成", orderBasicInfo.getOrderCode()); + } + /** * 微信退款 * diff --git a/jsowell-admin/src/main/java/com/jsowell/web/controller/pile/OrderBasicInfoController.java b/jsowell-admin/src/main/java/com/jsowell/web/controller/pile/OrderBasicInfoController.java index 90d334c32..c1fc136b0 100644 --- a/jsowell-admin/src/main/java/com/jsowell/web/controller/pile/OrderBasicInfoController.java +++ b/jsowell-admin/src/main/java/com/jsowell/web/controller/pile/OrderBasicInfoController.java @@ -179,15 +179,16 @@ public class OrderBasicInfoController extends BaseController { } /** - * 取消订单/关闭待支付订单 - * 仅待支付状态的订单可取消,取消后订单状态变为 7-订单关闭 + * 取消订单 + * 除订单完成/订单关闭外均可取消: + * 待支付直接关闭;已支付未启动关闭并退款;充电中发送停机指令并结算;未结算状态直接结算 * http://localhost:8080/order/closeOrderByOrderCode/{orderCode} */ @PreAuthorize("@ss.hasPermi('order:order:edit')") @Log(title = "订单", businessType = BusinessType.UPDATE) @PostMapping("/closeOrderByOrderCode/{orderCode}") public AjaxResult closeOrderByOrderCode(@PathVariable("orderCode") String orderCode) { - orderBasicInfoService.closeOrderByOrderCode(orderCode); + orderService.cancelOrderForWeb(orderCode); return AjaxResult.success(); }