This commit is contained in:
2023-08-30 09:54:39 +08:00
parent ae578eada7
commit 1f80d4e479
2 changed files with 624 additions and 28 deletions

View File

@@ -1,14 +1,36 @@
package com.jsowell.pile.service.orderlogic;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jsowell.adapay.service.AdapayService;
import com.jsowell.common.constant.CacheConstants;
import com.jsowell.common.core.domain.ykc.RealTimeMonitorData;
import com.jsowell.common.core.domain.ykc.TransactionRecordsData;
import com.jsowell.common.core.redis.RedisCache;
import com.jsowell.common.enums.ykc.OrderPayModeEnum;
import com.jsowell.common.enums.ykc.OrderStatusEnum;
import com.jsowell.common.util.DateUtils;
import com.jsowell.common.util.StringUtils;
import com.jsowell.pile.domain.OrderBasicInfo;
import com.jsowell.pile.domain.OrderDetail;
import com.jsowell.pile.domain.OrderMonitorData;
import com.jsowell.pile.domain.OrderPayRecord;
import com.jsowell.pile.dto.PayOrderDTO;
import com.jsowell.pile.dto.PayOrderSuccessCallbackDTO;
import com.jsowell.pile.service.IOrderBasicInfoService;
import com.jsowell.pile.service.*;
import com.jsowell.pile.transaction.service.TransactionService;
import com.jsowell.pile.vo.web.BalanceDeductionAmountVO;
import com.jsowell.wxpay.service.WxAppletRemoteService;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;
@@ -16,8 +38,52 @@ import java.util.Map;
* 描述订单逻辑
*/
public abstract class AbstractOrderLogic {
protected Logger logger = LoggerFactory.getLogger(this.getClass());
@Resource
private IOrderBasicInfoService orderBasicInfoService;
protected IOrderBasicInfoService orderBasicInfoService;
@Autowired
protected IMemberBasicInfoService memberBasicInfoService;
@Autowired
protected MemberAdapayRecordService memberAdapayRecordService;
@Autowired
protected OrderPayRecordService orderPayRecordService;
@Autowired
protected IMemberTransactionRecordService memberTransactionRecordService;
@Autowired
protected AdapayService adapayService;
@Autowired
protected IAdapayMemberAccountService adapayMemberAccountService;
@Autowired
protected IPileMerchantInfoService pileMerchantInfoService;
@Autowired
protected TransactionService transactionService;
@Autowired
protected AdapayCallbackRecordService adapayCallbackRecordService;
@Autowired
protected IPileAuthCardService pileAuthCardService;
@Autowired
protected IMemberPlateNumberRelationService memberPlateNumberRelationService;
@Autowired
protected WxAppletRemoteService wxAppletRemoteService;
@Autowired
protected OrderMonitorDataService orderMonitorDataService;
@Autowired
protected RedisCache redisCache;
/**
* 余额支付订单
@@ -42,7 +108,7 @@ public abstract class AbstractOrderLogic {
/**
* 余额支付订单退款
*/
public abstract void balancePayOrderRefund(OrderBasicInfo orderBasicInfo);
public abstract void balancePaymentOrderRefund(OrderBasicInfo orderBasicInfo);
/**
* 在线支付订单退款
@@ -62,4 +128,285 @@ public abstract class AbstractOrderLogic {
protected List<BalanceDeductionAmountVO> calculateTheBalanceDeductionAmount(String memberId, BigDecimal amount) {
return orderBasicInfoService.calculateTheBalanceDeductionAmount(memberId, amount);
}
/**
* 返回更新后的OrderBasicInfo对象
* 专用方法,其他地方如果要用请仔细检查
* 【公共方法】
*/
protected void returnUpdateOrderBasicInfo(OrderBasicInfo orderBasicInfo, TransactionRecordsData data) {
// 订单编号
String orderCode = orderBasicInfo.getOrderCode();
// 消费金额就是订单总金额/交易记录传过来的消费金额
BigDecimal orderAmount = new BigDecimal(data.getConsumptionAmount());
// 付款金额 - 实际消费金额,如果有剩余,需要走退款操作 当使用余额支付时payAmount = principalPay + giftPay
BigDecimal payAmount = orderBasicInfo.getPayAmount();
// 有时候充电桩到达金额停止充电会多出一点金额比如实际需要充50元的电充电桩传来的消费金额为50.01元,在后台记录的时候需要舍去
if (orderAmount.compareTo(payAmount) > 0) {
logger.info("结算订单:【{}】充电桩传来的消费金额:【{}】大于付款金额:【{}】, 消费金额设置为付款金额相等数据", orderCode, orderAmount, payAmount);
orderAmount = payAmount;
}
orderBasicInfo.setOrderAmount(orderAmount); // 订单总金额
// 虚拟金额 指订单消费中不参与结算的部分
BigDecimal virtualAmount = BigDecimal.ZERO;
if (OrderPayModeEnum.PAYMENT_OF_WHITELIST.getValue().equals(orderBasicInfo.getPayMode())) {
// 白名单支付所消费的金额,都属于虚拟金额,不参与结算对账
virtualAmount = new BigDecimal(orderAmount.toString());
}
// 剩余需要退回的金额 residue
BigDecimal residue = payAmount.subtract(orderAmount);
// 把交易记录中的用电量,金额等信息 更新到orderBasicInfo和orderDetail
orderBasicInfo.setVirtualAmount(virtualAmount); // 虚拟金额
orderBasicInfo.setSettleAmount(orderAmount.subtract(virtualAmount)); // 结算金额
orderBasicInfo.setOrderStatus(OrderStatusEnum.ORDER_COMPLETE.getValue());
orderBasicInfo.setReason(data.getStopReasonMsg()); // 充电停止原因
orderBasicInfo.setSettlementTime(DateUtils.getNowDate()); // 结算时间
orderBasicInfo.setRefundAmount(residue); // 结算退款金额
}
/**
* 获取更新数据后的orderDetail对象
* 专用方法,其他地方如果要用请仔细检查
* 【公共方法】
* @return 查询并更新过数据的orderDetail
*/
protected OrderDetail returnUpdateOrderDetail(OrderBasicInfo orderBasicInfo, TransactionRecordsData data) {
String orderCode = orderBasicInfo.getOrderCode();
BigDecimal orderAmount = orderBasicInfo.getOrderAmount();
// 更新订单详情 查询订单详情 修改订单数据
OrderDetail orderDetail = orderBasicInfoService.getOrderDetailByOrderCode(orderCode);
try {
// 总电费金额
BigDecimal totalElectricityAmount = BigDecimal.ZERO;
// 尖时段用电量
String sharpUsedElectricity = data.getSharpUsedElectricity();
if (sharpUsedElectricity != null) {
orderDetail.setSharpUsedElectricity(new BigDecimal(sharpUsedElectricity));
if (data.getSharpPrice() != null) {
orderDetail.setSharpPrice(new BigDecimal(data.getSharpPrice()));
}
if (data.getSharpAmount() != null) {
orderDetail.setSharpAmount(new BigDecimal(data.getSharpAmount()));
}
// 计算该时段电费
BigDecimal multiply = orderDetail.getSharpElectricityPrice()
.multiply(new BigDecimal(sharpUsedElectricity))
.setScale(2, RoundingMode.DOWN);
totalElectricityAmount = totalElectricityAmount.add(multiply);
}
// 峰时段用电量
String peakUsedElectricity = data.getPeakUsedElectricity();
if (peakUsedElectricity != null) {
orderDetail.setPeakUsedElectricity(new BigDecimal(peakUsedElectricity));
if (data.getPeakPrice() != null) {
orderDetail.setPeakPrice(new BigDecimal(data.getPeakPrice()));
}
if (data.getPeakAmount() != null) {
orderDetail.setPeakAmount(new BigDecimal(data.getPeakAmount()));
}
// 计算该时段电费
BigDecimal multiply = orderDetail.getPeakElectricityPrice()
.multiply(new BigDecimal(peakUsedElectricity))
.setScale(2, RoundingMode.DOWN);
totalElectricityAmount = totalElectricityAmount.add(multiply);
}
// 平时段用电量
String flatUsedElectricity = data.getFlatUsedElectricity();
if (flatUsedElectricity != null) {
orderDetail.setFlatUsedElectricity(new BigDecimal(flatUsedElectricity));
if (data.getFlatPrice() != null) {
orderDetail.setFlatPrice(new BigDecimal(data.getFlatPrice()));
}
if (data.getFlatAmount() != null) {
orderDetail.setFlatAmount(new BigDecimal(data.getFlatAmount()));
}
// 计算该时段电费
BigDecimal multiply = orderDetail.getFlatElectricityPrice()
.multiply(new BigDecimal(flatUsedElectricity))
.setScale(2, RoundingMode.DOWN);
totalElectricityAmount = totalElectricityAmount.add(multiply);
}
// 谷时段用电量
String valleyUsedElectricity = data.getValleyUsedElectricity();
if (valleyUsedElectricity != null) {
orderDetail.setValleyUsedElectricity(new BigDecimal(valleyUsedElectricity));
if (data.getValleyPrice() != null) {
orderDetail.setValleyPrice(new BigDecimal(data.getValleyPrice()));
}
if (data.getValleyAmount() != null) {
orderDetail.setValleyAmount(new BigDecimal(data.getValleyAmount()));
}
// 计算该时段电费
BigDecimal multiply = orderDetail.getValleyElectricityPrice()
.multiply(new BigDecimal(valleyUsedElectricity))
.setScale(2, RoundingMode.DOWN);
totalElectricityAmount = totalElectricityAmount.add(multiply);
}
// 如果算出来的电费金额大于总消费金额,则电费金额等于总消费金额
if (totalElectricityAmount.compareTo(orderAmount) > 0) {
totalElectricityAmount = orderAmount;
}
orderDetail.setTotalElectricityAmount(totalElectricityAmount);
orderDetail.setTotalServiceAmount(orderAmount.subtract(totalElectricityAmount));
orderDetail.setTotalUsedElectricity(new BigDecimal(data.getTotalElectricity())); // 总用电量
orderDetail.setTotalOrderAmount(orderAmount); // 订单总金额
} catch (Exception e) {
logger.error("设置订单详情参数发生异常", e);
}
return orderDetail;
}
/**
* 余额支付 计算需要退回的金额
* 【公共方法】
* @param principalPay 本金支付金额
* @param giftPay 赠送金额支付的金额
* @param orderAmount 订单消费金额
* @return
*/
protected Map<String, BigDecimal> calculateReturnAmount(BigDecimal principalPay, BigDecimal giftPay, BigDecimal orderAmount) {
Map<String, BigDecimal> resultMap = Maps.newHashMap();
// 消费金额优先使用本金
BigDecimal returnPrincipal = null; // 退回本金金额
BigDecimal returnGift = null; // 退回赠送金额
// 余额支付 有3种情况
if (principalPay != null && giftPay == null) {
// 只有本金支付
BigDecimal subtract = principalPay.subtract(orderAmount);
if (subtract.compareTo(BigDecimal.ZERO) > 0) {
returnPrincipal = subtract;
}
}
if (principalPay == null && giftPay != null) {
// 只有赠送金额支付
BigDecimal subtract = giftPay.subtract(orderAmount);
if (subtract.compareTo(BigDecimal.ZERO) > 0) {
returnGift = subtract;
}
}
if (principalPay != null && giftPay != null) {
// 本金+赠送支付
BigDecimal subtract = principalPay.subtract(orderAmount);
if (subtract.compareTo(BigDecimal.ZERO) > 0) {
// 本金减掉订单金额后还有剩余,那就把剩余的退回,赠送原封不动退回
returnPrincipal = subtract;
returnGift = giftPay;
} else if (subtract.compareTo(BigDecimal.ZERO) == 0) {
// 本金刚好够,那赠送金额支付的原封不动退回
returnGift = giftPay;
} else {
returnGift = giftPay.subtract(subtract.negate());
}
}
resultMap.put("returnPrincipal", returnPrincipal);
resultMap.put("returnGift", returnGift);
return resultMap;
}
/**
* 计算解冻金额
* @param orderAmount 订单消费金额
* @param payRecordList 订单支付记录
*/
protected List<Map<String, Object>> calculateUnfreezeAmount(BigDecimal orderAmount, List<OrderPayRecord> payRecordList) {
List<Map<String, Object>> resultList = Lists.newArrayList();
BigDecimal tempAmount = new BigDecimal(orderAmount.toString()); // 临时金额
for (OrderPayRecord record : payRecordList) {
JSONObject jsonObject = JSON.parseObject(record.getDeductionRecord());
String paymentId = jsonObject.getString("paymentId");
BigDecimal payAmount = record.getPayAmount(); // 此交易单支付的金额
// 该笔支付扣除金额
BigDecimal deductionAmount;
// 该笔支付解冻金额
BigDecimal unfreezeAmount = null;
// 临时消费金额 = 临时消费金额 - 该笔交易的剩余金额
tempAmount = tempAmount.subtract(payAmount);
if (tempAmount.compareTo(BigDecimal.ZERO) >= 0) {
// 计算以后大于等于0说明这笔支付剩余金额需要扣完还要继续扣下一笔
deductionAmount = payAmount;
unfreezeAmount = payAmount.subtract(deductionAmount); // 支付金额 - 扣除金额 = 需要退回的金额
Map<String, Object> map = Maps.newHashMap();
map.put("paymentId", paymentId);
map.put("unfreezeAmount", unfreezeAmount);
resultList.add(map);
} else {
// 如果小于0则说明该笔交易的剩余金额用不完扣除金额等于临时消费金额并结束循环
deductionAmount = payAmount.add(tempAmount); // 该笔交易的剩余金额加上一个负数临时消费金额,就是该笔交易扣除金额
unfreezeAmount = payAmount.subtract(deductionAmount); // 支付金额 - 扣除金额 = 需要退回的金额
Map<String, Object> map = Maps.newHashMap();
map.put("paymentId", paymentId);
map.put("unfreezeAmount", unfreezeAmount);
resultList.add(map);
break;
}
}
return resultList;
}
/**
* 从redis中取出实时记录保存到表中j
* 当订单完成的时候调用
* 【公共方法】
*/
protected void realTimeMonitorDataRedis2DB(String transactionCode, String orderCode) {
try {
if (StringUtils.isBlank(transactionCode) || StringUtils.isBlank(orderCode)) {
return;
}
// 校验有没有保存过
OrderMonitorData orderMonitorData = orderMonitorDataService.selectByOrderCode(orderCode);
if (orderMonitorData != null) {
return;
}
List<RealTimeMonitorData> chargingRealTimeData = orderBasicInfoService.getChargingRealTimeData(transactionCode);
if (CollectionUtils.isEmpty(chargingRealTimeData)) {
return;
}
List<RealTimeMonitorData> list = Lists.newArrayList();
for (RealTimeMonitorData data : chargingRealTimeData) {
RealTimeMonitorData build = RealTimeMonitorData.builder()
.outputCurrent(data.getOutputCurrent())
.outputCurrent(data.getOutputCurrent()) // 电流
.outputVoltage(data.getOutputVoltage()) // 电压
.outputPower(data.getOutputPower()) // 功率
.SOC(data.getSOC()) // soc
.dateTime(data.getDateTime()) // 时间
.batteryMaxTemperature(data.getBatteryMaxTemperature())
.chargingAmount(data.getChargingAmount())
.chargingDegree(data.getChargingDegree())
.sumChargingTime(data.getSumChargingTime())
.timeRemaining(data.getTimeRemaining())
.gunLineTemperature(data.getGunLineTemperature())
.build();
list.add(build);
}
OrderMonitorData record = new OrderMonitorData();
record.setOrderCode(orderCode);
record.setTransactionCode(transactionCode);
record.setMonitorData(JSONObject.toJSONString(list));
int insert = orderMonitorDataService.insertSelective(record);
if (insert > 0) {
// 删除redis中缓存
String pileConnectorCode = transactionCode.substring(0, 16);
String redisKey = CacheConstants.PILE_REAL_TIME_MONITOR_DATA + pileConnectorCode + "_" + transactionCode;
redisCache.deleteObject(redisKey);
}
} catch (Exception e) {
logger.info("redis中取出实时记录保存到表发生异常", e);
}
}
}

