更改合单交易的逻辑,增加了内部配送费字段
This commit is contained in:
parent
fc4f4c408d
commit
d9dd08e6d8
@ -28,6 +28,8 @@ public class LklSeparateDTO implements java.io.Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// ================================ 基础金额属性 ================================
|
||||
|
||||
@ApiModelProperty(value = "分账总金额(分)")
|
||||
private Integer totalSeparateAmount;
|
||||
|
||||
@ -40,6 +42,7 @@ public class LklSeparateDTO implements java.io.Serializable {
|
||||
@ApiModelProperty(value = "配送费(分)")
|
||||
private Integer shippingFee;
|
||||
|
||||
// ================================ 分账比例属性 ================================
|
||||
|
||||
@ApiModelProperty(value = "拉卡拉分账比例(如 0.0025=0.25%)")
|
||||
private BigDecimal lklRatio;
|
||||
@ -56,6 +59,7 @@ public class LklSeparateDTO implements java.io.Serializable {
|
||||
@ApiModelProperty(value = "二级代理商分账比例(如 0.03=3%)")
|
||||
private BigDecimal agent2ndRatio;
|
||||
|
||||
// ================================ 分账金额结果属性 ================================
|
||||
|
||||
@ApiModelProperty(value = "拉卡拉分账金额(分)")
|
||||
private Integer lklAmount;
|
||||
@ -72,6 +76,23 @@ public class LklSeparateDTO implements java.io.Serializable {
|
||||
@ApiModelProperty(value = "二级代理商分账金额(分)")
|
||||
private Integer agent2ndAmount;
|
||||
|
||||
// ================================ 内部状态属性 ================================
|
||||
|
||||
/**
|
||||
* 分账计算方法类型
|
||||
* true表示基于总金额分账(calcOnTotalAmount方法被调用)
|
||||
* false表示基于可分账金额分账(calcOnCanAmount方法被调用)
|
||||
*/
|
||||
private boolean isBasedOnTotalAmount = false;
|
||||
|
||||
// ================================ 构造方法 ================================
|
||||
|
||||
public LklSeparateDTO() {
|
||||
// 默认构造函数
|
||||
}
|
||||
|
||||
// ================================ 公共方法 ================================
|
||||
|
||||
/**
|
||||
* 测试方法
|
||||
*/
|
||||
@ -81,14 +102,15 @@ public class LklSeparateDTO implements java.io.Serializable {
|
||||
// 临界点测试用例2: 小金额测试
|
||||
logger.info("\n临界点测试用例2 - 小金额测试:");
|
||||
LklSeparateDTO dto2 = new LklSeparateDTO();
|
||||
dto2.setTotalSeparateAmount(2);
|
||||
dto2.setTotalSeparateAmount(1);
|
||||
dto2.setShippingFee(0);
|
||||
dto2.setLklRatio(new BigDecimal("0.0025"));
|
||||
dto2.setMchRatio(new BigDecimal("0.96"));
|
||||
dto2.setPlatRatio(new BigDecimal("0.01"));
|
||||
dto2.setAgent1stRatio(new BigDecimal("0.01"));
|
||||
dto2.setAgent2ndRatio(new BigDecimal("0.04"));
|
||||
dto2.setRefCanSeparateAmount(8079); // 设置参考可分账金额
|
||||
|
||||
// dto2.setAgent1stRatio(new BigDecimal("0.01"));
|
||||
// dto2.setAgent2ndRatio(new BigDecimal("0.04"));
|
||||
// dto2.setRefCanSeparateAmount(8079); // 设置参考可分账金额
|
||||
|
||||
logger.info("测试参数: 总分账金额={}分, 配送费={}分, 拉卡拉比例={}, 商户比例={}, 平台比例={}",
|
||||
dto2.getTotalSeparateAmount(), dto2.getShippingFee(), dto2.getLklRatio(),
|
||||
@ -149,66 +171,6 @@ public class LklSeparateDTO implements java.io.Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将对象转换为JSON字符串格式
|
||||
*
|
||||
* @return 包含所有属性的JSON字符串
|
||||
*/
|
||||
public String toJSON() {
|
||||
StringBuilder json = new StringBuilder();
|
||||
json.append("{");
|
||||
|
||||
// 添加基本属性
|
||||
appendProperty(json, "totalSeparateAmount", totalSeparateAmount, true);
|
||||
appendProperty(json, "canSeparateAmount", canSeparateAmount, false);
|
||||
appendProperty(json, "refCanSeparateAmount", refCanSeparateAmount, false);
|
||||
appendProperty(json, "shippingFee", shippingFee, false);
|
||||
|
||||
// 添加比例属性
|
||||
appendProperty(json, "lklRatio", lklRatio, false);
|
||||
appendProperty(json, "mchRatio", mchRatio, false);
|
||||
appendProperty(json, "platRatio", platRatio, false);
|
||||
appendProperty(json, "agent1stRatio", agent1stRatio, false);
|
||||
appendProperty(json, "agent2ndRatio", agent2ndRatio, false);
|
||||
|
||||
// 添加金额属性
|
||||
appendProperty(json, "lklAmount", lklAmount, false);
|
||||
appendProperty(json, "mchAmount", mchAmount, false);
|
||||
appendProperty(json, "platAmount", platAmount, false);
|
||||
appendProperty(json, "agent1stAmount", agent1stAmount, false);
|
||||
appendProperty(json, "agent2ndAmount", agent2ndAmount, false);
|
||||
|
||||
// 移除最后的逗号并关闭JSON对象
|
||||
if (json.charAt(json.length() - 1) == ',') {
|
||||
json.setLength(json.length() - 1);
|
||||
}
|
||||
json.append("}");
|
||||
|
||||
return json.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 向JSON字符串中添加属性
|
||||
*
|
||||
* @param json StringBuilder对象
|
||||
* @param key 属性名
|
||||
* @param value 属性值
|
||||
* @param first 是否为第一个属性
|
||||
*/
|
||||
private void appendProperty(StringBuilder json, String key, Object value, boolean first) {
|
||||
if (!first) {
|
||||
json.append(",");
|
||||
}
|
||||
json.append("\"").append(key).append("\":");
|
||||
if (value == null) {
|
||||
json.append("null");
|
||||
} else if (value instanceof String) {
|
||||
json.append("\"").append(value).append("\"");
|
||||
} else {
|
||||
json.append(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 基于可分账金额的分账计算方法(默认)
|
||||
* <p>
|
||||
@ -223,6 +185,9 @@ public class LklSeparateDTO implements java.io.Serializable {
|
||||
* @return 分账结果是否成功
|
||||
*/
|
||||
public boolean calcOnCanAmount() {
|
||||
// 设置分账计算方法类型
|
||||
isBasedOnTotalAmount = false;
|
||||
|
||||
// 检查前提条件
|
||||
if (!validateInputs()) {
|
||||
return false;
|
||||
@ -274,6 +239,9 @@ public class LklSeparateDTO implements java.io.Serializable {
|
||||
* @return 分账结果是否成功
|
||||
*/
|
||||
public boolean calcOnTotalAmount() {
|
||||
// 设置分账计算方法类型
|
||||
isBasedOnTotalAmount = true;
|
||||
|
||||
// 检查前提条件
|
||||
if (!validateInputsForTotalAmount()) {
|
||||
return false;
|
||||
@ -311,6 +279,133 @@ public class LklSeparateDTO implements java.io.Serializable {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出具体的分账结果
|
||||
*
|
||||
* @return 分账结果字符串
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
int canSeparateAmount = getCanSeparateAmount();
|
||||
int totalSeparateAmount = getTotalSeparateAmount();
|
||||
|
||||
// 计算各分账方占总金额和可分账金额的百分比
|
||||
double lklRatioOfTotal = 0.0;
|
||||
double mchRatioOfTotal = 0.0;
|
||||
double platRatioOfTotal = 0.0;
|
||||
double agent1stRatioOfTotal = 0.0;
|
||||
double agent2ndRatioOfTotal = 0.0;
|
||||
double shippingFeeRatioOfTotal = 0.0;
|
||||
|
||||
double lklRatioOfAvailable = 0.0;
|
||||
double mchRatioOfAvailable = 0.0;
|
||||
double platRatioOfAvailable = 0.0;
|
||||
double agent1stRatioOfAvailable = 0.0;
|
||||
double agent2ndRatioOfAvailable = 0.0;
|
||||
double shippingFeeRatioOfAvailable = 0.0;
|
||||
|
||||
if (totalSeparateAmount > 0) {
|
||||
if (getLklAmount() != null) {
|
||||
lklRatioOfTotal = (double) getLklAmount() / totalSeparateAmount * 100;
|
||||
}
|
||||
if (getMchAmount() != null) {
|
||||
mchRatioOfTotal = (double) getMchAmount() / totalSeparateAmount * 100;
|
||||
}
|
||||
if (getPlatAmount() != null) {
|
||||
platRatioOfTotal = (double) getPlatAmount() / totalSeparateAmount * 100;
|
||||
}
|
||||
if (getAgent1stAmount() != null) {
|
||||
agent1stRatioOfTotal = (double) getAgent1stAmount() / totalSeparateAmount * 100;
|
||||
}
|
||||
if (getAgent2ndAmount() != null) {
|
||||
agent2ndRatioOfTotal = (double) getAgent2ndAmount() / totalSeparateAmount * 100;
|
||||
}
|
||||
if (getShippingFee() != null) {
|
||||
shippingFeeRatioOfTotal = (double) getShippingFee() / totalSeparateAmount * 100;
|
||||
}
|
||||
}
|
||||
|
||||
if (canSeparateAmount > 0) {
|
||||
if (getLklAmount() != null) {
|
||||
lklRatioOfAvailable = (double) getLklAmount() / canSeparateAmount * 100;
|
||||
}
|
||||
if (getMchAmount() != null) {
|
||||
mchRatioOfAvailable = (double) getMchAmount() / canSeparateAmount * 100;
|
||||
}
|
||||
if (getPlatAmount() != null) {
|
||||
platRatioOfAvailable = (double) getPlatAmount() / canSeparateAmount * 100;
|
||||
}
|
||||
if (getAgent1stAmount() != null) {
|
||||
agent1stRatioOfAvailable = (double) getAgent1stAmount() / canSeparateAmount * 100;
|
||||
}
|
||||
if (getAgent2ndAmount() != null) {
|
||||
agent2ndRatioOfAvailable = (double) getAgent2ndAmount() / canSeparateAmount * 100;
|
||||
}
|
||||
if (getShippingFee() != null) {
|
||||
shippingFeeRatioOfAvailable = (double) getShippingFee() / canSeparateAmount * 100;
|
||||
}
|
||||
}
|
||||
|
||||
String calculationMethod = isBasedOnTotalAmount ? "基于总交易额方式计算" : "基于可分账额方式计算";
|
||||
|
||||
return String.format("分账结果%s,总交易额=%d分, 可分账额=%d分, 拉卡拉手续费=%d分(%.2f%%/%.2f%%), 配送费=%d分(%.2f%%/%.2f%%), 商户=%d分(%.2f%%/%.2f%%), 平台=%d分(%.2f%%/%.2f%%), 一级代理商=%d分(%.2f%%/%.2f%%), 二级代理商=%d分(%.2f%%/%.2f%%)",
|
||||
calculationMethod,
|
||||
totalSeparateAmount,
|
||||
canSeparateAmount,
|
||||
getLklAmount() != null ? getLklAmount() : 0,
|
||||
lklRatioOfTotal, lklRatioOfAvailable,
|
||||
getShippingFee() != null ? getShippingFee() : 0,
|
||||
shippingFeeRatioOfTotal, shippingFeeRatioOfAvailable,
|
||||
getMchAmount() != null ? getMchAmount() : 0,
|
||||
mchRatioOfTotal, mchRatioOfAvailable,
|
||||
getPlatAmount() != null ? getPlatAmount() : 0,
|
||||
platRatioOfTotal, platRatioOfAvailable,
|
||||
getAgent1stAmount() != null ? getAgent1stAmount() : 0,
|
||||
agent1stRatioOfTotal, agent1stRatioOfAvailable,
|
||||
getAgent2ndAmount() != null ? getAgent2ndAmount() : 0,
|
||||
agent2ndRatioOfTotal, agent2ndRatioOfAvailable);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将对象转换为JSON字符串格式
|
||||
*
|
||||
* @return 包含所有属性的JSON字符串
|
||||
*/
|
||||
public String toJSON() {
|
||||
StringBuilder json = new StringBuilder();
|
||||
json.append("{");
|
||||
|
||||
// 添加基本属性
|
||||
appendProperty(json, "totalSeparateAmount", totalSeparateAmount, true);
|
||||
appendProperty(json, "canSeparateAmount", canSeparateAmount, false);
|
||||
appendProperty(json, "refCanSeparateAmount", refCanSeparateAmount, false);
|
||||
appendProperty(json, "shippingFee", shippingFee, false);
|
||||
|
||||
// 添加比例属性
|
||||
appendProperty(json, "lklRatio", lklRatio, false);
|
||||
appendProperty(json, "mchRatio", mchRatio, false);
|
||||
appendProperty(json, "platRatio", platRatio, false);
|
||||
appendProperty(json, "agent1stRatio", agent1stRatio, false);
|
||||
appendProperty(json, "agent2ndRatio", agent2ndRatio, false);
|
||||
|
||||
// 添加金额属性
|
||||
appendProperty(json, "lklAmount", lklAmount, false);
|
||||
appendProperty(json, "mchAmount", mchAmount, false);
|
||||
appendProperty(json, "platAmount", platAmount, false);
|
||||
appendProperty(json, "agent1stAmount", agent1stAmount, false);
|
||||
appendProperty(json, "agent2ndAmount", agent2ndAmount, false);
|
||||
|
||||
// 移除最后的逗号并关闭JSON对象
|
||||
if (json.charAt(json.length() - 1) == ',') {
|
||||
json.setLength(json.length() - 1);
|
||||
}
|
||||
json.append("}");
|
||||
|
||||
return json.toString();
|
||||
}
|
||||
|
||||
// ================================ 私有方法 ================================
|
||||
|
||||
/**
|
||||
* 验证基于可分账金额分账的输入参数
|
||||
*/
|
||||
@ -724,4 +819,25 @@ public class LklSeparateDTO implements java.io.Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 向JSON字符串中添加属性
|
||||
*
|
||||
* @param json StringBuilder对象
|
||||
* @param key 属性名
|
||||
* @param value 属性值
|
||||
* @param first 是否为第一个属性
|
||||
*/
|
||||
private void appendProperty(StringBuilder json, String key, Object value, boolean first) {
|
||||
if (!first) {
|
||||
json.append(",");
|
||||
}
|
||||
json.append("\"").append(key).append("\":");
|
||||
if (value == null) {
|
||||
json.append("null");
|
||||
} else if (value instanceof String) {
|
||||
json.append("\"").append(value).append("\"");
|
||||
} else {
|
||||
json.append(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -476,9 +476,11 @@ public class LakalaPayServiceImpl implements LakalaPayService {
|
||||
return new JSONObject().set("code", "BBS00001").set("msg", "拉卡拉合单交易失败:" + respBody.getStr("msg")).set("resp_data", null);
|
||||
}
|
||||
|
||||
log.info("[拉卡拉合单预下单] 支付成功,准备保存订单记录, orderId={}", orderId);
|
||||
log.info("[拉卡拉合单预下单] 支付成功,准备保存订单记录, orderId={} shopping_fee_inner={}", orderId, agentAmountInt);
|
||||
// 新增一个拉卡拉订单记录 shop_order_lkl 表
|
||||
JSONObject lklPayReqAndRespJson = new JSONObject();
|
||||
reqData.set("shopping_fee_inner", agentAmountInt); // 内部配送费
|
||||
|
||||
lklPayReqAndRespJson.put("req", reqData);
|
||||
lklPayReqAndRespJson.put("resp", respBody); // 返回原始响应数据
|
||||
|
||||
|
||||
@ -130,6 +130,10 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
|
||||
@Value("${lakala.delivery_term_no}")
|
||||
private String delivery_term_no;
|
||||
|
||||
// 最低内部配送费要求,单位(分)
|
||||
@Value("${lakala.min_delivery_fee_inner}")
|
||||
private Integer min_delivery_fee_inner;
|
||||
|
||||
/**
|
||||
* 获取支付密码
|
||||
*
|
||||
@ -676,9 +680,13 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
|
||||
cn.hutool.json.JSONObject lakalaRespJSON = new cn.hutool.json.JSONObject();
|
||||
|
||||
BigDecimal shippingFee = shopService.getOrderShippingFee(out_trade_no);
|
||||
logger.debug("预支付时,查到的订单{},运费:{}", out_trade_no, shippingFee);
|
||||
if (shippingFee == null || shippingFee.intValue() <= 0) {
|
||||
shippingFee = BigDecimal.ZERO;
|
||||
}
|
||||
logger.debug("预支付时,查到的订单{},商家配送费:{}元,平台最低配送费要求:{}分", out_trade_no, shippingFee, min_delivery_fee_inner);
|
||||
|
||||
if (shippingFee == null || shippingFee.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
// 平台最低配送费,单位(分)
|
||||
if (min_delivery_fee_inner == null || min_delivery_fee_inner.intValue() <= 0) {
|
||||
// 没有运费
|
||||
// 拉卡拉预支付返回参数
|
||||
lakalaRespJSON = lakalaPayService.lklTransPreOrder(shopStoreBase.getLkl_merchant_no(), shopStoreBase.getLkl_term_no(),
|
||||
@ -687,11 +695,12 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
|
||||
requestIP, trade_remark);
|
||||
} else { // 有运费的情况
|
||||
// 拉卡拉合单预支付返回参数
|
||||
// TODO RMK 这里只有固定一个运费代理商代收运费,以后代理商模块做好了,要动态读取店铺的运费代理商。
|
||||
// RMK 这里只有固定一个运费代理商代收运费,以后代理商模块做好了,要动态读取店铺的运费代理商。
|
||||
lakalaRespJSON = lakalaPayService.lklTransMergePreOrder(shopStoreBase.getLkl_merchant_no(), shopStoreBase.getLkl_term_no(),
|
||||
delivery_merchant_no, delivery_term_no, // 以后根据代理商动态分配
|
||||
appId, openId, storeIdStr, out_trade_no, subject, total_amt,
|
||||
Convert.toStr(shippingFee.multiply(BigDecimal.valueOf(100)).intValue()),
|
||||
// Convert.toStr(shippingFee.multiply(BigDecimal.valueOf(100)).intValue()),
|
||||
Convert.toStr(min_delivery_fee_inner),
|
||||
notifyUrl,
|
||||
requestIP, trade_remark);
|
||||
}
|
||||
|
||||
@ -127,6 +127,8 @@ lakala:
|
||||
lkl_platform_cer_path: payKey/lakala/dev/lkl_notify_cert_v2.cer
|
||||
# 机构代码
|
||||
org_code: 1
|
||||
#最低内部配送费要求,单位(分)
|
||||
min_delivery_fee_inner: 0
|
||||
#运费代理商商户号(深圳立挚)
|
||||
delivery_merchant_no: 822584059990FYP
|
||||
#运费代理商终端号码(深圳立挚),M0780629(B2B收银台) M0780798(专业化扫码)
|
||||
|
||||
@ -129,6 +129,8 @@ lakala:
|
||||
lkl_platform_cer_path: payKey/lakala/dev/lkl_notify_cert_v2.cer
|
||||
# 机构代码
|
||||
org_code: 1
|
||||
#最低内部配送费要求,单位(分)
|
||||
min_delivery_fee_inner: 0
|
||||
#运费代理商商户号(深圳立挚)
|
||||
delivery_merchant_no: 822584059990FYP
|
||||
#运费代理商终端号码(深圳立挚),M0780629(B2B收银台) M0780798(专业化扫码)
|
||||
|
||||
@ -151,6 +151,8 @@ lakala:
|
||||
lkl_platform_cer_path: payKey/lakala/prod/lkl_platform.cer
|
||||
#机构代码
|
||||
org_code: 980688
|
||||
#最低内部配送费要求,单位(分)
|
||||
min_delivery_fee_inner: 0
|
||||
#运费代理商商户号(深圳立挚)
|
||||
delivery_merchant_no: 822584059990FYP
|
||||
#运费代理商终端号码(深圳立挚),M0780629(B2B收银台) M0780798(专业化扫码)
|
||||
|
||||
@ -127,6 +127,8 @@ lakala:
|
||||
lkl_platform_cer_path: payKey/lakala/dev/lkl_notify_cert_v2.cer
|
||||
# 机构代码
|
||||
org_code: 1
|
||||
#最低内部配送费要求,单位(分)
|
||||
min_delivery_fee_inner: 0
|
||||
#运费代理商商户号(深圳立挚)
|
||||
delivery_merchant_no: 822584059990FYP
|
||||
#运费代理商终端号码(深圳立挚),M0780629(B2B收银台) M0780798(专业化扫码)
|
||||
|
||||
@ -127,6 +127,8 @@ lakala:
|
||||
lkl_platform_cer_path: payKey/lakala/dev/lkl_notify_cert_v2.cer
|
||||
# 机构代码
|
||||
org_code: 1
|
||||
#最低内部配送费要求,单位(分)
|
||||
min_delivery_fee_inner: 0
|
||||
#运费代理商商户号(深圳立挚)
|
||||
delivery_merchant_no: 822584059990FYP
|
||||
#运费代理商终端号码(深圳立挚),M0780629(B2B收银台) M0780798(专业化扫码)
|
||||
|
||||
@ -31,6 +31,7 @@ import com.suisung.mall.common.modules.lakala.*;
|
||||
import com.suisung.mall.common.modules.order.ShopOrderLkl;
|
||||
import com.suisung.mall.common.modules.store.ShopMchEntry;
|
||||
import com.suisung.mall.common.modules.store.ShopStoreBase;
|
||||
import com.suisung.mall.common.pojo.dto.LklSeparateDTO;
|
||||
import com.suisung.mall.common.service.impl.CommonService;
|
||||
import com.suisung.mall.common.utils.*;
|
||||
import com.suisung.mall.shop.lakala.service.*;
|
||||
@ -2120,15 +2121,6 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
* 该方法用于处理拉卡拉订单的分账逻辑。在用户确认收货后,系统会根据订单信息执行分账操作,
|
||||
* 将订单金额按照预设比例分配给平台、商家和代理商(如果存在)。
|
||||
* </p>
|
||||
* <p>
|
||||
* 分账操作流程:
|
||||
* 1. 参数校验和订单查询
|
||||
* 2. 检查订单状态(是否已确认收货)
|
||||
* 3. 检查是否已分账,避免重复处理
|
||||
* 4. 计算分账金额
|
||||
* 5. 构建分账请求并发送至拉卡拉
|
||||
* 6. 保存分账结果
|
||||
* </p>
|
||||
*
|
||||
* @param lklMerchantNo 拉卡拉商户号
|
||||
* @param receiveTradeNo 收货交易号(对应拉卡拉的trade_no)
|
||||
@ -2145,6 +2137,268 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
return Pair.of(false, "缺少必要参数");
|
||||
}
|
||||
|
||||
try {
|
||||
log.info("[分账操作] 开始处理分账请求, lklMerchantNo={}, receiveTradeNo={}, receiveLogNo={}",
|
||||
lklMerchantNo, receiveTradeNo, receiveLogNo);
|
||||
|
||||
// 2. 查询订单信息
|
||||
ShopOrderLkl shopOrderLkl = shopOrderLklService.getByLklMchNoAndReceiveTradeNoAndReceiveLogNo(lklMerchantNo, receiveTradeNo, receiveLogNo);
|
||||
if (shopOrderLkl == null) {
|
||||
log.warn("[分账操作] 失败:对账流水号[{}]不存在", receiveLogNo);
|
||||
return Pair.of(false, "订单不存在");
|
||||
}
|
||||
|
||||
String orderId = shopOrderLkl.getOrder_id();
|
||||
log.info("[分账操作] 开始处理订单[{}]的分账", orderId);
|
||||
|
||||
// 3. 检查订单状态
|
||||
if (!CommonConstant.Enable.equals(shopOrderLkl.getReceive_status())) {
|
||||
log.warn("[分账操作] 订单[{}]交易流水号[{}]未被确认收货,跳过处理", orderId, receiveTradeNo);
|
||||
return Pair.of(false, "订单未确认收货,暂无法分账");
|
||||
}
|
||||
|
||||
// 4. 检查分账状态,避免重复处理
|
||||
LklOrderSeparate existingSeparateRecord = lklOrderSeparateService.getByLogNoAndOutTradeNo(shopOrderLkl.getLkl_receive_log_no(), shopOrderLkl.getOut_separate_no());
|
||||
if (existingSeparateRecord != null) {
|
||||
String status = existingSeparateRecord.getStatus();
|
||||
if ("SUCCESS".equals(status)) {
|
||||
log.info("[分账操作] 订单[{}]交易对账流水号[{}]已完成分账,跳过处理", orderId, shopOrderLkl.getLkl_receive_log_no());
|
||||
return Pair.of(true, "订单已处理");
|
||||
}
|
||||
if ("PROCESSING".equals(status) || "ACCEPTED".equals(status)) {
|
||||
log.info("[分账操作] 订单[{}]交易对账流水号[{}]分账处理中或已受理,跳过处理", orderId, shopOrderLkl.getLkl_receive_log_no());
|
||||
return Pair.of(true, "订单已处理中或已受理");
|
||||
}
|
||||
} else {
|
||||
if (CommonConstant.Enable.equals(shopOrderLkl.getSeparate_status())) {
|
||||
log.warn("[分账操作] 订单[{}]交易流水号[{}]订单已分账,跳过处理", orderId, receiveTradeNo);
|
||||
return Pair.of(true, "订单已分账,请勿重复操作");
|
||||
}
|
||||
}
|
||||
|
||||
// 可分账金额
|
||||
Integer canSeparateAmt = null;
|
||||
// 5. 检查可分账余额
|
||||
Pair<String, String> mchCanSplitAmt = queryMchCanSplitAmt(lklMerchantNo, receiveLogNo, shopOrderLkl.getLkl_log_date());
|
||||
if (mchCanSplitAmt != null) {
|
||||
log.error("[分账操作] 查询可分账余额失败:lklMerchantNo={} logDate={} receiveLogNo={}", lklMerchantNo, shopOrderLkl.getLkl_log_date(), receiveLogNo);
|
||||
|
||||
// 可分账金额
|
||||
canSeparateAmt = Convert.toInt(mchCanSplitAmt.getSecond());
|
||||
if (canSeparateAmt == null || canSeparateAmt <= 0) {
|
||||
log.warn("[分账操作] lklMerchantNo={} receiveTradeNo={} receiveLogNo={} 查询拉卡拉返回的可分账金额={}分,系统将自动计算可分账金额",
|
||||
lklMerchantNo, receiveTradeNo, receiveLogNo, canSeparateAmt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 6. 获取订单分账相关参数
|
||||
String merchantNo = shopOrderLkl.getLkl_merchant_no();
|
||||
|
||||
// 获取商家分账比例并校验
|
||||
BigDecimal merchantSplitRatioRaw = shopOrderLkl.getSplit_ratio();
|
||||
boolean canSplitForMerchant = merchantSplitRatioRaw != null
|
||||
&& merchantSplitRatioRaw.compareTo(BigDecimal.ZERO) > 0
|
||||
&& merchantSplitRatioRaw.compareTo(new BigDecimal(100)) <= 0;
|
||||
if (!canSplitForMerchant) {
|
||||
log.error("[分账操作] 店铺[{}]商家分账比例[{}]不在(0-100]范围内,无法分账",
|
||||
shopOrderLkl.getStore_id(), merchantSplitRatioRaw);
|
||||
return Pair.of(false, "商家分账比例有误");
|
||||
}
|
||||
|
||||
// 计算商家分账比例(转换为小数)
|
||||
BigDecimal merchantSplitRatio = merchantSplitRatioRaw.divide(new BigDecimal(100));
|
||||
|
||||
// 获取分账平台接收方信息
|
||||
LklLedgerMerReceiverBind platformReceiver = lklLedgerMerReceiverBindService.getPlatformByMerCupNo(merchantNo);
|
||||
if (platformReceiver == null) {
|
||||
log.error("[分账操作] 店铺[{}]未绑定平台方接收账户,跳过分账", shopOrderLkl.getStore_id());
|
||||
return Pair.of(false, "平台方未绑定账户");
|
||||
}
|
||||
|
||||
// 获取代理商分账信息
|
||||
BigDecimal platformSplitRatio = BigDecimal.valueOf(0.01);
|
||||
BigDecimal distributorSplitRatio = BigDecimal.ZERO;
|
||||
|
||||
List<LklLedgerMerReceiverBind> distributorReceivers = lklLedgerMerReceiverBindService.selectDistributorByMerCupNo(merchantNo);
|
||||
if (distributorReceivers != null && !distributorReceivers.isEmpty()) {
|
||||
distributorSplitRatio = BigDecimal.valueOf(1).subtract(platformSplitRatio).subtract(merchantSplitRatio);
|
||||
log.debug("[分账操作] 检测到代理商存在,调整分账比例: 代理商比例={}, 平台比例={}", distributorSplitRatio, platformSplitRatio);
|
||||
}
|
||||
|
||||
// 内部配送费
|
||||
Integer shoppingFeeInner = CheckUtil.isEmpty(shopOrderLkl.getShopping_fee_inner()) ? 0 : shopOrderLkl.getShopping_fee_inner();
|
||||
BigDecimal wxFeeRatio = StrUtil.isEmpty(wxFee) ? BigDecimal.valueOf(0.0025) : new BigDecimal(wxFee).divide(BigDecimal.valueOf(100));
|
||||
|
||||
// 构建分账参数对象
|
||||
LklSeparateDTO lklSeparateDTO = new LklSeparateDTO();
|
||||
lklSeparateDTO.setTotalSeparateAmount(shopOrderLkl.getTotal_amt());
|
||||
lklSeparateDTO.setShippingFee(shoppingFeeInner);
|
||||
lklSeparateDTO.setLklRatio(wxFeeRatio); // 拉卡拉给的微信分账比例 0.0025 千分之2.5
|
||||
lklSeparateDTO.setMchRatio(merchantSplitRatio);
|
||||
lklSeparateDTO.setPlatRatio(platformSplitRatio);
|
||||
if (distributorSplitRatio.compareTo(BigDecimal.ZERO) > 0) { // 二级代理商参与分账
|
||||
lklSeparateDTO.setAgent2ndRatio(distributorSplitRatio);
|
||||
}
|
||||
lklSeparateDTO.setRefCanSeparateAmount(canSeparateAmt); // 拉卡拉实时返回的可分账金额
|
||||
|
||||
|
||||
// 分账方式:根据可分账金额分账
|
||||
if (!lklSeparateDTO.calcOnCanAmount()) {
|
||||
log.error("[分账操作] 分账系统评估各项参数,发现无法分账 {}", lklSeparateDTO);
|
||||
return Pair.of(false, "分账系统评估各项参数,发现无法分账");
|
||||
}
|
||||
|
||||
if (CheckUtil.isEmpty(canSeparateAmt)) {
|
||||
canSeparateAmt = lklSeparateDTO.getCanSeparateAmount();
|
||||
}
|
||||
|
||||
log.debug("[分账操作] 分账参数计算结果:{}", lklSeparateDTO);
|
||||
|
||||
// 更新分账计算结果
|
||||
shopOrderLkl.setSeparate_remark(lklSeparateDTO.toString());
|
||||
shopOrderLkl.setSplit_amt(canSeparateAmt);
|
||||
shopOrderLklService.updateById(shopOrderLkl);
|
||||
|
||||
// 分账金额校验
|
||||
if (canSeparateAmt <= 0) {
|
||||
String errorMsg = String.format("[分账操作] 店铺[%s]订单[%s]分账金额[%d]低于1分钱,跳过分账",
|
||||
shopOrderLkl.getStore_id(), orderId, canSeparateAmt);
|
||||
log.error(errorMsg);
|
||||
if (existingSeparateRecord != null) {
|
||||
lklOrderSeparateService.updateRemark(existingSeparateRecord.getId(), errorMsg);
|
||||
}
|
||||
return Pair.of(false, "订单分账金额低于1分钱");
|
||||
}
|
||||
|
||||
// 构建分账接收方列表
|
||||
List<V3SacsSeparateRecvDatas> recvDatas = new ArrayList<>();
|
||||
|
||||
Integer merchantAmount = lklSeparateDTO.getMchAmount();
|
||||
Integer platformAmount = lklSeparateDTO.getPlatAmount();
|
||||
Integer agentAmount = lklSeparateDTO.getAgent2ndAmount();
|
||||
|
||||
log.info("[分账操作] 金额计算结果:订单={}, 商户={}, 总金额={}分, 可分金额={}分, 商家比例={}, 商家分得={}分, 平台比例={}, 平台分得={}分, 代理商比例={}, 代理商分得={}分",
|
||||
orderId, merchantNo, shopOrderLkl.getTotal_amt(), canSeparateAmt, merchantSplitRatio, merchantAmount, platformSplitRatio, platformAmount, distributorSplitRatio, agentAmount);
|
||||
|
||||
// 构建分账接收方分账参数
|
||||
// 商家分账参数
|
||||
if (merchantAmount > 0) {
|
||||
V3SacsSeparateRecvDatas receiver = new V3SacsSeparateRecvDatas();
|
||||
receiver.setRecvMerchantNo(merchantNo);
|
||||
receiver.setSeparateValue(merchantAmount.toString());
|
||||
recvDatas.add(receiver);
|
||||
log.debug("[分账操作] 添加商家接收方: merchantNo={}, amount={}", merchantNo, merchantAmount);
|
||||
}
|
||||
|
||||
// 平台分账参数
|
||||
if (platformAmount > 0) {
|
||||
V3SacsSeparateRecvDatas receiver = new V3SacsSeparateRecvDatas();
|
||||
receiver.setRecvNo(platformReceiver.getReceiver_no());
|
||||
receiver.setSeparateValue(platformAmount.toString());
|
||||
recvDatas.add(receiver);
|
||||
log.debug("[分账操作] 添加平台接收方: receiverNo={}, amount={}", platformReceiver.getReceiver_no(), platformAmount);
|
||||
}
|
||||
|
||||
// 二级代理商(县级)分账参数
|
||||
if (agentAmount > 0 && distributorReceivers != null && !distributorReceivers.isEmpty()) {
|
||||
V3SacsSeparateRecvDatas receiver = new V3SacsSeparateRecvDatas();
|
||||
receiver.setRecvNo(distributorReceivers.get(0).getReceiver_no());
|
||||
receiver.setSeparateValue(agentAmount.toString());
|
||||
recvDatas.add(receiver);
|
||||
log.debug("[分账操作] 添加代理商接收方: receiverNo={}, amount={}", distributorReceivers.get(0).getReceiver_no(), agentAmount);
|
||||
}
|
||||
|
||||
// 初始化拉卡拉SDK
|
||||
log.debug("[分账操作] 初始化拉卡拉SDK");
|
||||
initLKLSDK();
|
||||
|
||||
// 构建分账请求对象
|
||||
V3SacsSeparateRequest separateRequest = new V3SacsSeparateRequest();
|
||||
separateRequest.setMerchantNo(merchantNo);
|
||||
separateRequest.setOutSeparateNo(shopOrderLkl.getOut_separate_no());
|
||||
separateRequest.setLogNo(shopOrderLkl.getLkl_receive_log_no()); // 使用确认收货流水号作为分账流水号
|
||||
separateRequest.setLogDate(shopOrderLkl.getLkl_log_date());
|
||||
separateRequest.setTotalAmt(canSeparateAmt.toString());
|
||||
separateRequest.setLklOrgNo(orgCode);
|
||||
separateRequest.setCalType("0"); // 0- 按照指定金额,1- 按照指定比例。默认 0
|
||||
separateRequest.setNotifyUrl(projectDomain + "/api/mobile/shop/lakala/sacs/separateNotify");
|
||||
separateRequest.setRecvDatas(recvDatas);
|
||||
|
||||
log.info("[分账操作] 分账接收方数量={}", recvDatas.size());
|
||||
log.debug("[分账操作] 请求详细参数: {}", JSONUtil.toJsonStr(separateRequest));
|
||||
|
||||
// 发送分账请求
|
||||
log.info("[分账操作] 向拉卡拉发送分账请求:订单={}, 商户={}, 分账流水号={}",
|
||||
orderId, merchantNo, shopOrderLkl.getLkl_receive_log_no());
|
||||
String response = LKLSDK.httpPost(separateRequest);
|
||||
|
||||
if (StrUtil.isBlank(response)) {
|
||||
String errorMsg = String.format("[分账操作] 拉卡拉无响应,订单=%s,商户=%s,分账流水号=%s",
|
||||
orderId, merchantNo, shopOrderLkl.getLkl_receive_log_no());
|
||||
shopOrderLklService.updateSeparateStatusByReceiveLogNo(shopOrderLkl.getLkl_receive_log_no(), CommonConstant.Sta_Separate_Fail, errorMsg);
|
||||
log.error(errorMsg);
|
||||
return Pair.of(false, "拉卡拉无响应");
|
||||
}
|
||||
|
||||
log.debug("[分账操作] 响应结果: {}", response);
|
||||
|
||||
// 解析响应结果
|
||||
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",
|
||||
orderId, merchantNo, shopOrderLkl.getLkl_receive_log_no(), response);
|
||||
shopOrderLklService.updateSeparateStatusByReceiveLogNo(shopOrderLkl.getLkl_receive_log_no(), CommonConstant.Sta_Separate_Fail, errorMsg);
|
||||
log.error(errorMsg);
|
||||
return Pair.of(false, "拉卡拉分账异常:[" + (respJson != null ? respJson.getStr("code") : "未知错误码") + "]" +
|
||||
(respJson != null ? respJson.getStr("msg") : "未知错误"));
|
||||
}
|
||||
|
||||
// 保存分账记录
|
||||
JSONObject respData = respJson.getJSONObject("resp_data");
|
||||
LklOrderSeparate separateRecord = new LklOrderSeparate();
|
||||
separateRecord.setSeparate_no(respData.getStr("separate_no"));
|
||||
separateRecord.setOut_separate_no(separateRequest.getOutSeparateNo());
|
||||
separateRecord.setMerchant_no(merchantNo);
|
||||
separateRecord.setLog_no(separateRequest.getLogNo());
|
||||
separateRecord.setLog_date(separateRequest.getLogDate());
|
||||
separateRecord.setOrder_id(shopOrderLkl.getOrder_id());
|
||||
separateRecord.setTotal_amt(separateRequest.getTotalAmt());
|
||||
separateRecord.setNotify_url(separateRequest.getNotifyUrl());
|
||||
separateRecord.setLkl_org_no(separateRequest.getLklOrgNo());
|
||||
separateRecord.setRecv_datas(JSONUtil.toJsonStr(separateRequest.getRecvDatas()));
|
||||
separateRecord.setStatus(respData.getStr("status"));
|
||||
separateRecord.setTotal_separate_value(canSeparateAmt);
|
||||
|
||||
if (lklOrderSeparateService.addOrUpdateByReceiverNo(separateRecord)) {
|
||||
log.info("[分账操作] 记录保存成功:订单={}, 分账单号={}, 状态={}, 分账流水号={}",
|
||||
orderId, separateRecord.getSeparate_no(), separateRecord.getStatus(), separateRecord.getLog_no());
|
||||
log.info("[分账操作] 结果:订单[{}] 订单分账已提交处理", orderId);
|
||||
return Pair.of(true, "订单分账已提交处理");
|
||||
} else {
|
||||
String errorMsg = String.format("[分账操作] 保存分账记录失败,订单=%s,分账单号=%s,分账流水号=%s",
|
||||
orderId, separateRecord.getSeparate_no(), separateRecord.getLog_no());
|
||||
log.error(errorMsg);
|
||||
lklOrderSeparateService.updateRemark(separateRecord.getLog_no(), separateRecord.getSeparate_no(), errorMsg);
|
||||
return Pair.of(false, "保存分账记录失败");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
String errorMsg = String.format("[分账操作] 系统异常,分账对账流水号=%s,错误=%s", receiveLogNo, e.getMessage());
|
||||
log.error(errorMsg, e);
|
||||
return Pair.of(false, "系统异常,请稍后重试");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Pair<Boolean, String> innerDoOrderSeparateByMerchantAndLogNoBak(String lklMerchantNo, String receiveTradeNo, String receiveLogNo) {
|
||||
// 1. 输入参数校验
|
||||
if (StrUtil.isBlank(lklMerchantNo) || StrUtil.isBlank(receiveTradeNo) || StrUtil.isBlank(receiveLogNo)) {
|
||||
log.warn("[分账操作] 参数校验失败:缺少必要参数, lklMerchantNo={}, receiveTradeNo={}, receiveLogNo={}",
|
||||
lklMerchantNo, receiveTradeNo, receiveLogNo);
|
||||
return Pair.of(false, "缺少必要参数");
|
||||
}
|
||||
|
||||
try {
|
||||
log.info("[分账操作] 开始处理分账请求, lklMerchantNo={}, receiveTradeNo={}, receiveLogNo={}",
|
||||
lklMerchantNo, receiveTradeNo, receiveLogNo);
|
||||
@ -2175,7 +2429,12 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
// 3. 检查是否已确认收货
|
||||
if (!CommonConstant.Enable.equals(shopOrderLkl.getReceive_status())) {
|
||||
log.warn("[分账操作] 订单[{}]交易流水号[{}]未被确认收货,跳过处理", orderId, receiveTradeNo);
|
||||
return Pair.of(false, "订单未确认收货");
|
||||
return Pair.of(false, "订单未确认收货,暂无法分账");
|
||||
}
|
||||
|
||||
if (CommonConstant.Enable.equals(shopOrderLkl.getSeparate_status())) {
|
||||
log.warn("[分账操作] 订单[{}]交易流水号[{}]未被确认收货,跳过处理", orderId, receiveTradeNo);
|
||||
return Pair.of(true, "订单已分账,请勿重复操作");
|
||||
}
|
||||
|
||||
// 4. 检查分账状态,避免重复处理
|
||||
@ -2363,6 +2622,8 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
return Pair.of(false, "保存分账记录失败");
|
||||
}
|
||||
|
||||
// 保存 shop_order_lkl 关键字段
|
||||
|
||||
String result = "订单分账已提交处理";
|
||||
log.info("[分账操作] 结果:订单[{}] {}", orderId, result);
|
||||
return Pair.of(true, result);
|
||||
@ -2383,7 +2644,6 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 拉卡拉分账结果通知处理
|
||||
* <p>
|
||||
|
||||
@ -135,7 +135,7 @@ public class ShopOrderLklServiceImpl extends BaseServiceImpl<ShopOrderLklMapper,
|
||||
log.debug("[拉卡拉订单保存] 开始处理拉卡拉支付请求和响应数据: {}", lklPayReqAndRespJson);
|
||||
try {
|
||||
// 获取请求体和响应体
|
||||
JSONObject reqDataJson = lklPayReqAndRespJson.getJSONObject("req");// 驼峰命名
|
||||
JSONObject reqDataJson = lklPayReqAndRespJson.getJSONObject("req");// 下划线命名
|
||||
JSONObject respDataJson = JSONUtil.parseObj(lklPayReqAndRespJson.getByPath("resp.resp_data"));// 下划线命名
|
||||
|
||||
if (reqDataJson == null || respDataJson == null) {
|
||||
@ -162,6 +162,12 @@ public class ShopOrderLklServiceImpl extends BaseServiceImpl<ShopOrderLklMapper,
|
||||
ShopOrderLkl record = new ShopOrderLkl();
|
||||
record.setOrder_id(orderId);
|
||||
String outSeparateNo = JsonUtil.getJsonValueSmart(reqDataJson, "outTradeNo");
|
||||
|
||||
// 平台最低内部配送费
|
||||
Integer shoppingFeeInner = Convert.toInt(JsonUtil.getJsonValueSmart(reqDataJson, "shopping_fee_inner"));
|
||||
if (shoppingFeeInner == null) {
|
||||
shoppingFeeInner = 0;
|
||||
}
|
||||
record.setOut_separate_no(outSeparateNo);
|
||||
log.debug("[拉卡拉订单保存] 设置订单ID和分离订单号: orderId={} outSeparateNo={}", orderId, outSeparateNo);
|
||||
|
||||
@ -178,6 +184,8 @@ public class ShopOrderLklServiceImpl extends BaseServiceImpl<ShopOrderLklMapper,
|
||||
// 关键数据:获取店铺ID,分账比例用到
|
||||
Integer storeId = shopOrderBase.getStore_id();
|
||||
record.setStore_id(Convert.toStr(storeId));
|
||||
//平台内部配送费
|
||||
record.setShopping_fee_inner(shoppingFeeInner);
|
||||
log.debug("[拉卡拉订单保存] 设置店铺ID: storeId={}", storeId);
|
||||
|
||||
// 运费和商家分账比例
|
||||
@ -185,7 +193,7 @@ public class ShopOrderLklServiceImpl extends BaseServiceImpl<ShopOrderLklMapper,
|
||||
if (shipperFee != null) {
|
||||
int shipperFeeInCents = shipperFee.multiply(BigDecimal.valueOf(100)).intValue(); // 运费,单位:分
|
||||
record.setShopping_fee(shipperFeeInCents);
|
||||
log.debug("[拉卡拉订单保存] 设置运费: 元={} 分={}", shipperFee, shipperFeeInCents);
|
||||
log.debug("[拉卡拉订单保存] 商家设置运费: 元={} 分={}", shipperFee, shipperFeeInCents);
|
||||
} else {
|
||||
log.debug("[拉卡拉订单保存] 未获取到运费信息");
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user