增加了拉卡拉撤销分账接口

This commit is contained in:
Jack 2025-07-15 23:33:29 +08:00
parent bd5645296f
commit 809d0832c3
5 changed files with 156 additions and 19 deletions

View File

@ -67,6 +67,9 @@ public class LklOrderSeparate {
@ApiModelProperty(value = "完成日期 yyyyMMdd")
private String finish_date;
@ApiModelProperty(value = "是否已提交撤销分账1-是2-否;")
private Integer is_canceled;
@ApiModelProperty(value = "拉卡拉异步通知回调地址")
private String notify_url;

View File

@ -161,24 +161,6 @@ public interface LakalaApiService {
CommonResult getBankCardBin(String bankCardNo);
/**
* 查询拉卡拉商户可分账的金额
* 参考https://o.lakala.com/#/home/document/detail?id=394
*
* @param merchantNo 拉卡拉外部商户号
* @param logNo 拉卡拉对账单流水号
* @param logDate 拉卡拉对账单交易日期 yyyyMMdd
* @return 响应结果 分账总金额可分账金额 键值对
* {
* "merchant_no": "82229005943096D",
* "total_separate_amt": "9900",
* "can_separate_amt": "0",
* "log_date": "20221220",
* "log_no": "66210306990190"
* }
*/
Pair<String, String> queryMchCanSplitAmt(String merchantNo, String logNo, String logDate);
/**
* 拉卡拉订单分账用户下单成功之后进行分账
* 说明分账指令是异步处理模式响应报文成功时指令状态是status: PROCESSING需要等待分账结果通知或者主动发起查询建议主动发起查询与分账指令动作之间间隔15秒以上
@ -198,4 +180,36 @@ public interface LakalaApiService {
* @return
*/
JSONObject sacsSeparateNotify(HttpServletRequest request);
/**
* 查询拉卡拉商户可分账的金额
* 参考https://o.lakala.com/#/home/document/detail?id=394
*
* @param merchantNo 拉卡拉外部商户号
* @param logNo 拉卡拉对账单流水号
* @param logDate 拉卡拉对账单交易日期 yyyyMMdd
* @return 响应结果 分账总金额可分账金额 键值对
* {
* "merchant_no": "82229005943096D",
* "total_separate_amt": "9900",
* "can_separate_amt": "0",
* "log_date": "20221220",
* "log_no": "66210306990190"
* }
*/
Pair<String, String> queryMchCanSplitAmt(String merchantNo, String logNo, String logDate);
/**
* 订单分账撤销
* 参考https://o.lakala.com/#/home/document/detail?id=390
*
* @param merchantNo 拉卡拉外部商户号
* @param originSeparateNo 原分账指令流水,origin_out_separate_no和该字段至少二选一优先级: origin_separate_no> origin_out_separate_no
* @param originOutSeparateNo 原商户分账指令流水号,入参中的origin_separate_no该字段至少二选一优先级: origin_separate_no> origin_out_separate_no
* @param outSeparateNo 商户分账指令流水号
* @param totalAmt 撤销金额,用于金额校验与原分账金额一致否则校验失败
* @return 响应结果 提交是否成功
*/
Boolean sacsSeparateCancel(String merchantNo, String originSeparateNo, String originOutSeparateNo, String outSeparateNo, String totalAmt);
}

View File

@ -30,6 +30,15 @@ public interface LklOrderSeparateService extends IBaseService<LklOrderSeparate>
*/
LklOrderSeparate getByOutTradeNo(String logNo, String outSeparateNo);
/**
* 根据商户号和平台订单号查询记录
*
* @param merchantNo
* @param outSeparateNo
* @return
*/
LklOrderSeparate getByMerchantNoAndOutTradeNo(String merchantNo, String outSeparateNo);
/**
* 修改备注
*

View File

@ -15,6 +15,7 @@ import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.lkl.laop.sdk.LKLSDK;
import com.lkl.laop.sdk.exception.SDKException;
import com.lkl.laop.sdk.request.*;
@ -1388,7 +1389,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
return JSONUtil.createObj().put("code", "FAIL").put("message", "参数转换失败");
}
}
// 3. 提取核心参数
String merCupNo = paramsJSON.getStr("merCupNo");
String applyId = paramsJSON.getStr("applyId");
@ -1569,6 +1570,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
}
}
/**
* 拉卡拉订单分账用户下单成功之后大约15秒后进行分账
* 说明分账指令是异步处理模式响应报文成功时指令状态是status: PROCESSING需要等待分账结果通知或者主动发起查询建议主动发起查询与分账指令动作之间间隔15秒以上
@ -1873,4 +1875,82 @@ public class LakalaApiServiceImpl implements LakalaApiService {
}
/**
* 订单分账撤销
* 参考文档https://o.lakala.com/#/home/document/detail?id=390
*
* @param merchantNo 拉卡拉外部商户号必填
* @param originSeparateNo 原分账指令流水号与originOutSeparateNo二选一优先级更高
* @param originOutSeparateNo 原商户分账指令流水号与originSeparateNo二选一
* @param outSeparateNo 商户分账指令流水号必填
* @param totalAmt 撤销金额必填需与原分账金额一致
* @return Boolean 撤销操作是否成功
*/
@Override
public Boolean sacsSeparateCancel(String merchantNo, String originSeparateNo,
String originOutSeparateNo, String outSeparateNo, String totalAmt) {
try {
// === 1. 参数校验 ===
if (StringUtils.isAnyBlank(merchantNo, outSeparateNo, totalAmt) ||
StringUtils.isAllBlank(originSeparateNo, originOutSeparateNo)) {
log.error("分账撤销失败:缺少必要参数");
return false;
}
// 判断是否已经分账了只有分账的订单才能撤销
LklOrderSeparate lklOrderSeparate = lklOrderSeparateService.getByMerchantNoAndOutTradeNo(merchantNo, outSeparateNo);
if (lklOrderSeparate == null
|| !lklOrderSeparate.getStatus().equals("SUCCESS")) {
log.error("分账撤销失败:商户订单未分账");
return false;
}
// === 2. 初始化拉卡拉SDK ===
initLKLSDK();
// === 3. 构建请求参数 ===
V3SacsCancelRequest req = new V3SacsCancelRequest();
req.setMerchantNo(merchantNo);
req.setOutSeparateNo(outSeparateNo);
req.setTotalAmt(totalAmt);
// 根据接口文档要求originSeparateNo优先级高于originOutSeparateNo
if (StringUtils.isNotBlank(originSeparateNo)) {
req.setOriginSeparateNo(originSeparateNo);
} else {
req.setOriginOutSeparateNo(originOutSeparateNo);
}
// === 4. 发送请求并处理响应 ===
String responseStr = LKLSDK.httpPost(req);
if (StringUtils.isBlank(responseStr)) {
log.error("分账撤销失败:拉卡拉接口返回空响应");
return false;
}
JSONObject lklRespJSON = JSONUtil.parseObj(responseStr);
JSONObject respData = lklRespJSON.getJSONObject("resp_data");
if (lklRespJSON == null ||
!lklSacsSuccessCode.equals(lklRespJSON.getStr("code")) ||
respData == null ||
StringUtils.isBlank(respData.getStr("separate_no"))) {
log.error("分账撤销失败:响应数据异常");
return false;
}
UpdateWrapper<LklOrderSeparate> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("id", lklOrderSeparate.getId()).set("is_canceled", CommonConstant.Enable);
lklOrderSeparateService.update(updateWrapper);
return true;
} catch (SDKException e) {
log.error("分账撤销SDK异常merchantNo={}, outSeparateNo={}", merchantNo, outSeparateNo, e);
return false;
} catch (Exception e) {
log.error("分账撤销系统异常merchantNo={}, outSeparateNo={}", merchantNo, outSeparateNo, e);
return false;
}
}
}

