Compare commits

...

3 Commits

13 changed files with 613 additions and 160 deletions

View File

@ -18,6 +18,7 @@ import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
@Data
@ -32,6 +33,9 @@ public class EsignPlatformInfo implements Serializable {
@ApiModelProperty(value = "自增ID")
private Long id;
@ApiModelProperty(value = "父代理商 Id省级代理商Id")
private Long parent_id;
@ApiModelProperty(value = "公司邮箱")
private String email;
@ -110,6 +114,15 @@ public class EsignPlatformInfo implements Serializable {
@ApiModelProperty(value = "邀请码,后期跟收益有关")
private String invite_code;
@ApiModelProperty(value = "县级市代理商设定的配送费(单位:分)")
private Integer shipping_fee;
@ApiModelProperty(value = "顺丰商家Id 用于县级代理商创建店铺的商家Id")
private String supplier_id;
@ApiModelProperty(value = "分账比例值,取值范围:[0.01,1.00]")
private BigDecimal split_ratio;
@ApiModelProperty(value = "记录状态:1-有效2-无效;")
private Integer status;

View File

@ -101,6 +101,9 @@ public class ShopOrderData implements Serializable {
@ApiModelProperty(value = "平台费(分给平台或代理商的费用),根据不同的店铺分类,从商品原价中扣除相应的费用。")
private BigDecimal platform_fee;
@ApiModelProperty(value = "拉卡拉手续费,单位:元")
private BigDecimal lkl_fee;
@ApiModelProperty(value = "店铺统一设置的打包费")
private BigDecimal packing_fee;

View File

@ -74,6 +74,8 @@ public class MchOrderInfoDTO implements Serializable {
private BigDecimal order_shipping_fee;
@ApiModelProperty(value = "平台内部配送费")
private BigDecimal order_shipping_fee_inner;
@ApiModelProperty(value = "拉卡拉手续费")
private BigDecimal lkl_fee;
@ApiModelProperty(value = "平台费")
private BigDecimal platform_fee;
@ApiModelProperty(value = "店铺统一设置的打包费")

View File

@ -0,0 +1,413 @@
package com.suisung.mall.common.pojo.dto;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.data.util.Pair;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
* 拉卡拉订单基于总金额分账信息处理类
* 实现基于总金额的分账算法支持平台代理商和商家的多级分账类里涉及的金额单位
* <p>
* 分账计算逻辑
* 1totalSeparateAmount是必填参数订单的总金额必须大于0lklRatio 是必填参数拉卡拉的分账比例 0.0025
* 先减去拉卡拉配送费=lklRatio*totalSeparateAmount结果四舍五入保留整数以下计算结果一律四舍五入余额得到可分账金额() canSeparateAmount
* 2refCanSeparateAmount 是可选参数如果有效非空且大于0往下计算分账基准依据此参数计算实际的可分账金额A而不是以 canSeparateAmount 为基准
* 3shippingFee 是可选参数如果有效非空且大于0往下实际的可分账金额B = 实际的可分账金额A -shippingFee
* 4实际的可分账金额B 就是平台一级代理商二级代理商商家的可分账金额按照以下规则进行分账给四个对象
* 5四个对象之前需要知道他们的准则
* 6平台一定参加分账的如果 platRatio 无效空值或小于等于0默认0.01优先分账凭条分账金额 =totalSeparateAmount* platRatio
* 7平台和商家一定参加分账的一级代理商和二级代理商如果对应的比例agent1stRatioagent2ndRatio 有效非空且大于0就参与分账否则不参与
* 8mchRatio 可以根据分账金额动态调整到实际比例
* 9所有参与分账的主体其分账金额都不能为负数否则将抛出异常
* 10分账顺序按照优先级拉卡拉 -> 平台 -> 二级代理商 -> 一级代理商 -> 商家商家获得剩余的所有金额
* 11五方分账金额之和不能超过 totalSeparateAmount
* 12分账计算完成后会计算出 mchRatio 的实际比例
* 13如果商家实际分账比例低于0.2阈值会抛出异常商家分账低于阈值
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class LklSeparateWithTotalAmountDTO {
// 常量定义
private static final BigDecimal MCH_RATIO_THRESHOLD = new BigDecimal("0.2");
// 基础金额属性
private Integer totalSeparateAmount; // 分账总金额()
private Integer canSeparateAmount; // 可分账金额()
private Integer refCanSeparateAmount; // 拉卡拉可分账金额参考()
private Integer shippingFee; // 配送费()
// 分账比例属性
private BigDecimal lklRatio; // 拉卡拉分账比例( 0.0025=0.25%)
private BigDecimal mchRatio; // 商户分账比例( 0.96=96%)
private BigDecimal platRatio; // 平台分账比例( 0.01=1%)
private BigDecimal agent1stRatio; // 一级代理商分账比例( 0.01=1%)
private BigDecimal agent2ndRatio; // 二级代理商分账比例( 0.03=3%)
// 分账金额结果属性
private Integer lklAmount; // 拉卡拉分账金额()
private Integer mchAmount; // 商户分账金额()
private Integer platAmount; // 平台分账金额()
private Integer agent1stAmount; // 一级代理商分账金额()
private Integer agent2ndAmount; // 二级代理商分账金额()
/**
* 测试方法
* 包含多个测试用例验证分账计算逻辑的正确性和异常处理机制
*/
public static void main(String[] args) {
// 测试用例1: 所有参与方都参与分账符合比例要求
System.out.println("=== 测试用例1: 所有参与方都参与分账 ===");
LklSeparateWithTotalAmountDTO dto1 = new LklSeparateWithTotalAmountDTO();
dto1.setTotalSeparateAmount(1500); // 总金额100元(10000分)
dto1.setShippingFee(600);
// dto1.setRefCanSeparateAmount(1496);
dto1.setLklRatio(new BigDecimal("0.0025")); // 拉卡拉分账比例0.25%
dto1.setMchRatio(new BigDecimal("0.95")); // 商家分账比例94.75%
dto1.setPlatRatio(new BigDecimal("0.01")); // 平台分账比例1%
// dto1.setAgent2ndRatio(new BigDecimal("0.04")); // 二级代理商分账比例4%
// dto1.setAgent1stRatio(new BigDecimal("0.01")); // 一级代理商分账比例1%
Pair<Boolean, LklSeparateWithTotalAmountDTO> result = dto1.calculateSeparateAmount();
if (result.getFirst()) {
System.out.println("分账计算成功:");
System.out.println(result.getSecond());
System.out.println("JSON格式输出:");
System.out.println(result.getSecond().toJSON());
} else {
System.out.println("分账计算失败");
if (result.getSecond() != null) {
System.out.println("部分结果:");
System.out.println(result.getSecond());
}
}
}
/**
* 执行分账计算逻辑
*
* @return Pair<Boolean, LklSeparateWithTotalAmountDTO> Boolean表示是否成功LklSeparateWithTotalAmountDTO为分账结果
*/
public Pair<Boolean, LklSeparateWithTotalAmountDTO> calculateSeparateAmount() {
try {
// 参数校验
validateInputs();
// 1. 计算拉卡拉分账金额和可分账金额
calculateLklAmountAndCanSeparateAmount();
// 2. 确定实际可分账金额
int actualCanSeparateAmount = determineActualCanSeparateAmount();
// 3. 计算各参与方分账比例
calculateDefaultRatios();
// 4. 根据优先级顺序计算各参与方分账金额
calculateAmountsInPriorityOrder(actualCanSeparateAmount);
// 5. 校验分账金额总和不能超过总金额
validateSeparateAmountTotal();
// 6. 计算商家实际分账比例
calculateActualMchRatio();
return Pair.of(true, this);
} catch (IllegalArgumentException e) {
// 参数校验异常返回false和当前对象
System.err.println("分账计算参数异常: " + e.getMessage());
return Pair.of(false, this);
} catch (Exception e) {
// 其他异常返回false和null
System.err.println("分账计算异常: " + e.getMessage());
return Pair.of(false, null);
}
}
/**
* 校验必要参数
*
* @throws IllegalArgumentException 当参数不合法时抛出异常
*/
private void validateInputs() {
// 校验totalSeparateAmount必须为有效值且大于0
if (totalSeparateAmount == null || totalSeparateAmount <= 0) {
throw new IllegalArgumentException("分账计算缺少必要参数或参数不合法");
}
// 校验必要参数
if (lklRatio == null || mchRatio == null) {
throw new IllegalArgumentException("分账计算缺少必要参数");
}
// 校验shippingFee不能大于等于totalSeparateAmount
if (shippingFee != null && shippingFee >= totalSeparateAmount) {
throw new IllegalArgumentException("配送费不能大于等于总金额");
}
}
/**
* 计算拉卡拉分账金额和初始可分账金额
* 拉卡拉分账金额 = 总金额 * 拉卡拉分账比例四舍五入
* 可分账金额 = 总金额 - 拉卡拉分账金额
*
* @throws IllegalArgumentException 当计算出的分账金额为负数时抛出异常
*/
private void calculateLklAmountAndCanSeparateAmount() {
// 拉卡拉分账金额 = 总金额 * 拉卡拉分账比例四舍五入
lklAmount = lklRatio.multiply(new BigDecimal(totalSeparateAmount))
.setScale(0, RoundingMode.HALF_UP)
.intValue();
// 校验拉卡拉分账金额不能为负数
if (lklAmount < 0) {
// 记录详细日志
System.err.println("拉卡拉分账金额计算结果为负数: " + lklAmount);
throw new IllegalArgumentException("拉卡拉分账金额计算异常");
}
// 可分账金额 = 总金额 - 拉卡拉分账金额
canSeparateAmount = totalSeparateAmount - lklAmount;
// 校验可分账金额不能为负数
if (canSeparateAmount < 0) {
// 记录详细日志
System.err.println("可分账金额计算结果为负数: " + canSeparateAmount);
throw new IllegalArgumentException("可分账金额计算异常");
}
}
/**
* 确定实际可分账金额
* 实际可分账金额A: 如果refCanSeparateAmount有效则使用否则使用canSeparateAmount
* 实际可分账金额B = 实际可分账金额A - 配送费如果配送费有效
*
* @return 实际可分账金额
* @throws IllegalArgumentException 当实际可分账金额为负数时抛出异常
*/
private int determineActualCanSeparateAmount() {
// 实际可分账金额A: 如果refCanSeparateAmount有效则使用否则使用canSeparateAmount
int actualCanSeparateAmountA = (refCanSeparateAmount != null && refCanSeparateAmount > 0)
? refCanSeparateAmount : canSeparateAmount;
// 实际可分账金额B = 实际可分账金额A - 配送费如果配送费有效
int actualCanSeparateAmountB = actualCanSeparateAmountA;
if (shippingFee != null && shippingFee > 0) {
actualCanSeparateAmountB = actualCanSeparateAmountA - shippingFee;
}
// 校验实际可分账金额不能为负数
if (actualCanSeparateAmountB < 0) {
// 记录详细日志
System.err.println("实际可分账金额计算结果为负数: " + actualCanSeparateAmountB);
throw new IllegalArgumentException("实际可分账金额计算异常");
}
return actualCanSeparateAmountB;
}
/**
* 计算各参与方分账比例
* 如果平台比例无效设置默认值0.01
*/
private void calculateDefaultRatios() {
// 如果平台比例无效设置默认值0.01
if (platRatio == null || platRatio.compareTo(BigDecimal.ZERO) <= 0) {
platRatio = new BigDecimal("0.01");
}
}
/**
* 根据优先级顺序计算各参与方分账金额
* 分账顺序拉卡拉 -> 平台 -> 二级代理商 -> 一级代理商 -> 商家
* 商家获得所有剩余金额
*
* @param actualCanSeparateAmount 实际可分账金额
* @throws IllegalArgumentException 当计算出的分账金额为负数或分账金额超过可用金额时抛出异常
*/
private void 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("实际可分账金额不能为负数");
}
// 3. 初始化剩余金额为实际可分账金额
int remainingAmount = actualCanSeparateAmount;
// 4. 计算平台分账金额平台一定参与分账
platAmount = platRatio.multiply(new BigDecimal(totalSeparateAmount))
.setScale(0, RoundingMode.HALF_UP)
.intValue();
// 校验平台分账金额不能为负数
if (platAmount < 0) {
throw new IllegalArgumentException("平台分账金额计算异常");
}
// 确保不超过剩余金额
if (platAmount > remainingAmount) {
platAmount = remainingAmount;
}
// 更新剩余金额
remainingAmount -= platAmount;
// 5. 判断代理商是否参与分账
boolean isAgent2ndParticipate = agent2ndRatio != null && agent2ndRatio.compareTo(BigDecimal.ZERO) > 0;
boolean isAgent1stParticipate = agent1stRatio != null && agent1stRatio.compareTo(BigDecimal.ZERO) > 0;
// 6. 按优先级顺序计算代理商分账金额
// 优先级平台 -> 二级代理商 -> 一级代理商
if (isAgent2ndParticipate) {
// 计算二级代理商分账金额
agent2ndAmount = agent2ndRatio.multiply(new BigDecimal(totalSeparateAmount))
.setScale(0, RoundingMode.HALF_UP)
.intValue();
// 校验二级代理商分账金额不能为负数
if (agent2ndAmount < 0) {
throw new IllegalArgumentException("二级代理商分账金额计算异常");
}
// 确保不超过剩余金额
if (agent2ndAmount > remainingAmount) {
agent2ndAmount = remainingAmount;
}
remainingAmount -= agent2ndAmount;
}
if (isAgent1stParticipate) {
// 计算一级代理商分账金额
agent1stAmount = agent1stRatio.multiply(new BigDecimal(totalSeparateAmount))
.setScale(0, RoundingMode.HALF_UP)
.intValue();
// 校验一级代理商分账金额不能为负数
if (agent1stAmount < 0) {
throw new IllegalArgumentException("一级代理商分账金额计算异常");
}
// 确保不超过剩余金额
if (agent1stAmount > remainingAmount) {
agent1stAmount = remainingAmount;
}
remainingAmount -= agent1stAmount;
}
// 7. 最后计算商家分账金额使用剩余所有金额
mchAmount = remainingAmount;
// 校验商家分账金额不能为负数
if (mchAmount < 0) {
throw new IllegalArgumentException("商家分账金额计算异常");
}
}
/**
* 计算商家实际分账比例
*
* @throws IllegalArgumentException 当商家实际分账比例低于阈值时抛出异常
*/
private void calculateActualMchRatio() {
if (totalSeparateAmount != null && totalSeparateAmount > 0 && mchAmount != null) {
// 计算实际比例保留6位小数
mchRatio = new BigDecimal(mchAmount)
.divide(new BigDecimal(totalSeparateAmount), 6, RoundingMode.HALF_UP);
// 如果计算出的实际比例低于阈值打印日志并抛出异常
if (mchRatio.compareTo(MCH_RATIO_THRESHOLD) < 0) {
System.err.println("警告: 商家实际分账比例低于阈值,当前比例: " + mchRatio + ",阈值: " + MCH_RATIO_THRESHOLD);
throw new IllegalArgumentException("商家分账低于阈值");
}
}
}
/**
* 校验分账金额总和不能超过总金额
*
* @throws IllegalArgumentException 当分账金额总和超过总金额时抛出异常
*/
private void validateSeparateAmountTotal() {
int totalAmount = 0;
totalAmount += (lklAmount != null ? lklAmount : 0);
totalAmount += (platAmount != null ? platAmount : 0);
totalAmount += (agent2ndAmount != null ? agent2ndAmount : 0);
totalAmount += (agent1stAmount != null ? agent1stAmount : 0);
totalAmount += (mchAmount != null ? mchAmount : 0);
if (totalAmount > totalSeparateAmount) {
// 记录详细日志
System.err.println("分账金额总和超过总金额,分账金额总和: " + totalAmount + ",总金额: " + totalSeparateAmount);
throw new IllegalArgumentException("分账金额总和超过总金额");
}
}
/**
* 生成对象的字符串表示
*
* @return 对象的字符串表示
*/
@Override
public String toString() {
return "分账计算结果{" +
"总分账金额(分) totalSeparateAmount=" + totalSeparateAmount +
", 可分账金额(分) canSeparateAmount=" + canSeparateAmount +
", 拉卡拉可分账金额参考(分) refCanSeparateAmount=" + refCanSeparateAmount +
", 配送费(分) shippingFee=" + shippingFee +
", 拉卡拉分账比例 lklRatio=" + lklRatio +
", 商户分账比例 mchRatio=" + mchRatio +
", 平台分账比例 platRatio=" + platRatio +
", 一级代理商分账比例 agent1stRatio=" + agent1stRatio +
", 二级代理商分账比例 agent2ndRatio=" + agent2ndRatio +
", 拉卡拉分账金额(分) lklAmount=" + lklAmount +
", 商户分账金额(分) mchAmount=" + mchAmount +
", 平台分账金额(分) platAmount=" + platAmount +
", 一级代理商分账金额(分) agent1stAmount=" + agent1stAmount +
", 二级代理商分账金额(分) agent2ndAmount=" + agent2ndAmount +
'}';
}
/**
* 将对象转换为JSON格式字符串
*
* @return JSON格式字符串
*/
public String toJSON() {
String sb = "{" +
"\"totalSeparateAmount\":" + totalSeparateAmount + "," +
"\"canSeparateAmount\":" + canSeparateAmount + "," +
"\"refCanSeparateAmount\":" + refCanSeparateAmount + "," +
"\"shippingFee\":" + shippingFee + "," +
"\"lklRatio\":" + (lklRatio != null ? "\"" + lklRatio + "\"" : "null") + "," +
"\"mchRatio\":" + (mchRatio != null ? "\"" + mchRatio + "\"" : "null") + "," +
"\"platRatio\":" + (platRatio != null ? "\"" + platRatio + "\"" : "null") + "," +
"\"agent1stRatio\":" + (agent1stRatio != null ? "\"" + agent1stRatio + "\"" : "null") + "," +
"\"agent2ndRatio\":" + (agent2ndRatio != null ? "\"" + agent2ndRatio + "\"" : "null") + "," +
"\"lklAmount\":" + lklAmount + "," +
"\"mchAmount\":" + mchAmount + "," +
"\"platAmount\":" + platAmount + "," +
"\"agent1stAmount\":" + agent1stAmount + "," +
"\"agent2ndAmount\":" + agent2ndAmount +
"}";
return sb;
}
}

View File

@ -558,25 +558,27 @@ public class LakalaPayServiceImpl implements LakalaPayService {
log.warn("[拉卡拉退款] 退款金额不合法: refundAmount={}", refundAmount);
return Pair.of(false, I18nUtil._("退款金额不合法!"));
}
if (StrUtil.hasBlank(lklMerchantNo, lklTermNo)) {
// 4. 获取店铺的拉卡拉商户号和终端号
ShopStoreBase shopStoreBase = shopService.getLklMerchantNoAndTermNo(storeId);
if (shopStoreBase == null) {
log.error("[拉卡拉退款] 无法获取店铺信息: storeId={}", storeId);
return Pair.of(false, I18nUtil._("无法获取店铺信息,退款失败!"));
}
// 3. 初始化拉卡拉SDK
initLKLSDK();
if (StrUtil.isBlank(shopStoreBase.getLkl_merchant_no()) || StrUtil.isBlank(shopStoreBase.getLkl_term_no())) {
log.error("[拉卡拉退款] 无法获取店铺的拉卡拉商户号或终端号: storeId={}, merchantNo={}, termNo={}",
storeId, shopStoreBase.getLkl_merchant_no(), shopStoreBase.getLkl_term_no());
return Pair.of(false, I18nUtil._("缺少商户号参数,退款失败!"));
}
// 4. 获取店铺的拉卡拉商户号和终端号
ShopStoreBase shopStoreBase = shopService.getLklMerchantNoAndTermNo(storeId);
if (shopStoreBase == null) {
log.error("[拉卡拉退款] 无法获取店铺信息: storeId={}", storeId);
return Pair.of(false, I18nUtil._("无法获取店铺信息,退款失败!"));
}
if (StrUtil.isBlank(shopStoreBase.getLkl_merchant_no()) || StrUtil.isBlank(shopStoreBase.getLkl_term_no())) {
log.error("[拉卡拉退款] 无法获取店铺的拉卡拉商户号或终端号: storeId={}, merchantNo={}, termNo={}",
storeId, shopStoreBase.getLkl_merchant_no(), shopStoreBase.getLkl_term_no());
return Pair.of(false, I18nUtil._("缺少商户号参数,退款失败!"));
// 如果商户号和终端号是空的
lklMerchantNo = StrUtil.isBlank(lklMerchantNo) ? shopStoreBase.getLkl_merchant_no() : lklMerchantNo;
lklTermNo = StrUtil.isBlank(lklTermNo) ? shopStoreBase.getLkl_term_no() : lklTermNo;
}
// TODO 重要的逻辑获取是否已经分账已分账分账退回查商家账户余额够不够退回够就执行退回
if (StrUtil.isBlank(refundReason)) {
refundReason = "商家与买方协商退款";
}
@ -585,17 +587,16 @@ public class LakalaPayServiceImpl implements LakalaPayService {
V3LabsRelationRefundRequest refundRequest = new V3LabsRelationRefundRequest();
refundRequest.setOutTradeNo(outTradeNo);
refundRequest.setOriginTradeNo(originTradeNo);
lklMerchantNo = StrUtil.isBlank(lklMerchantNo) ? shopStoreBase.getLkl_merchant_no() : lklMerchantNo;
lklTermNo = StrUtil.isBlank(lklTermNo) ? shopStoreBase.getLkl_term_no() : lklTermNo;
refundRequest.setMerchantNo(lklMerchantNo);
refundRequest.setTermNo(lklTermNo);
refundRequest.setRefundAmount(refundAmount);
refundRequest.setRefundReason(refundReason);
refundRequest.setLocationInfo(new V3LabsTradeLocationInfo(requestIp, null, ""));
log.info("[拉卡拉退款] 请求参数: {}", JSONUtil.toJsonStr(refundRequest));
// 3. 初始化拉卡拉SDK
initLKLSDK();
String responseString = LKLSDK.httpPost(refundRequest);
// 6. 处理响应
if (StrUtil.isBlank(responseString)) {

File diff suppressed because one or more lines are too long

View File

@ -291,8 +291,8 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
// }
if (StrUtil.isBlank(trade_row.getTrade_title())) {
trade_row.setTrade_title("小发同城线上订单商品");
trade_row.setTrade_desc("小发同城线上订单商品");
trade_row.setTrade_title("小发同城-线上商品");
trade_row.setTrade_desc("小发同城-线上购买的商品");
}
// 设置店铺ID
@ -671,10 +671,7 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
String requestIP = IpKit.getRealIp(request);
String notifyUrl = domain + "/lkl_wxPay_notify_url";
String storeIdStr = Convert.toStr(storeId);// 店铺Id
// TODO 判断订单有没有运费有运费请求合单交易没有运费请求聚合主扫交易
cn.hutool.json.JSONObject lakalaRespJSON = new cn.hutool.json.JSONObject();
BigDecimal shippingFee = shopService.getOrderShippingFee(out_trade_no);
if (shippingFee == null || shippingFee.intValue() <= 0) {
shippingFee = BigDecimal.ZERO;
@ -686,24 +683,25 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
logger.debug("预支付时,查到的订单{},商家配送费:{}元,平台最低配送费要求:{}分", out_trade_no, shippingFee, innerMinDeliverFee);
// 平台最低配送费单位
if (innerMinDeliverFee == null || innerMinDeliverFee.intValue() <= 0) {
// 没有运费
// 拉卡拉预支付返回参数
lakalaRespJSON = lakalaPayService.lklTransPreOrder(shopStoreBase.getLkl_merchant_no(), shopStoreBase.getLkl_term_no(),
appId, openId, storeIdStr, out_trade_no, subject, total_amt,
notifyUrl,
requestIP, trade_remark);
} else { // 有运费的情况
// 拉卡拉合单预支付返回参数
// 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(innerMinDeliverFee),
notifyUrl,
requestIP, trade_remark);
}
// if (innerMinDeliverFee == null || innerMinDeliverFee.intValue() <= 0) { // 没有运费
// 内部运费统一由分账接收方收取了 2025-10-11
// 拉卡拉预支付返回参数
// TODO 判断订单有没有运费有运费请求合单交易没有运费请求聚合主扫交易
cn.hutool.json.JSONObject lakalaRespJSON = lakalaPayService.lklTransPreOrder(shopStoreBase.getLkl_merchant_no(), shopStoreBase.getLkl_term_no(),
appId, openId, storeIdStr, out_trade_no, subject, total_amt,
notifyUrl,
requestIP, trade_remark);
// } else { // 有运费的情况
// // 拉卡拉合单预支付返回参数
// // 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(innerMinDeliverFee),
// notifyUrl,
// requestIP, trade_remark);
// }
logger.debug("拉卡拉合单预支付返回参数:{}", lakalaRespJSON);

View File

@ -11,7 +11,7 @@ package com.suisung.mall.shop.lakala.service;
import cn.hutool.json.JSONObject;
import com.suisung.mall.common.api.CommonResult;
import com.suisung.mall.common.modules.store.ShopMchEntry;
import com.suisung.mall.common.pojo.dto.LklSeparateDTO;
import com.suisung.mall.common.pojo.dto.LklSeparateWithTotalAmountDTO;
import org.springframework.data.util.Pair;
import javax.servlet.http.HttpServletRequest;
@ -355,7 +355,6 @@ public interface LakalaApiService {
/**
* 商户分账参数计算及评估
*
* @param splitMode 分账模式1-总金额为基准分账2-可分账金额基准分账必填参数
* @param orderPayAmount 订单支付总金额单位必填参数
* @param shippingFeeInner 平台内部配送费单位必填参数
* @param mchSplitRatioRaw 商户分账比例值分子值如10表示10%必填参数
@ -365,13 +364,12 @@ public interface LakalaApiService {
* @param refCanSeparateAmt 参考可分金额单位 可选参数
* @return Pair<Boolean, LklSeparateDTO> 分账参数评估结果第一个元素表示是否成功第二个元素为分账参数对象
*/
Pair<Boolean, LklSeparateDTO> calculateAndEvaluateSharingParams(int splitMode,
Integer orderPayAmount,
Integer shippingFeeInner,
BigDecimal mchSplitRatioRaw,
BigDecimal platSplitRatio,
BigDecimal agent1stRatio,
BigDecimal agent2ndRatio,
Integer refCanSeparateAmt);
Pair<Boolean, LklSeparateWithTotalAmountDTO> calculateAndEvaluateSharingParams(Integer orderPayAmount,
Integer shippingFeeInner,
BigDecimal mchSplitRatioRaw,
BigDecimal platSplitRatio,
BigDecimal agent1stRatio,
BigDecimal agent2ndRatio,
Integer refCanSeparateAmt);
}

View File

@ -30,7 +30,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.pojo.dto.LklSeparateWithTotalAmountDTO;
import com.suisung.mall.common.service.impl.CommonService;
import com.suisung.mall.common.utils.*;
import com.suisung.mall.core.web.service.RedisService;
@ -860,7 +860,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
return JSONUtil.createObj().set("code", "FAIL").set("message", "交易状态未成功,不做任何处理!");
}
if (StrUtil.isBlank(logNo) || StrUtil.isBlank(merchantNo) || StrUtil.isBlank(originTradeNo) || StrUtil.isBlank(originLogNo)) {
if (StrUtil.hasBlank(logNo, merchantNo, originTradeNo, originLogNo)) {
log.warn("[确认收货通知] 关键参数为空: logNo={}, merchantNo={}, originTradeNo={}, originLogNo={}",
logNo, merchantNo, originTradeNo, originLogNo);
return JSONUtil.createObj().set("code", "FAIL").set("message", "关键编号返回空值!");
@ -888,7 +888,7 @@ 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());
@ -2510,34 +2510,36 @@ public class LakalaApiServiceImpl implements LakalaApiService {
}
// 获取代理商分账信息
BigDecimal platformSplitRatio = BigDecimal.valueOf(0.01);
BigDecimal distributorSplitRatio = BigDecimal.ZERO;
List<LklLedgerMerReceiverBind> distributorReceivers = lklLedgerMerReceiverBindService.selectDistributorByMerCupNo(merchantNo);
if (CollUtil.isNotEmpty(distributorReceivers)) {
distributorSplitRatio = BigDecimal.valueOf(1).subtract(mchSplitRatio).subtract(platformSplitRatio);
log.debug("[分账操作] 检测到代理商存在,调整分账比例: 代理商比例={}, 平台比例={}", distributorSplitRatio, platformSplitRatio);
BigDecimal platformSplitRatio = BigDecimal.valueOf(0.01); // 默认平台比例 1%
BigDecimal agent2ndSplitRatio = null;
// 代理商绑定列表
List<LklLedgerMerReceiverBind> lklLedgerMerReceiverBindList = lklLedgerMerReceiverBindService.selectDistributorByMerCupNo(merchantNo);
if (CollUtil.isNotEmpty(lklLedgerMerReceiverBindList)) {
// 县级代理商比例值 = 1-商家比例值-平台比例值
agent2ndSplitRatio = BigDecimal.ONE.subtract(mchSplitRatio).subtract(platformSplitRatio);
log.debug("[分账操作] 检测到代理商存在,调整分账比例: 代理商比例={}, 平台比例={}", agent2ndSplitRatio, platformSplitRatio);
} else {
platformSplitRatio = BigDecimal.valueOf(1).subtract(mchSplitRatio);
distributorSplitRatio = null;
// 平台比例值 = 1-商家比例值
platformSplitRatio = BigDecimal.ONE.subtract(mchSplitRatio);
}
// 内部配送费
// 内部配送费单位
Integer shoppingFeeInner = CheckUtil.isEmpty(shopOrderLkl.getShopping_fee_inner()) ? 0 : shopOrderLkl.getShopping_fee_inner();
// 计算拉卡拉手续费商家分账金额平台和代理商的分账金额
Pair<Boolean, LklSeparateDTO> calcResult = calculateAndEvaluateSharingParams(
CommonConstant.SeparateCalcMode_CanSeparateAmt,
Pair<Boolean, LklSeparateWithTotalAmountDTO> calcResult = calculateAndEvaluateSharingParams(
shopOrderLkl.getTotal_amt(),
shoppingFeeInner,
mchSplitRatio,
platformSplitRatio,
null, distributorSplitRatio, refCanSeparateAmt);
null, agent2ndSplitRatio, refCanSeparateAmt);
if (calcResult == null || !calcResult.getFirst() || calcResult.getSecond() == null) {
log.error("[分账操作] 分账参数评估,结果无法分账");
return Pair.of(false, "分账数据评估,结果无法分账");
}
LklSeparateDTO lklSeparateDTO = calcResult.getSecond();
LklSeparateWithTotalAmountDTO lklSeparateDTO = calcResult.getSecond();
log.debug("[分账操作] 分账参数计算结果:{}", lklSeparateDTO);
@ -2550,57 +2552,71 @@ public class LakalaApiServiceImpl implements LakalaApiService {
shopOrderLkl.setSplit_amt_ref(refCanSeparateAmt);
}
// 分账金额校验
// 分账金额校验
if (CheckUtil.isEmpty(refCanSeparateAmt)) {
String errorMsg = String.format("[分账操作] 店铺[%s]订单[%s]分账金额[%d]低于1分钱跳过分账",
String errorMsg = String.format("[分账操作] 店铺[%s]订单[%s]分账金额[%d]低于1分钱跳过分账",
shopOrderLkl.getStore_id(), orderId, refCanSeparateAmt);
log.error(errorMsg);
if (existingSeparateRecord != null) {
lklOrderSeparateService.updateRemark(existingSeparateRecord.getId(), errorMsg);
}
return Pair.of(false, "订单分账金额低于1分钱");
return Pair.of(false, "订单分账金额低于1分钱");
}
// 构建分账接收方列表
List<V3SacsSeparateRecvDatas> recvDatas = new ArrayList<>();
Integer merchantAmount = lklSeparateDTO.getMchAmount();
Integer platformAmount = lklSeparateDTO.getPlatAmount();
Integer agentAmount = lklSeparateDTO.getAgent2ndAmount();
Integer agent2ndAmount = lklSeparateDTO.getAgent2ndAmount();
log.info("[分账操作] 金额计算结果:订单={}, 商户={}, 总金额={}分, 可分金额={}分, 商家比例={}, 商家分得={}分, 平台比例={}, 平台分得={}分, 代理商比例={}, 代理商分得={}分",
log.info("[分账操作] 金额计算结果:订单={}, 商户={}, 总金额={}分, 可分金额={}分, 商家比例={}, 商家分得={}分, 平台比例={}, 平台分得={}分, 县级代理商比例={}, 县级代理商分得={}分",
orderId, merchantNo, shopOrderLkl.getTotal_amt(), refCanSeparateAmt, mchSplitRatio, merchantAmount,
platformSplitRatio, platformAmount, distributorSplitRatio, agentAmount);
platformSplitRatio, platformAmount, agent2ndSplitRatio, agent2ndAmount);
// 构建分账接收方分账参数
// 构建分账接收方分账列表参数
List<V3SacsSeparateRecvDatas> recvDatas = new ArrayList<>();
// 商家分账参数
if (merchantAmount != null && merchantAmount > 0) {
if (CheckUtil.isNotEmpty(merchantAmount)) {
V3SacsSeparateRecvDatas receiver = new V3SacsSeparateRecvDatas();
receiver.setRecvMerchantNo(merchantNo);
receiver.setSeparateValue(merchantAmount.toString());
recvDatas.add(receiver);
log.debug("[分账操作] 添加商家接收方: merchantNo={}, amount={}", merchantNo, merchantAmount);
}
// 平台分账参数
if (platformAmount != null && platformAmount > 0) {
if (CheckUtil.isNotEmpty(platformAmount)) {
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 != null && agentAmount > 0 && CollUtil.isNotEmpty(distributorReceivers)) {
LklLedgerMerReceiverBind distributorReceiver = distributorReceivers.get(0);
if (distributorReceiver != null && StrUtil.isNotBlank(distributorReceiver.getReceiver_no())) {
// 县级代理商分账参数
if (CollUtil.isNotEmpty(lklLedgerMerReceiverBindList) && CheckUtil.isNotEmpty(agent2ndAmount)) {
LklLedgerMerReceiverBind agent2ndReceiver = lklLedgerMerReceiverBindList.get(0);
if (agent2ndReceiver != null && StrUtil.isNotBlank(agent2ndReceiver.getReceiver_no())) {
V3SacsSeparateRecvDatas receiver = new V3SacsSeparateRecvDatas();
receiver.setRecvNo(distributorReceiver.getReceiver_no());
receiver.setSeparateValue(agentAmount.toString());
receiver.setRecvNo(agent2ndReceiver.getReceiver_no());
receiver.setSeparateValue(Convert.toStr(agent2ndAmount));
recvDatas.add(receiver);
log.debug("[分账操作] 添加代理商接收方: receiverNo={}, amount={}", distributorReceiver.getReceiver_no(), agentAmount);
log.debug("[分账操作] 添加县级代理商接收方: receiverNo={}, amount={}", agent2ndReceiver.getReceiver_no(), agent2ndAmount);
// 平台内部配送费由县级代理商代收 add 2025-10-11
V3SacsSeparateRecvDatas shippingFeeReceiver = new V3SacsSeparateRecvDatas();
shippingFeeReceiver.setRecvNo(agent2ndReceiver.getReceiver_no());
shippingFeeReceiver.setSeparateValue(Convert.toStr(shoppingFeeInner));
recvDatas.add(shippingFeeReceiver);
}
} else {
// 没有县级代理商的时候配送费暂由平台代收 add 2025-10-11
V3SacsSeparateRecvDatas shippingFeeReceiver = new V3SacsSeparateRecvDatas();
shippingFeeReceiver.setRecvNo(platformReceiver.getReceiver_no());
shippingFeeReceiver.setSeparateValue(Convert.toStr(shoppingFeeInner));
recvDatas.add(shippingFeeReceiver);
}
// 初始化拉卡拉SDK
@ -2619,8 +2635,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
separateRequest.setNotifyUrl(projectDomain + "/api/mobile/shop/lakala/sacs/separateNotify");
separateRequest.setRecvDatas(recvDatas);
log.info("[分账操作] 分账接收方数量={}", recvDatas.size());
log.debug("[分账操作] 请求详细参数: {}", JSONUtil.toJsonStr(separateRequest));
log.debug("[分账操作] 分账接收方数量={},请求详细参数: {}", recvDatas.size(), JSONUtil.toJsonStr(separateRequest));
// 发送分账请求
log.info("[分账操作] 向拉卡拉发送分账请求:订单={}, 商户={}, 分账流水号={}",
@ -3617,7 +3632,6 @@ public class LakalaApiServiceImpl implements LakalaApiService {
/**
* 商户分账参数计算及评估
*
* @param splitMode 分账模式1-总金额为基准分账2-可分账金额基准分账必填参数
* @param orderPayAmount 订单支付总金额单位必填参数
* @param shippingFeeInner 平台内部配送费单位必填参数
* @param mchSplitRatioRaw 商户分账比例值分子值如10表示10%必填参数
@ -3628,17 +3642,17 @@ public class LakalaApiServiceImpl implements LakalaApiService {
* @return Pair<Boolean, LklSeparateDTO> 分账参数评估结果第一个元素表示是否成功第二个元素为分账参数对象
*/
@Override
public Pair<Boolean, LklSeparateDTO> calculateAndEvaluateSharingParams(int splitMode,
Integer orderPayAmount,
Integer shippingFeeInner,
BigDecimal mchSplitRatioRaw,
BigDecimal platSplitRatio,
BigDecimal agent1stRatio,
BigDecimal agent2ndRatio,
Integer refCanSeparateAmt) {
log.debug("[分账参数计算] 开始计算分账参数: splitMode={}, orderPayAmount={}, shippingFeeInner={}, " +
public Pair<Boolean, LklSeparateWithTotalAmountDTO> calculateAndEvaluateSharingParams(
Integer orderPayAmount,
Integer shippingFeeInner,
BigDecimal mchSplitRatioRaw,
BigDecimal platSplitRatio,
BigDecimal agent1stRatio,
BigDecimal agent2ndRatio,
Integer refCanSeparateAmt) {
log.debug("[分账参数计算] 开始计算分账参数: orderPayAmount={}, shippingFeeInner={}, " +
"mchSplitRatioRaw={}, platSplitRatio={}, agent1stRatio={}, agent2ndRatio={}, refCanSeparateAmt={}",
splitMode, orderPayAmount, shippingFeeInner, mchSplitRatioRaw, platSplitRatio,
orderPayAmount, shippingFeeInner, mchSplitRatioRaw, platSplitRatio,
agent1stRatio, agent2ndRatio, refCanSeparateAmt);
// 参数校验
@ -3652,10 +3666,6 @@ public class LakalaApiServiceImpl implements LakalaApiService {
return Pair.of(false, null);
}
if (splitMode != 1 && splitMode != 2) {
log.warn("[分账参数计算] 分账模式参数错误: splitMode={}", splitMode);
return Pair.of(false, null);
}
// 计算商家分账比例转换为小数
BigDecimal mchSplitRatio = mchSplitRatioRaw.divide(new BigDecimal(100));
@ -3674,7 +3684,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
log.debug("[分账参数计算] 配送费: {}, 拉卡拉费率: {}", actualShippingFeeInner, wxFeeRatio);
// 构建分账参数对象
LklSeparateDTO lklSeparateDTO = new LklSeparateDTO();
LklSeparateWithTotalAmountDTO lklSeparateDTO = new LklSeparateWithTotalAmountDTO();
lklSeparateDTO.setTotalSeparateAmount(orderPayAmount);
lklSeparateDTO.setShippingFee(actualShippingFeeInner);
lklSeparateDTO.setLklRatio(wxFeeRatio); // 拉卡拉给的微信分账比例 0.0025 千分之2.5
@ -3698,25 +3708,20 @@ public class LakalaApiServiceImpl implements LakalaApiService {
log.debug("[分账参数计算] 设置参考可分账金额: {}", refCanSeparateAmt);
}
// 根据分账模式执行不同的分账计算
LklSeparateDTO.SharingResult canSeparateAmtResult;
if (splitMode == 1) {
// 总金额为基准分账
log.debug("[分账参数计算] 使用总金额为基准分账模式");
canSeparateAmtResult = lklSeparateDTO.sharingOnTotalAmount();
} else {
// 可分金额基准分账
log.debug("[分账参数计算] 使用可分账金额基准分账模式");
canSeparateAmtResult = lklSeparateDTO.sharingOnCanSeparateAmount();
}
try {
// 根据分账模式执行不同的分账计算
Pair<Boolean, LklSeparateWithTotalAmountDTO> canSeparateAmtResult = lklSeparateDTO.calculateSeparateAmount();
if (!canSeparateAmtResult.getFirst()) {
log.warn("[分账参数计算] 分账参数有误,分账估算失败");
return Pair.of(false, lklSeparateDTO);
}
if (!canSeparateAmtResult.isSuccess()) {
log.warn("[分账参数计算] 分账参数评估失败: {}", canSeparateAmtResult.getErrorMessage());
log.info("[分账参数计算] 分账估算成功, result={}", lklSeparateDTO);
return Pair.of(true, lklSeparateDTO);
} catch (Exception e) {
log.error("[分账参数计算] 分账参数有误,分账估算失败", e);
return Pair.of(false, lklSeparateDTO);
}
log.info("[分账参数计算] 分账参数计算评估成功, result={}", lklSeparateDTO);
return Pair.of(true, lklSeparateDTO);
}

View File

@ -56,7 +56,7 @@ import com.suisung.mall.common.modules.product.ShopProductItem;
import com.suisung.mall.common.modules.product.ShopProductValidPeriod;
import com.suisung.mall.common.modules.store.*;
import com.suisung.mall.common.modules.user.*;
import com.suisung.mall.common.pojo.dto.LklSeparateDTO;
import com.suisung.mall.common.pojo.dto.LklSeparateWithTotalAmountDTO;
import com.suisung.mall.common.pojo.dto.StandardAddressDTO;
import com.suisung.mall.common.pojo.dto.WxOrderBaseInfoDTO;
import com.suisung.mall.common.pojo.req.*;
@ -7679,8 +7679,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
BigDecimal storeSplitRatio = shopStoreBaseService.getStoreSplitRatio(store_id, false);
// 计算平台和代理商的分账金额
Pair<Boolean, LklSeparateDTO> calcResult = lakalaApiService.calculateAndEvaluateSharingParams(
CommonConstant.SeparateCalcMode_CanSeparateAmt,
Pair<Boolean, LklSeparateWithTotalAmountDTO> calcResult = lakalaApiService.calculateAndEvaluateSharingParams(
Convert.toInt(order_payment_amount.multiply(BigDecimal.valueOf(100))),
innerMinDeliverFee,
storeSplitRatio,
@ -7690,25 +7689,29 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
// 计算平台费
if (calcResult != null && calcResult.getFirst() && calcResult.getSecond() != null) {
try {
LklSeparateDTO lklSeparateDTO = calcResult.getSecond();
LklSeparateWithTotalAmountDTO lklSeparateDTO = calcResult.getSecond();
// 确保分账金额不为负数
BigDecimal totalSeparateAmount = BigDecimal.valueOf(lklSeparateDTO.getCanSeparateAmount())
.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
BigDecimal platformFee = BigDecimal.valueOf(lklSeparateDTO.getPlatAmount() + lklSeparateDTO.getAgent1stAmount() + lklSeparateDTO.getAgent2ndAmount())
.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
BigDecimal lklFee = BigDecimal.valueOf(lklSeparateDTO.getLklAmount()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
// 防止负值
data_row.setTotal_separate_value(totalSeparateAmount.max(BigDecimal.ZERO));
data_row.setPlatform_fee(platformFee.max(BigDecimal.ZERO));
data_row.setLkl_fee(lklFee.max(BigDecimal.ZERO));
} catch (Exception e) {
log.warn("分账金额计算异常,使用默认值: {}", e.getMessage());
data_row.setTotal_separate_value(BigDecimal.ZERO);
data_row.setPlatform_fee(BigDecimal.ZERO);
data_row.setLkl_fee(BigDecimal.ZERO);
}
} else {
log.warn("拉卡拉分账参数计算失败,使用默认值");
data_row.setTotal_separate_value(BigDecimal.ZERO);
data_row.setPlatform_fee(BigDecimal.ZERO);
data_row.setLkl_fee(BigDecimal.ZERO);
}
Integer voucher_id = (Integer) order_voucher_row.get("voucher_id");

View File

@ -1619,10 +1619,15 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
logger.debug("最后一个商品已添加打包费到退款金额订单ID: {}", order_id);
}
// 有运费的重新生成一个运费退单
// if (order_data_row != null &&
// order_data_row.getOrder_shipping_fee_inner() != null &&
// order_data_row.getOrder_shipping_fee_inner().compareTo(BigDecimal.ZERO) > 0) {
// 注意商家配置的配送费
if (order_data_row != null &&
order_data_row.getOrder_shipping_fee_inner() != null &&
order_data_row.getOrder_shipping_fee_inner().compareTo(BigDecimal.ZERO) > 0) {
order_data_row.getOrder_shipping_fee() != null &&
order_data_row.getOrder_shipping_fee().compareTo(BigDecimal.ZERO) > 0) {
// 运费大于0的 执行退运费操作, 有两种方案1生成退运费售后服务单 2直接执行退款
// 1生成独立退运费售后服务单需注意运费是退给运费代理商的需要获取代理商的交易单号
@ -1631,13 +1636,16 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
Integer buyer_user_id = info_row.getBuyer_user_id();
Integer storeId = info_row.getStore_id();
// 平台内部订单
BigDecimal orderShippingFeeInner = order_data_row.getOrder_shipping_fee_inner();
if (orderShippingFeeInner == null || orderShippingFeeInner.compareTo(BigDecimal.ZERO) <= 0) {
orderShippingFeeInner = shopOrderLklService.getOrderShippingFeeInnerToDecimal(storeId, order_id);
}
// // 平台内部订单配送
// BigDecimal orderShippingFeeInner = order_data_row.getOrder_shipping_fee_inner();
// if (orderShippingFeeInner == null || orderShippingFeeInner.compareTo(BigDecimal.ZERO) <= 0) {
// orderShippingFeeInner = shopOrderLklService.getOrderShippingFeeInnerToDecimal(storeId, order_id);
// }
return_order_shipping_fee_row.setReturn_refund_amount(orderShippingFeeInner); // 平台内部配送费退款金额
// 商家设置的配送费
BigDecimal orderShippingFee = order_data_row.getOrder_shipping_fee();
return_order_shipping_fee_row.setReturn_refund_amount(orderShippingFee); // 平台内部配送费退款金额
BigDecimal order_points_fee = ObjectUtil.defaultIfNull(order_data_row.getOrder_points_fee(), BigDecimal.ZERO);
BigDecimal order_refund_agree_points = ObjectUtil.defaultIfNull(order_data_row.getOrder_refund_agree_points(), BigDecimal.ZERO);
@ -1649,7 +1657,7 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
return_order_shipping_fee_row.setReturn_reason_id(0);
return_order_shipping_fee_row.setReturn_buyer_message(I18nUtil._("订单(配送费)退款"));
return_order_shipping_fee_row.setStore_id(storeId);
return_order_shipping_fee_row.setReturn_refund_point(NumberUtil.min(return_refund_point, orderShippingFeeInner));
return_order_shipping_fee_row.setReturn_refund_point(NumberUtil.min(return_refund_point, orderShippingFee));
return_order_shipping_fee_row.setReturn_add_time(now); // 添加时间
return_order_shipping_fee_row.setReturn_tel("");
@ -1733,12 +1741,12 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
try {
if (!payService.doRefund(returnOrder)) {
logger.error("执行退款操作失败!退单列表: {}", return_ids);
throw new ApiException(ResultCode.FAILED);
throw new ApiException("暂无法退款,请稍候再重试!");
}
} catch (Exception e) {
logger.error("执行退款操作异常!退单列表: {}", return_ids, e);
// 根据业务需要决定是抛出异常触发回滚还是其他处理方式
throw new ApiException("退款服务调用异常: " + e.getMessage());
throw new ApiException("暂无法退款,请稍候再重试!");
}
logger.info("退款操作执行成功,退单列表: {}", return_ids);

View File

@ -521,10 +521,10 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
shopOrderInfoService.changeOrderStatus(shopOrderId, StateCode.ORDER_STATE_PICKING, 0, 0);
// 个推推送消息
JSONObject payload = new JSONObject();
payload.put("category", CommonConstant.PUSH_MSG_CATE_MCH_ORDER_DETAIL);
payload.put("orderId", shopOrderId);
pushMessageService.noticeMerchantEmployeeOrderAction(null, shopOrderId, "您有一笔新的订单", "您有一笔同城订单[" + shopOrderId + "],请及时处理。", payload);
// JSONObject payload = new JSONObject();
// payload.put("category", CommonConstant.PUSH_MSG_CATE_MCH_ORDER_DETAIL);
// payload.put("orderId", shopOrderId);
// pushMessageService.noticeMerchantEmployeeOrderAction(null, shopOrderId, "您有一笔新的订单", "您有一笔同城订单[" + shopOrderId + "],请及时处理。", payload);
return Pair.of(true, "顺丰同城下单成功!");
}
@ -988,6 +988,7 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
// 上传发货信息到微信
wxOrderShippingService.uploadShippingInfoToWx(2, shopOrderId);
} else if (shopStoreSfOrder.getOrder_status().equals(StateCode.SF_ORDER_STATUS_ARRIVED)) {
// 顺丰同城状态12-配送员到店;
// 商城订单状态 2020-待配货 2030; //待发货
@ -1007,6 +1008,7 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
pushRemark = "配送员已取货。";
// 上传发货信息到微信
wxOrderShippingService.uploadShippingInfoToWx(2, shopOrderId);
} else if (shopStoreSfOrder.getOrder_status().equals(StateCode.SF_ORDER_STATUS_FINISH)) {
// 顺丰同城状态17-配送员妥投完单;
// orderStatus = StateCode.ORDER_STATE_FINISH;
@ -1028,10 +1030,10 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
shopOrderInfoService.changeOrderStatus(shopOrderId, orderStatus, orderIsOutStatus, orderIsShippedStatus);
// 消息推送
JSONObject payload = new JSONObject();
payload.put("category", CommonConstant.PUSH_MSG_CATE_MCH_ORDER_DETAIL);
payload.put("orderId", shopOrderId);
pushMessageService.noticeMerchantEmployeeOrderAction(null, shopOrderId, "", "顺丰同城订单[" + shopOrderId + "]" + pushRemark, payload);
// JSONObject payload = new JSONObject();
// payload.put("category", CommonConstant.PUSH_MSG_CATE_MCH_ORDER_DETAIL);
// payload.put("orderId", shopOrderId);
// pushMessageService.noticeMerchantEmployeeOrderAction(null, shopOrderId, "", "顺丰同城订单[" + shopOrderId + "]" + pushRemark, payload);
return new ThirdApiRes().success("success");
}
@ -1118,10 +1120,10 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
String orderId = shopStoreSfOrder.getShop_order_id();
// 消息推送
JSONObject payload = new JSONObject();
payload.put("category", CommonConstant.PUSH_MSG_CATE_MCH_ORDER_DETAIL);
payload.put("orderId", orderId);
pushMessageService.noticeMerchantEmployeeOrderAction(null, orderId, "", "顺丰同城订单[" + orderId + "]已完成配送。", null);
// JSONObject payload = new JSONObject();
// payload.put("category", CommonConstant.PUSH_MSG_CATE_MCH_ORDER_DETAIL);
// payload.put("orderId", orderId);
// pushMessageService.noticeMerchantEmployeeOrderAction(null, orderId, "", "顺丰同城订单[" + orderId + "]已完成配送。", null);
return new ThirdApiRes().success("success");

View File

@ -576,6 +576,7 @@
<result property="order_payment_amount" column="order_payment_amount"/>
<result property="order_shipping_fee" column="order_shipping_fee"/>
<result property="order_shipping_fee_inner" column="order_shipping_fee_inner"/>
<result property="lkl_fee" column="lkl_fee"/>
<result property="packing_fee" column="packing_fee"/>
<!--总计优惠金额 order_discount_amount + order_voucher_price + order_points_fee + order_adjust_fee-->
<result property="total_discount_amount" column="total_discount_amount"/>
@ -782,13 +783,14 @@
oi.payment_time,
od.order_shipping_fee,
IFNULL(od.order_shipping_fee_inner, 0) as order_shipping_fee_inner,
IFNULL(od.lkl_fee, 0) as lkl_fee,
<!--总计优惠金额 order_discount_amount + order_voucher_price + order_points_fee + order_adjust_fee-->
(od.order_discount_amount + od.voucher_price + od.order_points_fee + od.order_adjust_fee) as
total_discount_amount,
<!--预计收入:订单原价金额-总计优惠金额-配送费-平台费 + 打包费-->
(ob.order_product_amount-od.order_discount_amount-od.voucher_price-od.order_points_fee-od.order_adjust_fee-od.platform_fee-order_shipping_fee_inner+od.packing_fee)
<!--预计收入:订单原价金额-总计优惠金额-配送费-平台费-拉卡拉手续费 + 打包费-->
(ob.order_product_amount-od.order_discount_amount-od.voucher_price-od.order_points_fee-od.order_adjust_fee-od.platform_fee-order_shipping_fee_inner-lkl_fee+od.packing_fee)
as order_income_amount,
od.platform_fee,
(od.platform_fee+lkl_fee) as platform_fee,
od.packing_fee,
od.order_message,
sb.store_id,