分账逻辑调整
This commit is contained in:
parent
235dfa19a8
commit
c5d5c9ee5b
@ -57,6 +57,7 @@ import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@ -1646,17 +1647,14 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
|
||||
// 6. 获取订单分账相关参数
|
||||
String merchantNo = shopOrderLkl.getLkl_merchant_no();
|
||||
|
||||
// 分账金额 = 应付总金额-运费(支付时已计算好)
|
||||
Integer splitAmount = shopOrderLkl.getSplit_amt();
|
||||
splitAmount = CheckUtil.isEmpty(splitAmount) ? 0 : splitAmount;
|
||||
Integer shoppingFee = shopOrderLkl.getShopping_fee();
|
||||
shoppingFee = CheckUtil.isEmpty(shoppingFee) ? 0 : shoppingFee;
|
||||
// 商家分账比例
|
||||
BigDecimal splitRatioMch = shopOrderLkl.getSplit_ratio();
|
||||
|
||||
// 7. 分账金额校验
|
||||
if (splitAmount <= 0) {
|
||||
String errorMsg = String.format("店铺[%s]订单[%s]分账金额[%d]异常,跳过分账",
|
||||
String errorMsg = String.format("店铺[%s]订单[%s]分账金额[%d]低于1分钱,跳过分账",
|
||||
shopOrderLkl.getStore_id(), orderId, splitAmount);
|
||||
log.error(errorMsg);
|
||||
errorMessages.append(errorMsg).append("; ");
|
||||
@ -1666,9 +1664,8 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 8. 获取分账接收方信息
|
||||
// 获取分账平台接收方信息
|
||||
LklLedgerMerReceiverBind platform = lklLedgerMerReceiverBindService.getPlatformByMerCupNo(merchantNo);
|
||||
List<LklLedgerMerReceiverBind> distributors = lklLedgerMerReceiverBindService.selectDistributorByMerCupNo(merchantNo);
|
||||
|
||||
if (platform == null) {
|
||||
String errorMsg = String.format("店铺[%s]未绑定平台方接收账户,跳过分账", shopOrderLkl.getStore_id());
|
||||
@ -1677,17 +1674,140 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 9. 判断是否可以分账(商家比例不超过100%)
|
||||
boolean canSplit = splitRatioMch != null && splitRatioMch.compareTo(new BigDecimal(100)) <= 0;
|
||||
if (!canSplit) {
|
||||
String errorMsg = String.format("店铺[%s]分账比例[%s]异常,无法分账",
|
||||
// 8. 构建分账接收方列表
|
||||
List<V3SacsSeparateRecvDatas> recvDatas = new ArrayList<>();
|
||||
|
||||
// 9. 获取商家分账比例并校验
|
||||
BigDecimal splitRatioMch = shopOrderLkl.getSplit_ratio();
|
||||
// 判断商家分账比例是否有效(必须在(0, 100]范围内)
|
||||
boolean canSplitForMch = splitRatioMch != null
|
||||
&& splitRatioMch.compareTo(BigDecimal.ZERO) > 0
|
||||
&& splitRatioMch.compareTo(new BigDecimal(100)) <= 0;
|
||||
if (!canSplitForMch) {
|
||||
String errorMsg = String.format("店铺[%s]商家分账比例[%s]不在(0-100]范围内,无法分账",
|
||||
shopOrderLkl.getStore_id(), splitRatioMch);
|
||||
log.error(errorMsg);
|
||||
errorMessages.append(errorMsg).append("; ");
|
||||
continue;
|
||||
} else {
|
||||
log.info("店铺[%s]商家分账比例[%s]在(0-100]范围内,可以分账",
|
||||
shopOrderLkl.getStore_id(), splitRatioMch);
|
||||
// 商家分账
|
||||
BigDecimal mchRatio = splitRatioMch.divide(new BigDecimal(100)); // 比如:94/100
|
||||
Integer mchSplitCent = new BigDecimal(splitAmount).multiply(mchRatio).intValue();
|
||||
if (mchSplitCent > 0) {
|
||||
V3SacsSeparateRecvDatas receiver = new V3SacsSeparateRecvDatas();
|
||||
receiver.setRecvMerchantNo(merchantNo);
|
||||
receiver.setSeparateValue(mchSplitCent.toString());
|
||||
recvDatas.add(receiver);
|
||||
|
||||
log.debug("商家分账:金额={}分,商户号={}", mchSplitCent, merchantNo);
|
||||
}
|
||||
}
|
||||
|
||||
// 10. 构建分账请求对象
|
||||
// 10. 计算平台和代理商分账金额
|
||||
Integer pdSplitAmount = 0;
|
||||
|
||||
// 计算平台+代理商的总比例=100-商家分账比例
|
||||
BigDecimal splitRatioNoMch = new BigDecimal(100).subtract(splitRatioMch);
|
||||
// 判断平台和代理商分账比例是否有效(必须在[0, 100)范围内)
|
||||
boolean canSplitForNoMch = splitRatioNoMch != null
|
||||
&& splitRatioNoMch.compareTo(BigDecimal.ZERO) > 0
|
||||
&& splitRatioNoMch.compareTo(new BigDecimal(100)) < 0;
|
||||
if (!canSplitForNoMch) {
|
||||
String errorMsg = String.format("店铺[%s]平台和代理商分账比例[%s]不在[0-100)范围内,无法分账",
|
||||
shopOrderLkl.getStore_id(), splitRatioNoMch);
|
||||
log.warn(errorMsg);
|
||||
} else {
|
||||
log.info("店铺[%s]平台和代理商分账比例[%s]在[0-100)范围内,可以分账",
|
||||
shopOrderLkl.getStore_id(), splitRatioNoMch);
|
||||
|
||||
// 分账代理商接收方信息
|
||||
List<LklLedgerMerReceiverBind> distributors = Collections.emptyList();
|
||||
|
||||
// 判断要不要分账给平台和代理商(分账金额太低或者没有平台、代理商,就不用分账)
|
||||
// 计算平台和代理商分账金额,小于1分钱,不进行平台和代理商分账
|
||||
BigDecimal notMchRatio = splitRatioNoMch.divide(new BigDecimal(100)); // 比如:6/100
|
||||
|
||||
// 平台方和代理商总计分账金额
|
||||
pdSplitAmount = notMchRatio.multiply(new BigDecimal(splitAmount)).intValue();
|
||||
if (pdSplitAmount > 1) {
|
||||
|
||||
// 11. 判断是否能分账给代理商
|
||||
// 如果有平台和代理商同时存在,平台分账剩余资金20%;代理商分账剩余资金80%;
|
||||
// 能分账给代理商的条件:总分账金额*0.2要大于1分钱
|
||||
boolean canSplitForDistributors = pdSplitAmount * 0.2 > 1;
|
||||
|
||||
// 12. 根据是否能分账给代理商决定分账模式
|
||||
if (canSplitForDistributors) {
|
||||
// 获取分账代理商接收方信息
|
||||
distributors = lklLedgerMerReceiverBindService.selectDistributorByMerCupNo(merchantNo);
|
||||
// 根据是否有代理商决定分账模式
|
||||
if (!CollectionUtils.isEmpty(distributors)) {
|
||||
// 平台+代理商分账模式
|
||||
log.debug("订单[{}]采用平台+代理商分账模式", orderId);
|
||||
|
||||
// 平台收取剩余资金20%手续费
|
||||
Integer platformValue = pdSplitAmount * 20 / 100;
|
||||
if (platformValue >= 1) {
|
||||
V3SacsSeparateRecvDatas receiver = new V3SacsSeparateRecvDatas();
|
||||
receiver.setRecvNo(platform.getReceiver_no());
|
||||
receiver.setSeparateValue(platformValue.toString());
|
||||
recvDatas.add(receiver);
|
||||
log.debug("平台分账:金额={}分,接收方={}", platformValue, platform.getReceiver_no());
|
||||
}
|
||||
|
||||
// 代理商分账(扣除平台20%后的剩余比例)
|
||||
Integer distributorValue = pdSplitAmount - platformValue;
|
||||
if (distributorValue >= 1) {
|
||||
V3SacsSeparateRecvDatas receiver = new V3SacsSeparateRecvDatas();
|
||||
receiver.setRecvNo(distributors.get(0).getReceiver_no());
|
||||
receiver.setSeparateValue(distributorValue.toString());
|
||||
recvDatas.add(receiver);
|
||||
log.debug("代理商分账:金额={}分,接收方={}", distributorValue, distributors.get(0).getReceiver_no());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 仅平台分账模式
|
||||
log.debug("订单[{}]采用仅平台分账模式", orderId);
|
||||
|
||||
if (pdSplitAmount > 1) {
|
||||
V3SacsSeparateRecvDatas receiver = new V3SacsSeparateRecvDatas();
|
||||
receiver.setRecvNo(platform.getReceiver_no());
|
||||
receiver.setSeparateValue(pdSplitAmount.toString());
|
||||
recvDatas.add(receiver);
|
||||
log.debug("平台分账:金额={}分,接收方={}", pdSplitAmount, platform.getReceiver_no());
|
||||
}
|
||||
}
|
||||
|
||||
// 13. 记录详细的分账信息,便于部署后排查问题
|
||||
if (log.isDebugEnabled()) {
|
||||
StringBuilder detailLog = new StringBuilder();
|
||||
detailLog.append("详细分账信息:");
|
||||
detailLog.append("订单ID=").append(shopOrderLkl.getOrder_id()).append(", ");
|
||||
detailLog.append("商户号=").append(merchantNo).append(", ");
|
||||
detailLog.append("分账流水号=").append(shopOrderLkl.getLkl_split_log_no()).append(", ");
|
||||
detailLog.append("外部分账单号=").append(shopOrderLkl.getOut_separate_no()).append(", ");
|
||||
detailLog.append("分账总金额=").append(splitAmount).append("分, ");
|
||||
detailLog.append("商家分账比例=").append(splitRatioMch).append("%, ");
|
||||
detailLog.append("平台接收方=").append(platform.getReceiver_no()).append(", ");
|
||||
|
||||
if (canSplitForDistributors && !CollectionUtils.isEmpty(distributors)) {
|
||||
detailLog.append("代理商接收方=[");
|
||||
for (int i = 0; i < distributors.size(); i++) {
|
||||
if (i > 0) detailLog.append(",");
|
||||
detailLog.append(distributors.get(i).getReceiver_no());
|
||||
}
|
||||
detailLog.append("], ");
|
||||
}
|
||||
|
||||
detailLog.append("分账接收方数量=").append(recvDatas.size());
|
||||
log.debug(detailLog.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 14. 构建分账请求对象
|
||||
V3SacsSeparateRequest request = new V3SacsSeparateRequest();
|
||||
request.setMerchantNo(merchantNo);
|
||||
request.setLogNo(shopOrderLkl.getLkl_split_log_no()); // 合单和非合单的流水号保存在此字段
|
||||
@ -1695,101 +1815,17 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
request.setOutSeparateNo(shopOrderLkl.getOut_separate_no());
|
||||
request.setTotalAmt(splitAmount.toString());
|
||||
request.setLklOrgNo(orgCode);
|
||||
request.setCalType("0");
|
||||
request.setCalType("0"); // 0- 按照指定金额,1- 按照指定比例。默认 0
|
||||
request.setNotifyUrl(projectDomain + "/api/mobile/shop/lakala/sacs/separateNotify");
|
||||
|
||||
// 11. 构建分账接收方列表
|
||||
List<V3SacsSeparateRecvDatas> recvDatas = new ArrayList<>();
|
||||
|
||||
Integer totalSeparateValue = 0;// 平台方和代理商总计分账金额
|
||||
// 12. 处理分账逻辑(如果可以分账)
|
||||
if (canSplit) {
|
||||
// 计算平台+代理商的总比例
|
||||
BigDecimal splitRatioNoMch = new BigDecimal(100).subtract(splitRatioMch);
|
||||
|
||||
// 13. 根据是否有代理商决定分账模式
|
||||
if (!CollectionUtils.isEmpty(distributors) && splitRatioNoMch.compareTo(BigDecimal.ONE) > 0) {
|
||||
// 平台+代理商分账模式
|
||||
log.debug("订单[{}]采用平台+代理商分账模式", orderId);
|
||||
|
||||
// 平台收取1%手续费
|
||||
BigDecimal platformValue = CommonUtil.DecimalRoundHalfDown(
|
||||
new BigDecimal(splitAmount).multiply(new BigDecimal("0.01")));
|
||||
if (platformValue.compareTo(BigDecimal.ZERO) > 0) {
|
||||
V3SacsSeparateRecvDatas receiver = new V3SacsSeparateRecvDatas();
|
||||
receiver.setRecvNo(platform.getReceiver_no());
|
||||
receiver.setSeparateValue(platformValue.toString());
|
||||
recvDatas.add(receiver);
|
||||
|
||||
totalSeparateValue += platformValue.intValue();
|
||||
log.debug("平台分账:金额={}分,接收方={}", platformValue, platform.getReceiver_no());
|
||||
}
|
||||
|
||||
// 代理商分账(扣除平台1%后的剩余比例)
|
||||
BigDecimal distributorRatio = splitRatioNoMch.subtract(new BigDecimal("1")).divide(new BigDecimal(100));
|
||||
BigDecimal distributorValue = CommonUtil.DecimalRoundHalfDown(
|
||||
new BigDecimal(splitAmount).multiply(distributorRatio));
|
||||
if (distributorValue.compareTo(BigDecimal.ZERO) > 0 && !distributors.isEmpty()) {
|
||||
V3SacsSeparateRecvDatas receiver = new V3SacsSeparateRecvDatas();
|
||||
receiver.setRecvNo(distributors.get(0).getReceiver_no());
|
||||
receiver.setSeparateValue(distributorValue.toString());
|
||||
recvDatas.add(receiver);
|
||||
|
||||
totalSeparateValue += distributorValue.intValue();
|
||||
log.debug("代理商分账:金额={}分,接收方={}", distributorValue, distributors.get(0).getReceiver_no());
|
||||
}
|
||||
} else {
|
||||
// 仅平台分账模式
|
||||
log.debug("订单[{}]采用仅平台分账模式", orderId);
|
||||
|
||||
BigDecimal platformRatio = splitRatioNoMch.divide(new BigDecimal(100));
|
||||
BigDecimal platformValue = new BigDecimal(splitAmount).multiply(platformRatio);
|
||||
if (platformValue.compareTo(BigDecimal.ZERO) > 0) {
|
||||
V3SacsSeparateRecvDatas receiver = new V3SacsSeparateRecvDatas();
|
||||
receiver.setRecvNo(platform.getReceiver_no());
|
||||
receiver.setSeparateValue(platformValue.toString());
|
||||
recvDatas.add(receiver);
|
||||
|
||||
totalSeparateValue += platformValue.intValue();
|
||||
log.debug("平台分账:金额={}分,接收方={}", platformValue, platform.getReceiver_no());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 14. 设置分账接收方列表
|
||||
// 15. 设置分账接收方列表
|
||||
request.setRecvDatas(recvDatas);
|
||||
log.info("分账请求参数: 订单={}, 商户={}, 金额={}分, 分账接收方数量={}",
|
||||
orderId, merchantNo, splitAmount, recvDatas.size());
|
||||
|
||||
// 记录详细的分账信息,便于部署后排查问题
|
||||
if (log.isDebugEnabled()) {
|
||||
StringBuilder detailLog = new StringBuilder();
|
||||
detailLog.append("详细分账信息:");
|
||||
detailLog.append("订单ID=").append(shopOrderLkl.getOrder_id()).append(", ");
|
||||
detailLog.append("商户号=").append(merchantNo).append(", ");
|
||||
detailLog.append("分账流水号=").append(shopOrderLkl.getLkl_split_log_no()).append(", ");
|
||||
detailLog.append("外部分账单号=").append(shopOrderLkl.getOut_separate_no()).append(", ");
|
||||
detailLog.append("分账总金额=").append(splitAmount).append("分, ");
|
||||
detailLog.append("运费=").append(shoppingFee).append("分, ");
|
||||
detailLog.append("商家分账比例=").append(splitRatioMch).append("%, ");
|
||||
detailLog.append("平台接收方=").append(platform.getReceiver_no()).append(", ");
|
||||
|
||||
if (!CollectionUtils.isEmpty(distributors)) {
|
||||
detailLog.append("代理商接收方=[");
|
||||
for (int i = 0; i < distributors.size(); i++) {
|
||||
if (i > 0) detailLog.append(",");
|
||||
detailLog.append(distributors.get(i).getReceiver_no());
|
||||
}
|
||||
detailLog.append("], ");
|
||||
}
|
||||
|
||||
detailLog.append("分账接收方数量=").append(recvDatas.size());
|
||||
log.debug(detailLog.toString());
|
||||
}
|
||||
|
||||
log.debug("分账请求详细参数: {}", JSONUtil.toJsonStr(request));
|
||||
|
||||
// 15. 发送分账请求
|
||||
// 16. 发送分账请求
|
||||
log.info("向拉卡拉发送分账请求:订单={}, 商户={}, 分账流水号={}",
|
||||
orderId, merchantNo, shopOrderLkl.getLkl_split_log_no());
|
||||
String response = LKLSDK.httpPost(request);
|
||||
@ -1803,7 +1839,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
|
||||
log.debug("分账响应结果: {}", response);
|
||||
|
||||
// 16. 解析响应结果
|
||||
// 17. 解析响应结果
|
||||
JSONObject respJson = JSONUtil.parseObj(response);
|
||||
if (respJson == null || !lklSacsSuccessCode.equals(respJson.getStr("code")) || respJson.getJSONObject("resp_data") == null) {
|
||||
String errorMsg = String.format("拉卡拉返回格式异常,订单=%s,商户=%s,分账流水号=%s,响应=%s,respJson=%s",
|
||||
@ -1813,7 +1849,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 17. 保存分账记录
|
||||
// 18. 保存分账记录
|
||||
JSONObject respData = respJson.getJSONObject("resp_data");
|
||||
LklOrderSeparate lklOrderSeparate = new LklOrderSeparate();
|
||||
lklOrderSeparate.setSeparate_no(respData.getStr("separate_no"));
|
||||
@ -1827,7 +1863,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
lklOrderSeparate.setLkl_org_no(request.getLklOrgNo());
|
||||
lklOrderSeparate.setRecv_datas(JSONUtil.toJsonStr(request.getRecvDatas()));
|
||||
lklOrderSeparate.setStatus(respData.getStr("status"));
|
||||
lklOrderSeparate.setTotal_separate_value(totalSeparateValue);
|
||||
lklOrderSeparate.setTotal_separate_value(pdSplitAmount);
|
||||
|
||||
try {
|
||||
if (lklOrderSeparateService.addOrUpdateByReceiverNo(lklOrderSeparate)) {
|
||||
@ -1852,7 +1888,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
}
|
||||
}
|
||||
|
||||
// 18. 返回最终处理结果
|
||||
// 19. 返回最终处理结果
|
||||
log.info("订单[{}]分账处理完成:总订单数={},成功处理数={}", orderId, totalCount, successCount);
|
||||
if (successCount == 0) {
|
||||
String result = "分账全部失败: " + errorMessages;
|
||||
|
||||
@ -41,7 +41,7 @@ public class RedisKeyExpiredListener implements MessageListener {
|
||||
String patternStr = pattern != null ? new String(pattern) : "无模式";
|
||||
|
||||
// 基本日志记录
|
||||
log.info("[Redis过期监听] 接收到Redis键过期事件. 过期键: {}, 订阅模式: {}", expiredKey, patternStr);
|
||||
log.debug("[Redis过期监听] 接收到Redis键过期事件. 过期键: {}, 订阅模式: {}", expiredKey, patternStr);
|
||||
|
||||
// 参数验证
|
||||
if (StrUtil.isBlank(expiredKey)) {
|
||||
@ -68,7 +68,7 @@ public class RedisKeyExpiredListener implements MessageListener {
|
||||
log.error("[Redis过期监听] 订单超时事件处理失败. 店铺ID: {}, 订单号: {}", args[0], args[1]);
|
||||
}
|
||||
} else {
|
||||
log.debug("[Redis过期监听] 忽略非订单超时事件. 过期键: {}", expiredKey);
|
||||
//log.debug("[Redis过期监听] 忽略非订单超时事件. 过期键: {}", expiredKey);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -488,6 +488,7 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
|
||||
ShopStoreSfOrder shopStoreSfOrder = JSONUtil.toBean(sfExpressApiRes.get("result").toString(), ShopStoreSfOrder.class);
|
||||
shopStoreSfOrder.setDev_id(sfCreateOrderReq.getDev_id());
|
||||
shopStoreSfOrder.setOrder_status(SFExpressConstant.Cons_CreatedOrder);
|
||||
shopStoreSfOrder.setShop_id(sfCreateOrderReq.getShop_id());
|
||||
shopStoreSfOrder.setStatus_desc("已创建顺丰同城订单");
|
||||
|
||||
// 下单成功,保存顺丰同城订单记录到 shop_store_sf_order 表里
|
||||
|
||||
Loading…
Reference in New Issue
Block a user