增加确认收货通知 逻辑
This commit is contained in:
parent
ad7f89cb42
commit
6c479e744a
@ -0,0 +1,42 @@
|
||||
package com.suisung.mall.common.modules.lakala;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 拉卡拉确认收货通知数据日志
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@TableName("lkl_receive_notify_log")
|
||||
@ApiModel(value = "拉卡拉确认收货通知数据日志", description = "拉卡拉确认收货通知数据日志")
|
||||
public class LklReceiveNotifyLog {
|
||||
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
@ApiModelProperty(value = "自增 Id", example = "1")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "订单Id")
|
||||
private String orderId = "";
|
||||
|
||||
@ApiModelProperty(value = "通知 JSON 响应数据")
|
||||
private String respJson;
|
||||
|
||||
@ApiModelProperty(value = "使用状态:1-被使用过;2-未被使用;")
|
||||
private Integer status = 2;
|
||||
|
||||
@ApiModelProperty(value = "创建时间")
|
||||
private Date createdAt;
|
||||
|
||||
@ApiModelProperty(value = "更新时间")
|
||||
private Date updatedAt;
|
||||
}
|
||||
@ -2,6 +2,7 @@ package com.suisung.mall.common.pojo.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.util.Pair;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
@ -29,10 +30,11 @@ import java.math.RoundingMode;
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Slf4j
|
||||
public class LklSeparateWithTotalAmountDTO {
|
||||
|
||||
// 常量定义
|
||||
private static final BigDecimal MCH_RATIO_THRESHOLD = new BigDecimal("0.2");
|
||||
private static final BigDecimal MCH_RATIO_THRESHOLD = BigDecimal.valueOf(0.2);
|
||||
|
||||
// 基础金额属性
|
||||
private Integer totalSeparateAmount; // 分账总金额(分)
|
||||
@ -41,7 +43,7 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
private Integer shippingFee; // 配送费(分)
|
||||
|
||||
// 分账比例属性
|
||||
private BigDecimal lklRatio; // 拉卡拉分账比例(如 0.0025=0.25%)
|
||||
private BigDecimal lklRatio; // 拉卡拉分账比例(如 0.0025=0.025%)
|
||||
private BigDecimal mchRatio; // 商户分账比例(如 0.96=96%)
|
||||
private BigDecimal platRatio; // 平台分账比例(如 0.01=1%)
|
||||
private BigDecimal agent1stRatio; // 一级代理商分账比例(如 0.01=1%)
|
||||
@ -53,6 +55,7 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
private Integer platAmount; // 平台分账金额(分)
|
||||
private Integer agent1stAmount; // 一级代理商分账金额(分)
|
||||
private Integer agent2ndAmount; // 二级代理商分账金额(分)
|
||||
private String errMsg; // 错误信息字段
|
||||
|
||||
/**
|
||||
* 测试方法
|
||||
@ -62,26 +65,75 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
// 测试用例1: 所有参与方都参与分账(符合比例要求)
|
||||
System.out.println("=== 测试用例1: 所有参与方都参与分账 ===");
|
||||
LklSeparateWithTotalAmountDTO dto1 = new LklSeparateWithTotalAmountDTO();
|
||||
dto1.setTotalSeparateAmount(1696); // 总金额100元(10000分)
|
||||
dto1.setTotalSeparateAmount(800); // 总金额16.96元(1696分)
|
||||
dto1.setShippingFee(500);
|
||||
// dto1.setRefCanSeparateAmount(1496);
|
||||
dto1.setLklRatio(new BigDecimal("0.0025")); // 拉卡拉分账比例0.25%
|
||||
dto1.setMchRatio(new BigDecimal("0.96")); // 商家分账比例94.75%
|
||||
dto1.setPlatRatio(new BigDecimal("0.04")); // 平台分账比例1%
|
||||
// dto1.setAgent2ndRatio(new BigDecimal("0.04")); // 二级代理商分账比例4%
|
||||
// dto1.setAgent1stRatio(new BigDecimal("0.01")); // 一级代理商分账比例1%
|
||||
dto1.setLklRatio(BigDecimal.valueOf(0.0025)); // 拉卡拉分账比例0.25%
|
||||
dto1.setMchRatio(BigDecimal.valueOf(0.96)); // 商家分账比例94.75%
|
||||
dto1.setPlatRatio(BigDecimal.valueOf(0.04)); // 平台分账比例1%
|
||||
// dto1.setAgent2ndRatio(BigDecimal.valueOf(0.04)); // 二级代理商分账比例4%
|
||||
// dto1.setAgent1stRatio(BigDecimal.valueOf(0.01)); // 一级代理商分账比例1%
|
||||
|
||||
Pair<Boolean, LklSeparateWithTotalAmountDTO> result = dto1.calculateSeparateAmount();
|
||||
if (result.getFirst()) {
|
||||
SeparateResult result = dto1.calculateSeparateAmount();
|
||||
if (result.getIsSuccess()) {
|
||||
System.out.println("分账计算成功:");
|
||||
System.out.println(result.getSecond());
|
||||
System.out.println(result.getData());
|
||||
System.out.println("JSON格式输出:");
|
||||
System.out.println(result.getSecond().toJSON());
|
||||
System.out.println(result.getData().toJSON());
|
||||
} else {
|
||||
System.out.println("分账计算失败");
|
||||
if (result.getSecond() != null) {
|
||||
if (result.getErrMsg() != null) {
|
||||
System.out.println("部分结果:");
|
||||
System.out.println(result.getSecond());
|
||||
System.out.println(result.getErrMsg());
|
||||
// 输出错误信息
|
||||
if (result.getErrMsg() != null && !result.getErrMsg().isEmpty()) {
|
||||
System.out.println("错误信息: " + result.getErrMsg());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 测试用例2: 商家分账比例过低的情况
|
||||
System.out.println("\n=== 测试用例2: 商家分账比例过低 ===");
|
||||
LklSeparateWithTotalAmountDTO dto2 = new LklSeparateWithTotalAmountDTO();
|
||||
dto2.setTotalSeparateAmount(10000); // 总金额100元(10000分)
|
||||
dto2.setLklRatio(BigDecimal.valueOf(0.0025)); // 拉卡拉分账比例0.25%
|
||||
dto2.setMchRatio(BigDecimal.valueOf(0.1)); // 商家分账比例过低(10%)
|
||||
dto2.setPlatRatio(BigDecimal.valueOf(0.04)); // 平台分账比例4%
|
||||
|
||||
SeparateResult result2 = dto2.calculateSeparateAmount();
|
||||
if (result2.getIsSuccess()) {
|
||||
System.out.println("分账计算成功:");
|
||||
System.out.println(result2.getData());
|
||||
} else {
|
||||
System.out.println("分账计算失败");
|
||||
if (result2.getData() != null) {
|
||||
System.out.println("部分结果:");
|
||||
System.out.println(result2.getData());
|
||||
// 输出错误信息
|
||||
if (result2.getErrMsg() != null && !result2.getErrMsg().isEmpty()) {
|
||||
System.out.println("错误信息: " + result2.getErrMsg());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 测试用例3: 使用calculateSeparateAmountWithResult方法获取SeparateResult结果
|
||||
System.out.println("\n=== 测试用例3: 使用calculateSeparateAmountWithResult方法获取SeparateResult结果 ===");
|
||||
LklSeparateWithTotalAmountDTO dto3 = new LklSeparateWithTotalAmountDTO();
|
||||
dto3.setTotalSeparateAmount(10000); // 总金额100元(10000分)
|
||||
dto3.setLklRatio(BigDecimal.valueOf(0.0025)); // 拉卡拉分账比例0.25%
|
||||
dto3.setMchRatio(BigDecimal.valueOf(0.8)); // 商家分账比例80%
|
||||
dto3.setPlatRatio(BigDecimal.valueOf(0.04)); // 平台分账比例4%
|
||||
|
||||
LklSeparateWithTotalAmountDTO.SeparateResult separateResult = dto3.calculateSeparateAmountWithResult();
|
||||
|
||||
if (separateResult.getIsSuccess()) {
|
||||
System.out.println("分账计算成功:");
|
||||
System.out.println(separateResult.getData());
|
||||
} else {
|
||||
System.out.println("分账计算失败: " + separateResult.getErrMsg());
|
||||
if (separateResult.getData() != null) {
|
||||
System.out.println("部分结果:");
|
||||
System.out.println(separateResult.getData());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -89,63 +141,124 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
/**
|
||||
* 执行分账计算逻辑
|
||||
*
|
||||
* @return Pair<Boolean, LklSeparateWithTotalAmountDTO> Boolean表示是否成功,LklSeparateWithTotalAmountDTO为分账结果
|
||||
* @return SeparateResult 包含成功状态、分账结果和错误信息的包装类
|
||||
*/
|
||||
public Pair<Boolean, LklSeparateWithTotalAmountDTO> calculateSeparateAmount() {
|
||||
public SeparateResult calculateSeparateAmount() {
|
||||
try {
|
||||
// 清空之前的错误信息
|
||||
this.errMsg = null;
|
||||
|
||||
// 参数校验
|
||||
validateInputs();
|
||||
Pair<Boolean, String> validateResult = validateInputs();
|
||||
if (!validateResult.getFirst()) {
|
||||
String errorMsg = "分账计算参数异常: " + validateResult.getSecond();
|
||||
log.error(errorMsg);
|
||||
this.errMsg = errorMsg;
|
||||
return SeparateResult.failure(errorMsg);
|
||||
}
|
||||
|
||||
// 1. 计算拉卡拉分账金额和可分账金额
|
||||
calculateLklAmountAndCanSeparateAmount();
|
||||
Pair<Boolean, String> lklResult = calculateLklAmountAndCanSeparateAmount();
|
||||
if (!lklResult.getFirst()) {
|
||||
String errorMsg = "分账计算参数异常: " + lklResult.getSecond();
|
||||
log.error(errorMsg);
|
||||
this.errMsg = errorMsg;
|
||||
return SeparateResult.failure(errorMsg);
|
||||
}
|
||||
|
||||
// 2. 确定实际可分账金额
|
||||
int actualCanSeparateAmount = determineActualCanSeparateAmount();
|
||||
Pair<Boolean, String> canSeparateResult = determineActualCanSeparateAmount();
|
||||
if (!canSeparateResult.getFirst()) {
|
||||
String errorMsg = "分账计算参数异常: " + canSeparateResult.getSecond();
|
||||
log.error(errorMsg);
|
||||
this.errMsg = errorMsg;
|
||||
return SeparateResult.failure(errorMsg);
|
||||
}
|
||||
|
||||
int actualCanSeparateAmount = Integer.parseInt(canSeparateResult.getSecond());
|
||||
|
||||
// 3. 计算各参与方分账比例
|
||||
calculateDefaultRatios();
|
||||
Pair<Boolean, String> ratioResult = calculateDefaultRatios();
|
||||
if (!ratioResult.getFirst()) {
|
||||
String errorMsg = "分账计算参数异常: " + ratioResult.getSecond();
|
||||
log.error(errorMsg);
|
||||
this.errMsg = errorMsg;
|
||||
return SeparateResult.failure(errorMsg);
|
||||
}
|
||||
|
||||
// 4. 根据优先级顺序计算各参与方分账金额
|
||||
calculateAmountsInPriorityOrder(actualCanSeparateAmount);
|
||||
Pair<Boolean, String> amountResult = calculateAmountsInPriorityOrder(actualCanSeparateAmount);
|
||||
if (!amountResult.getFirst()) {
|
||||
String errorMsg = "分账计算参数异常: " + amountResult.getSecond();
|
||||
log.error(errorMsg);
|
||||
this.errMsg = errorMsg;
|
||||
return SeparateResult.failure(errorMsg);
|
||||
}
|
||||
|
||||
// 5. 校验分账金额总和不能超过总金额
|
||||
validateSeparateAmountTotal();
|
||||
Pair<Boolean, String> totalResult = validateSeparateAmountTotal();
|
||||
if (!totalResult.getFirst()) {
|
||||
String errorMsg = "分账计算参数异常: " + totalResult.getSecond();
|
||||
log.error(errorMsg);
|
||||
this.errMsg = errorMsg;
|
||||
return SeparateResult.failure(errorMsg);
|
||||
}
|
||||
|
||||
// 6. 计算商家实际分账比例
|
||||
calculateActualMchRatio();
|
||||
Pair<Boolean, String> mchResult = calculateActualMchRatio();
|
||||
if (!mchResult.getFirst()) {
|
||||
String errorMsg = "分账计算参数异常: " + mchResult.getSecond();
|
||||
log.error(errorMsg);
|
||||
this.errMsg = errorMsg;
|
||||
return SeparateResult.failure(errorMsg);
|
||||
}
|
||||
|
||||
return Pair.of(true, this);
|
||||
return SeparateResult.success(this);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// 参数校验异常,返回false和当前对象
|
||||
System.err.println("分账计算参数异常: " + e.getMessage());
|
||||
return Pair.of(false, this);
|
||||
String errorMsg = "分账计算参数异常: " + e.getMessage();
|
||||
log.error(errorMsg, e);
|
||||
this.errMsg = errorMsg;
|
||||
return SeparateResult.failure(errorMsg);
|
||||
} catch (Exception e) {
|
||||
// 其他异常,返回false和null
|
||||
System.err.println("分账计算异常: " + e.getMessage());
|
||||
return Pair.of(false, null);
|
||||
String errorMsg = "分账计算异常: " + e.getMessage();
|
||||
log.error(errorMsg, e);
|
||||
this.errMsg = errorMsg;
|
||||
return SeparateResult.failure(errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验必要参数
|
||||
*
|
||||
* @throws IllegalArgumentException 当参数不合法时抛出异常
|
||||
* @return Pair<Boolean, String> Boolean表示是否成功,String为错误信息
|
||||
*/
|
||||
private void validateInputs() {
|
||||
private Pair<Boolean, String> validateInputs() {
|
||||
// 校验totalSeparateAmount必须为有效值且大于0
|
||||
if (totalSeparateAmount == null || totalSeparateAmount <= 0) {
|
||||
throw new IllegalArgumentException("分账计算缺少必要参数或参数不合法");
|
||||
log.error("分账计算:总分账金额小于等于0");
|
||||
return Pair.of(false, "分账计算:总分账金额小于等于0");
|
||||
}
|
||||
|
||||
// 校验必要参数
|
||||
if (lklRatio == null || mchRatio == null) {
|
||||
throw new IllegalArgumentException("分账计算缺少必要参数");
|
||||
if (lklRatio == null || lklRatio.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
log.error("分账计算:拉卡拉分账比例小于等于0");
|
||||
return Pair.of(false, "分账计算:拉卡拉分账比例小于等于0");
|
||||
}
|
||||
|
||||
if (mchRatio == null || mchRatio.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
log.error("分账计算:商户分账比例小于等于0");
|
||||
return Pair.of(false, "分账计算:商户分账比例小于等于0");
|
||||
}
|
||||
|
||||
// 校验shippingFee不能大于等于totalSeparateAmount
|
||||
if (shippingFee != null && shippingFee >= totalSeparateAmount) {
|
||||
throw new IllegalArgumentException("配送费不能大于等于总金额");
|
||||
log.error("分账计算:分账总金额低于平台内部运费");
|
||||
return Pair.of(false, "分账计算:分账总金额低于平台内部运费");
|
||||
}
|
||||
|
||||
return Pair.of(true, "");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -153,19 +266,20 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
* 拉卡拉分账金额 = 总金额 * 拉卡拉分账比例(四舍五入)
|
||||
* 可分账金额 = 总金额 - 拉卡拉分账金额
|
||||
*
|
||||
* @throws IllegalArgumentException 当计算出的分账金额为负数时抛出异常
|
||||
* @return Pair<Boolean, String> Boolean表示是否成功,String为错误信息
|
||||
*/
|
||||
private void calculateLklAmountAndCanSeparateAmount() {
|
||||
private Pair<Boolean, String> calculateLklAmountAndCanSeparateAmount() {
|
||||
// 拉卡拉分账金额 = 总金额 * 拉卡拉分账比例(四舍五入)
|
||||
lklAmount = lklRatio.multiply(new BigDecimal(totalSeparateAmount))
|
||||
lklAmount = lklRatio.multiply(BigDecimal.valueOf(totalSeparateAmount))
|
||||
.setScale(0, RoundingMode.HALF_UP)
|
||||
.intValue();
|
||||
|
||||
// 校验拉卡拉分账金额不能为负数
|
||||
if (lklAmount < 0) {
|
||||
// 记录详细日志
|
||||
System.err.println("拉卡拉分账金额计算结果为负数: " + lklAmount);
|
||||
throw new IllegalArgumentException("拉卡拉分账金额计算异常");
|
||||
String errorMsg = "拉卡拉分账金额计算结果为负数: " + lklAmount;
|
||||
log.error(errorMsg);
|
||||
return Pair.of(false, "拉卡拉分账金额计算异常");
|
||||
}
|
||||
|
||||
// 可分账金额 = 总金额 - 拉卡拉分账金额
|
||||
@ -174,9 +288,12 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
// 校验可分账金额不能为负数
|
||||
if (canSeparateAmount < 0) {
|
||||
// 记录详细日志
|
||||
System.err.println("可分账金额计算结果为负数: " + canSeparateAmount);
|
||||
throw new IllegalArgumentException("可分账金额计算异常");
|
||||
String errorMsg = "可分账金额计算结果为负数: " + canSeparateAmount;
|
||||
log.error(errorMsg);
|
||||
return Pair.of(false, "可分账金额计算异常");
|
||||
}
|
||||
|
||||
return Pair.of(true, "");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -184,10 +301,9 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
* 实际可分账金额A: 如果refCanSeparateAmount有效则使用,否则使用canSeparateAmount
|
||||
* 实际可分账金额B = 实际可分账金额A - 配送费(如果配送费有效)
|
||||
*
|
||||
* @return 实际可分账金额
|
||||
* @throws IllegalArgumentException 当实际可分账金额为负数时抛出异常
|
||||
* @return Pair<Boolean, String> Boolean表示是否成功,String为错误信息
|
||||
*/
|
||||
private int determineActualCanSeparateAmount() {
|
||||
private Pair<Boolean, String> determineActualCanSeparateAmount() {
|
||||
// 实际可分账金额A: 如果refCanSeparateAmount有效则使用,否则使用canSeparateAmount
|
||||
int actualCanSeparateAmountA = (refCanSeparateAmount != null && refCanSeparateAmount > 0)
|
||||
? refCanSeparateAmount : canSeparateAmount;
|
||||
@ -201,22 +317,26 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
// 校验实际可分账金额不能为负数
|
||||
if (actualCanSeparateAmountB < 0) {
|
||||
// 记录详细日志
|
||||
System.err.println("实际可分账金额计算结果为负数: " + actualCanSeparateAmountB);
|
||||
throw new IllegalArgumentException("实际可分账金额计算异常");
|
||||
String errorMsg = "实际可分账金额计算结果为负数: " + actualCanSeparateAmountB;
|
||||
log.error(errorMsg);
|
||||
return Pair.of(false, "实际可分账金额计算异常");
|
||||
}
|
||||
|
||||
return actualCanSeparateAmountB;
|
||||
return Pair.of(true, String.valueOf(actualCanSeparateAmountB));
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算各参与方分账比例
|
||||
* 如果平台比例无效,设置默认值0.01
|
||||
*
|
||||
* @return Pair<Boolean, String> Boolean表示是否成功,String为错误信息
|
||||
*/
|
||||
private void calculateDefaultRatios() {
|
||||
private Pair<Boolean, String> calculateDefaultRatios() {
|
||||
// 如果平台比例无效,设置默认值0.01
|
||||
if (platRatio == null || platRatio.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
platRatio = new BigDecimal("0.01");
|
||||
}
|
||||
|
||||
return Pair.of(true, "");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -225,41 +345,35 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
* 商家获得所有剩余金额
|
||||
*
|
||||
* @param actualCanSeparateAmount 实际可分账金额
|
||||
* @throws IllegalArgumentException 当计算出的分账金额为负数或分账金额超过可用金额时抛出异常
|
||||
* @return Pair<Boolean, String> Boolean表示是否成功,String为错误信息
|
||||
*/
|
||||
private void calculateAmountsInPriorityOrder(int actualCanSeparateAmount) {
|
||||
private Pair<Boolean, String> calculateAmountsInPriorityOrder(int actualCanSeparateAmount) {
|
||||
// 重置所有分账金额
|
||||
platAmount = 0;
|
||||
agent1stAmount = 0;
|
||||
agent2ndAmount = 0;
|
||||
mchAmount = 0;
|
||||
|
||||
// 1. 计算拉卡拉分账金额(拉卡拉一定参与分账)
|
||||
lklAmount = lklRatio.multiply(new BigDecimal(totalSeparateAmount))
|
||||
.setScale(0, RoundingMode.HALF_UP)
|
||||
.intValue();
|
||||
|
||||
// 校验拉卡拉分账金额不能为负数
|
||||
if (lklAmount < 0) {
|
||||
throw new IllegalArgumentException("拉卡拉分账金额计算异常");
|
||||
}
|
||||
|
||||
// 2. 校验实际可分账金额不能小于0
|
||||
if (actualCanSeparateAmount < 0) {
|
||||
throw new IllegalArgumentException("实际可分账金额不能为负数");
|
||||
String errorMsg = "实际可分账金额不能为负数";
|
||||
log.error(errorMsg);
|
||||
return Pair.of(false, errorMsg);
|
||||
}
|
||||
|
||||
// 3. 初始化剩余金额为实际可分账金额
|
||||
int remainingAmount = actualCanSeparateAmount;
|
||||
|
||||
// 4. 计算平台分账金额(平台一定参与分账)
|
||||
platAmount = platRatio.multiply(new BigDecimal(totalSeparateAmount))
|
||||
platAmount = platRatio.multiply(BigDecimal.valueOf(totalSeparateAmount))
|
||||
.setScale(0, RoundingMode.HALF_UP)
|
||||
.intValue();
|
||||
|
||||
// 校验平台分账金额不能为负数
|
||||
if (platAmount < 0) {
|
||||
throw new IllegalArgumentException("平台分账金额计算异常");
|
||||
String errorMsg = "平台分账金额计算异常";
|
||||
log.error(errorMsg);
|
||||
return Pair.of(false, errorMsg);
|
||||
}
|
||||
|
||||
// 确保不超过剩余金额
|
||||
@ -278,13 +392,15 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
// 优先级:平台 -> 二级代理商 -> 一级代理商
|
||||
if (isAgent2ndParticipate) {
|
||||
// 计算二级代理商分账金额
|
||||
agent2ndAmount = agent2ndRatio.multiply(new BigDecimal(totalSeparateAmount))
|
||||
agent2ndAmount = agent2ndRatio.multiply(BigDecimal.valueOf(totalSeparateAmount))
|
||||
.setScale(0, RoundingMode.HALF_UP)
|
||||
.intValue();
|
||||
|
||||
// 校验二级代理商分账金额不能为负数
|
||||
if (agent2ndAmount < 0) {
|
||||
throw new IllegalArgumentException("二级代理商分账金额计算异常");
|
||||
String errorMsg = "二级代理商分账金额计算异常";
|
||||
log.error(errorMsg);
|
||||
return Pair.of(false, errorMsg);
|
||||
}
|
||||
|
||||
// 确保不超过剩余金额
|
||||
@ -296,13 +412,15 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
|
||||
if (isAgent1stParticipate) {
|
||||
// 计算一级代理商分账金额
|
||||
agent1stAmount = agent1stRatio.multiply(new BigDecimal(totalSeparateAmount))
|
||||
agent1stAmount = agent1stRatio.multiply(BigDecimal.valueOf(totalSeparateAmount))
|
||||
.setScale(0, RoundingMode.HALF_UP)
|
||||
.intValue();
|
||||
|
||||
// 校验一级代理商分账金额不能为负数
|
||||
if (agent1stAmount < 0) {
|
||||
throw new IllegalArgumentException("一级代理商分账金额计算异常");
|
||||
String errorMsg = "一级代理商分账金额计算异常";
|
||||
log.error(errorMsg);
|
||||
return Pair.of(false, errorMsg);
|
||||
}
|
||||
|
||||
// 确保不超过剩余金额
|
||||
@ -317,37 +435,44 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
|
||||
// 校验商家分账金额不能为负数
|
||||
if (mchAmount < 0) {
|
||||
throw new IllegalArgumentException("商家分账金额计算异常");
|
||||
String errorMsg = "商家分账金额计算异常";
|
||||
log.error(errorMsg);
|
||||
return Pair.of(false, errorMsg);
|
||||
}
|
||||
|
||||
return Pair.of(true, "");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 计算商家实际分账比例
|
||||
*
|
||||
* @throws IllegalArgumentException 当商家实际分账比例低于阈值时抛出异常
|
||||
* @return Pair<Boolean, String> Boolean表示是否成功,String为错误信息
|
||||
*/
|
||||
private void calculateActualMchRatio() {
|
||||
private Pair<Boolean, String> calculateActualMchRatio() {
|
||||
if (totalSeparateAmount != null && totalSeparateAmount > 0 && mchAmount != null) {
|
||||
// 计算实际比例,保留6位小数
|
||||
mchRatio = new BigDecimal(mchAmount)
|
||||
.divide(new BigDecimal(totalSeparateAmount), 6, RoundingMode.HALF_UP);
|
||||
mchRatio = BigDecimal.valueOf(mchAmount)
|
||||
.divide(BigDecimal.valueOf(totalSeparateAmount), 6, RoundingMode.HALF_UP);
|
||||
|
||||
// 如果计算出的实际比例低于阈值,打印日志并抛出异常
|
||||
// 如果计算出的实际比例低于阈值,打印日志并返回错误
|
||||
if (mchRatio.compareTo(MCH_RATIO_THRESHOLD) < 0) {
|
||||
System.err.println("警告: 商家实际分账比例低于阈值,当前比例: " + mchRatio + ",阈值: " + MCH_RATIO_THRESHOLD);
|
||||
throw new IllegalArgumentException("商家分账低于阈值");
|
||||
String errorMsg = "警告: 商家实际分账比例低于阈值,当前比例: " + mchRatio + ",阈值: " + MCH_RATIO_THRESHOLD;
|
||||
log.warn(errorMsg);
|
||||
return Pair.of(false, "商家分账低于阈值");
|
||||
}
|
||||
}
|
||||
|
||||
return Pair.of(true, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验分账金额总和不能超过总金额
|
||||
*
|
||||
* @throws IllegalArgumentException 当分账金额总和超过总金额时抛出异常
|
||||
* @return Pair<Boolean, String> Boolean表示是否成功,String为错误信息
|
||||
*/
|
||||
private void validateSeparateAmountTotal() {
|
||||
int totalAmount = 0;
|
||||
private Pair<Boolean, String> validateSeparateAmountTotal() {
|
||||
long totalAmount = 0;
|
||||
totalAmount += (lklAmount != null ? lklAmount : 0);
|
||||
totalAmount += (platAmount != null ? platAmount : 0);
|
||||
totalAmount += (agent2ndAmount != null ? agent2ndAmount : 0);
|
||||
@ -356,9 +481,12 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
|
||||
if (totalAmount > totalSeparateAmount) {
|
||||
// 记录详细日志
|
||||
System.err.println("分账金额总和超过总金额,分账金额总和: " + totalAmount + ",总金额: " + totalSeparateAmount);
|
||||
throw new IllegalArgumentException("分账金额总和超过总金额");
|
||||
String errorMsg = "分账金额总和超过总金额,分账金额总和: " + totalAmount + ",总金额: " + totalSeparateAmount;
|
||||
log.error(errorMsg);
|
||||
return Pair.of(false, "分账金额总和超过总金额");
|
||||
}
|
||||
|
||||
return Pair.of(true, "");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -392,8 +520,7 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
* @return JSON格式字符串
|
||||
*/
|
||||
public String toJSON() {
|
||||
String sb = "{" +
|
||||
"\"totalSeparateAmount\":" + totalSeparateAmount + "," +
|
||||
String sb = "{" + "\"totalSeparateAmount\":" + totalSeparateAmount + "," +
|
||||
"\"canSeparateAmount\":" + canSeparateAmount + "," +
|
||||
"\"refCanSeparateAmount\":" + refCanSeparateAmount + "," +
|
||||
"\"shippingFee\":" + shippingFee + "," +
|
||||
@ -410,4 +537,78 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
"}";
|
||||
return sb;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分账计算结果(包含错误信息)
|
||||
*
|
||||
* @return SeparateResult 包含成功状态、分账结果和错误信息的包装类
|
||||
*/
|
||||
public SeparateResult getSeparateResult() {
|
||||
SeparateResult result = new SeparateResult();
|
||||
result.setIsSuccess(true);
|
||||
result.setData(this);
|
||||
result.setErrMsg(this.errMsg);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行分账计算逻辑
|
||||
*
|
||||
* @return SeparateResult 包含成功状态、分账结果和错误信息的包装类
|
||||
*/
|
||||
public SeparateResult calculateSeparateAmountWithResult() {
|
||||
return calculateSeparateAmount();
|
||||
}
|
||||
|
||||
/**
|
||||
* 分账计算结果包装类
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode
|
||||
public static class SeparateResult {
|
||||
private Boolean isSuccess;
|
||||
private LklSeparateWithTotalAmountDTO data;
|
||||
private String errMsg = ""; // 默认值为空字符串,保证不为null
|
||||
|
||||
public SeparateResult() {
|
||||
}
|
||||
|
||||
public SeparateResult(Boolean isSuccess, LklSeparateWithTotalAmountDTO data, String errMsg) {
|
||||
this.isSuccess = isSuccess;
|
||||
this.data = data;
|
||||
this.errMsg = errMsg != null ? errMsg : ""; // 确保不为null
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建成功结果
|
||||
*
|
||||
* @param data 分账数据
|
||||
* @return SeparateResult
|
||||
*/
|
||||
public static SeparateResult success(LklSeparateWithTotalAmountDTO data) {
|
||||
return new SeparateResult(Boolean.TRUE, data, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建失败结果
|
||||
*
|
||||
* @param errMsg 错误信息
|
||||
* @return SeparateResult
|
||||
*/
|
||||
public static SeparateResult failure(String errMsg) {
|
||||
return new SeparateResult(Boolean.FALSE, null, errMsg != null ? errMsg : "");
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建部分成功结果(带错误信息的成功)
|
||||
*
|
||||
* @param data 分账数据
|
||||
* @param errMsg 错误信息
|
||||
* @return SeparateResult
|
||||
*/
|
||||
public static SeparateResult partialSuccess(LklSeparateWithTotalAmountDTO data, String errMsg) {
|
||||
return new SeparateResult(Boolean.TRUE, data, errMsg != null ? errMsg : "");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -92,7 +92,9 @@ public class LakalaController extends BaseControllerImpl {
|
||||
|
||||
// return lklLedgerReceiverService.selectAgentAndPlatformByMchId(36L);
|
||||
|
||||
return lakalaApiService.ewalletWithDrawNotify(null, paramsJSON.getStr("a"), paramsJSON.getStr("b"));
|
||||
// return lakalaApiService.ewalletWithDrawNotify(null, paramsJSON.getStr("a"), paramsJSON.getStr("b"));
|
||||
|
||||
return lakalaApiService.tradeQuery(paramsJSON.getInt("storeId"), paramsJSON.getStr("orderId"));
|
||||
}
|
||||
|
||||
@ApiOperation(value = "批量发送推送消息 - 测试案例", notes = "批量发送推送消息 - 测试案例")
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
|
||||
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
|
||||
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
|
||||
* Vestibulum commodo. Ut rhoncus gravida arcu.
|
||||
*/
|
||||
|
||||
package com.suisung.mall.shop.lakala.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.suisung.mall.common.modules.lakala.LklReceiveNotifyLog;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
|
||||
@Repository
|
||||
public interface LklReceiveNotifyLogMapper extends BaseMapper<LklReceiveNotifyLog> {
|
||||
|
||||
}
|
||||
@ -376,7 +376,7 @@ public interface LakalaApiService {
|
||||
* @param refCanSeparateAmt 参考可分金额(单位:分) 可选参数
|
||||
* @return Pair<Boolean, LklSeparateDTO> 分账参数评估结果,第一个元素表示是否成功,第二个元素为分账参数对象
|
||||
*/
|
||||
Pair<Boolean, LklSeparateWithTotalAmountDTO> calculateAndEvaluateSharingParams(Integer orderPayAmount,
|
||||
LklSeparateWithTotalAmountDTO.SeparateResult calculateAndEvaluateSharingParams(Integer orderPayAmount,
|
||||
Integer shippingFeeInner,
|
||||
BigDecimal mchSplitRatioRaw,
|
||||
BigDecimal platSplitRatio,
|
||||
|
||||
@ -31,7 +31,7 @@ public interface LklOrderDrawService extends IBaseService<LklOrderDraw> {
|
||||
* @param merOrderNo 商户订单号
|
||||
* @return
|
||||
*/
|
||||
LklOrderDraw getByByMercIdAndMerOrderNo(String mercId, String merOrderNo);
|
||||
LklOrderDraw getByMercIdAndMerOrderNo(String mercId, String merOrderNo);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
|
||||
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
|
||||
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
|
||||
* Vestibulum commodo. Ut rhoncus gravida arcu.
|
||||
*/
|
||||
|
||||
package com.suisung.mall.shop.lakala.service;
|
||||
|
||||
import com.suisung.mall.common.modules.lakala.LklReceiveNotifyLog;
|
||||
import com.suisung.mall.core.web.service.IBaseService;
|
||||
|
||||
public interface LklReceiveNotifyLogService extends IBaseService<LklReceiveNotifyLog> {
|
||||
|
||||
/**
|
||||
* 新增或更新拉卡拉确认收货通知日志记录
|
||||
*
|
||||
* @param lklReceiveNotifyJSON 拉卡拉通知的JSON数据
|
||||
* @return 处理结果,true表示成功,false表示失败
|
||||
*/
|
||||
Boolean addOrUpdate(String lklReceiveNotifyJSON);
|
||||
|
||||
/**
|
||||
* 根据订单号获取拉卡拉确认收货通知日志记录
|
||||
*
|
||||
* @param orderId 商户订单号
|
||||
* @return 拉卡拉确认收货通知日志记录,如果不存在则返回null
|
||||
*/
|
||||
LklReceiveNotifyLog getByOrderId(String orderId);
|
||||
|
||||
}
|
||||
@ -153,10 +153,10 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
@Lazy
|
||||
@Resource
|
||||
private ShopOrderBaseService shopOrderBaseService;
|
||||
//
|
||||
// @Lazy
|
||||
// @Resource
|
||||
// private ShopOrderInfoService shopOrderInfoService;
|
||||
|
||||
@Lazy
|
||||
@Resource
|
||||
private LklReceiveNotifyLogService lklReceiveNotifyLogService;
|
||||
|
||||
@Lazy
|
||||
@Resource
|
||||
@ -197,6 +197,8 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
|
||||
/**
|
||||
* 聚合扫码-交易查询
|
||||
* 参考:https://o.lakala.com/#/home/document/detail?id=116
|
||||
* 说明:查询交易中,如果返回响应CODE为BBS00000,仅表示查到了这笔交易。交易本身的成功与否状态,要查看响应报文中的trade_state这个值。
|
||||
*
|
||||
* @param storeId
|
||||
* @param orderId
|
||||
@ -204,7 +206,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
*/
|
||||
@Override
|
||||
public JSONObject tradeQuery(Integer storeId, String orderId) {
|
||||
if (ObjectUtil.isEmpty(storeId) || StrUtil.isBlank(orderId)) {
|
||||
if (CheckUtil.isEmpty(storeId) || StrUtil.isBlank(orderId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -228,13 +230,18 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
//3. 发送请求
|
||||
String responseStr = LKLSDK.httpPost(v3LabsQueryTradequeryRequest);
|
||||
if (StrUtil.isBlank(responseStr)) {
|
||||
throw new ApiException(I18nUtil._("交易查询无响应!"));
|
||||
return null;
|
||||
}
|
||||
|
||||
JSONObject lakalaRespJSON = JSONUtil.parseObj(responseStr);
|
||||
// || !lakalaRespJSON.getStr("code").equals("BBS00000")
|
||||
if (lakalaRespJSON != null
|
||||
&& StrUtil.isNotBlank(lakalaRespJSON.getStr("code"))
|
||||
&& lakalaRespJSON.getStr("code").equals("BBS00000")
|
||||
&& lakalaRespJSON.getJSONObject("resp_data") != null) {
|
||||
return lakalaRespJSON.getJSONObject("resp_data");
|
||||
}
|
||||
|
||||
return lakalaRespJSON;
|
||||
return null;
|
||||
} catch (SDKException e) {
|
||||
log.error("交易查询失败:", e);
|
||||
throw new ApiException(I18nUtil._("交易查询失败!"), e);
|
||||
@ -781,7 +788,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
|
||||
|
||||
/**
|
||||
* 发货类交易确认收货通知处理, 微信通知拉卡拉,拉卡拉通知我们系统,已经完成确认收货
|
||||
* 重要接口(直接影响到分账执行的):发货类交易确认收货通知处理, 微信通知拉卡拉,拉卡拉通知我们系统,已经完成确认收货
|
||||
* <p>
|
||||
* 参考文档:https://o.lakala.com/#/home/document/detail?id=1003
|
||||
* </p>
|
||||
@ -813,6 +820,9 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
return JSONUtil.createObj().set("code", "FAIL").set("message", "返回数据转换异常!");
|
||||
}
|
||||
|
||||
// 写上确认收货通知日志
|
||||
lklReceiveNotifyLogService.addOrUpdate(paramsJSON.toString());
|
||||
|
||||
// 订单是否为合单
|
||||
boolean isCombine = paramsJSON.containsKey("out_split_rsp_infos");
|
||||
log.debug("[确认收货通知] 检查是否为合单订单: isCombine={}", isCombine);
|
||||
@ -825,9 +835,9 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
String tradeNo = paramsJSON.getStr("trade_no");
|
||||
String tradeTime = paramsJSON.getStr("trade_time"); // 实际交易完成时间。yyyyMMddHHmmss
|
||||
// 直接截取前8位,获取日期部分
|
||||
String logDate = tradeTime != null && tradeTime.length() >= 8 ? tradeTime.substring(0, 8) : null;
|
||||
String logDate = StrUtil.isNotBlank(tradeTime) && tradeTime.length() >= 8 ? tradeTime.substring(0, 8) : null;
|
||||
if (logDate == null) {
|
||||
logDate = DateUtil.format(new Date(), "yyyyMMdd"); // 当前时间
|
||||
logDate = DateUtil.format(new Date(), "yyyyMMdd"); // 收到确认收货通知的日期(当前日期)
|
||||
}
|
||||
|
||||
log.debug("[确认收货通知] 获取基础交易信息: logNo={} tradeNo={} logDate={}", logNo, tradeNo, logDate);
|
||||
@ -844,6 +854,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
logNo, tradeState, merchantNo, originTradeNo, originLogNo);
|
||||
|
||||
if (isCombine) {
|
||||
// 该分支要废弃,支付时请不要走合单交易
|
||||
log.debug("[确认收货通知] 处理合单订单,开始获取子单信息");
|
||||
// 合单的时候获取子单信息
|
||||
JSONObject goodsOrderInfo = CommonService.getLklCombineSplitRespInfo(merchantNo, paramsJSON.getStr("out_split_rsp_infos"), false);
|
||||
@ -862,6 +873,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
log.warn("[确认收货通知] 未能获取到商品子单信息,使用原始参数进行处理");
|
||||
}
|
||||
} else {
|
||||
|
||||
// 非合单订单,确认收货响应数据:{"trade_no":"20251015110110000066202154232129","log_no":"66202154232129","trade_state":"SUCCESS",
|
||||
// "total_amount":"2950","trade_time":"20251015165538",
|
||||
// "complete_notify_url":"https://mall.gpxscs.cn/api/mobile/shop/lakala/trans/receive/completeNotify",
|
||||
@ -882,6 +894,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
return JSONUtil.createObj().set("code", "FAIL").set("message", "关键编号返回空值!");
|
||||
}
|
||||
|
||||
// 查询
|
||||
ShopOrderLkl shopOrderLkl = shopOrderLklService.getByLklMchNoAndSubTradeNoAndSubLogNo(merchantNo, originTradeNo, originLogNo);
|
||||
if (shopOrderLkl == null) {
|
||||
log.warn("[确认收货通知] 订单不存在: merchantNo={}, originTradeNo={}, originLogNo={}",
|
||||
@ -904,9 +917,10 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
}
|
||||
log.info("[确认收货通知] 订单信息更新成功: orderId={}", shopOrderLkl.getOrder_id());
|
||||
|
||||
// 重要:准备发起分账指令
|
||||
|
||||
log.info("[确认收货通知] 开始发起分账指令: merchantNo={}, receiveTradeNo={}, logNo={}",
|
||||
merchantNo, shopOrderLkl.getLkl_receive_trade_no(), logNo);
|
||||
// 重要:准备发起分账指令
|
||||
Pair<Boolean, String> separateResult = innerDoOrderSeparateByMerchantAndLogNo(merchantNo, shopOrderLkl.getLkl_receive_trade_no(), shopOrderLkl.getLkl_receive_log_no(), logDate);
|
||||
if (!separateResult.getFirst()) {
|
||||
|
||||
@ -2398,23 +2412,23 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
}
|
||||
|
||||
// 计算拉卡拉手续费、商家分账金额、平台和代理商的分账金额
|
||||
Pair<Boolean, LklSeparateWithTotalAmountDTO> calcResult = calculateAndEvaluateSharingParams(
|
||||
LklSeparateWithTotalAmountDTO.SeparateResult calcResult = calculateAndEvaluateSharingParams(
|
||||
shopOrderLkl.getTotal_amt(),
|
||||
shoppingFeeInner,
|
||||
mchSplitRatio,
|
||||
platformSplitRatio,
|
||||
agent1stSplitRatio, agent2ndSplitRatio, refCanSeparateAmt);
|
||||
|
||||
if (calcResult == null || !calcResult.getFirst() || calcResult.getSecond() == null) {
|
||||
if (calcResult == null || !calcResult.getIsSuccess() || calcResult.getData() == null) {
|
||||
log.error("[分账操作] 分账参数评估失败,无法分账, orderId={}, merchantNo={}", orderId, merchantNo);
|
||||
|
||||
// 更新分账出错信息
|
||||
shopOrderLkl.setSeparate_msg("分账数据评估,结果无法分账");
|
||||
shopOrderLkl.setSeparate_msg(calcResult.getErrMsg());
|
||||
shopOrderLklService.safeUpdate(shopOrderLkl);
|
||||
|
||||
return Pair.of(false, "分账数据评估,结果无法分账");
|
||||
return Pair.of(false, calcResult.getErrMsg());
|
||||
}
|
||||
LklSeparateWithTotalAmountDTO lklSeparateDTO = calcResult.getSecond();
|
||||
LklSeparateWithTotalAmountDTO lklSeparateDTO = calcResult.getData();
|
||||
|
||||
log.info("[分账操作] 分账计算完成, orderId={}, merchantNo={}, 分账总金额={}",
|
||||
orderId, merchantNo, lklSeparateDTO.getCanSeparateAmount());
|
||||
@ -3702,7 +3716,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
* @return Pair<Boolean, LklSeparateDTO> 分账参数评估结果,第一个元素表示是否成功,第二个元素为分账参数对象
|
||||
*/
|
||||
@Override
|
||||
public Pair<Boolean, LklSeparateWithTotalAmountDTO> calculateAndEvaluateSharingParams(
|
||||
public LklSeparateWithTotalAmountDTO.SeparateResult calculateAndEvaluateSharingParams(
|
||||
Integer orderPayAmount,
|
||||
Integer shippingFeeInner,
|
||||
BigDecimal mchSplitRatioRaw,
|
||||
@ -3710,7 +3724,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
BigDecimal agent1stRatio,
|
||||
BigDecimal agent2ndRatio,
|
||||
Integer refCanSeparateAmt) {
|
||||
log.debug("[分账参数计算] 开始计算分账参数: orderPayAmount={}, shippingFeeInner={}, " +
|
||||
log.debug("[分账计算] 开始计算分账参数: orderPayAmount={}, shippingFeeInner={}, " +
|
||||
"mchSplitRatioRaw={}, platSplitRatio={}, agent1stRatio={}, agent2ndRatio={}, refCanSeparateAmt={}",
|
||||
orderPayAmount, shippingFeeInner, mchSplitRatioRaw, platSplitRatio,
|
||||
agent1stRatio, agent2ndRatio, refCanSeparateAmt);
|
||||
@ -3718,32 +3732,31 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
String errMsg = "";
|
||||
// 参数校验
|
||||
if (orderPayAmount == null || orderPayAmount <= 0) {
|
||||
// errMsg = String.format("订单支付金额参数无效: orderPayAmount={}", orderPayAmount);
|
||||
log.warn("[分账参数计算] 订单支付金额参数无效: orderPayAmount={}", orderPayAmount);
|
||||
return Pair.of(false, null);
|
||||
log.warn("[分账计算] 订单支付金额参数无效: orderPayAmount={}", orderPayAmount);
|
||||
return LklSeparateWithTotalAmountDTO.SeparateResult.failure("订单支付金额参数无效");
|
||||
}
|
||||
|
||||
if (mchSplitRatioRaw == null || mchSplitRatioRaw.compareTo(BigDecimal.ZERO) <= 0 || mchSplitRatioRaw.compareTo(BigDecimal.valueOf(100)) > 0) {
|
||||
log.warn("[分账参数计算] 商户分账比例参数无效: mchSplitRatioRaw={}", mchSplitRatioRaw);
|
||||
return Pair.of(false, null);
|
||||
log.warn("[分账计算] 商户分账比例参数无效: mchSplitRatioRaw={}", mchSplitRatioRaw);
|
||||
return LklSeparateWithTotalAmountDTO.SeparateResult.failure("订单支付金额参数无效");
|
||||
}
|
||||
|
||||
|
||||
// 计算商家分账比例(转换为小数)
|
||||
BigDecimal mchSplitRatio = mchSplitRatioRaw.divide(new BigDecimal(100));
|
||||
log.debug("[分账参数计算] 商家分账比例转换: {} -> {}", mchSplitRatioRaw, mchSplitRatio);
|
||||
log.debug("[分账计算] 商家分账比例转换: {} -> {}", mchSplitRatioRaw, mchSplitRatio);
|
||||
|
||||
// 平台分账比例处理
|
||||
BigDecimal platformSplitRatio = platSplitRatio;
|
||||
if (platformSplitRatio == null || platformSplitRatio.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
platformSplitRatio = BigDecimal.valueOf(0.01); // 默认平台分账1%
|
||||
log.debug("[分账参数计算] 使用默认平台分账比例: {}", platformSplitRatio);
|
||||
log.debug("[分账计算] 使用默认平台分账比例: {}", platformSplitRatio);
|
||||
}
|
||||
|
||||
// 内部配送费处理
|
||||
Integer actualShippingFeeInner = CheckUtil.isEmpty(shippingFeeInner) ? 0 : shippingFeeInner;
|
||||
BigDecimal wxFeeRatio = StrUtil.isEmpty(wxFee) ? BigDecimal.valueOf(0.0025) : new BigDecimal(wxFee).divide(BigDecimal.valueOf(100));
|
||||
log.debug("[分账参数计算] 配送费: {}, 拉卡拉费率: {}", actualShippingFeeInner, wxFeeRatio);
|
||||
log.debug("[分账计算] 配送费: {}, 拉卡拉费率: {}", actualShippingFeeInner, wxFeeRatio);
|
||||
|
||||
// 构建分账参数对象
|
||||
LklSeparateWithTotalAmountDTO lklSeparateDTO = new LklSeparateWithTotalAmountDTO();
|
||||
@ -3756,35 +3769,28 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
// 设置代理商分账比例
|
||||
if (agent1stRatio != null && agent1stRatio.compareTo(BigDecimal.ZERO) > 0) {
|
||||
lklSeparateDTO.setAgent1stRatio(agent1stRatio);
|
||||
log.debug("[分账参数计算] 设置一级代理商分账比例: {}", agent1stRatio);
|
||||
log.debug("[分账计算] 设置一级代理商分账比例: {}", agent1stRatio);
|
||||
}
|
||||
|
||||
if (agent2ndRatio != null && agent2ndRatio.compareTo(BigDecimal.ZERO) > 0) {
|
||||
lklSeparateDTO.setAgent2ndRatio(agent2ndRatio);
|
||||
log.debug("[分账参数计算] 设置二级代理商分账比例: {}", agent2ndRatio);
|
||||
log.debug("[分账计算] 设置二级代理商分账比例: {}", agent2ndRatio);
|
||||
}
|
||||
|
||||
// 设置参考可分账金额
|
||||
if (CheckUtil.isNotEmpty(refCanSeparateAmt)) {
|
||||
lklSeparateDTO.setRefCanSeparateAmount(refCanSeparateAmt);
|
||||
log.debug("[分账参数计算] 拉卡拉的参考可分账金额: {}", refCanSeparateAmt);
|
||||
log.debug("[分账计算] 拉卡拉的参考可分账金额: {}", refCanSeparateAmt);
|
||||
} else {
|
||||
log.error("[分账参数计算] 注意:拉卡拉的参考可分账金额无效:{}", refCanSeparateAmt);
|
||||
log.error("[分账计算] 注意:拉卡拉的参考可分账金额无效:{}", refCanSeparateAmt);
|
||||
}
|
||||
|
||||
try {
|
||||
// 根据分账模式执行不同的分账计算
|
||||
Pair<Boolean, LklSeparateWithTotalAmountDTO> canSeparateAmtResult = lklSeparateDTO.calculateSeparateAmount();
|
||||
if (!canSeparateAmtResult.getFirst()) {
|
||||
log.warn("[分账参数计算] 分账参数有误,分账估算失败");
|
||||
return Pair.of(false, lklSeparateDTO);
|
||||
}
|
||||
|
||||
log.info("[分账参数计算] 分账估算成功, result={}", lklSeparateDTO);
|
||||
return Pair.of(true, lklSeparateDTO);
|
||||
return lklSeparateDTO.calculateSeparateAmount();
|
||||
} catch (Exception e) {
|
||||
log.error("[分账参数计算] 分账参数有误,分账估算失败", e);
|
||||
return Pair.of(false, lklSeparateDTO);
|
||||
log.error("[分账计算] 分账参数有误,分账估算失败", e);
|
||||
return LklSeparateWithTotalAmountDTO.SeparateResult.failure("分账参数有误,分账估算失败");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -81,7 +81,7 @@ public class LklOrderDrawServiceImpl extends BaseServiceImpl<LklOrderDrawMapper,
|
||||
* @return 拉卡拉订单分账记录,未找到返回null
|
||||
*/
|
||||
@Override
|
||||
public LklOrderDraw getByByMercIdAndMerOrderNo(String mercId, String merOrderNo) {
|
||||
public LklOrderDraw getByMercIdAndMerOrderNo(String mercId, String merOrderNo) {
|
||||
// 参数校验
|
||||
if (StrUtil.isBlank(mercId) && StrUtil.isBlank(merOrderNo)) {
|
||||
log.warn("[LklOrderDraw] 查询记录参数校验失败,商户号和商户订单号均为空");
|
||||
|
||||
@ -0,0 +1,107 @@
|
||||
package com.suisung.mall.shop.lakala.service.impl;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.suisung.mall.common.constant.CommonConstant;
|
||||
import com.suisung.mall.common.modules.lakala.LklReceiveNotifyLog;
|
||||
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
|
||||
import com.suisung.mall.shop.lakala.mapper.LklReceiveNotifyLogMapper;
|
||||
import com.suisung.mall.shop.lakala.service.LklReceiveNotifyLogService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class LklReceiveNotifyLogServiceImpl extends BaseServiceImpl<LklReceiveNotifyLogMapper, LklReceiveNotifyLog> implements LklReceiveNotifyLogService {
|
||||
|
||||
/**
|
||||
* 新增或更新拉卡拉确认收货通知日志记录
|
||||
*
|
||||
* @param lklReceiveNotifyJSON 拉卡拉确认收货通知的JSON数据
|
||||
* @return 操作结果,成功返回true,失败返回false
|
||||
*/
|
||||
@Override
|
||||
public Boolean addOrUpdate(String lklReceiveNotifyJSON) {
|
||||
// 参数校验
|
||||
if (StrUtil.isBlank(lklReceiveNotifyJSON)) {
|
||||
log.warn("[LklReceiveNotifyLog] 新增或更新记录参数校验失败,通知数据为空");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
JSONObject respJson = JSONUtil.parseObj(lklReceiveNotifyJSON);
|
||||
if (ObjectUtil.isEmpty(respJson)) {
|
||||
log.warn("[LklReceiveNotifyLog] 新增或更新记录参数校验失败,拉卡拉返回数据为空");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
String orderId = respJson.getStr("origin_out_trade_no");
|
||||
if (StrUtil.isBlank(orderId)) {
|
||||
log.warn("[LklReceiveNotifyLog] 新增或更新记录参数校验失败,订单号为空");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 直接构建记录对象
|
||||
LklReceiveNotifyLog record = new LklReceiveNotifyLog();
|
||||
record.setOrderId(orderId);
|
||||
record.setRespJson(lklReceiveNotifyJSON);
|
||||
record.setStatus(CommonConstant.Disable2);
|
||||
|
||||
// 使用 saveOrUpdate 方法替代先查询再判断的方式
|
||||
boolean result = saveOrUpdate(record,
|
||||
new QueryWrapper<LklReceiveNotifyLog>().eq("order_id", orderId));
|
||||
|
||||
if (result) {
|
||||
log.debug("[LklReceiveNotifyLog] 记录保存成功,订单号={}", orderId);
|
||||
} else {
|
||||
log.error("[LklReceiveNotifyLog] 记录保存失败,订单号={}", orderId);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("[LklReceiveNotifyLog] 处理拉卡拉确认收货通知记录异常,通知数据={}",
|
||||
lklReceiveNotifyJSON.substring(0, Math.min(lklReceiveNotifyJSON.length(), 100)), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据订单号获取拉卡拉确认收货通知日志记录
|
||||
*
|
||||
* @param orderId 订单号
|
||||
* @return 拉卡拉确认收货通知日志记录,未找到返回null
|
||||
*/
|
||||
@Override
|
||||
public LklReceiveNotifyLog getByOrderId(String orderId) {
|
||||
// 参数校验
|
||||
if (StrUtil.isBlank(orderId)) {
|
||||
log.warn("[LklReceiveNotifyLog] 查询记录参数校验失败,订单号为空");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
log.debug("[LklReceiveNotifyLog] 开始查询拉卡拉确认收货通知记录,订单号={}", orderId);
|
||||
|
||||
QueryWrapper<LklReceiveNotifyLog> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("order_id", orderId);
|
||||
|
||||
LklReceiveNotifyLog result = getOne(queryWrapper);
|
||||
if (result != null) {
|
||||
log.debug("[LklReceiveNotifyLog] 查询到拉卡拉确认收货通知记录,ID={}", result.getId());
|
||||
} else {
|
||||
log.debug("[LklReceiveNotifyLog] 未查询到拉卡拉确认收货通知记录");
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
log.error("[LklReceiveNotifyLog] 查询拉卡拉确认收货通知记录异常,订单号={}", orderId, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7784,7 +7784,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
BigDecimal storeSplitRatio = shopStoreBaseService.getStoreSplitRatio(store_id, false);
|
||||
|
||||
// 计算平台和代理商的分账金额
|
||||
Pair<Boolean, LklSeparateWithTotalAmountDTO> calcResult = lakalaApiService.calculateAndEvaluateSharingParams(
|
||||
LklSeparateWithTotalAmountDTO.SeparateResult calcResult = lakalaApiService.calculateAndEvaluateSharingParams(
|
||||
Convert.toInt(order_payment_amount.multiply(BigDecimal.valueOf(100))),
|
||||
innerMinDeliverFee,
|
||||
storeSplitRatio,
|
||||
@ -7792,9 +7792,9 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
null, null, null);
|
||||
|
||||
// 计算平台费
|
||||
if (calcResult != null && calcResult.getFirst() && calcResult.getSecond() != null) {
|
||||
if (calcResult != null && calcResult.getIsSuccess() && calcResult.getData() != null) {
|
||||
try {
|
||||
LklSeparateWithTotalAmountDTO lklSeparateDTO = calcResult.getSecond();
|
||||
LklSeparateWithTotalAmountDTO lklSeparateDTO = calcResult.getData();
|
||||
// 确保分账金额不为负数
|
||||
BigDecimal totalSeparateAmount = BigDecimal.valueOf(lklSeparateDTO.getCanSeparateAmount())
|
||||
.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.suisung.mall.shop.lakala.mapper.LklReceiveNotifyLogMapper">
|
||||
<!-- 通用查询结果列 -->
|
||||
<sql id="Base_Column_List">
|
||||
*
|
||||
</sql>
|
||||
</mapper>
|
||||
Loading…
Reference in New Issue
Block a user