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;
|
}
|
}
|