package com.ruoyi.order.service.impl; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.ruoyi.order.api.model.TChargingOrder; import com.ruoyi.order.api.model.TChargingOrderShareRecord; import com.ruoyi.payment.api.vo.IcbcPaymentResp; import com.ruoyi.payment.api.vo.IcbcRefundReq; import com.ruoyi.payment.api.vo.IcbcSubOrderQueryReq; import com.ruoyi.payment.api.vo.IcbcSubOrderRefundReq; import java.math.BigDecimal; final class IcbcAdminFundOperationSupport { private IcbcAdminFundOperationSupport() { } static void validateOrder(TChargingOrder order) { validateIcbcOrder(order); if (!Integer.valueOf(2).equals(order.getRechargePaymentStatus())) { throw new IllegalArgumentException("订单尚未支付成功"); } } static void validateIcbcOrder(TChargingOrder order) { if (order == null) { throw new IllegalArgumentException("充电订单不存在"); } if (!"ICBC".equals(order.getSourceName())) { throw new IllegalArgumentException("仅支持工商银行支付订单"); } } static boolean isBankPaid(IcbcPaymentResp payment) { if (payment == null) { return false; } try { JSONObject response = JSON.parseObject(payment.getRawResponse()); if (response != null && response.getIntValue("returnCode") == 0 && "0".equals(response.getString("pay_status"))) { return true; } } catch (Exception ignored) { } return "0".equals(payment.getStatus()); } static BigDecimal requireAmount(BigDecimal amount) { if (amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) { throw new IllegalArgumentException("操作金额必须大于0"); } if (amount.stripTrailingZeros().scale() > 2) { throw new IllegalArgumentException("操作金额最多保留两位小数"); } BigDecimal normalized = amount.setScale(2, BigDecimal.ROUND_HALF_UP); if (normalized.compareTo(BigDecimal.ZERO) <= 0) { throw new IllegalArgumentException("操作金额必须大于0"); } return normalized; } static String buildPendingRefundValue(String operationToken, BigDecimal amount) { if (isBlank(operationToken)) { throw new IllegalArgumentException("退款流水号不能为空"); } return operationToken + "|" + requireAmount(amount).toPlainString(); } static String resolveRefundNo(String pendingValue, BigDecimal amount, String newOperationToken) { BigDecimal normalized = requireAmount(amount); if (isBlank(pendingValue)) { return newOperationToken; } int separator = pendingValue.lastIndexOf('|'); if (separator <= 0 || separator == pendingValue.length() - 1) { throw new IllegalArgumentException("退款幂等记录格式错误"); } BigDecimal pendingAmount; try { pendingAmount = new BigDecimal(pendingValue.substring(separator + 1)); } catch (NumberFormatException e) { throw new IllegalArgumentException("退款幂等记录格式错误"); } if (pendingAmount.compareTo(normalized) != 0) { throw new IllegalArgumentException("上一笔退款结果未知,请按原金额重试"); } return pendingValue.substring(0, separator); } static boolean shouldClearPendingRefund(boolean reusedPending, String status, boolean definitiveResponse) { return "SUCCESS".equals(status) || (!reusedPending && definitiveResponse); } static IcbcRefundReq buildRefundRequest(TChargingOrder order, BigDecimal amount, String outRefundNo) { validateOrder(order); IcbcRefundReq request = new IcbcRefundReq(); request.setOutTradeNo(order.getCode()); request.setOrderId(order.getRechargeSerialNumber()); request.setOutRefundNo(outRefundNo); request.setRefundAmount(requireAmount(amount)); request.setTotalAmount(order.getThirdPayAmount()); request.setReason("管理后台工行退款"); return request; } static IcbcSubOrderQueryReq buildSubOrderQueryRequest(TChargingOrder order, TChargingOrderShareRecord shareRecord) { validateOrder(order); validateShareRecord(order, shareRecord); IcbcSubOrderQueryReq request = new IcbcSubOrderQueryReq(); request.setOrderNoType("2"); request.setMerOrderId(order.getCode()); request.setPrtiId(shareRecord.getOriMerId()); request.setQueryType("1"); request.setMerTrnscSerno(shareRecord.getSubOrderId()); request.setSubPrtiId(shareRecord.getSubMerId()); return request; } static IcbcSubOrderRefundReq buildSubOrderRefundRequest(TChargingOrder order, TChargingOrderShareRecord shareRecord, BigDecimal amount, String retSubOrderId, String outtrxSerialNo) { validateOrder(order); validateShareRecord(order, shareRecord); if (Boolean.TRUE.equals(shareRecord.getDelFlag())) { throw new IllegalArgumentException("分账记录已删除"); } if (!"SUCCESS".equals(shareRecord.getOnlineShareStatus())) { throw new IllegalArgumentException("仅支持已成功的工行分账记录退款"); } if (shareRecord.getOriTrxDate() == null || isBlank(shareRecord.getSubMerId()) || isBlank(shareRecord.getSubMerPrtclNo())) { throw new IllegalArgumentException("分账记录缺少工行退款参数"); } IcbcSubOrderRefundReq request = new IcbcSubOrderRefundReq(); request.setChargingOrderCode(order.getCode()); request.setSeqNo(firstNotBlank(shareRecord.getSeqNo(), order.getCode())); request.setBusiType(firstNotBlank(shareRecord.getBusiType(), "1")); request.setOriMerId(shareRecord.getOriMerId()); request.setOriTrxDate(shareRecord.getOriTrxDate() == null ? null : shareRecord.getOriTrxDate().toString()); request.setSubOrderId(shareRecord.getSubOrderId()); request.setRetSubOrderId(retSubOrderId); request.setOuttrxSerialNo(outtrxSerialNo); request.setSubMerId(shareRecord.getSubMerId()); request.setSubMerPrtclNo(shareRecord.getSubMerPrtclNo()); request.setRefundAmount(requireAmount(amount)); request.setMerAcct(shareRecord.getMerAcct()); request.setMerSpInfor("管理后台工行分账退款"); return request; } private static void validateShareRecord(TChargingOrder order, TChargingOrderShareRecord shareRecord) { if (shareRecord == null || !order.getId().equals(shareRecord.getChargingOrderId())) { throw new IllegalArgumentException("分账记录不属于当前订单"); } if (!"ICBC".equals(shareRecord.getPayChannel())) { throw new IllegalArgumentException("仅支持工商银行分账记录"); } if (shareRecord.getSubOrderId() == null || shareRecord.getSubOrderId().trim().isEmpty()) { throw new IllegalArgumentException("分账记录缺少工行子订单号"); } } private static boolean isBlank(String value) { return value == null || value.trim().isEmpty(); } private static String firstNotBlank(String... values) { for (String value : values) { if (!isBlank(value)) { return value; } } return null; } }