diff --git a/src/main/java/com/yn/bftl/thirdparty/modules/business/service/impl/SubaccountServiceImpl.java b/src/main/java/com/yn/bftl/thirdparty/modules/business/service/impl/SubaccountServiceImpl.java index c43594f..8eaea9b 100644 --- a/src/main/java/com/yn/bftl/thirdparty/modules/business/service/impl/SubaccountServiceImpl.java +++ b/src/main/java/com/yn/bftl/thirdparty/modules/business/service/impl/SubaccountServiceImpl.java @@ -674,45 +674,14 @@ @Override public void generateSubaccountByOrder(Long orderId) { - Order order = orderRepository.findById(orderId).orElse(null); + Order order = getOrderAndCheck(orderId); if (order == null) { - throw new YnceErrorException(YnceError.YNCE_204003); - } - // 判断订单是否在申请售后中 - if (order.getIsReturnRefund() || order.getIsRefund()) { - writeSeparateLog(String.format("[分账][生成][普通订单][%s],订单在售后中。", order.getSn())); return; } - // 判断是否当前订单所有的商品是否全部退货 - Optional orderItemOptional = order.getOrderItems().stream().filter(orderItem -> orderItem.getQuantity() > (orderItem.getReturnCount() + orderItem.getCloseCount())).findAny(); - if (BooleanUtils.isFalse(orderItemOptional.isPresent())) { - // 此订单下面的所有商品已全部退退货,不执行分账 - stopOrderSubaccount(order.getId()); - writeSeparateLog(String.format("[分账][生成][普通订单][%s],订单已退货,不执行分账。", order.getSn())); - return; - } - // 判断当前订单是否已经退款 - if (order.getPaymentStatus().equals(PaymentStatus.REFUNDED)) { - stopOrderSubaccount(order.getId()); - writeSeparateLog(String.format("[分账][生成][普通订单][%s],订单已退款,不执行分账。", order.getSn())); - return; - } + // 获取所有的退款单并判断退款结算单是否都生成 - List refundList = refundRepository.findAllByOrdersId(orderId); - if (CollectionUtils.isNotEmpty(refundList)) { - BigDecimal refundAmount = refundList.stream().map(Refund::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add); - // 获取退款结算单 - List statementList = statementRepository.findAllByOrdersIdAndStatementType(orderId, StatementType.AFTERSALES); - BigDecimal refundStatementAmount = statementList.stream().map(Statement::getStatementAmount).reduce(BigDecimal.ZERO, BigDecimal::add); - if (refundAmount.add(refundStatementAmount).compareTo(BigDecimal.ZERO) != 0) { - writeSeparateLog(String.format("[分账][生成][普通订单][%s],退款单金额与退款结算单金额不一致,分账失败。", order.getSn())); - return; - } - // 判断所有退款单状态是否都为已退款 - if(refundList.stream().filter(refund -> !RefundStatus.REFUNDED.equals(refund.getRefundStatus())).findAny().isPresent()){ - writeSeparateLog(String.format("[分账][生成][普通订单][%s],存在未完成退款的退款单,分账失败。", order.getSn())); - return; - } + if (checkRefundList(orderId, order)) { + return; } // 根据支付方式进行分账 @@ -731,6 +700,53 @@ } } + private boolean checkRefundList(Long orderId, Order order) { + List refundList = refundRepository.findAllByOrdersId(orderId); + if (CollectionUtils.isNotEmpty(refundList)) { + BigDecimal refundAmount = refundList.stream().map(Refund::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add); + // 获取退款结算单 + List statementList = statementRepository.findAllByOrdersIdAndStatementType(orderId, StatementType.AFTERSALES); + BigDecimal refundStatementAmount = statementList.stream().map(Statement::getStatementAmount).reduce(BigDecimal.ZERO, BigDecimal::add); + if (refundAmount.add(refundStatementAmount).compareTo(BigDecimal.ZERO) != 0) { + writeSeparateLog(String.format("[分账][生成][普通订单][%s],退款单金额与退款结算单金额不一致,分账失败。", order.getSn())); + return true; + } + // 判断所有退款单状态是否都为已退款 + if(refundList.stream().filter(refund -> !RefundStatus.REFUNDED.equals(refund.getRefundStatus())).findAny().isPresent()){ + writeSeparateLog(String.format("[分账][生成][普通订单][%s],存在未完成退款的退款单,分账失败。", order.getSn())); + return true; + } + } + return false; + } + + private Order getOrderAndCheck(Long orderId) { + Order order = orderRepository.findById(orderId).orElse(null); + if (order == null) { + throw new YnceErrorException(YnceError.YNCE_204003); + } + // 判断订单是否在申请售后中 + if (order.getIsReturnRefund() || order.getIsRefund()) { + writeSeparateLog(String.format("[分账][生成][普通订单][%s],订单在售后中。", order.getSn())); + return null; + } + // 判断是否当前订单所有的商品是否全部退货 + Optional orderItemOptional = order.getOrderItems().stream().filter(orderItem -> orderItem.getQuantity() > (orderItem.getReturnCount() + orderItem.getCloseCount())).findAny(); + if (BooleanUtils.isFalse(orderItemOptional.isPresent())) { + // 此订单下面的所有商品已全部退退货,不执行分账 + stopOrderSubaccount(order.getId()); + writeSeparateLog(String.format("[分账][生成][普通订单][%s],订单已退货,不执行分账。", order.getSn())); + return null; + } + // 判断当前订单是否已经退款 + if (order.getPaymentStatus().equals(PaymentStatus.REFUNDED)) { + stopOrderSubaccount(order.getId()); + writeSeparateLog(String.format("[分账][生成][普通订单][%s],订单已退款,不执行分账。", order.getSn())); + return null; + } + return order; + } + @Override public void handleSubaccount(SettlementCallbackVO settlementCallbackVO) { // 获取分账单 @@ -1572,11 +1588,8 @@ } OrderFeeRatio orderFeeRatio = orderFeeRatioRepository.findByOrdersId(order.getId()); // 获取所有结算单(包含正常订单和退货退款) - List allStatementList = statementRepository.findAllByOrdersId(order.getId()); - if (CollectionUtils.isEmpty(allStatementList)) { - writeSeparateLog(String.format("[分账][生成][普通订单][%s],未存在结算单。", order.getSn())); - return; - } + List allStatementList = getStatementList(order); + if (allStatementList == null) return; List chinaumsTransferParamsDTOList = new ArrayList<>(); // 正常订单结算单 List statementList = allStatementList.stream().filter(statement -> statement.getStatementType().equals(StatementType.NORMALORDER)).collect(Collectors.toList()); @@ -2270,24 +2283,17 @@ @Transactional(rollbackFor = YnceErrorException.class) public void confirmsCombinedGuaranteeByOrder(Order order) { // 获取银联支付单 - List chinaumsPaymentList = chinaumsPaymentRepository.findAllByOrdersId(order.getId()); - if (CollectionUtils.isEmpty(chinaumsPaymentList)) { - chinaumsPaymentList = walletService.handleChinaumsPayment(order); - } + List chinaumsPaymentList = getChinaumsPaymentList(order); // 获取分账记录 - List subaccountList = subaccountRepository.findAllByOrdersId(order.getId()); - if (checkIsSubaccountOrder(subaccountList)) { - // 更新订单已分账 - finishOrderSubaccount(order); - writeSeparateLog(String.format("[分账][生成][普通订单][%s],分账单已存在,更新订单为已分账", order.getSn())); + List subaccountList = getSubaccountListAndCheck(order); + if (subaccountList == null) { return; } // 获取订单费用比例 OrderFeeRatio orderFeeRatio = orderFeeRatioRepository.findByOrdersId(order.getId()); // 获取所有结算单(包含正常订单和退货退款) - List allStatementList = statementRepository.findAllByOrdersId(order.getId()); - if (CollectionUtils.isEmpty(allStatementList)) { - writeSeparateLog(String.format("[分账][生成][普通订单][%s],未存在结算单。", order.getSn())); + List allStatementList = getStatementList(order); + if (allStatementList == null) { return; } // 正常订单结算单 @@ -2295,132 +2301,75 @@ // 退货退款结算单 List allAfterSaleStatementList = allStatementList.stream().filter(statement -> statement.getStatementType().equals(StatementType.AFTERSALES)).collect(Collectors.toList()); // 平台服务费分账记录 - List platformSubaccountList = new ArrayList<>(); - for (Statement statement : statementList) { - // 退款金额 - BigDecimal refundAmount = BigDecimal.ZERO; - // 退款品牌授权费 - BigDecimal refundBrandAuthFee = BigDecimal.ZERO; - // 该结算单对应的退款结算单 - List afterSaleStatementList = allAfterSaleStatementList.stream().filter(filterStatement -> filterStatement.getSubaccountType().equals(statement.getSubaccountType())).collect(Collectors.toList()); - // 查询所有已完成售后单 - List afterSaleList = afterSaleRepository.findAllByOrdersIdAndAfterSaleStatus(order.getId(), AfterSaleStatus.COMPLETED); - if (CollectionUtils.isNotEmpty(afterSaleList)) { - if (CollectionUtils.isNotEmpty(afterSaleStatementList)) { - // 若存在退款结算单,需判断单据数量是否一致(注意,可能存在非售后途径退款) - if (afterSaleList.size() != afterSaleStatementList.stream().filter(filterStatement -> filterStatement.getAfterSale() != null).count()) { - writeSeparateLog(String.format("[分账][生成][普通订单][%s][结算单][%s],该分账单存在退款结算单未生成", order.getSn(), statement.getStatementNo())); - return; - } - for (Statement afterSaleStatement : afterSaleStatementList) { - refundAmount = refundAmount.add(afterSaleStatement.getStatementAmount()); - refundBrandAuthFee = refundBrandAuthFee.add(afterSaleStatement.getStatementLine().stream().map(StatementLine::getBrandAuthFee).reduce(BigDecimal.ZERO, BigDecimal::add)); - } - } else { - writeSeparateLog(String.format("[分账][生成][普通订单][%s][结算单][%s],该分账单存在退款结算单未生成", order.getSn(), statement.getStatementNo())); - return; - } - } else { - refundAmount = afterSaleStatementList.stream().map(Statement::getStatementAmount).reduce(BigDecimal.ZERO, BigDecimal::add); - } - - // 平台服务费 - BigDecimal platformServiceFee = BigDecimal.ZERO; - // 拼接平台服务费分账 - Subaccount platformSubaccount = calculationPlatformServiceFee(statement, orderFeeRatio, refundAmount.add(refundBrandAuthFee)); - if (platformSubaccount != null) { - platformSubaccountList.add(platformSubaccount); - platformServiceFee = platformSubaccount.getSubaccountAmount(); - } - // 判断是否存在分账记录(根据分账企业和分账类型) - Subaccount subaccount = subaccountList.stream().filter(filterSubaccount -> filterSubaccount.getSubaccountType().equals(statement.getSubaccountType()) && filterSubaccount.getCompany() != null && filterSubaccount.getCompany().equals(statement.getCompany())).findFirst().orElse(null); - if (subaccount != null) { - // 若是未分账则调用银联接口 - if (subaccount.getSubaccountState().equals(SubaccountState.SEPARATE_NOT)) { - handleSubaccountStatus(subaccount, false); - } - if (platformSubaccount != null && platformSubaccount.getSubaccountAmount().compareTo(subaccount.getPlatformServiceFee()) != 0) { - platformSubaccount.setSubaccountAmount(subaccount.getPlatformServiceFee()); - platformSubaccount.setSubaccountTotalAmount(subaccount.getPlatformServiceFee()); - } - continue; - } - // 获取银联支付单 - ChinaumsPayment chinaumsPayment = chinaumsPaymentList.stream().filter(filterChinaumsPayment -> filterChinaumsPayment.getRecvBalanceAcctId().equals(statement.getCompany().getWalletId()) && filterChinaumsPayment.getSubaccountType().equals(statement.getSubaccountType())).findFirst().orElse(null); - if (chinaumsPayment == null) { - continue; - } - subaccount = new Subaccount(); - subaccount.setSubaccountNo(sequenceUtil.getNextSequenceNumber("FZ")); - subaccount.setCompany(companyRepository.findById(statement.getCompany().getId()).orElse(null)); - - // 以订单进行分账,则分账金额 = 银联支付单金额 - if (statement.getSubaccountType().equals(SubaccountType.GOODS_COST)) { - // 货款分账金额 = 结算金额 + 退款金额 - 平台服务费 - 品牌授权费 + 退款品牌授权费 - BigDecimal brandAuthFee = statement.getStatementLine().stream().map(statementLine -> statementLine.getBrandAuthFee()).reduce(BigDecimal.ZERO, BigDecimal::add); - subaccount.setSubaccountAmount(statement.getStatementAmount().add(refundAmount).subtract(platformServiceFee).subtract(brandAuthFee).add(refundBrandAuthFee)); - if (CollectionUtils.isNotEmpty(orderFeeRatio.getOrderItemFeeRatio())) { - subaccount.setBrandAuthCostRatio(orderFeeRatio.getOrderItemFeeRatio().get(0).getBrandAuthCostRatio()); - } - subaccount.setBrandAuthFee(brandAuthFee.add(refundBrandAuthFee)); - } else { - // 其他分账金额 = 结算金额 - 退款金额 - 平台服务费 - subaccount.setSubaccountAmount(statement.getStatementAmount().add(refundAmount).subtract(platformServiceFee)); - } - - // 根据银联支付单和银联退款单计算最终分账金额 - List chinaumsRefundList = chinaumsRefundRepository.findAllByOrigTradeId(chinaumsPayment.getGuaranteePaymentId()); - BigDecimal chinaumsRefundAmount = chinaumsRefundList.stream().map(ChinaumsRefund::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add); - BigDecimal finallySubaccountAmount = chinaumsPayment.getAmount().subtract(chinaumsRefundAmount); - if (finallySubaccountAmount.compareTo(subaccount.getSubaccountAmount()) != 0) { - BigDecimal balance = subaccount.getSubaccountAmount().subtract(finallySubaccountAmount); - subaccount.setSubaccountAmount(finallySubaccountAmount); - // 计算实际服务费 - BigDecimal finallyPlatformSubaccountAmount = platformSubaccount.getSubaccountAmount().add(balance); - platformSubaccount.setSubaccountAmount(finallyPlatformSubaccountAmount); - platformSubaccount.setSubaccountTotalAmount(finallyPlatformSubaccountAmount); - } - - subaccount.getSubaccountAmount(); - subaccount.setSubaccountCostRatio(getCostRatio(statement, orderFeeRatio)); - subaccount.setSubaccountType(statement.getSubaccountType()); - subaccount.setOrders(statement.getOrders()); - subaccount.setSubaccountState(SubaccountState.SEPARATE_NOT); - subaccount.setSourceCompany(order.getBuyerCompany()); - subaccount.setSubaccountTotalAmount(statement.getStatementAmount().add(refundAmount)); - if (platformSubaccount != null) { - subaccount.setPlatformServiceCostRatio(platformSubaccount.getSubaccountCostRatio()); - subaccount.setPlatformServiceFee(platformSubaccount.getSubaccountAmount()); - } - - // 拼接扩展字段:商品信息 - ChinaumsGuaranteePayExtraDTO chinaumsGuaranteePayExtraDTO = new ChinaumsGuaranteePayExtraDTO(); - chinaumsGuaranteePayExtraDTO.setProductInfos(this.handleProductInfoByOrder(order.getOrderItems(), order.getSn(), order.getAmount(), subaccount.getSubaccountAmount())); - // 拼接分账确认请求参数 - ChinaumsGuaranteePayConfirmsDTO chinaumsGuaranteePayConfirmsDTO = ChinaumsGuaranteePayConfirmsDTO - .builder() - .outOrderNo(subaccount.getSubaccountNo()) - .guaranteePaymentId(chinaumsPayment.getGuaranteePaymentId()) - .sentAt(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").format(new Date())) - .amount(subaccount.getSubaccountAmount().multiply(new BigDecimal(100)).intValue()) - .extra(chinaumsGuaranteePayExtraDTO) - .build(); - ChinaumsGuaranteePayConfirmsVO chinaumsGuaranteePayConfirmsVO; - try { - chinaumsGuaranteePayConfirmsVO = walletService.paySettlement(chinaumsGuaranteePayConfirmsDTO); - } catch (Exception exception) { - // 当请求返回异常时,直接跳过 - platformSubaccountList.remove(platformSubaccount); - continue; - } - subaccount.setExternalId(chinaumsGuaranteePayConfirmsVO.getCombinedGuaranteeConfirmId()); - subaccountRepository.saveAndFlush(subaccount); - writeSeparateLog(String.format("[分账][生成][普通订单][%s],生成分账单成功,银联结算单号[%s]。", order.getSn(), chinaumsGuaranteePayConfirmsVO.getCombinedGuaranteeConfirmId())); - handleSubaccountStatus(subaccount, false); - subaccountList.add(subaccount); + List platformSubaccountList = getSubaccountListAndCheck(order, chinaumsPaymentList, subaccountList, orderFeeRatio, statementList, allAfterSaleStatementList); + if (platformSubaccountList == null) { + return; } // 品牌授权费 + setBrandInfoToSubAccountList(order, chinaumsPaymentList, subaccountList, orderFeeRatio, statementList, allAfterSaleStatementList, platformSubaccountList); + + // 获取已生成的平台服务费分账记录 + List platformSubaccounts = subaccountList.stream().filter(subaccount -> subaccount.getCompany() == null).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(platformSubaccounts)) { + for (Subaccount platformSubaccount : platformSubaccounts) { + handleSubaccountStatus(platformSubaccount, false); + } + } else if (CollectionUtils.isNotEmpty(platformSubaccountList)) { + // 获取平台电子账簿ID + String balanceAcctId = chinaumsUtil.getFeeBalanceAcctId(); + // 获取平台服务费对应的银联支付单 + ChinaumsPayment chinaumsPayment = chinaumsPaymentRepository.findFirstByOrdersIdAndRecvBalanceAcctId(order.getId(), balanceAcctId); + if (chinaumsPayment != null) { + // 平台服务费退款金额 + BigDecimal platformServiceFeeRefundAmount = BigDecimal.ZERO; + // 获取银联退款单 + List chinaumsRefundList = chinaumsRefundRepository.findAllByOrigTradeId(chinaumsPayment.getGuaranteePaymentId()); + if (CollectionUtils.isNotEmpty(chinaumsRefundList)) { + platformServiceFeeRefundAmount = chinaumsRefundList.stream().map(ChinaumsRefund::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add); + } + // 分账记录总平台服务费 + BigDecimal totalPlatformServiceFee = platformSubaccountList.stream().map(subaccount -> subaccount.getSubaccountAmount()).reduce(BigDecimal.ZERO, BigDecimal::add); + // 银联单据计算平台服务费 + BigDecimal platformServiceFee = chinaumsPayment.getAmount().subtract(platformServiceFeeRefundAmount); + // 只有当分账记录的金额和银联支付单金额一致才进行分账 + if (totalPlatformServiceFee.compareTo(platformServiceFee) == 0) { + ChinaumsGuaranteePayExtraDTO chinaumsGuaranteePayExtraDTO = new ChinaumsGuaranteePayExtraDTO(); + chinaumsGuaranteePayExtraDTO.setProductInfos(this.handleProductInfoByOrder(order.getOrderItems(), order.getSn(), order.getAmount(), platformServiceFee)); + // 拼接分账确认请求参数 + ChinaumsGuaranteePayConfirmsDTO chinaumsGuaranteePayConfirmsDTO = ChinaumsGuaranteePayConfirmsDTO + .builder() + .outOrderNo(platformSubaccountList.get(0).getSubaccountNo()) + .guaranteePaymentId(chinaumsPayment.getGuaranteePaymentId()) + .sentAt(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").format(new Date())) + .amount(platformServiceFee.multiply(new BigDecimal(100)).intValue()) + .extra(chinaumsGuaranteePayExtraDTO) + .build(); + try { + ChinaumsGuaranteePayConfirmsVO chinaumsGuaranteePayConfirmsVO = walletService.paySettlement(chinaumsGuaranteePayConfirmsDTO); + writeSeparateLog(String.format("[分账][生成][普通订单][%s],生成分账单成功,银联结算单号[%s]。", order.getSn(), chinaumsGuaranteePayConfirmsVO.getCombinedGuaranteeConfirmId())); + for (Subaccount subaccount : platformSubaccountList) { + subaccount.setExternalId(chinaumsGuaranteePayConfirmsVO.getCombinedGuaranteeConfirmId()); + subaccountRepository.saveAndFlush(subaccount); + handleSubaccountStatus(subaccount, false); + } + subaccountList.addAll(platformSubaccountList); + } catch (Exception exception) { + // TODO 当请求返回异常时,直接跳过 + } + } else { + writeSeparateLog(String.format("[分账][生成][普通订单][%s],生成分账单失败,分账金额与银联支付单剩余金额不一致。", order.getSn())); + } + } + } + // 判断是否分账结束 + if (checkIsSubaccountOrder(subaccountList)) { + // 更新订单已分账 + finishOrderSubaccount(order); + } + } + + private void setBrandInfoToSubAccountList(Order order, List chinaumsPaymentList, List subaccountList, OrderFeeRatio orderFeeRatio, List statementList, List allAfterSaleStatementList, List platformSubaccountList) { if (CollectionUtils.isNotEmpty(orderFeeRatio.getOrderItemFeeRatio())) { // 获取品牌授权费银联支付单 List brandAuthFeeChinaumsPaymentList = chinaumsPaymentList.stream().filter(filterChinaumsPayment -> filterChinaumsPayment.getSubaccountType().equals(SubaccountType.BRAND_AUTH_FEE)).collect(Collectors.toList()); @@ -2523,65 +2472,162 @@ } subaccountList.addAll(brandAuthFeeSubaccountList); } + } - // 获取已生成的平台服务费分账记录 - List platformSubaccounts = subaccountList.stream().filter(subaccount -> subaccount.getCompany() == null).collect(Collectors.toList()); - if (CollectionUtils.isNotEmpty(platformSubaccounts)) { - for (Subaccount platformSubaccount : platformSubaccounts) { - handleSubaccountStatus(platformSubaccount, false); - } - } else if (CollectionUtils.isNotEmpty(platformSubaccountList)) { - // 获取平台电子账簿ID - String balanceAcctId = chinaumsUtil.getFeeBalanceAcctId(); - // 获取平台服务费对应的银联支付单 - ChinaumsPayment chinaumsPayment = chinaumsPaymentRepository.findFirstByOrdersIdAndRecvBalanceAcctId(order.getId(), balanceAcctId); - if (chinaumsPayment != null) { - // 平台服务费退款金额 - BigDecimal platformServiceFeeRefundAmount = BigDecimal.ZERO; - // 获取银联退款单 - List chinaumsRefundList = chinaumsRefundRepository.findAllByOrigTradeId(chinaumsPayment.getGuaranteePaymentId()); - if (CollectionUtils.isNotEmpty(chinaumsRefundList)) { - platformServiceFeeRefundAmount = chinaumsRefundList.stream().map(ChinaumsRefund::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add); - } - // 分账记录总平台服务费 - BigDecimal totalPlatformServiceFee = platformSubaccountList.stream().map(subaccount -> subaccount.getSubaccountAmount()).reduce(BigDecimal.ZERO, BigDecimal::add); - // 银联单据计算平台服务费 - BigDecimal platformServiceFee = chinaumsPayment.getAmount().subtract(platformServiceFeeRefundAmount); - // 只有当分账记录的金额和银联支付单金额一致才进行分账 - if (totalPlatformServiceFee.compareTo(platformServiceFee) == 0) { - ChinaumsGuaranteePayExtraDTO chinaumsGuaranteePayExtraDTO = new ChinaumsGuaranteePayExtraDTO(); - chinaumsGuaranteePayExtraDTO.setProductInfos(this.handleProductInfoByOrder(order.getOrderItems(), order.getSn(), order.getAmount(), platformServiceFee)); - // 拼接分账确认请求参数 - ChinaumsGuaranteePayConfirmsDTO chinaumsGuaranteePayConfirmsDTO = ChinaumsGuaranteePayConfirmsDTO - .builder() - .outOrderNo(platformSubaccountList.get(0).getSubaccountNo()) - .guaranteePaymentId(chinaumsPayment.getGuaranteePaymentId()) - .sentAt(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").format(new Date())) - .amount(platformServiceFee.multiply(new BigDecimal(100)).intValue()) - .extra(chinaumsGuaranteePayExtraDTO) - .build(); - try { - ChinaumsGuaranteePayConfirmsVO chinaumsGuaranteePayConfirmsVO = walletService.paySettlement(chinaumsGuaranteePayConfirmsDTO); - writeSeparateLog(String.format("[分账][生成][普通订单][%s],生成分账单成功,银联结算单号[%s]。", order.getSn(), chinaumsGuaranteePayConfirmsVO.getCombinedGuaranteeConfirmId())); - for (Subaccount subaccount : platformSubaccountList) { - subaccount.setExternalId(chinaumsGuaranteePayConfirmsVO.getCombinedGuaranteeConfirmId()); - subaccountRepository.saveAndFlush(subaccount); - handleSubaccountStatus(subaccount, false); - } - subaccountList.addAll(platformSubaccountList); - } catch (Exception exception) { - // TODO 当请求返回异常时,直接跳过 + private List getSubaccountListAndCheck(Order order, List chinaumsPaymentList, List subaccountList, OrderFeeRatio orderFeeRatio, List statementList, List allAfterSaleStatementList) { + List platformSubaccountList = new ArrayList<>(); + for (Statement statement : statementList) { + // 退款金额 + BigDecimal refundAmount = BigDecimal.ZERO; + // 退款品牌授权费 + BigDecimal refundBrandAuthFee = BigDecimal.ZERO; + // 该结算单对应的退款结算单 + List afterSaleStatementList = allAfterSaleStatementList.stream().filter(filterStatement -> filterStatement.getSubaccountType().equals(statement.getSubaccountType())).collect(Collectors.toList()); + // 查询所有已完成售后单 + List afterSaleList = afterSaleRepository.findAllByOrdersIdAndAfterSaleStatus(order.getId(), AfterSaleStatus.COMPLETED); + if (CollectionUtils.isNotEmpty(afterSaleList)) { + if (CollectionUtils.isNotEmpty(afterSaleStatementList)) { + // 若存在退款结算单,需判断单据数量是否一致(注意,可能存在非售后途径退款) + if (afterSaleList.size() != afterSaleStatementList.stream().filter(filterStatement -> filterStatement.getAfterSale() != null).count()) { + writeSeparateLog(String.format("[分账][生成][普通订单][%s][结算单][%s],该分账单存在退款结算单未生成", order.getSn(), statement.getStatementNo())); + return null; + } + for (Statement afterSaleStatement : afterSaleStatementList) { + refundAmount = refundAmount.add(afterSaleStatement.getStatementAmount()); + refundBrandAuthFee = refundBrandAuthFee.add(afterSaleStatement.getStatementLine().stream().map(StatementLine::getBrandAuthFee).reduce(BigDecimal.ZERO, BigDecimal::add)); } } else { - writeSeparateLog(String.format("[分账][生成][普通订单][%s],生成分账单失败,分账金额与银联支付单剩余金额不一致。", order.getSn())); + writeSeparateLog(String.format("[分账][生成][普通订单][%s][结算单][%s],该分账单存在退款结算单未生成", order.getSn(), statement.getStatementNo())); + return null; } + } else { + refundAmount = afterSaleStatementList.stream().map(Statement::getStatementAmount).reduce(BigDecimal.ZERO, BigDecimal::add); } + + // 平台服务费 + BigDecimal platformServiceFee = BigDecimal.ZERO; + // 拼接平台服务费分账 + Subaccount platformSubaccount = calculationPlatformServiceFee(statement, orderFeeRatio, refundAmount.add(refundBrandAuthFee)); + if (platformSubaccount != null) { + platformSubaccountList.add(platformSubaccount); + platformServiceFee = platformSubaccount.getSubaccountAmount(); + } + // 判断是否存在分账记录(根据分账企业和分账类型) + Subaccount subaccount = subaccountList.stream().filter(filterSubaccount -> filterSubaccount.getSubaccountType().equals(statement.getSubaccountType()) && filterSubaccount.getCompany() != null && filterSubaccount.getCompany().equals(statement.getCompany())).findFirst().orElse(null); + if (subaccount != null) { + // 若是未分账则调用银联接口 + if (subaccount.getSubaccountState().equals(SubaccountState.SEPARATE_NOT)) { + handleSubaccountStatus(subaccount, false); + } + if (platformSubaccount != null && platformSubaccount.getSubaccountAmount().compareTo(subaccount.getPlatformServiceFee()) != 0) { + platformSubaccount.setSubaccountAmount(subaccount.getPlatformServiceFee()); + platformSubaccount.setSubaccountTotalAmount(subaccount.getPlatformServiceFee()); + } + continue; + } + // 获取银联支付单 + ChinaumsPayment chinaumsPayment = chinaumsPaymentList.stream().filter(filterChinaumsPayment -> filterChinaumsPayment.getRecvBalanceAcctId().equals(statement.getCompany().getWalletId()) && filterChinaumsPayment.getSubaccountType().equals(statement.getSubaccountType())).findFirst().orElse(null); + if (chinaumsPayment == null) { + continue; + } + subaccount = new Subaccount(); + subaccount.setSubaccountNo(sequenceUtil.getNextSequenceNumber("FZ")); + subaccount.setCompany(companyRepository.findById(statement.getCompany().getId()).orElse(null)); + + // 以订单进行分账,则分账金额 = 银联支付单金额 + if (statement.getSubaccountType().equals(SubaccountType.GOODS_COST)) { + // 货款分账金额 = 结算金额 + 退款金额 - 平台服务费 - 品牌授权费 + 退款品牌授权费 + BigDecimal brandAuthFee = statement.getStatementLine().stream().map(statementLine -> statementLine.getBrandAuthFee()).reduce(BigDecimal.ZERO, BigDecimal::add); + subaccount.setSubaccountAmount(statement.getStatementAmount().add(refundAmount).subtract(platformServiceFee).subtract(brandAuthFee).add(refundBrandAuthFee)); + if (CollectionUtils.isNotEmpty(orderFeeRatio.getOrderItemFeeRatio())) { + subaccount.setBrandAuthCostRatio(orderFeeRatio.getOrderItemFeeRatio().get(0).getBrandAuthCostRatio()); + } + subaccount.setBrandAuthFee(brandAuthFee.add(refundBrandAuthFee)); + } else { + // 其他分账金额 = 结算金额 - 退款金额 - 平台服务费 + subaccount.setSubaccountAmount(statement.getStatementAmount().add(refundAmount).subtract(platformServiceFee)); + } + + // 根据银联支付单和银联退款单计算最终分账金额 + List chinaumsRefundList = chinaumsRefundRepository.findAllByOrigTradeId(chinaumsPayment.getGuaranteePaymentId()); + BigDecimal chinaumsRefundAmount = chinaumsRefundList.stream().map(ChinaumsRefund::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add); + BigDecimal finallySubaccountAmount = chinaumsPayment.getAmount().subtract(chinaumsRefundAmount); + if (finallySubaccountAmount.compareTo(subaccount.getSubaccountAmount()) != 0) { + BigDecimal balance = subaccount.getSubaccountAmount().subtract(finallySubaccountAmount); + subaccount.setSubaccountAmount(finallySubaccountAmount); + // 计算实际服务费 + BigDecimal finallyPlatformSubaccountAmount = platformSubaccount.getSubaccountAmount().add(balance); + platformSubaccount.setSubaccountAmount(finallyPlatformSubaccountAmount); + platformSubaccount.setSubaccountTotalAmount(finallyPlatformSubaccountAmount); + } + + subaccount.getSubaccountAmount(); + subaccount.setSubaccountCostRatio(getCostRatio(statement, orderFeeRatio)); + subaccount.setSubaccountType(statement.getSubaccountType()); + subaccount.setOrders(statement.getOrders()); + subaccount.setSubaccountState(SubaccountState.SEPARATE_NOT); + subaccount.setSourceCompany(order.getBuyerCompany()); + subaccount.setSubaccountTotalAmount(statement.getStatementAmount().add(refundAmount)); + if (platformSubaccount != null) { + subaccount.setPlatformServiceCostRatio(platformSubaccount.getSubaccountCostRatio()); + subaccount.setPlatformServiceFee(platformSubaccount.getSubaccountAmount()); + } + + // 拼接扩展字段:商品信息 + ChinaumsGuaranteePayExtraDTO chinaumsGuaranteePayExtraDTO = new ChinaumsGuaranteePayExtraDTO(); + chinaumsGuaranteePayExtraDTO.setProductInfos(this.handleProductInfoByOrder(order.getOrderItems(), order.getSn(), order.getAmount(), subaccount.getSubaccountAmount())); + // 拼接分账确认请求参数 + ChinaumsGuaranteePayConfirmsDTO chinaumsGuaranteePayConfirmsDTO = ChinaumsGuaranteePayConfirmsDTO + .builder() + .outOrderNo(subaccount.getSubaccountNo()) + .guaranteePaymentId(chinaumsPayment.getGuaranteePaymentId()) + .sentAt(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").format(new Date())) + .amount(subaccount.getSubaccountAmount().multiply(new BigDecimal(100)).intValue()) + .extra(chinaumsGuaranteePayExtraDTO) + .build(); + ChinaumsGuaranteePayConfirmsVO chinaumsGuaranteePayConfirmsVO; + try { + chinaumsGuaranteePayConfirmsVO = walletService.paySettlement(chinaumsGuaranteePayConfirmsDTO); + } catch (Exception exception) { + // 当请求返回异常时,直接跳过 + platformSubaccountList.remove(platformSubaccount); + continue; + } + subaccount.setExternalId(chinaumsGuaranteePayConfirmsVO.getCombinedGuaranteeConfirmId()); + subaccountRepository.saveAndFlush(subaccount); + writeSeparateLog(String.format("[分账][生成][普通订单][%s],生成分账单成功,银联结算单号[%s]。", order.getSn(), chinaumsGuaranteePayConfirmsVO.getCombinedGuaranteeConfirmId())); + handleSubaccountStatus(subaccount, false); + subaccountList.add(subaccount); } - // 判断是否分账结束 + return platformSubaccountList; + } + + private List getStatementList(Order order) { + List allStatementList = statementRepository.findAllByOrdersId(order.getId()); + if (CollectionUtils.isEmpty(allStatementList)) { + writeSeparateLog(String.format("[分账][生成][普通订单][%s],未存在结算单。", order.getSn())); + return null; + } + return allStatementList; + } + + private List getChinaumsPaymentList(Order order) { + List chinaumsPaymentList = chinaumsPaymentRepository.findAllByOrdersId(order.getId()); + if (CollectionUtils.isEmpty(chinaumsPaymentList)) { + chinaumsPaymentList = walletService.handleChinaumsPayment(order); + } + return chinaumsPaymentList; + } + + private List getSubaccountListAndCheck(Order order) { + List subaccountList = subaccountRepository.findAllByOrdersId(order.getId()); if (checkIsSubaccountOrder(subaccountList)) { // 更新订单已分账 finishOrderSubaccount(order); + writeSeparateLog(String.format("[分账][生成][普通订单][%s],分账单已存在,更新订单为已分账", order.getSn())); + return null; } + return subaccountList; } /** @@ -2600,10 +2646,7 @@ // 获取订单费用比例 OrderFeeRatio orderFeeRatio = orderFeeRatioRepository.findByOrdersId(order.getId()); // 获取银联支付单 - List chinaumsPaymentList = chinaumsPaymentRepository.findAllByOrdersId(order.getId()); - if (CollectionUtils.isEmpty(chinaumsPaymentList)) { - chinaumsPaymentList = walletService.handleChinaumsPayment(order); - } + List chinaumsPaymentList = getChinaumsPaymentList(order); // 待确认平台服务费金额 BigDecimal toBeConfirmedServiceFeeAmount = BigDecimal.ZERO; // 查询平台服务费对应银联支付单