分账接口优化
This commit is contained in:
parent
c511e991d1
commit
b753dedf71
@ -1268,73 +1268,70 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
|
|||||||
try {
|
try {
|
||||||
lakalaPayService.initLKLSDK();
|
lakalaPayService.initLKLSDK();
|
||||||
|
|
||||||
// spring-boot 2.x 直接调用读取请求体并验签方法,返回请求体
|
// 读取请求体并验签
|
||||||
String body = LKLSDK.notificationHandle(request);
|
String body = LKLSDK.notificationHandle(request);
|
||||||
|
String authorization = request.getHeader("Authorization");
|
||||||
|
|
||||||
if (StrUtil.isBlank(body)) {
|
if (StrUtil.isBlank(body)) {
|
||||||
return lklNotifyMsg(false, "验签失败!");
|
return lklNotifyMsg(false, "验签失败!");
|
||||||
}
|
}
|
||||||
// logger.debug("支付回调 body 数据:{}", body);
|
|
||||||
|
|
||||||
// 拉卡拉返回 json 格式的 数据
|
// 敏感头信息脱敏打印
|
||||||
|
logger.debug("拉卡拉支付异步通知回调 body:{} \n authorization: {}", body, authorization);
|
||||||
|
|
||||||
|
// 解析JSON格式响应
|
||||||
params = Convert.toMap(String.class, String.class, JSONUtil.parseObj(body));
|
params = Convert.toMap(String.class, String.class, JSONUtil.parseObj(body));
|
||||||
String order_id = getParameter("out_trade_no");
|
String order_id = params.getOrDefault("out_trade_no", "");
|
||||||
if (StrUtil.isBlank(order_id)) {
|
|
||||||
order_id = params.getOrDefault("out_trade_no", "");
|
|
||||||
}
|
|
||||||
// logger.debug("支付回调 params 数据:{}", params);
|
|
||||||
|
|
||||||
String authorization = request.getHeader("Authorization");
|
// 提取授权签名信息
|
||||||
// logger.debug("支付回调 Authorization 数据:{}", authorization);
|
|
||||||
Map<String, String> authMap = LakalaUtil.getLakalaAuthorizationMap(authorization);
|
Map<String, String> authMap = LakalaUtil.getLakalaAuthorizationMap(authorization);
|
||||||
if (authMap != null && authMap.get("signature") != null) {
|
if (authMap != null && authMap.containsKey("signature")) {
|
||||||
params.put("sign", authMap.get("signature"));
|
params.put("sign", authMap.get("signature"));
|
||||||
|
} else {
|
||||||
|
logger.error("缺少签名信息");
|
||||||
|
return lklNotifyMsg(false, "缺少签名信息");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 基于安全考虑,检测支付模式及数据
|
// 查询交易信息
|
||||||
// 判断是门店 店铺 平台
|
|
||||||
Integer payment_store_id = 0;
|
|
||||||
Integer payment_chain_id = 0;
|
|
||||||
String orderSubject = "";
|
|
||||||
Integer userId = 0;
|
|
||||||
|
|
||||||
QueryWrapper<PayConsumeTrade> tradeQueryWrapper = new QueryWrapper<>();
|
QueryWrapper<PayConsumeTrade> tradeQueryWrapper = new QueryWrapper<>();
|
||||||
tradeQueryWrapper.eq("order_id", order_id);
|
tradeQueryWrapper.eq("order_id", order_id);
|
||||||
PayConsumeTrade trade_row_tmp = payConsumeTradeService.findOne(tradeQueryWrapper);
|
PayConsumeTrade trade_row_tmp = payConsumeTradeService.findOne(tradeQueryWrapper);
|
||||||
if (trade_row_tmp != null) {
|
|
||||||
payment_store_id = trade_row_tmp.getStore_id();
|
|
||||||
orderSubject = trade_row_tmp.getTrade_title();
|
|
||||||
userId = trade_row_tmp.getBuyer_id();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Integer payment_store_id = trade_row_tmp != null ? trade_row_tmp.getStore_id() : 0;
|
||||||
|
String orderSubject = trade_row_tmp != null ? trade_row_tmp.getTrade_title() : "";
|
||||||
|
Integer userId = trade_row_tmp != null ? trade_row_tmp.getBuyer_id() : 0;
|
||||||
|
|
||||||
|
// 查询支付渠道
|
||||||
QueryWrapper<PayPaymentChannel> channelQueryWrapper = new QueryWrapper<>();
|
QueryWrapper<PayPaymentChannel> channelQueryWrapper = new QueryWrapper<>();
|
||||||
channelQueryWrapper.eq("payment_channel_code", "lakala");
|
channelQueryWrapper.eq("payment_channel_code", "lakala");
|
||||||
PayPaymentChannel payPaymentChannel = payPaymentChannelService.findOne(channelQueryWrapper);
|
PayPaymentChannel payPaymentChannel = payPaymentChannelService.findOne(channelQueryWrapper);
|
||||||
|
|
||||||
|
if (payPaymentChannel == null) {
|
||||||
|
logger.error("支付渠道不存在");
|
||||||
|
return lklNotifyMsg(false, "支付渠道不存在");
|
||||||
|
}
|
||||||
Integer payment_channel_id = payPaymentChannel.getPayment_channel_id();
|
Integer payment_channel_id = payPaymentChannel.getPayment_channel_id();
|
||||||
|
|
||||||
// 插入充值记录
|
// 插入充值记录
|
||||||
PayConsumeDeposit notify_row = createNotify(params, payPaymentChannel);
|
PayConsumeDeposit payConsumeDeposit = createNotify(params, payPaymentChannel);
|
||||||
notify_row.setOrder_id(order_id);
|
payConsumeDeposit.setOrder_id(order_id);
|
||||||
notify_row.setStore_id(payment_store_id); // 所属店铺
|
payConsumeDeposit.setStore_id(payment_store_id); // 所属店铺
|
||||||
notify_row.setChain_id(payment_chain_id); // 所属门店
|
payConsumeDeposit.setChain_id(0); // 所属门店默认为0
|
||||||
notify_row.setPayment_channel_id(payment_channel_id);
|
payConsumeDeposit.setPayment_channel_id(payment_channel_id);
|
||||||
notify_row.setDeposit_subject(orderSubject);
|
payConsumeDeposit.setDeposit_subject(orderSubject);
|
||||||
notify_row.setDeposit_body(orderSubject);
|
payConsumeDeposit.setDeposit_body(orderSubject);
|
||||||
notify_row.setUser_id(userId);
|
payConsumeDeposit.setUser_id(userId);
|
||||||
// notify_row.setDeposit_state(1);// 支付状态:0-默认; 1-接收正确数据处理完逻辑; 9-异常订单
|
|
||||||
// notify_row.setDeposit_async(0); // 是否同步:0-同步; 1-异步回调使用
|
|
||||||
|
|
||||||
|
|
||||||
BigDecimal zero = BigDecimal.ZERO;
|
|
||||||
|
|
||||||
// 判断是否联合支付
|
// 判断是否联合支付
|
||||||
PayConsumeTradeCombine tradeCombine = payConsumeTradeCombineService.get(order_id);
|
PayConsumeTradeCombine tradeCombine = payConsumeTradeCombineService.get(order_id);
|
||||||
TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition);
|
TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition);
|
||||||
try {
|
try {
|
||||||
if (tradeCombine != null && StrUtil.isNotBlank(tradeCombine.getOrder_ids())) {
|
if (tradeCombine != null && StrUtil.isNotBlank(tradeCombine.getOrder_ids())) {
|
||||||
notify_row.setOrder_id(tradeCombine.getOrder_ids());
|
payConsumeDeposit.setOrder_id(tradeCombine.getOrder_ids());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!payConsumeDepositService.processDeposit(notify_row, zero, zero, zero, zero, zero)) {
|
if (!payConsumeDepositService.processDeposit(payConsumeDeposit, BigDecimal.ZERO, BigDecimal.ZERO,
|
||||||
|
BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO)) {
|
||||||
log.error("支付失败!");
|
log.error("支付失败!");
|
||||||
return lklNotifyMsg(false, "支付失败!");
|
return lklNotifyMsg(false, "支付失败!");
|
||||||
}
|
}
|
||||||
@ -1342,13 +1339,13 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
|
|||||||
transactionManager.commit(transactionStatus);
|
transactionManager.commit(transactionStatus);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
transactionManager.rollback(transactionStatus);
|
transactionManager.rollback(transactionStatus);
|
||||||
log.error("支付失败,错误信息:", e);
|
log.error("支付失败,错误信息:{}", e);
|
||||||
throw new ApiException(e.getMessage());
|
throw new ApiException(e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return lklNotifyMsg(true, "执行成功");
|
return lklNotifyMsg(true, "执行成功");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("通知处理发生异常:" + e.getMessage() + ", {}", e);
|
logger.error("通知处理发生异常:{}", e.getMessage(), e);
|
||||||
return lklNotifyMsg(false, "通知处理发生异常!");
|
return lklNotifyMsg(false, "通知处理发生异常!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -803,19 +803,13 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
log.debug("商户入网电子合同申请回调通知开始");
|
log.debug("商户入网电子合同申请回调通知开始");
|
||||||
|
|
||||||
// 验签
|
// 验签
|
||||||
String authorization = request.getHeader("Authorization");
|
Pair<Boolean, String> checkResult = LakalaUtil.chkLklApiNotifySign(request, lklNotifyCerPath);
|
||||||
String requestBody = LakalaUtil.getBody(request);
|
if (!checkResult.getFirst()) {
|
||||||
log.debug("商户入网电子合同申请回调返回requestbody 参数:{}\n authorization参数:{}\n", requestBody, authorization);
|
return JSONUtil.createObj().set("code", "FAIL").set("retMsg", checkResult.getSecond());
|
||||||
|
}
|
||||||
|
JSONObject paramsJSON = JSONUtil.parseObj(checkResult.getSecond());
|
||||||
|
|
||||||
String errMsg = "入网电子合同申请回调:";
|
String errMsg = "入网电子合同申请回调:";
|
||||||
boolean checkSuccess = LakalaUtil.verify(authorization, requestBody, lklNotifyCerPath);
|
|
||||||
if (!checkSuccess) {
|
|
||||||
log.error(errMsg + "验签失败");
|
|
||||||
return JSONUtil.createObj().set("code", "FAIL").set("retMsg", "验签失败!");
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONObject paramsJSON = JSONUtil.parseObj(requestBody);
|
|
||||||
|
|
||||||
JSONObject respData = new JSONObject();
|
JSONObject respData = new JSONObject();
|
||||||
respData.put("code", "FAIL");
|
respData.put("code", "FAIL");
|
||||||
@ -1143,17 +1137,12 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
log.debug("商户分账申请业务异步回调通知开始");
|
log.debug("商户分账申请业务异步回调通知开始");
|
||||||
|
|
||||||
// 验签
|
// 验签
|
||||||
String authorization = request.getHeader("Authorization");
|
Pair<Boolean, String> checkResult = LakalaUtil.chkLklApiNotifySign(request, lklNotifyCerPath);
|
||||||
String requestBody = LakalaUtil.getBody(request);
|
if (!checkResult.getFirst()) {
|
||||||
log.debug("商户分账申请业务异步回调返回requestbody 参数:{}\n authorization参数:{}\n", requestBody, authorization);
|
return JSONUtil.createObj().set("code", "FAIL").set("retMsg", checkResult.getSecond());
|
||||||
|
|
||||||
|
|
||||||
if (!LakalaUtil.verify(authorization, requestBody, lklNotifyCerPath)) {
|
|
||||||
log.error("商户分账申请业务回调:验签失败");
|
|
||||||
return JSONUtil.createObj().put("code", "FAIL").put("message", "验签失败!");
|
|
||||||
}
|
}
|
||||||
|
JSONObject paramsJSON = JSONUtil.parseObj(checkResult.getSecond());
|
||||||
|
|
||||||
JSONObject paramsJSON = JSONUtil.parseObj(requestBody);
|
|
||||||
if (paramsJSON == null) {
|
if (paramsJSON == null) {
|
||||||
log.error("商户分账申请业务回调:请求参数为空");
|
log.error("商户分账申请业务回调:请求参数为空");
|
||||||
return JSONUtil.createObj().put("code", "FAIL").put("message", "请求参数为空");
|
return JSONUtil.createObj().put("code", "FAIL").put("message", "请求参数为空");
|
||||||
@ -1767,17 +1756,13 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
log.debug("分账商家绑定接收方异步回调通知开始");
|
log.debug("分账商家绑定接收方异步回调通知开始");
|
||||||
|
|
||||||
// 1. 验签处理(提前失败返回)
|
// 1. 验签处理(提前失败返回)
|
||||||
String authorization = request.getHeader("Authorization");
|
// 验签
|
||||||
String requestBody = LakalaUtil.getBody(request);
|
Pair<Boolean, String> checkResult = LakalaUtil.chkLklApiNotifySign(request, lklNotifyCerPath);
|
||||||
log.debug("回调参数:requestBody={}\n authorization={}", requestBody, authorization);
|
if (!checkResult.getFirst()) {
|
||||||
|
return JSONUtil.createObj().set("code", "FAIL").set("retMsg", checkResult.getSecond());
|
||||||
if (!LakalaUtil.verify(authorization, requestBody, lklNotifyCerPath)) {
|
|
||||||
log.error("验签失败,拒绝处理回调");
|
|
||||||
return JSONUtil.createObj().put("code", "FAIL").put("message", "验签失败");
|
|
||||||
}
|
}
|
||||||
|
JSONObject paramsJSON = JSONUtil.parseObj(checkResult.getSecond());
|
||||||
|
|
||||||
// 2. 参数解析与校验
|
|
||||||
JSONObject paramsJSON = JSONUtil.parseObj(requestBody);
|
|
||||||
if (paramsJSON == null || !paramsJSON.containsKey("respData")) {
|
if (paramsJSON == null || !paramsJSON.containsKey("respData")) {
|
||||||
log.error("回调参数缺失respData字段");
|
log.error("回调参数缺失respData字段");
|
||||||
return JSONUtil.createObj().put("code", "FAIL").put("message", "参数格式错误");
|
return JSONUtil.createObj().put("code", "FAIL").put("message", "参数格式错误");
|
||||||
@ -1960,6 +1945,179 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Pair<Boolean, String> innerDoOrderSeparate(String orderId) {
|
public Pair<Boolean, String> innerDoOrderSeparate(String orderId) {
|
||||||
|
// 输入参数校验
|
||||||
|
if (StrUtil.isBlank(orderId)) {
|
||||||
|
return Pair.of(false, "订单号不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 初始化拉卡拉SDK
|
||||||
|
initLKLSDK();
|
||||||
|
|
||||||
|
// 查询订单信息
|
||||||
|
List<ShopOrderLkl> shopOrders = shopOrderLklService.selectByOrderId(orderId, "");
|
||||||
|
if (CollectionUtil.isEmpty(shopOrders)) {
|
||||||
|
return Pair.of(false, "订单不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
int totalCount = shopOrders.size();
|
||||||
|
int successCount = 0;
|
||||||
|
StringBuilder errorMessages = new StringBuilder();
|
||||||
|
|
||||||
|
// 遍历处理每个店铺订单的分账
|
||||||
|
for (ShopOrderLkl order : shopOrders) {
|
||||||
|
String merchantNo = order.getMerchant_no();
|
||||||
|
Integer paymentAmount = order.getTotal_amt();
|
||||||
|
Integer shoppingFee = order.getShopping_fee();
|
||||||
|
BigDecimal splitRatioMch = order.getSplit_ratio();
|
||||||
|
|
||||||
|
// 金额合法性校验
|
||||||
|
if (paymentAmount <= 0 || (shoppingFee != null && paymentAmount <= shoppingFee)) {
|
||||||
|
String errorMsg = String.format("店铺[%s]订单金额异常或运费过高,跳过分账", order.getStore_id());
|
||||||
|
log.error(errorMsg);
|
||||||
|
errorMessages.append(errorMsg).append("; ");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取分账接收方信息
|
||||||
|
LklLedgerMerReceiverBind platform = lklLedgerMerReceiverBindService.getPlatformByMerCupNo(merchantNo);
|
||||||
|
List<LklLedgerMerReceiverBind> distributors = lklLedgerMerReceiverBindService.selectDistributorByMerCupNo(merchantNo);
|
||||||
|
|
||||||
|
if (platform == null) {
|
||||||
|
String errorMsg = String.format("店铺[%s]未绑定平台方接收账户,跳过分账", order.getStore_id());
|
||||||
|
log.error(errorMsg);
|
||||||
|
errorMessages.append(errorMsg).append("; ");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是否可以分账(商家比例非100%)
|
||||||
|
boolean canSplit = splitRatioMch != null && splitRatioMch.compareTo(new BigDecimal("100")) < 0;
|
||||||
|
if (!canSplit) {
|
||||||
|
log.warn("店铺[{}]分账比例为0,仅扣除运费", order.getStore_id());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建分账请求对象
|
||||||
|
V3SacsSeparateRequest request = new V3SacsSeparateRequest();
|
||||||
|
request.setMerchantNo(merchantNo);
|
||||||
|
request.setLogNo(order.getLog_no());
|
||||||
|
request.setLogDate(order.getLog_date());
|
||||||
|
request.setOutSeparateNo(orderId);
|
||||||
|
request.setTotalAmt(paymentAmount.toString());
|
||||||
|
request.setLklOrgNo(orgCode);
|
||||||
|
request.setCalType("0");
|
||||||
|
request.setNotifyUrl(projectDomain + "/api/mobile/shop/lakala/sacs/separateNotify");
|
||||||
|
|
||||||
|
// 构建分账接收方列表
|
||||||
|
List<V3SacsSeparateRecvDatas> recvDatas = new ArrayList<>();
|
||||||
|
|
||||||
|
// 1. 先处理运费分账(如果有运费)
|
||||||
|
if (shoppingFee != null && shoppingFee > 0) {
|
||||||
|
V3SacsSeparateRecvDatas receiver = new V3SacsSeparateRecvDatas();
|
||||||
|
receiver.setRecvNo(platform.getReceiver_no());
|
||||||
|
receiver.setSeparateValue(shoppingFee.toString());
|
||||||
|
recvDatas.add(receiver);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 再处理剩余金额的分账(如果可以分账)
|
||||||
|
if (canSplit) {
|
||||||
|
// 计算实际可分账金额(扣除运费后)
|
||||||
|
Integer splitAmount = paymentAmount - shoppingFee;
|
||||||
|
// 计算平台+代理商的总比例
|
||||||
|
BigDecimal splitRatioNoMch = new BigDecimal("100").subtract(splitRatioMch);
|
||||||
|
|
||||||
|
if (!CollectionUtils.isEmpty(distributors) && splitRatioNoMch.compareTo(BigDecimal.ONE) > 0) {
|
||||||
|
// 平台+代理商分账模式
|
||||||
|
// 平台收取1%手续费
|
||||||
|
BigDecimal platformValue = CommonUtil.DecimalRoundHalfDown(new BigDecimal(splitAmount).multiply(new BigDecimal("0.01")));
|
||||||
|
if (platformValue.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
V3SacsSeparateRecvDatas receiver = new V3SacsSeparateRecvDatas();
|
||||||
|
receiver.setRecvNo(platform.getReceiver_no());
|
||||||
|
receiver.setSeparateValue(platformValue.toString());
|
||||||
|
recvDatas.add(receiver);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 代理商分账(扣除平台1%后的剩余比例)
|
||||||
|
BigDecimal distributorRatio = splitRatioNoMch.subtract(new BigDecimal("1")).divide(new BigDecimal(100));
|
||||||
|
BigDecimal distributorValue = CommonUtil.DecimalRoundHalfDown(new BigDecimal(splitAmount).multiply(distributorRatio));
|
||||||
|
if (distributorValue.compareTo(BigDecimal.ZERO) > 0 && !distributors.isEmpty()) {
|
||||||
|
V3SacsSeparateRecvDatas receiver = new V3SacsSeparateRecvDatas();
|
||||||
|
receiver.setRecvNo(distributors.get(0).getReceiver_no());
|
||||||
|
receiver.setSeparateValue(distributorValue.toString());
|
||||||
|
recvDatas.add(receiver);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 仅平台分账模式
|
||||||
|
BigDecimal platformRatio = splitRatioNoMch.divide(new BigDecimal(100));
|
||||||
|
BigDecimal platformValue = new BigDecimal(splitAmount).multiply(platformRatio);
|
||||||
|
if (platformValue.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
V3SacsSeparateRecvDatas receiver = new V3SacsSeparateRecvDatas();
|
||||||
|
receiver.setRecvNo(platform.getReceiver_no());
|
||||||
|
receiver.setSeparateValue(platformValue.toString());
|
||||||
|
recvDatas.add(receiver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置分账接收方列表
|
||||||
|
request.setRecvDatas(recvDatas);
|
||||||
|
log.debug("分账请求参数: {}", JSONUtil.toJsonStr(request));
|
||||||
|
|
||||||
|
// 发送分账请求
|
||||||
|
String response = LKLSDK.httpPost(request);
|
||||||
|
if (StrUtil.isBlank(response)) {
|
||||||
|
errorMessages.append("拉卡拉无响应; ");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("分账响应结果: {}", response);
|
||||||
|
|
||||||
|
// 解析响应结果
|
||||||
|
JSONObject respJson = JSONUtil.parseObj(response);
|
||||||
|
if (respJson == null || !lklSacsSuccessCode.equals(respJson.getStr("code")) || respJson.getJSONObject("resp_data") == null) {
|
||||||
|
errorMessages.append("拉卡拉返回格式异常; ");
|
||||||
|
log.error("拉卡拉分账失败:{}", response);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存分账记录
|
||||||
|
JSONObject respData = respJson.getJSONObject("resp_data");
|
||||||
|
LklOrderSeparate record = new LklOrderSeparate();
|
||||||
|
record.setSeparate_no(respData.getStr("separate_no"));
|
||||||
|
record.setOut_separate_no(request.getOutSeparateNo());
|
||||||
|
record.setMerchant_no(merchantNo);
|
||||||
|
record.setLog_no(request.getLogNo());
|
||||||
|
record.setLog_date(request.getLogDate());
|
||||||
|
record.setOrder_id(order.getOrder_id());
|
||||||
|
record.setTotal_amt(request.getTotalAmt());
|
||||||
|
record.setNotify_url(request.getNotifyUrl());
|
||||||
|
record.setLkl_org_no(request.getLklOrgNo());
|
||||||
|
record.setRecv_datas(JSONUtil.toJsonStr(request.getRecvDatas()));
|
||||||
|
record.setStatus(respData.getStr("status"));
|
||||||
|
|
||||||
|
try {
|
||||||
|
lklOrderSeparateService.addOrUpdateByReceiverNo(record);
|
||||||
|
successCount++;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("保存分账记录失败: {}", e.getMessage(), e);
|
||||||
|
errorMessages.append("保存分账记录失败; ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回最终处理结果
|
||||||
|
if (successCount == 0) {
|
||||||
|
return Pair.of(false, "分账全部失败: " + errorMessages);
|
||||||
|
} else if (successCount < totalCount) {
|
||||||
|
return Pair.of(true, "部分分账成功,处理中: " + errorMessages);
|
||||||
|
} else {
|
||||||
|
return Pair.of(true, "全部订单分账已提交处理");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("分账系统异常: {}", e.getMessage(), e);
|
||||||
|
return Pair.of(false, "系统异常,请稍后重试");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pair<Boolean, String> innerDoOrderSeparateTemp(String orderId) {
|
||||||
if (StrUtil.isBlank(orderId)) {
|
if (StrUtil.isBlank(orderId)) {
|
||||||
return Pair.of(false, "订单号不能为空");
|
return Pair.of(false, "订单号不能为空");
|
||||||
}
|
}
|
||||||
@ -1975,7 +2133,6 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
return Pair.of(false, "订单不存在");
|
return Pair.of(false, "订单不存在");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int successCnt = 0;
|
int successCnt = 0;
|
||||||
// 一个订单里包含了多个商家的时候,需要处理
|
// 一个订单里包含了多个商家的时候,需要处理
|
||||||
for (ShopOrderLkl shopOrderLkl : shopOrderLklList) {
|
for (ShopOrderLkl shopOrderLkl : shopOrderLklList) {
|
||||||
@ -2011,7 +2168,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
req.setMerchantNo(merchantNo); // 拉卡拉商户号
|
req.setMerchantNo(merchantNo); // 拉卡拉商户号
|
||||||
req.setLogNo(shopOrderLkl.getLog_no());
|
req.setLogNo(shopOrderLkl.getLog_no());
|
||||||
req.setLogDate(shopOrderLkl.getLog_date());
|
req.setLogDate(shopOrderLkl.getLog_date());
|
||||||
req.setOutSeparateNo(StringUtils.genLklOrderNo(18)); // 14+18=32位商户分账指令流水号,每个商户号下唯一,否则会校验失败
|
req.setOutSeparateNo(orderId); // 暂时传入平台订单Id
|
||||||
req.setTotalAmt(shopOrderLkl.getTotal_amt().toString());
|
req.setTotalAmt(shopOrderLkl.getTotal_amt().toString());
|
||||||
req.setLklOrgNo(orgCode);
|
req.setLklOrgNo(orgCode);
|
||||||
req.setCalType("0"); // 0- 按照指定金额,1- 按照指定比例。默认 0
|
req.setCalType("0"); // 0- 按照指定金额,1- 按照指定比例。默认 0
|
||||||
@ -2091,18 +2248,17 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
|
|
||||||
// 4. 处理返回结果,等待异步通知
|
// 4. 处理返回结果,等待异步通知
|
||||||
LklOrderSeparate record = new LklOrderSeparate();
|
LklOrderSeparate record = new LklOrderSeparate();
|
||||||
|
record.setSeparate_no(respData.getStr("separate_no")); // 必填参数
|
||||||
|
record.setOut_separate_no(req.getOutSeparateNo());// 必填参数
|
||||||
record.setMerchant_no(merchantNo);
|
record.setMerchant_no(merchantNo);
|
||||||
record.setLog_no(shopOrderLkl.getLog_no());
|
record.setLog_no(shopOrderLkl.getLog_no());
|
||||||
record.setLog_date(shopOrderLkl.getLog_date());
|
record.setLog_date(shopOrderLkl.getLog_date());
|
||||||
record.setOrder_id(shopOrderLkl.getOrder_id());
|
record.setOrder_id(shopOrderLkl.getOrder_id());
|
||||||
record.setTotal_amt(shopOrderLkl.getTotal_amt().toString());
|
record.setTotal_amt(shopOrderLkl.getTotal_amt().toString());
|
||||||
record.setOut_separate_no(req.getOutSeparateNo());// 必填参数
|
|
||||||
record.setNotify_url(req.getNotifyUrl());
|
record.setNotify_url(req.getNotifyUrl());
|
||||||
record.setLkl_org_no(req.getLklOrgNo());
|
record.setLkl_org_no(req.getLklOrgNo());
|
||||||
record.setRecv_datas(JSONUtil.toJsonStr(req.getRecvDatas()));
|
record.setRecv_datas(JSONUtil.toJsonStr(req.getRecvDatas()));
|
||||||
record.setSeparate_no(respData.getStr("separate_no")); // 必填参数
|
|
||||||
record.setStatus(respData.getStr("status"));
|
record.setStatus(respData.getStr("status"));
|
||||||
|
|
||||||
lklOrderSeparateService.addOrUpdateByReceiverNo(record);
|
lklOrderSeparateService.addOrUpdateByReceiverNo(record);
|
||||||
|
|
||||||
successCnt++;
|
successCnt++;
|
||||||
@ -2130,61 +2286,80 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public JSONObject sacsSeparateNotify(HttpServletRequest request) {
|
public JSONObject sacsSeparateNotify(HttpServletRequest request) {
|
||||||
log.debug("分账结果通知异步回调通知开始");
|
log.debug("分账结果通知异步回调开始");
|
||||||
|
|
||||||
// 验签
|
// 1. 验签处理
|
||||||
String authorization = request.getHeader("Authorization");
|
Pair<Boolean, String> signCheckResult = LakalaUtil.chkLklApiNotifySign(request, lklNotifyCerPath);
|
||||||
String requestBody = LakalaUtil.getBody(request);
|
if (!signCheckResult.getFirst()) {
|
||||||
log.debug("分账结果通知异步回调返回requestbody 参数:{}\n authorization参数:{}\n", requestBody, authorization);
|
log.warn("分账通知验签失败: {}", signCheckResult.getSecond());
|
||||||
|
return JSONUtil.createObj()
|
||||||
|
.set("code", "FAIL")
|
||||||
if (!LakalaUtil.verify(authorization, requestBody, lklNotifyCerPath)) {
|
.set("retMsg", signCheckResult.getSecond());
|
||||||
log.error("分账结果通知异步回调:验签失败");
|
|
||||||
return JSONUtil.createObj().put("code", "FAIL").put("message", "验签失败!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONObject paramsJSON = JSONUtil.parseObj(requestBody);
|
// 2. 解析请求参数
|
||||||
if (paramsJSON == null) {
|
JSONObject paramsJson = JSONUtil.parseObj(signCheckResult.getSecond());
|
||||||
log.error("分账结果通知异步回调:请求参数为空");
|
if (paramsJson == null) {
|
||||||
return JSONUtil.createObj().put("code", "FAIL").put("message", "请求参数为空");
|
log.error("分账通知参数解析失败: 请求参数为空");
|
||||||
|
return JSONUtil.createObj()
|
||||||
|
.put("code", "FAIL")
|
||||||
|
.put("message", "请求参数为空");
|
||||||
}
|
}
|
||||||
|
|
||||||
String logNo = paramsJSON.getStr("log_no");
|
// 3. 提取关键参数并校验
|
||||||
String separateNo = paramsJSON.getStr("separate_no");
|
String logNo = paramsJson.getStr("log_no");
|
||||||
String outSeparateNo = paramsJSON.getStr("out_separate_no");
|
String separateNo = paramsJson.getStr("separate_no");
|
||||||
String status = paramsJSON.getStr("status");
|
String outSeparateNo = paramsJson.getStr("out_separate_no");
|
||||||
String finalStatus = paramsJSON.getStr("final_status");
|
String status = paramsJson.getStr("status");
|
||||||
|
String finalStatus = paramsJson.getStr("final_status");
|
||||||
|
|
||||||
if (StrUtil.isBlank(outSeparateNo) || StrUtil.isBlank(separateNo) || StrUtil.isBlank(status)) {
|
List<String> missingParams = new ArrayList<>();
|
||||||
String errMsg = "分账结果通知异步回调:缺少必要参数(outSeparateNo/separateNo/status)";
|
if (StrUtil.isBlank(outSeparateNo)) missingParams.add("outSeparateNo");
|
||||||
log.error(errMsg + ":logNo={}, separateNo={}, status={}", outSeparateNo, separateNo, status);
|
if (StrUtil.isBlank(separateNo)) missingParams.add("separateNo");
|
||||||
return JSONUtil.createObj().put("code", "FAIL").put("message", "返回缺少必要参数");
|
if (StrUtil.isBlank(status)) missingParams.add("status");
|
||||||
|
|
||||||
|
if (!missingParams.isEmpty()) {
|
||||||
|
String errorMsg = "分账通知缺少必要参数: " + String.join(", ", missingParams);
|
||||||
|
log.error(errorMsg + ", 参数详情: {}", paramsJson);
|
||||||
|
return JSONUtil.createObj()
|
||||||
|
.put("code", "FAIL")
|
||||||
|
.put("message", errorMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 4. 构建分账记录对象
|
||||||
|
LklOrderSeparate record = new LklOrderSeparate();
|
||||||
|
record.setLog_no(logNo);
|
||||||
|
record.setSeparate_no(separateNo);
|
||||||
|
record.setOut_separate_no(outSeparateNo);
|
||||||
|
record.setStatus(status);
|
||||||
|
record.setFinal_status(finalStatus);
|
||||||
|
record.setCal_type(paramsJson.getStr("cal_type"));
|
||||||
|
record.setSeparate_type(paramsJson.getStr("separate_type"));
|
||||||
|
record.setSeparate_date(paramsJson.getStr("separate_date"));
|
||||||
|
|
||||||
|
// 处理detail_datas(避免空指针)
|
||||||
|
JSONArray detailDatas = paramsJson.getJSONArray("detail_datas");
|
||||||
|
record.setDetail_datas(detailDatas != null ? detailDatas.toString() : "[]");
|
||||||
|
|
||||||
|
// 5. 持久化处理
|
||||||
try {
|
try {
|
||||||
|
boolean updateSuccess = lklOrderSeparateService.addOrUpdateByReceiverNo(record);
|
||||||
// 4. 处理返回结果,等待异步通知
|
if (!updateSuccess) {
|
||||||
LklOrderSeparate record = new LklOrderSeparate();
|
log.error("分账记录更新失败, separateNo={}", separateNo);
|
||||||
record.setLog_no(logNo);
|
return JSONUtil.createObj()
|
||||||
record.setSeparate_no(separateNo);
|
.put("code", "FAIL")
|
||||||
record.setOut_separate_no(paramsJSON.getStr("out_separate_no"));
|
.put("message", "数据更新失败");
|
||||||
record.setStatus(status);
|
|
||||||
record.setFinal_status(finalStatus);
|
|
||||||
record.setCal_type(paramsJSON.getStr("cal_type"));
|
|
||||||
record.setSeparate_type(paramsJSON.getStr("separate_type"));
|
|
||||||
record.setSeparate_date(paramsJSON.getStr("separate_date"));
|
|
||||||
record.setDetail_datas(paramsJSON.getJSONArray("detail_datas").toString());
|
|
||||||
|
|
||||||
Boolean success = lklOrderSeparateService.addOrUpdateByReceiverNo(record);
|
|
||||||
if (!success) {
|
|
||||||
return JSONUtil.createObj().put("code", "FAIL").put("message", "处理数据失败!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log.debug("分账结果通知异步回调:处理成功,separateNo={}", separateNo);
|
log.debug("分账通知处理成功, separateNo={}, status={}", separateNo, status);
|
||||||
return JSONUtil.createObj().put("code", "SUCCESS").put("message", "操作成功!");
|
return JSONUtil.createObj()
|
||||||
|
.put("code", "SUCCESS")
|
||||||
|
.put("message", "操作成功");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("分账结果通知异步回调:处理数据异常", e);
|
log.error("分账通知数据处理异常, separateNo={}: {}", separateNo, e.getMessage(), e);
|
||||||
return JSONUtil.createObj().put("code", "FAIL").put("message", "处理数据异常");
|
return JSONUtil.createObj()
|
||||||
|
.put("code", "FAIL")
|
||||||
|
.put("message", "系统处理异常");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -22,7 +22,7 @@ import org.springframework.stereotype.Service;
|
|||||||
public class LklOrderSeparateServiceImpl extends BaseServiceImpl<LklOrderSeparateMapper, LklOrderSeparate> implements LklOrderSeparateService {
|
public class LklOrderSeparateServiceImpl extends BaseServiceImpl<LklOrderSeparateMapper, LklOrderSeparate> implements LklOrderSeparateService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增或更新记录
|
* 新增或更新记录(根据out_separate_no 和 separate_no 更新记录)
|
||||||
*
|
*
|
||||||
* @param record
|
* @param record
|
||||||
* @return
|
* @return
|
||||||
|
|||||||
@ -18,6 +18,7 @@ import com.suisung.mall.common.utils.StringUtils;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
import org.springframework.data.util.Pair;
|
||||||
|
|
||||||
import javax.crypto.BadPaddingException;
|
import javax.crypto.BadPaddingException;
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
@ -403,4 +404,26 @@ public class LakalaUtil {
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拉卡拉异步回调通知,签名验证公共方法
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* @param lklNotifyCerPath
|
||||||
|
* @return 验签成功,返回解密后的json字符串,验签失败,返回错误信息
|
||||||
|
*/
|
||||||
|
public static Pair<Boolean, String> chkLklApiNotifySign(HttpServletRequest request, String lklNotifyCerPath) {
|
||||||
|
// 验签
|
||||||
|
String authorization = request.getHeader("Authorization");
|
||||||
|
String requestBody = getBody(request);
|
||||||
|
log.debug("{} 回调通知 requestbody 参数:{}\n authorization参数:{}\n", request.getRequestURL(), requestBody, authorization);
|
||||||
|
|
||||||
|
boolean checkSuccess = LakalaUtil.verify(authorization, requestBody, lklNotifyCerPath);
|
||||||
|
if (!checkSuccess) {
|
||||||
|
log.error("{} 回调通知验签失败", request.getRequestURL());
|
||||||
|
return Pair.of(false, "验签失败!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Pair.of(true, requestBody);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2743,7 +2743,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ShopOrderInfo> order_rows = null;
|
List<ShopOrderInfo> order_rows;
|
||||||
List<String> review_id_row = new ArrayList<>();
|
List<String> review_id_row = new ArrayList<>();
|
||||||
// 检测数据是否合法,过滤允许修改的数据
|
// 检测数据是否合法,过滤允许修改的数据
|
||||||
if (CollUtil.isNotEmpty(order_ids)) {
|
if (CollUtil.isNotEmpty(order_ids)) {
|
||||||
@ -2821,7 +2821,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
|||||||
Integer store_id = order_row.getStore_id();
|
Integer store_id = order_row.getStore_id();
|
||||||
|
|
||||||
// 判断是否可以读取到下一个状态,如果读不到,则为订货系统使用,可以不支付直接处理发货流程
|
// 判断是否可以读取到下一个状态,如果读不到,则为订货系统使用,可以不支付直接处理发货流程
|
||||||
Integer order_next_state_id = null;
|
Integer order_next_state_id;
|
||||||
|
|
||||||
// 虚拟设置为StateCode.ORDER_STATE_SHIPPED 待收货状态
|
// 虚拟设置为StateCode.ORDER_STATE_SHIPPED 待收货状态
|
||||||
Integer kind_id = order_row.getKind_id();
|
Integer kind_id = order_row.getKind_id();
|
||||||
|
|||||||
@ -57,7 +57,7 @@ public class ShopOrderLklServiceImpl extends BaseServiceImpl<ShopOrderLklMapper,
|
|||||||
}
|
}
|
||||||
|
|
||||||
QueryWrapper<ShopOrderLkl> queryWrapper = new QueryWrapper<>();
|
QueryWrapper<ShopOrderLkl> queryWrapper = new QueryWrapper<>();
|
||||||
queryWrapper.eq("order_id", orderId);
|
queryWrapper.eq("order_id", orderId).orderByAsc("id");
|
||||||
if (StrUtil.isNotBlank(storeId)) {
|
if (StrUtil.isNotBlank(storeId)) {
|
||||||
queryWrapper.eq("store_id", storeId);
|
queryWrapper.eq("store_id", storeId);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user