View File

@ -82,6 +82,37 @@ public class LklOrderSeparateServiceImpl extends BaseServiceImpl<LklOrderSeparat
}
}
/**
* 根据商户号和平台订单号查询记录
*
* @param merchantNo
* @param outSeparateNo
* @return
*/
@Override
public LklOrderSeparate getByMerchantNoAndOutTradeNo(String merchantNo, String outSeparateNo) {
try {
if (StrUtil.isBlank(merchantNo) || StrUtil.isBlank(outSeparateNo)) {
log.warn("查询参数为空merchantNo={}, outSeparateNo={}", merchantNo, outSeparateNo);
return null;
}
LklOrderSeparate lklOrderSeparate = findOne(new QueryWrapper<LklOrderSeparate>()
.eq("merchant_no", merchantNo)
.eq("out_separate_no", outSeparateNo).orderByAsc("id"));
if (lklOrderSeparate == null) {
log.info("未找到记录merchantNo={}, outSeparateNo={}", merchantNo, outSeparateNo);
return null;
}
return lklOrderSeparate;
} catch (Exception e) {
log.error("查询记录时发生异常merchantNo={}, outSeparateNo={}, 异常信息={}", merchantNo, outSeparateNo, e.getMessage(), e);
return null;
}
}
/**
* 修改备注
*