View File

@@ -3,31 +3,34 @@ package com.jsowell.pile.service.orderlogic;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.collect.Lists;
import com.jsowell.adapay.service.AdapayService;
import com.jsowell.adapay.operation.PaymentReverseOperation;
import com.jsowell.adapay.response.PaymentReverseResponse;
import com.jsowell.adapay.vo.OrderSettleResult;
import com.jsowell.common.constant.Constants;
import com.jsowell.common.core.domain.ykc.TransactionRecordsData;
import com.jsowell.common.enums.AcquirerEnum;
import com.jsowell.common.enums.MemberWalletEnum;
import com.jsowell.common.enums.ykc.*;
import com.jsowell.common.exception.BusinessException;
import com.jsowell.pile.domain.MemberTransactionRecord;
import com.jsowell.pile.domain.OrderBasicInfo;
import com.jsowell.pile.domain.OrderPayRecord;
import com.jsowell.common.util.StringUtils;
import com.jsowell.pile.domain.*;
import com.jsowell.pile.dto.ApplyRefundDTO;
import com.jsowell.pile.dto.PayOrderDTO;
import com.jsowell.pile.dto.PayOrderSuccessCallbackDTO;
import com.jsowell.pile.service.IMemberBasicInfoService;
import com.jsowell.pile.service.IMemberTransactionRecordService;
import com.jsowell.pile.service.MemberAdapayRecordService;
import com.jsowell.pile.service.OrderPayRecordService;
import com.jsowell.pile.transaction.dto.OrderTransactionDTO;
import com.jsowell.pile.vo.uniapp.MemberVO;
import com.jsowell.pile.vo.web.BalanceDeductionAmountVO;
import com.jsowell.pile.vo.web.UpdateMemberBalanceDTO;
import com.jsowell.wxpay.dto.WechatSendMsgDTO;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 设置延时分账的运营商订单逻辑
@@ -35,21 +38,6 @@ import java.util.Map;
@Service
public class DelayMerchantOrderLogic extends AbstractOrderLogic {
@Autowired
private IMemberBasicInfoService memberBasicInfoService;
@Autowired
private MemberAdapayRecordService memberAdapayRecordService;
@Autowired
private OrderPayRecordService orderPayRecordService;
@Autowired
private IMemberTransactionRecordService memberTransactionRecordService;
@Autowired
private AdapayService adapayService;
/**
* 余额支付订单
*/
@@ -150,7 +138,19 @@ public class DelayMerchantOrderLogic extends AbstractOrderLogic {
*/
@Override
public void whitelistPaymentOrder(PayOrderDTO dto) {
String orderCode = dto.getOrderCode();
BigDecimal payAmount = dto.getPayAmount();
String payMode = dto.getPayMode();
// 白名单直接算支付成功
PayOrderSuccessCallbackDTO callbackDTO = PayOrderSuccessCallbackDTO.builder()
.orderCode(orderCode)
.payAmount(payAmount)
.payMode(payMode)
.startMode(dto.getStartMode())
.acquirer(AcquirerEnum.LOCAL.getValue())
.build();
payOrderSuccessCallback(callbackDTO);
}
/**
@@ -158,15 +158,179 @@ public class DelayMerchantOrderLogic extends AbstractOrderLogic {
*/
@Override
public void orderSettle(TransactionRecordsData data, OrderBasicInfo orderBasicInfo) {
logger.info("结算订单start data:{}, orderBasicInfo:{}", data.toString(), orderBasicInfo.toString());
// 判断订单状态
if (StringUtils.equals(orderBasicInfo.getOrderStatus(), OrderStatusEnum.ORDER_COMPLETE.getValue())) {
logger.info("结算订单:{}, 是订单完成状态", orderBasicInfo.getOrderCode());
return;
}
// 获取更新数据后的orderBasicInfo对象
returnUpdateOrderBasicInfo(orderBasicInfo, data);
// 获取更新数据后的orderDetail对象/更新订单详情 查询订单详情 修改订单数据
OrderDetail orderDetail = returnUpdateOrderDetail(orderBasicInfo, data);
// 更新数据库
OrderTransactionDTO dto = new OrderTransactionDTO();
dto.setOrderBasicInfo(orderBasicInfo);
dto.setOrderDetail(orderDetail);
transactionService.doUpdateOrder(dto);
// 订单支付结算and退款, delay商户部分解冻并退款, 非delay商户全部解冻并退款
orderPaymentSettlementAndRefund(orderBasicInfo);
// 将卡/vin状态解锁
if (!StringUtils.equals("0000000000000000", data.getLogicCard())) {
cardStatusUnlocked(orderBasicInfo.getLogicCard());
}
// 如果是vin启动将启动锁定状态改为正常
if (StringUtils.equals(data.getTransactionIdentifier(), "05")) {
vinStatusUnlocked(data.getVinCode());
}
// 发送停止充电订阅消息
sendMsg(orderBasicInfo);
// 从redis中取出实时记录保存到表中
realTimeMonitorDataRedis2DB(orderBasicInfo.getTransactionCode(), orderBasicInfo.getOrderCode());
// TODO 如果该站点的停车场优惠券信息配置不为空,则需绑定一张优惠券
logger.info("结算订单end:{} OrderTransactionDTO:{}", orderBasicInfo.getOrderCode(), JSONObject.toJSONString(dto));
}
/**
* 卡状态解锁
*/
private void cardStatusUnlocked(String logicCard) {
try {
// 根据物理卡号查出当前为锁定状态的卡
PileAuthCard cardInfo = pileAuthCardService.selectSomeStatusCardInfo(CardStatusEnum.START_LOCK.getCode(), logicCard);
if (cardInfo != null) {
// 将此卡状态改为正常
cardInfo.setStatus(CardStatusEnum.NORMAL.getCode());
pileAuthCardService.updatePileAuthCard(cardInfo);
}
} catch (Exception e) {
logger.error("解锁卡状态 error,", e);
}
}
/**
* 解锁vin状态
*
* @param vinCode
*/
private void vinStatusUnlocked(String vinCode) {
try {
MemberPlateNumberRelation plateInfo = memberPlateNumberRelationService.getMemberPlateInfoByVinCode(vinCode);
if (plateInfo != null && (StringUtils.equals(plateInfo.getVinStatus(), "2"))) {
plateInfo.setVinStatus("1");
memberPlateNumberRelationService.updateMemberPlateNumberRelation(plateInfo);
}
} catch (Exception e) {
logger.error("解锁vin状态 error,", e);
}
}
// uniApp 发送停止充电订阅消息
private void sendMsg(OrderBasicInfo orderBasicInfo) {
try {
WechatSendMsgDTO wechatSendMsgDTO = new WechatSendMsgDTO();
wechatSendMsgDTO.setOrderCode(orderBasicInfo.getOrderCode());
Map<String, String> resultMap = wxAppletRemoteService.stopChargingSendMsg(wechatSendMsgDTO);
logger.info("小程序发送充电停止推送消息 result:{}", JSON.toJSONString(resultMap));
} catch (Exception e) {
logger.error("小程序发送充电停止推送消息 error", e);
}
}
/**
* 订单分账逻辑
* 订单结算完成就执行清分and退款
*/
private OrderSettleResult orderPaymentSettlementAndRefund(OrderBasicInfo orderBasicInfo) {
String merchantId = orderBasicInfo.getMerchantId();
String orderCode = orderBasicInfo.getOrderCode();
// 获取一级运营商信息
PileMerchantInfo merchantInfo = pileMerchantInfoService.getFirstLevelMerchantByMerchantId(merchantId);
if (merchantInfo == null) {
logger.info("订单分账逻辑-订单:{}, 查不到一级运营商信息", orderCode);
return null;
}
// 获取结算账户信息
AdapayMemberAccount adapayMemberAccount = adapayMemberAccountService.selectByMerchantId(merchantId);
if (adapayMemberAccount == null) {
logger.info("订单分账逻辑-订单:{}, 运营商id:{}, 没有配置结算账户信息", orderCode, merchantId);
return null;
}
try {
String payMode = orderBasicInfo.getPayMode();
if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue())) {
// 余额支付
balancePaymentOrderRefund(orderBasicInfo);
} else if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue())) {
// 微信支付
onlinePaymentOrderRefund(orderBasicInfo);
} else {
// 白名单支付
logger.info("订单:{}使用白名单支付,不进行退款处理", orderBasicInfo.getOrderCode());
}
} catch (Exception e) {
logger.error("订单退款逻辑异常orderCode:{}", orderBasicInfo.getOrderCode(), e);
}
return null;
}
/**
* 余额支付订单退款
*/
@Override
public void balancePayOrderRefund(OrderBasicInfo orderBasicInfo) {
public void balancePaymentOrderRefund(OrderBasicInfo orderBasicInfo) {
// 订单编号
String orderCode = orderBasicInfo.getOrderCode();
// 订单消费金额
BigDecimal orderAmount = orderBasicInfo.getOrderAmount();
// 查支付记录
List<OrderPayRecord> payRecordList = orderPayRecordService.getOrderPayRecordList(orderCode);
Map<String, OrderPayRecord> payRecordMap = payRecordList.stream()
.collect(Collectors.toMap(OrderPayRecord::getPayMode, Function.identity(), (k1, k2) -> k1));
// 取出本金支付金额
BigDecimal principalPay = null;
// 获取本金支付的记录
OrderPayRecord principalPayRecord = payRecordMap.get(Constants.ONE);
if (principalPayRecord != null) {
principalPay = principalPayRecord.getPayAmount();
}
// 计算需要退回的金额
Map<String, BigDecimal> returnAmountMap = calculateReturnAmount(principalPay, null, orderAmount);
logger.info("结算订单:{}, 剩余金额退回余额, 订单消费金额:{}, 本金支付金额:{}, 赠送支付金额:{}, 退回金额map:{}",
orderCode, orderAmount, principalPay, null, JSONObject.toJSONString(returnAmountMap));
// 需要退回本金的金额
BigDecimal returnPrincipal = returnAmountMap.get("returnPrincipal");
// 更新会员钱包/余额退回到钱包
UpdateMemberBalanceDTO updateMemberBalanceDTO = UpdateMemberBalanceDTO.builder()
.memberId(orderBasicInfo.getMemberId())
.type(MemberWalletEnum.TYPE_IN.getValue()) // 进账
.subType(MemberWalletEnum.SUBTYPE_ORDER_SETTLEMENT_REFUND.getValue()) // 订单结算退款
.updatePrincipalBalance(returnPrincipal)
.relatedOrderCode(orderCode)
.build();
memberBasicInfoService.updateMemberBalance(updateMemberBalanceDTO);
// 更新order_pay_record, 解冻部分
List<Map<String, Object>> list = calculateUnfreezeAmount(orderAmount, payRecordList);
for (Map<String, Object> map : list) {
String paymentId = (String) map.get("paymentId");
String unfreezeAmount = (String) map.get("unfreezeAmount");
memberAdapayRecordService.unfreezeAmount(paymentId, new BigDecimal(unfreezeAmount));
}
}
/**
@@ -174,6 +338,91 @@ public class DelayMerchantOrderLogic extends AbstractOrderLogic {
*/
@Override
public void onlinePaymentOrderRefund(OrderBasicInfo orderBasicInfo) {
// 订单编号
String orderCode = orderBasicInfo.getOrderCode();
// 需要退款的金额
BigDecimal refundAmount = orderBasicInfo.getRefundAmount();
// 微信退款逻辑
ApplyRefundDTO applyRefundDTO = new ApplyRefundDTO();
applyRefundDTO.setOrderCode(orderCode);
applyRefundDTO.setRefundType(Constants.ONE);
applyRefundDTO.setRefundAmount(refundAmount);
// 汇付退款需要一级运营商的小程序appId, 否则会退款失败
String wechatAppId = pileMerchantInfoService.queryAppIdByMerchantId(orderBasicInfo.getMerchantId());
if (StringUtils.isNotBlank(wechatAppId)) {
applyRefundDTO.setWechatAppId(wechatAppId);
}
this.refundOrderWithAdapay(applyRefundDTO);
}
/**
* 汇付支付-订单退款处理逻辑
* 汇付支付订单退款
*
* @param dto
*/
public void refundOrderWithAdapay(ApplyRefundDTO dto) {
logger.info("汇付支付订单:{}, 执行退款逻辑 param:{}", dto.getOrderCode(), JSON.toJSONString(dto));
// 查出来原来的支付信息
AdapayCallbackRecord callbackRecord = adapayCallbackRecordService.selectByOrderCode(dto.getOrderCode());
if (Objects.isNull(callbackRecord)) {
logger.error("汇付支付orderCode:{}, 订单退款处理逻辑, 查询订单微信支付记录为空!", dto.getOrderCode());
throw new BusinessException(ReturnCodeEnum.CODE_REFUND_ORDER_CALLBACK_RECORD_ERROR);
}
String paymentId = callbackRecord.getPaymentId();
// 判断支付金额和退款金额
BigDecimal refundAmount = dto.getRefundAmount();
BigDecimal payAmt = callbackRecord.getPayAmt();
if (refundAmount.compareTo(payAmt) > 0) {
logger.error("汇付支付订单号:{}, 退款金额:{}(元),大于付款金额{}(元), 抛出异常", dto.getOrderCode(), refundAmount, payAmt);
throw new BusinessException(ReturnCodeEnum.CODE_REFUND_ORDER_AMOUNT_ERROR);
}
BigDecimal refundAmt = null; // 交易退款金额
// 延迟分账未确认调撤销调撤销接口退款
PaymentReverseOperation operation = new PaymentReverseOperation();
operation.setPaymentId(paymentId);
operation.setReverseAmt(refundAmount);
operation.setMerchantKey(dto.getWechatAppId());
operation.setMemberId(dto.getMemberId());
operation.setScenarioType(ScenarioEnum.ORDER.getValue());
operation.setOrderCode(dto.getOrderCode());
PaymentReverseResponse response = adapayService.createPaymentReverseRequest(operation);
if (response != null && response.isNotFailed()) {
refundAmt = new BigDecimal(response.getReverse_amt());
memberAdapayRecordService.updateRefundAmountFromFreezeAmount(paymentId, refundAmt);
}
// 获取延时分账模式 延时分账的使用撤销方法退款,实时分账的使用退款方法
// String expend = callbackRecord.getExpend();
// JSONObject expendJsonObject = JSON.parseObject(expend);
// String payMode = expendJsonObject.getString("payMode");
// if (StringUtils.equalsIgnoreCase(payMode, Constants.ADAPAY_PAY_MODE_DELAY)) {
// // 延迟分账未确认调撤销调撤销接口退款
// PaymentReverseOperation operation = new PaymentReverseOperation();
// operation.setPaymentId(paymentId);
// operation.setReverseAmt(refundAmount);
// operation.setMerchantKey(dto.getWechatAppId());
// operation.setMemberId(dto.getMemberId());
// operation.setScenarioType(ScenarioEnum.ORDER.getValue());
// operation.setOrderCode(dto.getOrderCode());
// PaymentReverseResponse response = adapayService.createPaymentReverseRequest(operation);
// if (response != null && response.isNotFailed()) {
// refundAmt = new BigDecimal(response.getReverse_amt());
// memberAdapayRecordService.updateRefundAmountFromFreezeAmount(paymentId, refundAmt);
// }
// } else {
// // // 实时分账的调退款接口
// RefundResponse refundRequest = adapayService.createRefundRequest(paymentId, refundAmount,
// dto.getWechatAppId(), dto.getMemberId(), ScenarioEnum.ORDER.getValue(), dto.getOrderCode());
// if (refundRequest != null && refundRequest.isNotFailed()) {
// refundAmt = new BigDecimal(refundRequest.getRefund_amt());
// memberAdapayRecordService.unfreezeAmountAndUpdateSpendAmount(paymentId, payAmt, refundAmt);
// }
// }
}
}