diff --git a/jsowell-admin/src/test/java/SpringBootTestController.java b/jsowell-admin/src/test/java/SpringBootTestController.java index 66d38249d..67eac14c4 100644 --- a/jsowell-admin/src/test/java/SpringBootTestController.java +++ b/jsowell-admin/src/test/java/SpringBootTestController.java @@ -212,6 +212,46 @@ public class SpringBootTestController { @Autowired private MemberAdapayRecordService memberAdapayRecordService; + /** + * 测试多笔支付情况,解冻部分金额 + */ + @Test + public void calculateUnfreezeAmountTest() { + BigDecimal orderAmount = new BigDecimal("28"); + List payRecordList = Lists.newArrayList(); + // 第一笔支付记录 + JSONObject jsonObject = new JSONObject(); + jsonObject.put("paymentId", "1"); + jsonObject.put("amount", "10"); + OrderPayRecord build = OrderPayRecord.builder() + .payAmount(new BigDecimal("10")) + .deductionRecord(jsonObject.toJSONString()) + .build(); + payRecordList.add(build); + + // 第二笔支付记录 + JSONObject jsonObject2 = new JSONObject(); + jsonObject2.put("paymentId", "2"); + jsonObject2.put("amount", "10"); + OrderPayRecord build2 = OrderPayRecord.builder() + .payAmount(new BigDecimal("10")) + .deductionRecord(jsonObject2.toJSONString()) + .build(); + payRecordList.add(build2); + + // 第三笔支付记录 + JSONObject jsonObject3 = new JSONObject(); + jsonObject3.put("paymentId", "3"); + jsonObject3.put("amount", "10"); + OrderPayRecord build3 = OrderPayRecord.builder() + .payAmount(new BigDecimal("10")) + .deductionRecord(jsonObject3.toJSONString()) + .build(); + payRecordList.add(build3); + List> maps = orderBasicInfoService.calculateUnfreezeAmount(orderAmount, payRecordList); + System.out.println(maps); + } + @Test public void unfreezeAmountAndUpdateSpendAmountTest() { String paymentId = "123"; diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/domain/OrderPayRecord.java b/jsowell-pile/src/main/java/com/jsowell/pile/domain/OrderPayRecord.java index ff4985da8..3f34a485a 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/domain/OrderPayRecord.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/domain/OrderPayRecord.java @@ -1,12 +1,9 @@ package com.jsowell.pile.domain; +import lombok.*; + import java.math.BigDecimal; import java.util.Date; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; /** * 订单支付明细 @@ -29,6 +26,7 @@ public class OrderPayRecord { /** * 支付方式(1-本金余额支付;2-赠送余额支付;3-白名单支付;4-微信支付;5-支付宝支付) + * @see com.jsowell.common.enums.ykc.OrderPayRecordEnum */ private String payMode; @@ -49,6 +47,10 @@ public class OrderPayRecord { /** * 扣款记录 + * { + * "paymentId": "123123", + * "amount": "1.00" + * } */ private String deductionRecord; diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/IOrderBasicInfoService.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/IOrderBasicInfoService.java index d7a44d097..55bb94214 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/IOrderBasicInfoService.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/IOrderBasicInfoService.java @@ -5,10 +5,7 @@ import com.jsowell.adapay.response.PaymentReverseResponse; import com.jsowell.adapay.vo.OrderSettleResult; import com.jsowell.common.core.domain.ykc.RealTimeMonitorData; import com.jsowell.common.core.domain.ykc.TransactionRecordsData; -import com.jsowell.pile.domain.AdapayMemberAccount; -import com.jsowell.pile.domain.OrderBasicInfo; -import com.jsowell.pile.domain.OrderDetail; -import com.jsowell.pile.domain.SettleOrderReport; +import com.jsowell.pile.domain.*; import com.jsowell.pile.dto.*; import com.jsowell.pile.vo.base.MerchantOrderInfoVO; import com.jsowell.pile.vo.base.OrderAmountDetailVO; @@ -147,7 +144,9 @@ public interface IOrderBasicInfoService { List getListByMemberIdAndOrderStatus(String memberId, List orderStatusList, LocalDateTime dateTime, String stationId); - void orderSplittingOperations(AdapayMemberAccount adapayMemberAccount, List stationReportList); + List> calculateUnfreezeAmount(BigDecimal orderAmount, List payRecordList); + + void orderSplittingOperations(AdapayMemberAccount adapayMemberAccount, List stationReportList); void orderSplittingOperations(String merchantId, String tradeDate); diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/MemberAdapayRecordService.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/MemberAdapayRecordService.java index 07a5cab07..859e5a519 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/MemberAdapayRecordService.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/MemberAdapayRecordService.java @@ -38,6 +38,8 @@ public interface MemberAdapayRecordService{ void updateSpendAmount(String paymentId, BigDecimal amount); + void unfreezeAmount(String paymentId, BigDecimal unfreezeAmount); + void unfreezeAmountAndUpdateSpendAmount(String paymentId, BigDecimal unfreezeAmount, BigDecimal spendAmount); void updateRefundAmountFromFreezeAmount(String paymentId, BigDecimal refundAmount); diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/MemberAdapayRecordServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/MemberAdapayRecordServiceImpl.java index 0ae2e1b3e..cb0de28d7 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/MemberAdapayRecordServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/MemberAdapayRecordServiceImpl.java @@ -89,6 +89,14 @@ public class MemberAdapayRecordServiceImpl implements MemberAdapayRecordService commonUpdateAmountMethod(paymentId, spendAmount, null, null); } + /** + * 解冻金额 + */ + @Override + public void unfreezeAmount(String paymentId, BigDecimal unfreezeAmount) { + commonUpdateAmountMethod(paymentId, null, null, unfreezeAmount.negate()); + } + /** * 解冻金额并更新消费金额 * @param unfreezeAmount 解冻金额 diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java index ec691efd1..d5f3ad1ad 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java @@ -749,42 +749,46 @@ public class OrderBasicInfoServiceImpl implements IOrderBasicInfoService { return null; } - /* - 获取一级运营商的 延时分账设置 - 使用延时分账的一级运营商,需要 - - 未使用延时分账的一级运营商 - */ + // 获取一级运营商的 延时分账设置 String delayMode = merchantInfo.getDelayMode(); - if (StringUtils.equals(delayMode, Constants.ADAPAY_PAY_MODE_DELAY)) { - // 记账 冻结金额 - // freezeAmount(orderBasicInfo); + if (StringUtils.equals(delayMode, Constants.ONE)) { + /* + delay商户, 如果存在退款金额, 支付的钱部分解冻(也就是只解冻需要退款的部分), 剩下的钱继续冻结等待第二天凌晨分账 + */ + // 执行退款逻辑 + + delayMerchantOrderRefundLogic(orderBasicInfo, adapayMemberAccount, merchantInfo.getAppId()); + } else { + /* + 非delay商户, 支付的钱全部解冻后, 更新消费金额和退款金额(只有在线支付才退款, 余额支付退到余额) + */ + notDelayMerchantOrderRefundLogic(orderBasicInfo, adapayMemberAccount, merchantInfo.getAppId()); } - OrderSettleResult orderSettleResult = null; + // OrderSettleResult orderSettleResult = null; // 退款逻辑/需要退款的情况 - BigDecimal residue = orderBasicInfo.getRefundAmount(); - if (residue.compareTo(BigDecimal.ZERO) > 0) { - // 执行退款逻辑 - try { - String payMode = orderBasicInfo.getPayMode(); - if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue())) { - // 余额支付 - balancePaymentOrderRefundV2(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); - } - } + // BigDecimal residue = orderBasicInfo.getRefundAmount(); + // if (residue.compareTo(BigDecimal.ZERO) > 0) { + // // 执行退款逻辑 + // try { + // String payMode = orderBasicInfo.getPayMode(); + // if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue())) { + // // 余额支付 + // balancePaymentOrderRefundV2(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 orderSettleResult; + return null; } @@ -827,21 +831,33 @@ public class OrderBasicInfoServiceImpl implements IOrderBasicInfoService { } /** - * 延迟商家订单处理逻辑 + * 延迟商家订单退款处理逻辑 * 例如:举视以及下面的二级运营商 - * + * 因为在结算时还没有到分账的时间,先解冻需要退款的金额,并退款 * @param orderBasicInfo 订单信息 * @param adapayMemberAccount 汇付用户信息 * @param wechatAppId 小程序appId - * @return */ - private OrderSettleResult delayMerchantOrderProcessingLogic(OrderBasicInfo orderBasicInfo, AdapayMemberAccount adapayMemberAccount, String wechatAppId) { - - return null; + private void delayMerchantOrderRefundLogic(OrderBasicInfo orderBasicInfo, AdapayMemberAccount adapayMemberAccount, String wechatAppId) { + try { + String payMode = orderBasicInfo.getPayMode(); + if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue())) { + // 余额支付 + balancePaymentOrderRefundV2(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); + } } /** - * 不延迟商家订单处理逻辑 + * 不延迟商家订单退款处理逻辑 * 例如:希晓 * 相当于已经分账完成了 * @@ -850,7 +866,7 @@ public class OrderBasicInfoServiceImpl implements IOrderBasicInfoService { * @param wechatAppId 小程序appId * @return */ - private OrderSettleResult notDelayMerchantOrderProcessingLogic(OrderBasicInfo orderBasicInfo, AdapayMemberAccount adapayMemberAccount, String wechatAppId) { + private OrderSettleResult notDelayMerchantOrderRefundLogic(OrderBasicInfo orderBasicInfo, AdapayMemberAccount adapayMemberAccount, String wechatAppId) { return null; } @@ -1156,7 +1172,7 @@ public class OrderBasicInfoServiceImpl implements IOrderBasicInfoService { // 需要退回本金的金额 BigDecimal returnPrincipal = returnAmountMap.get("returnPrincipal"); - // 更新会员钱包 + // 更新会员钱包/余额退回到钱包 UpdateMemberBalanceDTO updateMemberBalanceDTO = UpdateMemberBalanceDTO.builder() .memberId(orderBasicInfo.getMemberId()) .type(MemberWalletEnum.TYPE_IN.getValue()) // 进账 @@ -1166,24 +1182,57 @@ public class OrderBasicInfoServiceImpl implements IOrderBasicInfoService { .build(); memberBasicInfoService.updateMemberBalance(updateMemberBalanceDTO); - // TODO 更新member_adapay_record - for (OrderPayRecord record : payRecordList) { - + // 更新order_pay_record, 解冻部分 + List> list = calculateUnfreezeAmount(orderAmount, payRecordList); + for (Map map : list) { + String paymentId = (String) map.get("paymentId"); + String unfreezeAmount = (String) map.get("unfreezeAmount"); + memberAdapayRecordService.unfreezeAmount(paymentId, new BigDecimal(unfreezeAmount)); } - - // 更新order_pay_record - // 更新订单支付记录 - // List updatePayRecordList = Lists.newArrayList(); - // if (returnPrincipal != null && principalPayRecord != null) { - // principalPayRecord.setRefundAmount(returnPrincipal); - // updatePayRecordList.add(principalPayRecord); - // } - // if (CollectionUtils.isNotEmpty(updatePayRecordList)) { - // orderPayRecordService.updateBatch(updatePayRecordList); - // } } + /** + * 计算解冻金额 + * @param orderAmount 订单消费金额 + * @param payRecordList 订单支付记录 + */ + @Override + public List> calculateUnfreezeAmount(BigDecimal orderAmount, List payRecordList) { + List> 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 amount = jsonObject.getBigDecimal("amount"); + 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 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 map = Maps.newHashMap(); + map.put("paymentId", paymentId); + map.put("unfreezeAmount", unfreezeAmount); + resultList.add(map); + break; + } + } + return resultList; + } /** * 订单分账逻辑