增加 确认收货 异步通知接收地址,优化 拉卡拉预支付 日志
This commit is contained in:
parent
d55dd93b05
commit
846cc94c0d
@ -60,22 +60,32 @@ public class ShopOrderLkl implements Serializable {
|
|||||||
|
|
||||||
private String lkl_log_date;
|
private String lkl_log_date;
|
||||||
|
|
||||||
private String lkl_split_log_no;
|
private String lkl_sub_log_no;
|
||||||
|
|
||||||
private String lkl_trade_no;
|
private String lkl_trade_no;
|
||||||
|
|
||||||
|
private String lkl_receive_trade_no;
|
||||||
|
|
||||||
|
private String lkl_receive_log_no;
|
||||||
|
|
||||||
private String lkl_merchant_no;
|
private String lkl_merchant_no;
|
||||||
|
|
||||||
private String lkl_term_no;
|
private String lkl_term_no;
|
||||||
|
|
||||||
private String notify_url;
|
private String notify_url;
|
||||||
|
|
||||||
|
private String receive_notify_url;
|
||||||
|
|
||||||
private String lkl_req;
|
private String lkl_req;
|
||||||
|
|
||||||
private String lkl_resp;
|
private String lkl_resp;
|
||||||
|
|
||||||
private String lkl_notify_resp;
|
private String lkl_notify_resp;
|
||||||
|
|
||||||
|
private String lkl_receive_notify_resp;
|
||||||
|
|
||||||
|
private Integer receive_status;
|
||||||
|
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
private Date created_at;
|
private Date created_at;
|
||||||
|
|||||||
@ -182,7 +182,7 @@ public class UniCloudPushServiceImpl implements UniCloudPushService {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
JSONObject json = JSONUtil.parseObj(body);
|
JSONObject json = JSONUtil.parseObj(body);
|
||||||
log.info("[推送服务] 原始响应: {}", json.toStringPretty());
|
// log.debug("[推送服务] 原始响应: {}", json.toStringPretty());
|
||||||
|
|
||||||
// 解析标准响应字段
|
// 解析标准响应字段
|
||||||
Integer errCode = json.getInt("errCode", -1);
|
Integer errCode = json.getInt("errCode", -1);
|
||||||
|
|||||||
@ -86,6 +86,7 @@ secure:
|
|||||||
- "/shop/sf-express/cancel-order/notify"
|
- "/shop/sf-express/cancel-order/notify"
|
||||||
- "/shop/sf-express/rider-order-status/notify"
|
- "/shop/sf-express/rider-order-status/notify"
|
||||||
- "/shop/sf-express/order-complete/notify"
|
- "/shop/sf-express/order-complete/notify"
|
||||||
|
- "/mobile/shop/lakala/trans/receive/completeNotify"
|
||||||
- "/shop/sync/third/**"
|
- "/shop/sync/third/**"
|
||||||
- "/esProduct/**"
|
- "/esProduct/**"
|
||||||
- "/admin/oss/upload/**"
|
- "/admin/oss/upload/**"
|
||||||
|
|||||||
@ -24,44 +24,10 @@ import java.io.IOException;
|
|||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/mobile/pay/lakala")
|
@RequestMapping("/mobile/pay/lakala")
|
||||||
public class LakalaController extends BaseControllerImpl {
|
public class LakalaController extends BaseControllerImpl {
|
||||||
//
|
|
||||||
// @Resource
|
|
||||||
// private LakalaPayService lakalaPayService;
|
|
||||||
|
|
||||||
@ApiOperation(value = "本地文件转base64", notes = "本地文件转base64")
|
@ApiOperation(value = "本地文件转base64", notes = "本地文件转base64")
|
||||||
@RequestMapping(value = "/file2base64", method = RequestMethod.POST)
|
@RequestMapping(value = "/file2base64", method = RequestMethod.POST)
|
||||||
public String file2Base64(@RequestParam("file") MultipartFile file) throws IOException {
|
public String file2Base64(@RequestParam("file") MultipartFile file) throws IOException {
|
||||||
String str = Base64Utils.encodeToString(file.getBytes());
|
String str = Base64Utils.encodeToString(file.getBytes());
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ApiOperation(value = "商户分账业务开通申请", notes = "商户分账业务开通申请")
|
|
||||||
// @RequestMapping(value = "/ledger/applyLedgerMer", method = RequestMethod.POST)
|
|
||||||
// public CommonResult ledgerApplyLedgerMer(@RequestBody JSONObject paramsJSON) {
|
|
||||||
// return lakalaPayService.applyLedgerMer(paramsJSON);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @ApiOperation(value = "商户分账业务开通申请异步回调回调", notes = "商户分账业务开通申请异步回调回调")
|
|
||||||
// @RequestMapping(value = "/ledger/applyLedgerMerNotify", method = RequestMethod.POST)
|
|
||||||
// public JSONObject ledgerApplyLedgerMerNotify(HttpServletRequest request) {
|
|
||||||
// return lakalaPayService.applyLedgerMerNotify(request);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @ApiOperation(value = "分账接收方创建申请", notes = "分账接收方创建申请")
|
|
||||||
// @RequestMapping(value = "/ledger/applyLedgerReceiver", method = RequestMethod.POST)
|
|
||||||
// public CommonResult applyLedgerReceiver(@RequestBody JSONObject paramsJSON) {
|
|
||||||
// return lakalaPayService.applyLedgerReceiver(paramsJSON);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @ApiOperation(value = "分账关系绑定申请", notes = "分账关系绑定申请")
|
|
||||||
// @RequestMapping(value = "/ledger/applyBind", method = RequestMethod.POST)
|
|
||||||
// public CommonResult applyBind(@RequestBody JSONObject paramsJSON) {
|
|
||||||
// return lakalaPayService.applyLedgerMerReceiverBind(paramsJSON);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @ApiOperation(value = "分账关系绑定申请异步回调通知", notes = "分账关系绑定申请异步回调通知")
|
|
||||||
// @RequestMapping(value = "/ledger/applyBindNotify", method = RequestMethod.POST)
|
|
||||||
// public JSONObject applyBindNotify(HttpServletRequest request) {
|
|
||||||
// return lakalaPayService.applyLedgerMerReceiverBindNotify(request);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -111,7 +111,7 @@ public class LakalaPayServiceImpl implements LakalaPayService {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 拉卡拉预下单
|
* 拉卡拉预下单(废弃)
|
||||||
* 参考:https://o.lakala.com/#/home/document/detail?id=110
|
* 参考:https://o.lakala.com/#/home/document/detail?id=110
|
||||||
*
|
*
|
||||||
* @param merchantNo 商户号
|
* @param merchantNo 商户号
|
||||||
@ -127,34 +127,38 @@ public class LakalaPayServiceImpl implements LakalaPayService {
|
|||||||
* @param remark 备注
|
* @param remark 备注
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@Override
|
// @Override
|
||||||
public JSONObject lklTransPreOrder(String merchantNo, String termNo, String xcxAppId, String openId, String storeId, String orderId, String subject, String totalAmount, String notifyURL, String requestIP, String remark) {
|
public JSONObject lklTransPreOrderBak(String merchantNo, String termNo, String xcxAppId, String openId, String storeId, String orderId, String subject, String totalAmount, String notifyURL, String requestIP, String remark) {
|
||||||
// 1. 配置初始化
|
// 1. 配置初始化
|
||||||
initLKLSDK();
|
initLKLSDK();
|
||||||
|
|
||||||
if (StrUtil.isBlank(merchantNo) || StrUtil.isBlank(termNo)) {
|
if (StrUtil.isBlank(merchantNo) || StrUtil.isBlank(termNo)) {
|
||||||
|
log.warn("[拉卡拉预下单] 参数校验失败:缺少商户号或终端号, merchantNo={}, termNo={}", merchantNo, termNo);
|
||||||
throw new ApiException(I18nUtil._("缺少商户号或终端号!"));
|
throw new ApiException(I18nUtil._("缺少商户号或终端号!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.info("[拉卡拉预下单] 开始处理请求, merchantNo={}, termNo={}, orderId={}", merchantNo, termNo, orderId);
|
||||||
|
|
||||||
//2. 装配数据
|
//2. 装配数据
|
||||||
/*** 微信主扫场景示例 */
|
/*** 微信主扫场景示例 */
|
||||||
V3LabsTransPreorderRequest v3LabsTransPreorderWechatReq = new V3LabsTransPreorderRequest();
|
V3LabsTransPreorderRequest v3LabsTransPreorderRequest = new V3LabsTransPreorderRequest();
|
||||||
v3LabsTransPreorderWechatReq.setMerchantNo(merchantNo);
|
v3LabsTransPreorderRequest.setMerchantNo(merchantNo);
|
||||||
v3LabsTransPreorderWechatReq.setTermNo(termNo);
|
v3LabsTransPreorderRequest.setTermNo(termNo);
|
||||||
v3LabsTransPreorderWechatReq.setOutTradeNo(orderId);
|
v3LabsTransPreorderRequest.setOutTradeNo(orderId);
|
||||||
v3LabsTransPreorderWechatReq.setSubject(subject);
|
v3LabsTransPreorderRequest.setSubject(subject);
|
||||||
//微信:WECHAT 支付宝:ALIPAY 银联:UQRCODEPAY 翼支付: BESTPAY 苏宁易付宝: SUNING 拉卡拉支付账户:LKLACC 网联小钱包:NUCSPAY 京东钱包:JD
|
//微信:WECHAT 支付宝:ALIPAY 银联:UQRCODEPAY 翼支付: BESTPAY 苏宁易付宝: SUNING 拉卡拉支付账户:LKLACC 网联小钱包:NUCSPAY 京东钱包:JD
|
||||||
v3LabsTransPreorderWechatReq.setAccountType("WECHAT");
|
v3LabsTransPreorderRequest.setAccountType("WECHAT");
|
||||||
// 41:NATIVE((ALIPAY,云闪付支持,京东白条分期)51:JSAPI(微信公众号支付,支付宝服务窗支付,银联JS支付,翼支付JS支付、拉卡拉钱包支付)71:微信小程序支付 61:APP支付(微信APP支付)
|
// 41:NATIVE((ALIPAY,云闪付支持,京东白条分期)51:JSAPI(微信公众号支付,支付宝服务窗支付,银联JS支付,翼支付JS支付、拉卡拉钱包支付)71:微信小程序支付 61:APP支付(微信APP支付)
|
||||||
v3LabsTransPreorderWechatReq.setTransType("51");
|
v3LabsTransPreorderRequest.setTransType("51");
|
||||||
v3LabsTransPreorderWechatReq.setTotalAmount(totalAmount); // 应支付金额,单位:分
|
v3LabsTransPreorderRequest.setTotalAmount(totalAmount); // 应支付金额,单位:分
|
||||||
v3LabsTransPreorderWechatReq.setSettleType("1"); //“0”或者空,常规结算方式,如需接拉卡拉分账通需传“1”,商户未开通分账之前切记不用上送此参数。;
|
v3LabsTransPreorderRequest.setSettleType("1"); //“0”或者空,常规结算方式,如需接拉卡拉分账通需传“1”,商户未开通分账之前切记不用上送此参数。;
|
||||||
v3LabsTransPreorderWechatReq.setNotifyUrl(notifyURL);
|
v3LabsTransPreorderRequest.setNotifyUrl(notifyURL);
|
||||||
v3LabsTransPreorderWechatReq.setRemark(remark);
|
v3LabsTransPreorderRequest.setRemark(remark);
|
||||||
|
// v3LabsTransPreorderRequest.setCompleteNotifyUrl("https://mall.gpxscs.cn/api/mobile/shop/lakala/trans/receive/completeNotify");
|
||||||
|
|
||||||
//地址位置信息
|
//地址位置信息
|
||||||
V3LabsTradeLocationInfo v3LabsTradePreorderLocationInfo = new V3LabsTradeLocationInfo(requestIP);
|
V3LabsTradeLocationInfo v3LabsTradePreorderLocationInfo = new V3LabsTradeLocationInfo(requestIP);
|
||||||
v3LabsTransPreorderWechatReq.setLocationInfo(v3LabsTradePreorderLocationInfo);
|
v3LabsTransPreorderRequest.setLocationInfo(v3LabsTradePreorderLocationInfo);
|
||||||
|
|
||||||
//微信主扫场景下 acc_busi_fields 域内容
|
//微信主扫场景下 acc_busi_fields 域内容
|
||||||
V3LabsTradePreorderWechatBus wechatBus = new V3LabsTradePreorderWechatBus();
|
V3LabsTradePreorderWechatBus wechatBus = new V3LabsTradePreorderWechatBus();
|
||||||
@ -162,35 +166,217 @@ public class LakalaPayServiceImpl implements LakalaPayService {
|
|||||||
wechatBus.setUserId(openId); // 微信 openId
|
wechatBus.setUserId(openId); // 微信 openId
|
||||||
wechatBus.setDeviceInfo("WEB"); // 终端设备号(门店号或收银设备ID),注意:PC网页或JSAPI支付请传”WEB”
|
wechatBus.setDeviceInfo("WEB"); // 终端设备号(门店号或收银设备ID),注意:PC网页或JSAPI支付请传”WEB”
|
||||||
// wechatBus.setAttach(storeId); // 附加数据,商户自定义数据,在查询交易结果时原样返回。
|
// wechatBus.setAttach(storeId); // 附加数据,商户自定义数据,在查询交易结果时原样返回。
|
||||||
v3LabsTransPreorderWechatReq.setAccBusiFields(wechatBus);
|
v3LabsTransPreorderRequest.setAccBusiFields(wechatBus);
|
||||||
|
|
||||||
|
JSONObject reqParams = JSONUtil.parseObj(v3LabsTransPreorderRequest);
|
||||||
|
reqParams.set("complete_notify_url", "https://mall.gpxscs.cn/api/mobile/shop/lakala/trans/receive/completeNotify");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
log.info("拉卡拉预下单请求参数:{}", JSONUtil.toJsonStr(v3LabsTransPreorderWechatReq));
|
log.info("[拉卡拉预下单] 请求参数: {}", JSONUtil.toJsonStr(reqParams));
|
||||||
|
|
||||||
//3. 发送请求
|
//3. 发送请求
|
||||||
String responseStr = LKLSDK.httpPost(v3LabsTransPreorderWechatReq);
|
String reqUrl = serverUrl + "/api/v3/labs/trans/preorder";
|
||||||
log.info("拉卡拉预下单响应数据:{}", responseStr);
|
log.debug("[拉卡拉预下单] 请求URL: {}", reqUrl);
|
||||||
|
String responseStr = LKLSDK.httpPost(reqUrl, reqParams.toString(), appId);
|
||||||
|
log.info("[拉卡拉预下单] 响应数据: {}", responseStr);
|
||||||
if (StrUtil.isBlank(responseStr)) {
|
if (StrUtil.isBlank(responseStr)) {
|
||||||
|
log.warn("[拉卡拉预下单] 响应为空, orderId={}", orderId);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONObject lakalaRespJSON = JSONUtil.parseObj(responseStr);
|
JSONObject lakalaRespJSON = JSONUtil.parseObj(responseStr);
|
||||||
|
|
||||||
if (lakalaRespJSON != null && lakalaRespJSON.getStr("code").equals("BBS00000")) {
|
if (lakalaRespJSON != null && lakalaRespJSON.getStr("code").equals("BBS00000")) {
|
||||||
|
log.debug("[拉卡拉预下单] 支付成功,保存订单记录, orderId={}", orderId);
|
||||||
// 新增一个拉卡拉订单记录 shop_order_lkl 表
|
// 新增一个拉卡拉订单记录 shop_order_lkl 表
|
||||||
JSONObject lklPayReqAndRespJson = new JSONObject();
|
JSONObject lklPayReqAndRespJson = new JSONObject();
|
||||||
lklPayReqAndRespJson.put("req", JSONUtil.parseObj(v3LabsTransPreorderWechatReq));
|
lklPayReqAndRespJson.put("req", JSONUtil.parseObj(v3LabsTransPreorderRequest));
|
||||||
lklPayReqAndRespJson.put("resp", lakalaRespJSON);
|
lklPayReqAndRespJson.put("resp", lakalaRespJSON);
|
||||||
shopService.lklPayAddShopOrderLkl(lklPayReqAndRespJson);
|
shopService.lklPayAddShopOrderLkl(lklPayReqAndRespJson);
|
||||||
}
|
}
|
||||||
//4. 响应
|
//4. 响应
|
||||||
|
log.info("[拉卡拉预下单] 处理完成, orderId={}, responseCode={}", orderId, lakalaRespJSON != null ? lakalaRespJSON.getStr("code") : "NULL");
|
||||||
return lakalaRespJSON;
|
return lakalaRespJSON;
|
||||||
} catch (SDKException e) {
|
} catch (SDKException e) {
|
||||||
log.error("拉卡拉支付出错:", e);
|
log.error("[拉卡拉预下单] SDK异常, orderId=" + orderId, e);
|
||||||
throw new ApiException(I18nUtil._("支付失败!"), e);
|
throw new ApiException(I18nUtil._("支付失败!"), e);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("[拉卡拉预下单] 系统异常, orderId=" + orderId, e);
|
||||||
|
throw new ApiException(I18nUtil._("系统异常!"), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拉卡拉预下单
|
||||||
|
* 参考:https://o.lakala.com/#/home/document/detail?id=110
|
||||||
|
*
|
||||||
|
* @param merchantNo 商户号
|
||||||
|
* @param termNo 终端号
|
||||||
|
* @param xcxAppId 小程序appid
|
||||||
|
* @param openId openid
|
||||||
|
* @param storeId 店铺号
|
||||||
|
* @param orderId 订单号
|
||||||
|
* @param subject 订单标题
|
||||||
|
* @param totalAmount 订单金额(单位:分)
|
||||||
|
* @param notifyURL 回调地址
|
||||||
|
* @param requestIP 请求IP
|
||||||
|
* @param remark 备注
|
||||||
|
* @return 拉卡拉预下单响应结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public JSONObject lklTransPreOrder(String merchantNo, String termNo, String xcxAppId, String openId, String storeId, String orderId, String subject, String totalAmount, String notifyURL, String requestIP, String remark) {
|
||||||
|
// 1. 参数校验
|
||||||
|
if (StrUtil.isBlank(merchantNo)) {
|
||||||
|
log.warn("[拉卡拉预下单] 参数校验失败:商户号不能为空, orderId={}", orderId);
|
||||||
|
throw new ApiException(I18nUtil._("商户号不能为空!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isBlank(termNo)) {
|
||||||
|
log.warn("[拉卡拉预下单] 参数校验失败:终端号不能为空, orderId={}", orderId);
|
||||||
|
throw new ApiException(I18nUtil._("终端号不能为空!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isBlank(orderId)) {
|
||||||
|
log.warn("[拉卡拉预下单] 参数校验失败:订单号不能为空, merchantNo={}", merchantNo);
|
||||||
|
throw new ApiException(I18nUtil._("订单号不能为空!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isBlank(subject)) {
|
||||||
|
log.warn("[拉卡拉预下单] 参数校验失败:订单标题不能为空, orderId={}", orderId);
|
||||||
|
throw new ApiException(I18nUtil._("订单标题不能为空!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isBlank(totalAmount)) {
|
||||||
|
log.warn("[拉卡拉预下单] 参数校验失败:订单金额不能为空, orderId={}", orderId);
|
||||||
|
throw new ApiException(I18nUtil._("订单金额不能为空!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isBlank(notifyURL)) {
|
||||||
|
log.warn("[拉卡拉预下单] 参数校验失败:回调地址不能为空, orderId={}", orderId);
|
||||||
|
throw new ApiException(I18nUtil._("回调地址不能为空!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isBlank(requestIP)) {
|
||||||
|
log.warn("[拉卡拉预下单] 参数校验失败:请求IP不能为空, orderId={}", orderId);
|
||||||
|
throw new ApiException(I18nUtil._("请求IP不能为空!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("[拉卡拉预下单] 开始处理请求, merchantNo={}, termNo={}, orderId={}", merchantNo, termNo, orderId);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 2. 装配请求数据
|
||||||
|
JSONObject reqData = new JSONObject();
|
||||||
|
reqData.put("merchant_no", merchantNo);
|
||||||
|
reqData.put("term_no", termNo);
|
||||||
|
reqData.put("out_trade_no", orderId);
|
||||||
|
reqData.put("subject", subject);
|
||||||
|
// 微信:WECHAT 支付宝:ALIPAY 银联:UQRCODEPAY 翼支付: BESTPAY 苏宁易付宝: SUNING 拉卡拉支付账户:LKLACC 网联小钱包:NUCSPAY 京东钱包:JD
|
||||||
|
reqData.put("account_type", "WECHAT");
|
||||||
|
// 41:NATIVE((ALIPAY,云闪付支持,京东白条分期)51:JSAPI(微信公众号支付,支付宝服务窗支付,银联JS支付,翼支付JS支付、拉卡拉钱包支付)71:微信小程序支付 61:APP支付(微信APP支付)
|
||||||
|
reqData.put("trans_type", "51");
|
||||||
|
reqData.put("total_amount", totalAmount); // 应支付金额,单位:分
|
||||||
|
reqData.put("settle_type", "1"); // "0"或者空,常规结算方式,如需接拉卡拉分账通需传"1",商户未开通分账之前切记不用上送此参数。
|
||||||
|
reqData.put("notify_url", notifyURL);
|
||||||
|
reqData.put("remark", remark);
|
||||||
|
reqData.put("complete_notify_url", "https://mall.gpxscs.cn/api/mobile/shop/lakala/trans/receive/completeNotify");
|
||||||
|
|
||||||
|
// 地址位置信息
|
||||||
|
JSONObject locationInfo = new JSONObject();
|
||||||
|
locationInfo.put("request_ip", requestIP);
|
||||||
|
reqData.put("location_info", locationInfo);
|
||||||
|
|
||||||
|
// 微信业务参数
|
||||||
|
if (StrUtil.isNotBlank(xcxAppId) && StrUtil.isNotBlank(openId)) {
|
||||||
|
JSONObject accBusiFields = new JSONObject();
|
||||||
|
accBusiFields.put("sub_appid", xcxAppId); // 小程序appId
|
||||||
|
accBusiFields.put("user_id", openId); // 微信 openId
|
||||||
|
accBusiFields.put("device_info", "WEB"); // 终端设备号(门店号或收银设备ID),注意:PC网页或JSAPI支付请传"WEB"
|
||||||
|
reqData.put("acc_busi_fields", accBusiFields);
|
||||||
|
log.debug("[拉卡拉预下单] 已添加微信业务参数, xcxAppId={}, openId={}", xcxAppId, openId);
|
||||||
|
} else {
|
||||||
|
log.warn("[拉卡拉预下单] 微信业务参数不完整或不需要, xcxAppId={}, openId={}", xcxAppId, openId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 构造请求体
|
||||||
|
JSONObject reqBody = new JSONObject();
|
||||||
|
reqBody.put("req_time", DateTimeUtils.formatDateTime(LocalDateTime.now(), "yyyyMMddHHmmss"));
|
||||||
|
reqBody.put("version", "3.0");
|
||||||
|
reqBody.put("req_data", reqData);
|
||||||
|
|
||||||
|
log.info("[拉卡拉预下单] 请求参数组装完成, orderId={}", orderId);
|
||||||
|
log.debug("[拉卡拉预下单] 完整请求参数: {}", JSONUtil.toJsonStr(reqBody));
|
||||||
|
|
||||||
|
// 4. 发送请求
|
||||||
|
String reqUrl = serverUrl + "/api/v3/labs/trans/preorder";
|
||||||
|
log.info("[拉卡拉预下单] 准备发送请求, orderId={}, url={}", orderId, reqUrl);
|
||||||
|
|
||||||
|
String authorization = LakalaUtil.genAuthorizationByPath(priKeyPath, appId, serialNo, reqBody.toString());
|
||||||
|
if (StrUtil.isBlank(authorization)) {
|
||||||
|
log.error("[拉卡拉预下单] 生成签名失败, orderId={}", orderId);
|
||||||
|
throw new ApiException("生成请求签名失败!");
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject header = new JSONObject();
|
||||||
|
header.put("Authorization", authorization);
|
||||||
|
header.put("Content-Type", "application/json");
|
||||||
|
|
||||||
|
log.debug("[拉卡拉预下单] 请求头信息生成完成, orderId={}", orderId);
|
||||||
|
|
||||||
|
// 使用RestTemplate发送POST请求
|
||||||
|
ResponseEntity<JSONObject> lakalaRespEntity = RestTemplateHttpUtil.sendPostBodyBackEntity(reqUrl, header, reqBody, JSONObject.class);
|
||||||
|
log.info("[拉卡拉预下单] 收到响应, orderId={}, responseStatus={}", orderId, lakalaRespEntity != null ? lakalaRespEntity.getStatusCode() : "NULL");
|
||||||
|
|
||||||
|
// 5. 处理响应结果
|
||||||
|
if (lakalaRespEntity == null) {
|
||||||
|
log.warn("[拉卡拉预下单] 响应为空, orderId={}", orderId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject respBody = lakalaRespEntity.getBody();
|
||||||
|
log.debug("[拉卡拉预下单] 响应体内容, orderId={}, responseBody={}", orderId, respBody);
|
||||||
|
|
||||||
|
if (respBody == null) {
|
||||||
|
log.warn("[拉卡拉预下单] 响应体为空, orderId={}", orderId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String responseCode = respBody.getStr("code");
|
||||||
|
if (StrUtil.isBlank(responseCode)) {
|
||||||
|
log.warn("[拉卡拉预下单] 响应码为空, orderId={}", orderId);
|
||||||
|
return respBody;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用安全的字符串比较方式,避免空指针异常
|
||||||
|
if (!lklPaySuccessCode.equals(responseCode)) {
|
||||||
|
log.warn("[拉卡拉预下单] 响应码异常, orderId={}, code={}, msg={}", orderId, responseCode, respBody.getStr("msg"));
|
||||||
|
return respBody;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("[拉卡拉预下单] 支付成功,准备保存订单记录, orderId={}", orderId);
|
||||||
|
// 新增一个拉卡拉订单记录 shop_order_lkl 表
|
||||||
|
JSONObject lklPayReqAndRespJson = new JSONObject();
|
||||||
|
lklPayReqAndRespJson.put("req", reqData);
|
||||||
|
lklPayReqAndRespJson.put("resp", respBody);
|
||||||
|
|
||||||
|
try {
|
||||||
|
shopService.lklPayAddShopOrderLkl(lklPayReqAndRespJson);
|
||||||
|
log.debug("[拉卡拉预下单] 订单记录保存成功, orderId={}", orderId);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("[拉卡拉预下单] 保存订单记录失败, orderId={}", orderId, e);
|
||||||
|
// 不中断主流程,仅记录错误
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. 返回响应结果
|
||||||
|
log.info("[拉卡拉预下单] 处理完成, orderId={}, responseCode={}", orderId, responseCode);
|
||||||
|
return respBody;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("[拉卡拉预下单] 系统异常, merchantNo={}, termNo={}, orderId={}", merchantNo, termNo, orderId, e);
|
||||||
|
throw new ApiException("拉卡拉预下单出错:" + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 拉卡拉合单预下单(主要有运费的订单使用合单)
|
* 拉卡拉合单预下单(主要有运费的订单使用合单)
|
||||||
* 参考:https://o.lakala.com/#/home/document/detail?id=208
|
* 参考:https://o.lakala.com/#/home/document/detail?id=208
|
||||||
@ -204,41 +390,64 @@ public class LakalaPayServiceImpl implements LakalaPayService {
|
|||||||
* @param storeId 店铺Id
|
* @param storeId 店铺Id
|
||||||
* @param orderId 订单号
|
* @param orderId 订单号
|
||||||
* @param subject 订单标题
|
* @param subject 订单标题
|
||||||
* @param totalAmount 订单总金额
|
* @param totalAmount 订单总金额(单位:分)
|
||||||
* @param agentAmount 代理商收取金额
|
* @param agentAmount 代理商收取金额(单位:分)
|
||||||
* @param notifyURL 回调地址
|
* @param notifyURL 回调地址
|
||||||
* @param requestIP 请求ip
|
* @param requestIP 请求IP
|
||||||
* @param remark 备注
|
* @param remark 备注
|
||||||
|
* @return 拉卡拉合单预下单响应结果
|
||||||
**/
|
**/
|
||||||
@Override
|
@Override
|
||||||
public JSONObject lklTransMergePreOrder(String merchantNo, String termNo, String agentMerchantNo, String agentTermNo, String xcxAppId, String openId, String storeId, String orderId, String subject, String totalAmount, String agentAmount, String notifyURL, String requestIP, String remark) {
|
public JSONObject lklTransMergePreOrder(String merchantNo, String termNo, String agentMerchantNo, String agentTermNo, String xcxAppId, String openId, String storeId, String orderId, String subject, String totalAmount, String agentAmount, String notifyURL, String requestIP, String remark) {
|
||||||
// 2. 参数校验
|
log.info("[拉卡拉合单预下单] 开始处理请求, merchantNo={}, termNo={}, agentMerchantNo={}, agentTermNo={}, orderId={}",
|
||||||
|
merchantNo, termNo, agentMerchantNo, agentTermNo, orderId);
|
||||||
|
|
||||||
|
// 1. 参数校验
|
||||||
if (StrUtil.isBlank(merchantNo)) {
|
if (StrUtil.isBlank(merchantNo)) {
|
||||||
|
log.warn("[拉卡拉合单预下单] 参数校验失败:商家商户号不能为空, orderId={}", orderId);
|
||||||
throw new ApiException("商家商户号不能为空!");
|
throw new ApiException("商家商户号不能为空!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StrUtil.isBlank(termNo)) {
|
if (StrUtil.isBlank(termNo)) {
|
||||||
|
log.warn("[拉卡拉合单预下单] 参数校验失败:终端号不能为空, orderId={}", orderId);
|
||||||
throw new ApiException("终端号不能为空!");
|
throw new ApiException("终端号不能为空!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 校验其他必要参数
|
|
||||||
if (StrUtil.isBlank(orderId)) {
|
if (StrUtil.isBlank(orderId)) {
|
||||||
|
log.warn("[拉卡拉合单预下单] 参数校验失败:订单号不能为空, merchantNo={}, termNo={}", merchantNo, termNo);
|
||||||
throw new ApiException("订单号不能为空!");
|
throw new ApiException("订单号不能为空!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isBlank(subject)) {
|
||||||
|
log.warn("[拉卡拉合单预下单] 参数校验失败:订单标题不能为空, orderId={}", orderId);
|
||||||
|
throw new ApiException("订单标题不能为空!");
|
||||||
|
}
|
||||||
|
|
||||||
if (StrUtil.isBlank(totalAmount)) {
|
if (StrUtil.isBlank(totalAmount)) {
|
||||||
|
log.warn("[拉卡拉合单预下单] 参数校验失败:订单总金额不能为空, orderId={}", orderId);
|
||||||
throw new ApiException("订单总金额不能为空!");
|
throw new ApiException("订单总金额不能为空!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isBlank(notifyURL)) {
|
||||||
|
log.warn("[拉卡拉合单预下单] 参数校验失败:回调地址不能为空, orderId={}", orderId);
|
||||||
|
throw new ApiException("回调地址不能为空!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isBlank(requestIP)) {
|
||||||
|
log.warn("[拉卡拉合单预下单] 参数校验失败:请求IP不能为空, orderId={}", orderId);
|
||||||
|
throw new ApiException("请求IP不能为空!");
|
||||||
|
}
|
||||||
|
|
||||||
// 如果不符合合单交易条件,则走聚合主扫单笔交易
|
// 如果不符合合单交易条件,则走聚合主扫单笔交易
|
||||||
if (StrUtil.isBlank(agentMerchantNo) || StrUtil.isBlank(agentTermNo) || StrUtil.isBlank(agentAmount) || "0".equals(agentAmount)) {
|
if (StrUtil.isBlank(agentMerchantNo) || StrUtil.isBlank(agentTermNo) || StrUtil.isBlank(agentAmount) || "0".equals(agentAmount)) {
|
||||||
log.info("不符合合单交易条件,转为单笔交易处理。商家商户号:{},代理商商户号:{},代理商终端号:{},代理商金额:{}",
|
log.info("[拉卡拉合单预下单] 不符合合单交易条件,转为单笔交易处理。商家商户号:{},代理商商户号:{},代理商终端号:{},代理商金额:{}",
|
||||||
merchantNo, agentMerchantNo, agentTermNo, agentAmount);
|
merchantNo, agentMerchantNo, agentTermNo, agentAmount);
|
||||||
return lklTransPreOrder(merchantNo, termNo, xcxAppId, openId, storeId, orderId, subject, totalAmount, notifyURL, requestIP, remark);
|
return lklTransPreOrder(merchantNo, termNo, xcxAppId, openId, storeId, orderId, subject, totalAmount, notifyURL, requestIP, remark);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 4. 装配请求数据
|
log.debug("[拉卡拉合单预下单] 开始装配请求数据, orderId={}", orderId);
|
||||||
|
// 2. 装配请求数据
|
||||||
JSONObject reqData = new JSONObject();
|
JSONObject reqData = new JSONObject();
|
||||||
|
|
||||||
// 基本交易信息
|
// 基本交易信息
|
||||||
@ -251,6 +460,7 @@ public class LakalaPayServiceImpl implements LakalaPayService {
|
|||||||
reqData.put("subject", subject); // 订单标题
|
reqData.put("subject", subject); // 订单标题
|
||||||
reqData.put("notify_url", notifyURL); // 异步通知地址
|
reqData.put("notify_url", notifyURL); // 异步通知地址
|
||||||
reqData.put("remark", remark); // 备注
|
reqData.put("remark", remark); // 备注
|
||||||
|
reqData.put("complete_notify_url", "https://mall.gpxscs.cn/api/mobile/shop/lakala/trans/receive/completeNotify"); // 发货类小程序确认收获后通知商户的地址
|
||||||
|
|
||||||
// 位置信息
|
// 位置信息
|
||||||
JSONObject locationInfo = new JSONObject();
|
JSONObject locationInfo = new JSONObject();
|
||||||
@ -258,10 +468,15 @@ public class LakalaPayServiceImpl implements LakalaPayService {
|
|||||||
reqData.put("location_info", locationInfo);
|
reqData.put("location_info", locationInfo);
|
||||||
|
|
||||||
// 微信业务参数
|
// 微信业务参数
|
||||||
JSONObject accBusiFields = new JSONObject();
|
if (StrUtil.isNotBlank(xcxAppId) && StrUtil.isNotBlank(openId)) {
|
||||||
accBusiFields.put("sub_appid", xcxAppId); // 小程序appid
|
JSONObject accBusiFields = new JSONObject();
|
||||||
accBusiFields.put("user_id", openId); // 用户openid
|
accBusiFields.put("sub_appid", xcxAppId); // 小程序appId
|
||||||
reqData.put("acc_busi_fields", accBusiFields);
|
accBusiFields.put("user_id", openId); // 用户openid
|
||||||
|
reqData.put("acc_busi_fields", accBusiFields);
|
||||||
|
log.debug("[拉卡拉合单预下单] 已添加微信业务参数, xcxAppId={}, openId={}", xcxAppId, openId);
|
||||||
|
} else {
|
||||||
|
log.warn("[拉卡拉合单预下单] 微信业务参数不完整或不需要, xcxAppId={}, openId={}", xcxAppId, openId);
|
||||||
|
}
|
||||||
|
|
||||||
// 重要约定,订单号规则:商品订单:ORD_订单号,运费订单:DF_订单号
|
// 重要约定,订单号规则:商品订单:ORD_订单号,运费订单:DF_订单号
|
||||||
// 分单信息
|
// 分单信息
|
||||||
@ -269,8 +484,20 @@ public class LakalaPayServiceImpl implements LakalaPayService {
|
|||||||
goodsSplitInfo.put("out_sub_trade_no", CommonConstant.Sep_GoodsFee_Prefix + orderId); // 商品子订单号
|
goodsSplitInfo.put("out_sub_trade_no", CommonConstant.Sep_GoodsFee_Prefix + orderId); // 商品子订单号
|
||||||
goodsSplitInfo.put("merchant_no", merchantNo); // 分账商户号
|
goodsSplitInfo.put("merchant_no", merchantNo); // 分账商户号
|
||||||
goodsSplitInfo.put("term_no", termNo); // 分账终端号
|
goodsSplitInfo.put("term_no", termNo); // 分账终端号
|
||||||
int totalAmountInt = Convert.toInt(totalAmount) - Convert.toInt(agentAmount);
|
|
||||||
goodsSplitInfo.put("amount", Convert.toStr(totalAmountInt)); // 分账金额
|
// 安全转换金额,避免类型转换异常
|
||||||
|
int totalAmountInt = 0;
|
||||||
|
int agentAmountInt = 0;
|
||||||
|
try {
|
||||||
|
totalAmountInt = Convert.toInt(totalAmount);
|
||||||
|
agentAmountInt = Convert.toInt(agentAmount);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
log.error("[拉卡拉合单预下单] 金额转换异常, totalAmount={}, agentAmount={}, orderId={}", totalAmount, agentAmount, orderId, e);
|
||||||
|
throw new ApiException("金额格式错误!");
|
||||||
|
}
|
||||||
|
|
||||||
|
int goodsAmountInt = totalAmountInt - agentAmountInt;
|
||||||
|
goodsSplitInfo.put("amount", Convert.toStr(goodsAmountInt)); // 分账金额
|
||||||
goodsSplitInfo.put("settle_type", "0"); // "0"或者空,常规结算方式
|
goodsSplitInfo.put("settle_type", "0"); // "0"或者空,常规结算方式
|
||||||
goodsSplitInfo.put("sub_remark", "商品订单金额"); // 子单备注信息
|
goodsSplitInfo.put("sub_remark", "商品订单金额"); // 子单备注信息
|
||||||
|
|
||||||
@ -287,50 +514,87 @@ public class LakalaPayServiceImpl implements LakalaPayService {
|
|||||||
outSplitInfo.add(goodsSplitInfo);
|
outSplitInfo.add(goodsSplitInfo);
|
||||||
reqData.put("out_split_info", outSplitInfo);
|
reqData.put("out_split_info", outSplitInfo);
|
||||||
|
|
||||||
// 5. 构造请求体
|
log.info("[拉卡拉合单预下单] 分单信息组装完成, orderId={}, goodsAmount={}分, deliveryAmount={}分",
|
||||||
|
orderId, goodsAmountInt, agentAmountInt);
|
||||||
|
|
||||||
|
// 3. 构造请求体
|
||||||
JSONObject reqBody = new JSONObject();
|
JSONObject reqBody = new JSONObject();
|
||||||
reqBody.put("req_time", DateTimeUtils.formatDateTime(LocalDateTime.now(), "yyyyMMddHHmmss"));
|
reqBody.put("req_time", DateTimeUtils.formatDateTime(LocalDateTime.now(), "yyyyMMddHHmmss"));
|
||||||
reqBody.put("version", "3.0");
|
reqBody.put("version", "3.0");
|
||||||
reqBody.put("req_data", reqData);
|
reqBody.put("req_data", reqData);
|
||||||
|
|
||||||
// 6. 发送请求
|
log.info("[拉卡拉合单预下单] 请求参数组装完成, orderId={}", orderId);
|
||||||
|
log.debug("[拉卡拉合单预下单] 完整请求参数: {}", JSONUtil.toJsonStr(reqBody));
|
||||||
|
|
||||||
|
// 4. 发送请求
|
||||||
String reqUrl = serverUrl + "/api/v3/labs/trans/merge/preorder";
|
String reqUrl = serverUrl + "/api/v3/labs/trans/merge/preorder";
|
||||||
log.info("拉卡拉合单预下单请求参数:{}", reqBody);
|
log.info("[拉卡拉合单预下单] 准备发送请求, orderId={}, url={}", orderId, reqUrl);
|
||||||
|
|
||||||
String authorization = LakalaUtil.genAuthorizationByPath(priKeyPath, appId, serialNo, reqBody.toString());
|
String authorization = LakalaUtil.genAuthorizationByPath(priKeyPath, appId, serialNo, reqBody.toString());
|
||||||
|
if (StrUtil.isBlank(authorization)) {
|
||||||
|
log.error("[拉卡拉合单预下单] 生成签名失败, orderId={}", orderId);
|
||||||
|
return new JSONObject().set("code", "BBS00001").set("msg", "生成请求签名失败").set("resp_data", null);
|
||||||
|
}
|
||||||
|
|
||||||
JSONObject header = new JSONObject();
|
JSONObject header = new JSONObject();
|
||||||
header.put("Authorization", authorization);
|
header.put("Authorization", authorization);
|
||||||
|
header.put("Content-Type", "application/json");
|
||||||
|
|
||||||
// 这里的请求方法,对返回的字段进行了处理,需要注意
|
log.debug("[拉卡拉合单预下单] 请求头信息生成完成, orderId={}", orderId);
|
||||||
ResponseEntity<JSONObject> lakalaRespJSON = RestTemplateHttpUtil.sendPostBodyBackEntity(reqUrl, header, reqBody, JSONObject.class);
|
|
||||||
log.info("拉卡拉合单交易响应参数:{}", lakalaRespJSON);
|
|
||||||
|
|
||||||
// 7. 处理响应结果
|
// 发送请求
|
||||||
if (lakalaRespJSON == null) {
|
ResponseEntity<JSONObject> lakalaRespEntity = RestTemplateHttpUtil.sendPostBodyBackEntity(reqUrl, header, reqBody, JSONObject.class);
|
||||||
|
log.info("[拉卡拉合单预下单] 收到响应, orderId={}, responseStatus={}", orderId, lakalaRespEntity != null ? lakalaRespEntity.getStatusCode() : "NULL");
|
||||||
|
|
||||||
|
// 5. 处理响应结果
|
||||||
|
if (lakalaRespEntity == null) {
|
||||||
|
log.warn("[拉卡拉合单预下单] 响应为空, orderId={}", orderId);
|
||||||
return new JSONObject().set("code", "BBS00001").set("msg", "拉卡拉合单交易无响应值").set("resp_data", null);
|
return new JSONObject().set("code", "BBS00001").set("msg", "拉卡拉合单交易无响应值").set("resp_data", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONObject respBody = lakalaRespJSON.getBody();
|
JSONObject respBody = lakalaRespEntity.getBody();
|
||||||
|
log.debug("[拉卡拉合单预下单] 响应体内容, orderId={}, responseBody={}", orderId, respBody);
|
||||||
|
|
||||||
// 7. 处理响应结果
|
// 6. 处理响应结果
|
||||||
if (!lklPaySuccessCode.equals(respBody.getStr("code")) || respBody == null) {
|
if (respBody == null) {
|
||||||
return new JSONObject().set("code", "BBS00001").set("msg", "拉卡拉合单交易无响应值").set("resp_data", null);
|
log.warn("[拉卡拉合单预下单] 响应体为空, orderId={}", orderId);
|
||||||
|
return new JSONObject().set("code", "BBS00001").set("msg", "拉卡拉合单交易响应体为空").set("resp_data", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String responseCode = respBody.getStr("code");
|
||||||
|
if (StrUtil.isBlank(responseCode)) {
|
||||||
|
log.warn("[拉卡拉合单预下单] 响应码为空, orderId={}", orderId);
|
||||||
|
return new JSONObject().set("code", "BBS00001").set("msg", "拉卡拉合单交易响应码为空").set("resp_data", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用安全的字符串比较方式,避免空指针异常
|
||||||
|
if (!lklPaySuccessCode.equals(responseCode)) {
|
||||||
|
log.warn("[拉卡拉合单预下单] 响应码异常, orderId={}, code={}, msg={}", orderId, responseCode, respBody.getStr("msg"));
|
||||||
|
return new JSONObject().set("code", "BBS00001").set("msg", "拉卡拉合单交易失败:" + respBody.getStr("msg")).set("resp_data", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("[拉卡拉合单预下单] 支付成功,准备保存订单记录, orderId={}", orderId);
|
||||||
// 新增一个拉卡拉订单记录 shop_order_lkl 表
|
// 新增一个拉卡拉订单记录 shop_order_lkl 表
|
||||||
JSONObject lklPayReqAndRespJson = new JSONObject();
|
JSONObject lklPayReqAndRespJson = new JSONObject();
|
||||||
lklPayReqAndRespJson.put("req", reqData);
|
lklPayReqAndRespJson.put("req", reqData);
|
||||||
lklPayReqAndRespJson.put("resp", respBody); // 返回原始响应数据
|
lklPayReqAndRespJson.put("resp", respBody); // 返回原始响应数据
|
||||||
|
|
||||||
// 新增 shopOrderLkl 记录
|
try {
|
||||||
shopService.lklPayAddShopOrderLkl(lklPayReqAndRespJson);
|
// 新增 shopOrderLkl 记录
|
||||||
|
shopService.lklPayAddShopOrderLkl(lklPayReqAndRespJson);
|
||||||
|
log.debug("[拉卡拉合单预下单] 订单记录保存成功, orderId={}", orderId);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("[拉卡拉合单预下单] 保存订单记录失败, orderId={}", orderId, e);
|
||||||
|
// 不中断主流程,仅记录错误
|
||||||
|
}
|
||||||
|
|
||||||
// 8. 返回响应结果
|
// 7. 返回响应结果
|
||||||
|
log.info("[拉卡拉合单预下单] 处理完成, orderId={}, responseCode={}", orderId, responseCode);
|
||||||
return respBody;
|
return respBody;
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("拉卡拉合单交易出错,订单号:{},错误信息:", orderId, e);
|
log.error("[拉卡拉合单预下单] 系统异常, merchantNo={}, termNo={}, orderId={}", merchantNo, termNo, orderId, e);
|
||||||
throw new ApiException("拉卡拉合单交易出错:" + e.getMessage(), e);
|
return new JSONObject().set("code", "BBS00001").set("msg", "系统异常:" + e.getMessage()).set("resp_data", null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -340,7 +604,7 @@ public class LakalaPayServiceImpl implements LakalaPayService {
|
|||||||
* 参考地址:https://o.lakala.com/#/home/document/detail?id=113
|
* 参考地址:https://o.lakala.com/#/home/document/detail?id=113
|
||||||
*
|
*
|
||||||
* @param storeId 店铺ID
|
* @param storeId 店铺ID
|
||||||
* @param outTradeNo 退货订单号,如: FX-20241214-1
|
* @param outTradeNo 外部交易订单号
|
||||||
* @param originTradeNo 原拉卡拉交易流水号
|
* @param originTradeNo 原拉卡拉交易流水号
|
||||||
* @param refundAmount 退款金额(单位:分)
|
* @param refundAmount 退款金额(单位:分)
|
||||||
* @param refundReason 退款原因
|
* @param refundReason 退款原因
|
||||||
@ -351,33 +615,58 @@ public class LakalaPayServiceImpl implements LakalaPayService {
|
|||||||
@Override
|
@Override
|
||||||
public Pair<Boolean, String> innerLklRefund(Integer storeId, String outTradeNo, String originTradeNo, String refundAmount, String refundReason, String lklMerchantNo, String lklTermNo) {
|
public Pair<Boolean, String> innerLklRefund(Integer storeId, String outTradeNo, String originTradeNo, String refundAmount, String refundReason, String lklMerchantNo, String lklTermNo) {
|
||||||
try {
|
try {
|
||||||
log.info("开始执行拉卡拉内部退款,参数: storeId={}, outTradeNo={}, originTradeNo={}, refundAmount={}, refundReason={}",
|
log.info("[拉卡拉退款] 开始执行拉卡拉内部退款,参数: storeId={}, outTradeNo={}, originTradeNo={}, refundAmount={}, refundReason={}",
|
||||||
storeId, outTradeNo, originTradeNo, refundAmount, refundReason);
|
storeId, outTradeNo, originTradeNo, refundAmount, refundReason);
|
||||||
|
|
||||||
// 1. 获取请求IP
|
// 1. 获取请求IP
|
||||||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||||
if (attributes == null) {
|
if (attributes == null) {
|
||||||
log.error("无法获取HttpServletRequest,退款失败");
|
log.error("[拉卡拉退款] 无法获取HttpServletRequest,退款失败");
|
||||||
return Pair.of(false, I18nUtil._("系统异常,无法获取请求信息!"));
|
return Pair.of(false, I18nUtil._("系统异常,无法获取请求信息!"));
|
||||||
}
|
}
|
||||||
HttpServletRequest request = attributes.getRequest();
|
HttpServletRequest request = attributes.getRequest();
|
||||||
String requestIp = IpKit.getRealIp(request);
|
String requestIp = IpKit.getRealIp(request);
|
||||||
|
|
||||||
// 2. 校验参数
|
// 2. 校验参数
|
||||||
if (ObjectUtil.isEmpty(storeId) || org.apache.commons.lang3.StringUtils.isAnyBlank(outTradeNo, refundAmount, originTradeNo)) {
|
if (ObjectUtil.isEmpty(storeId)) {
|
||||||
log.warn("退款请求参数不完整: storeId={}, outTradeNo={}, originTradeNo={}, refundAmount={}, requestIp={}", storeId, outTradeNo, originTradeNo, refundAmount, requestIp);
|
log.warn("[拉卡拉退款] 店铺ID不能为空: storeId={}", storeId);
|
||||||
return Pair.of(false, I18nUtil._("缺少必要参数,退款失败!"));
|
return Pair.of(false, I18nUtil._("店铺ID不能为空,退款失败!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isBlank(outTradeNo)) {
|
||||||
|
log.warn("[拉卡拉退款] 外部交易订单号不能为空: outTradeNo={}", outTradeNo);
|
||||||
|
return Pair.of(false, I18nUtil._("外部交易订单号不能为空,退款失败!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isBlank(originTradeNo)) {
|
||||||
|
log.warn("[拉卡拉退款] 原拉卡拉交易流水号不能为空: originTradeNo={}", originTradeNo);
|
||||||
|
return Pair.of(false, I18nUtil._("原拉卡拉交易流水号不能为空,退款失败!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isBlank(refundAmount)) {
|
||||||
|
log.warn("[拉卡拉退款] 退款金额不能为空: refundAmount={}", refundAmount);
|
||||||
|
return Pair.of(false, I18nUtil._("退款金额不能为空,退款失败!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校验退款金额格式
|
||||||
if (!refundAmount.matches("\\d+") || Integer.parseInt(refundAmount) <= 0) {
|
if (!refundAmount.matches("\\d+") || Integer.parseInt(refundAmount) <= 0) {
|
||||||
log.warn("退款金额不合法: refundAmount={}", refundAmount);
|
log.warn("[拉卡拉退款] 退款金额不合法: refundAmount={}", refundAmount);
|
||||||
return Pair.of(false, I18nUtil._("退款金额不合法!"));
|
return Pair.of(false, I18nUtil._("退款金额不合法!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 初始化拉卡拉SDK
|
// 3. 初始化拉卡拉SDK
|
||||||
initLKLSDK();
|
initLKLSDK();
|
||||||
|
|
||||||
// 4. 获取店铺的拉卡拉商户号和终端号
|
// 4. 获取店铺的拉卡拉商户号和终端号
|
||||||
ShopStoreBase shopStoreBase = shopService.getLklMerchantNoAndTermNo(storeId);
|
ShopStoreBase shopStoreBase = shopService.getLklMerchantNoAndTermNo(storeId);
|
||||||
if (shopStoreBase == null || org.apache.commons.lang3.StringUtils.isAnyBlank(shopStoreBase.getLkl_merchant_no(), shopStoreBase.getLkl_term_no())) {
|
if (shopStoreBase == null) {
|
||||||
log.error("无法获取店铺的拉卡拉商户号或终端号: storeId={}", storeId);
|
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._("缺少商户号参数,退款失败!"));
|
return Pair.of(false, I18nUtil._("缺少商户号参数,退款失败!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,37 +685,44 @@ public class LakalaPayServiceImpl implements LakalaPayService {
|
|||||||
|
|
||||||
refundRequest.setLocationInfo(new V3LabsTradeLocationInfo(requestIp, null, ""));
|
refundRequest.setLocationInfo(new V3LabsTradeLocationInfo(requestIp, null, ""));
|
||||||
|
|
||||||
log.info("拉卡拉退款请求参数: {}", JSONUtil.toJsonStr(refundRequest));
|
log.info("[拉卡拉退款] 请求参数: {}", JSONUtil.toJsonStr(refundRequest));
|
||||||
|
|
||||||
String responseString = LKLSDK.httpPost(refundRequest);
|
String responseString = LKLSDK.httpPost(refundRequest);
|
||||||
// 6. 处理响应
|
// 6. 处理响应
|
||||||
if (StrUtil.isBlank(responseString)) {
|
if (StrUtil.isBlank(responseString)) {
|
||||||
log.error("拉卡拉退款接口无响应");
|
log.error("[拉卡拉退款] 拉卡拉退款接口无响应");
|
||||||
return Pair.of(false, I18nUtil._("服务端无返回值,退款失败!"));
|
return Pair.of(false, I18nUtil._("服务端无返回值,退款失败!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info("拉卡拉退款接口响应: {}", responseString);
|
log.info("[拉卡拉退款] 拉卡拉退款接口响应: {}", responseString);
|
||||||
|
|
||||||
JSONObject lakalaResponseJson = JSONUtil.parseObj(responseString);
|
JSONObject lakalaResponseJson = JSONUtil.parseObj(responseString);
|
||||||
if (lakalaResponseJson == null) {
|
if (lakalaResponseJson == null) {
|
||||||
log.error("拉卡拉退款接口返回值解析失败: responseString={}", responseString);
|
log.error("[拉卡拉退款] 拉卡拉退款接口返回值解析失败: responseString={}", responseString);
|
||||||
return Pair.of(false, I18nUtil._("返回值解析失败,退款失败!"));
|
return Pair.of(false, I18nUtil._("返回值解析失败,退款失败!"));
|
||||||
}
|
}
|
||||||
if (!"BBS00000".equals(lakalaResponseJson.getStr("code"))) {
|
|
||||||
|
String responseCode = lakalaResponseJson.getStr("code");
|
||||||
|
if (StrUtil.isBlank(responseCode)) {
|
||||||
|
log.error("[拉卡拉退款] 拉卡拉退款响应码为空: response={}", responseString);
|
||||||
|
return Pair.of(false, I18nUtil._("返回值格式错误,退款失败!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!"BBS00000".equals(responseCode)) {
|
||||||
String errorMessage = lakalaResponseJson.getStr("msg", "未知错误");
|
String errorMessage = lakalaResponseJson.getStr("msg", "未知错误");
|
||||||
log.error("拉卡拉退款失败, 错误信息: {}", errorMessage);
|
log.error("[拉卡拉退款] 拉卡拉退款失败, 错误信息: {}, 响应码: {}", errorMessage, responseCode);
|
||||||
return Pair.of(false, I18nUtil._(errorMessage));
|
return Pair.of(false, I18nUtil._(errorMessage));
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONObject responseData = lakalaResponseJson.getJSONObject("resp_data");
|
JSONObject responseData = lakalaResponseJson.getJSONObject("resp_data");
|
||||||
log.info("拉卡拉退款成功: outTradeNo={}", outTradeNo);
|
log.info("[拉卡拉退款] 拉卡拉退款成功: outTradeNo={}", outTradeNo);
|
||||||
return Pair.of(true, responseData == null ? "" : responseData.toString());
|
return Pair.of(true, responseData == null ? "" : responseData.toString());
|
||||||
|
|
||||||
} catch (SDKException e) {
|
} catch (SDKException e) {
|
||||||
log.error("拉卡拉退款SDK异常: ", e);
|
log.error("[拉卡拉退款] 拉卡拉退款SDK异常: ", e);
|
||||||
return Pair.of(false, I18nUtil._("拉卡拉退款SDK异常,退款失败!") + e.getMessage());
|
return Pair.of(false, I18nUtil._("拉卡拉退款SDK异常,退款失败!") + e.getMessage());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("拉卡拉退款发生未知异常: ", e);
|
log.error("[拉卡拉退款] 拉卡拉退款发生未知异常: ", e);
|
||||||
return Pair.of(false, I18nUtil._("拉卡拉退款发生未知异常,退款失败!") + e.getMessage());
|
return Pair.of(false, I18nUtil._("拉卡拉退款发生未知异常,退款失败!") + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1434,7 +1434,7 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
|
|||||||
payConsumeDeposit.setUser_id(userId);
|
payConsumeDeposit.setUser_id(userId);
|
||||||
|
|
||||||
lklNotifyRespJSON.set("out_separate_no", orderId);// 默认非合单主单订单号
|
lklNotifyRespJSON.set("out_separate_no", orderId);// 默认非合单主单订单号
|
||||||
lklNotifyRespJSON.set("lkl_split_log_no", lklNotifyRespJSON.getStr("log_no")); // 默认非合单主单的流水号
|
lklNotifyRespJSON.set("lkl_sub_log_no", lklNotifyRespJSON.getStr("log_no")); // 默认非合单主单的流水号
|
||||||
lklNotifyRespJSON.set("split_amt", lklNotifyRespJSON.getStr("total_amount")); // 默认非合单主单支付金额
|
lklNotifyRespJSON.set("split_amt", lklNotifyRespJSON.getStr("total_amount")); // 默认非合单主单支付金额
|
||||||
// 拉卡拉订单合单信息
|
// 拉卡拉订单合单信息
|
||||||
if (StrUtil.isNotBlank(outSplitRspInfos)) {
|
if (StrUtil.isNotBlank(outSplitRspInfos)) {
|
||||||
@ -1453,7 +1453,7 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
|
|||||||
cn.hutool.json.JSONObject goodsOrderInfo = payConsumeTradeService.getLklCombineSplitRespInfo(outSplitRspInfos, false);
|
cn.hutool.json.JSONObject goodsOrderInfo = payConsumeTradeService.getLklCombineSplitRespInfo(outSplitRspInfos, false);
|
||||||
if (goodsOrderInfo != null) {
|
if (goodsOrderInfo != null) {
|
||||||
lklNotifyRespJSON.set("out_separate_no", goodsOrderInfo.getStr("out_sub_trade_no"));// 合单子订单号
|
lklNotifyRespJSON.set("out_separate_no", goodsOrderInfo.getStr("out_sub_trade_no"));// 合单子订单号
|
||||||
lklNotifyRespJSON.set("lkl_split_log_no", lklNotifyRespJSON.getStr("sub_log_no")); // 合单子商品订单的流水号
|
lklNotifyRespJSON.set("lkl_sub_log_no", lklNotifyRespJSON.getStr("sub_log_no")); // 合单子商品订单的流水号
|
||||||
lklNotifyRespJSON.set("split_amt", lklNotifyRespJSON.getStr("amount")); // 合单子商品订单支付金额
|
lklNotifyRespJSON.set("split_amt", lklNotifyRespJSON.getStr("amount")); // 合单子商品订单支付金额
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -131,6 +131,18 @@ public class LakalaController extends BaseControllerImpl {
|
|||||||
return lakalaPayService.getBankCardBin(paramsJSON.getStr("bankCardNo"));
|
return lakalaPayService.getBankCardBin(paramsJSON.getStr("bankCardNo"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ApiOperation(value = "发货类交易确认收货通知", notes = "发货类交易确认收货通知 https://o.lakala.com/#/home/document/detail?id=1003")
|
||||||
|
@RequestMapping(value = "/trans/receive/completeNotify", method = RequestMethod.POST)
|
||||||
|
public ResponseEntity<JSONObject> receiveCompleteNotify(HttpServletRequest request) {
|
||||||
|
// 完整地址: https://mall.gpxscs.cn/api/mobile/shop/lakala/trans/receive/completeNotify
|
||||||
|
JSONObject resp = lakalaPayService.receiveCompleteNotify(request);
|
||||||
|
if (resp != null && "SUCCESS".equals(resp.get("code"))) {
|
||||||
|
return ResponseEntity.ok(resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(resp);
|
||||||
|
}
|
||||||
|
|
||||||
@ApiOperation(value = "商户入网电子合同申请回调通知", notes = "商户入网电子合同申请回调通知")
|
@ApiOperation(value = "商户入网电子合同申请回调通知", notes = "商户入网电子合同申请回调通知")
|
||||||
@RequestMapping(value = "/ec/applyNotify", method = RequestMethod.POST)
|
@RequestMapping(value = "/ec/applyNotify", method = RequestMethod.POST)
|
||||||
public ResponseEntity<JSONObject> ecApplyNotify(HttpServletRequest request) {
|
public ResponseEntity<JSONObject> ecApplyNotify(HttpServletRequest request) {
|
||||||
|
|||||||
@ -95,6 +95,19 @@ public interface LakalaApiService {
|
|||||||
*/
|
*/
|
||||||
Pair<Boolean, String> innerApplyLedgerMer(String merCupNo);
|
Pair<Boolean, String> innerApplyLedgerMer(String merCupNo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发货类交易确认收货通知
|
||||||
|
* 参考:https://o.lakala.com/#/home/document/detail?id=1003
|
||||||
|
* 注意:
|
||||||
|
* (1)交易通知接口是交易成功完成后会向 complete_notify_url 这个地址(主扫交易或者主扫合单请求中的complete_notify_url字段)发起交易结果通知。拉卡拉系统通知时,如果商户的应答没有按照以下“响应参考报文”示例返回成功状态时,则系统认为通知失败,系统会通过一定的策略定期重新发起通知。
|
||||||
|
* (2)同样的通知可能会多次发送给商户系统,商户系统必须能够正确处理重复的通知。
|
||||||
|
* (3)在没有收到拉卡拉支付交易通知的情况下,建议商户主动调用【06查询交易】确认交易状态。
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
JSONObject receiveCompleteNotify(HttpServletRequest request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 商户入网电子合同申请回调通知
|
* 商户入网电子合同申请回调通知
|
||||||
* 参考:https://o.lakala.com/#/home/document/detail?id=289
|
* 参考:https://o.lakala.com/#/home/document/detail?id=289
|
||||||
@ -172,6 +185,29 @@ public interface LakalaApiService {
|
|||||||
*/
|
*/
|
||||||
Pair<Boolean, String> innerDoOrderSeparate(String orderId, String storeId);
|
Pair<Boolean, String> innerDoOrderSeparate(String orderId, String storeId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据商户号、交易号和收货流水号执行订单分账操作
|
||||||
|
* <p>
|
||||||
|
* 该方法用于处理拉卡拉订单的分账逻辑。在用户确认收货后,系统会根据订单信息执行分账操作,
|
||||||
|
* 将订单金额按照预设比例分配给平台、商家和代理商(如果存在)。
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* 分账操作流程:
|
||||||
|
* 1. 参数校验和订单查询
|
||||||
|
* 2. 检查订单状态(是否已确认收货)
|
||||||
|
* 3. 检查是否已分账,避免重复处理
|
||||||
|
* 4. 计算分账金额
|
||||||
|
* 5. 构建分账请求并发送至拉卡拉
|
||||||
|
* 6. 保存分账结果
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param lklMerchantNo 拉卡拉商户号
|
||||||
|
* @param receiveTradeNo 收货交易号(对应拉卡拉的trade_no)
|
||||||
|
* @param receiveLogNo 收货流水号(对应拉卡拉的log_no)
|
||||||
|
* @return Pair<Boolean, String> 处理结果对,first为是否成功,second为结果描述信息
|
||||||
|
*/
|
||||||
|
Pair<Boolean, String> innerDoOrderSeparateByMerchantAndLogNo(String lklMerchantNo, String receiveTradeNo, String receiveLogNo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分账结果通知
|
* 分账结果通知
|
||||||
* 参考:https://o.lakala.com/#/home/document/detail?id=393
|
* 参考:https://o.lakala.com/#/home/document/detail?id=393
|
||||||
|
|||||||
@ -675,6 +675,104 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发货类交易确认收货通知处理
|
||||||
|
* <p>
|
||||||
|
* 参考文档:https://o.lakala.com/#/home/document/detail?id=1003
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* 注意事项:
|
||||||
|
* (1)交易通知接口是交易成功完成后会向 complete_notify_url 这个地址(主扫交易或者主扫合单请求中的complete_notify_url字段)发起交易结果通知。
|
||||||
|
* 拉卡拉系统通知时,如果商户的应答没有按照以下"响应参考报文"示例返回成功状态时,则系统认为通知失败,系统会通过一定的策略定期重新发起通知。
|
||||||
|
* (2)同样的通知可能会多次发送给商户系统,商户系统必须能够正确处理重复的通知。
|
||||||
|
* (3)在没有收到拉卡拉支付交易通知的情况下,建议商户主动调用【06查询交易】确认交易状态。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param request HTTP请求对象,包含拉卡拉确认收货通知的参数
|
||||||
|
* @return JSONObject 响应结果对象
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public JSONObject receiveCompleteNotify(HttpServletRequest request) {
|
||||||
|
log.info("[确认收货通知] 开始处理发货类交易确认收货通知");
|
||||||
|
|
||||||
|
// 验签
|
||||||
|
Pair<Boolean, String> checkResult = LakalaUtil.chkLklApiNotifySign(request, lklNotifyCerPath, false);
|
||||||
|
if (!checkResult.getFirst()) {
|
||||||
|
log.warn("[确认收货通知] 验签失败: {}", checkResult.getSecond());
|
||||||
|
return JSONUtil.createObj().set("code", "FAIL").set("message", checkResult.getSecond());
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject paramsJSON = JSONUtil.parseObj(checkResult.getSecond());
|
||||||
|
if (paramsJSON == null) {
|
||||||
|
log.warn("[确认收货通知] 参数解析失败: 返回数据转换异常");
|
||||||
|
return JSONUtil.createObj().set("code", "FAIL").set("message", "返回数据转换异常!");
|
||||||
|
}
|
||||||
|
|
||||||
|
String logNo = paramsJSON.getStr("log_no");
|
||||||
|
String tradeState = paramsJSON.getStr("trade_state");
|
||||||
|
String merchantNo = paramsJSON.getStr("merchant_no");
|
||||||
|
String originTradeNo = paramsJSON.getStr("origin_trade_no");
|
||||||
|
String originLogNo = paramsJSON.getStr("origin_log_no");
|
||||||
|
|
||||||
|
log.info("[确认收货通知] 接收到通知参数: logNo={}, tradeState={}, merchantNo={}, originTradeNo={}, originLogNo={}",
|
||||||
|
logNo, tradeState, merchantNo, originTradeNo, originLogNo);
|
||||||
|
|
||||||
|
if (StrUtil.isBlank(tradeState) || !"SUCCESS".equals(tradeState)) {
|
||||||
|
log.warn("[确认收货通知] 交易状态未成功,不做任何处理: tradeState={}", tradeState);
|
||||||
|
return JSONUtil.createObj().set("code", "FAIL").set("message", "交易状态未成功,不做任何处理!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isBlank(logNo) || StrUtil.isBlank(merchantNo) || StrUtil.isBlank(originTradeNo) || StrUtil.isBlank(originLogNo)) {
|
||||||
|
log.warn("[确认收货通知] 关键参数为空: logNo={}, merchantNo={}, originTradeNo={}, originLogNo={}",
|
||||||
|
logNo, merchantNo, originTradeNo, originLogNo);
|
||||||
|
return JSONUtil.createObj().set("code", "FAIL").set("message", "关键编号返回空值!");
|
||||||
|
}
|
||||||
|
|
||||||
|
ShopOrderLkl shopOrderLkl = shopOrderLklService.getByMerchantNoAndTradeNoAndSubLogNo(merchantNo, originTradeNo, originLogNo);
|
||||||
|
if (shopOrderLkl == null) {
|
||||||
|
log.warn("[确认收货通知] 订单不存在: merchantNo={}, originTradeNo={}, originLogNo={}",
|
||||||
|
merchantNo, originTradeNo, originLogNo);
|
||||||
|
return JSONUtil.createObj().set("code", "FAIL").set("message", "订单不存在!");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 更新订单信息
|
||||||
|
shopOrderLkl.setLkl_receive_log_no(logNo);
|
||||||
|
shopOrderLkl.setLkl_receive_trade_no(paramsJSON.getStr("trade_no"));
|
||||||
|
shopOrderLkl.setLkl_receive_notify_resp(checkResult.getSecond());
|
||||||
|
shopOrderLkl.setReceive_status(CommonConstant.Enable);
|
||||||
|
|
||||||
|
log.debug("[确认收货通知] 准备更新订单信息: orderId={}", shopOrderLkl.getOrder_id());
|
||||||
|
Boolean updateResult = shopOrderLklService.addOrUpdateByStoreOrder(shopOrderLkl);
|
||||||
|
if (Boolean.FALSE.equals(updateResult)) {
|
||||||
|
log.error("[确认收货通知] 更新订单信息失败: orderId={}", shopOrderLkl.getOrder_id());
|
||||||
|
return JSONUtil.createObj().set("code", "FAIL").set("message", "更新订单信息失败!");
|
||||||
|
}
|
||||||
|
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(), logNo);
|
||||||
|
if (!separateResult.getFirst()) {
|
||||||
|
log.error("[确认收货通知] 发起分账指令失败: orderId={}, reason={}", shopOrderLkl.getOrder_id(), separateResult.getSecond());
|
||||||
|
return JSONUtil.createObj().set("code", "FAIL").set("message", "发起分账指令失败:" + separateResult.getSecond());
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("[确认收货通知] 处理完成: orderId={}, log_no={}", shopOrderLkl.getOrder_id(), shopOrderLkl.getLkl_receive_log_no());
|
||||||
|
JSONObject respData = JSONUtil.createObj();
|
||||||
|
respData.set("code", "SUCCESS");
|
||||||
|
respData.set("message", "操作成功!");
|
||||||
|
return respData;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("[确认收货通知] 处理过程中发生异常: orderId=" + shopOrderLkl.getOrder_id(), e);
|
||||||
|
return JSONUtil.createObj().set("code", "FAIL").set("message", "系统处理异常:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 商户入网电子合同申请回调通知
|
* 商户入网电子合同申请回调通知
|
||||||
* 参考:https://o.lakala.com/#/home/document/detail?id=289
|
* 参考:https://o.lakala.com/#/home/document/detail?id=289
|
||||||
@ -694,7 +792,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
|
|
||||||
String errMsg = "入网电子合同申请回调:";
|
String errMsg = "入网电子合同申请回调:";
|
||||||
JSONObject respData = new JSONObject();
|
JSONObject respData = new JSONObject();
|
||||||
respData.set("code", "FAIL").set("message", "处理失败!");
|
respData.set("code", "FAIL").set("message", "返回数据转换异常!");
|
||||||
|
|
||||||
JSONObject paramsJSON = JSONUtil.parseObj(checkResult.getSecond());
|
JSONObject paramsJSON = JSONUtil.parseObj(checkResult.getSecond());
|
||||||
if (paramsJSON == null) {
|
if (paramsJSON == null) {
|
||||||
@ -1601,7 +1699,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
public Pair<Boolean, String> innerDoOrderSeparate(String orderId, String storeId) {
|
public Pair<Boolean, String> innerDoOrderSeparate(String orderId, String storeId) {
|
||||||
// 1. 输入参数校验
|
// 1. 输入参数校验
|
||||||
if (StrUtil.isBlank(orderId)) {
|
if (StrUtil.isBlank(orderId)) {
|
||||||
log.warn("分账操作参数校验失败:订单号为空");
|
log.warn("[分账操作] 参数校验失败:订单号为空");
|
||||||
return Pair.of(false, "订单号不能为空");
|
return Pair.of(false, "订单号不能为空");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1609,10 +1707,10 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
// TODO 检查可分账余额是否足够?
|
// TODO 检查可分账余额是否足够?
|
||||||
|
|
||||||
// 2. 查询订单信息
|
// 2. 查询订单信息
|
||||||
log.info("开始执行订单[{}]分账操作", orderId);
|
log.info("[分账操作] 开始执行订单[{}]分账操作", orderId);
|
||||||
List<ShopOrderLkl> shopOrderLklList = shopOrderLklService.selectByOrderId(orderId, "", storeId);
|
List<ShopOrderLkl> shopOrderLklList = shopOrderLklService.selectByOrderId(orderId, "", storeId);
|
||||||
if (CollectionUtil.isEmpty(shopOrderLklList)) {
|
if (CollectionUtil.isEmpty(shopOrderLklList)) {
|
||||||
log.warn("分账操作失败:订单[{}]不存在", orderId);
|
log.warn("[分账操作] 失败:订单[{}]不存在", orderId);
|
||||||
return Pair.of(false, "订单不存在");
|
return Pair.of(false, "订单不存在");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1624,21 +1722,26 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
initLKLSDK();
|
initLKLSDK();
|
||||||
|
|
||||||
// 4. 遍历处理每个店铺订单的分账
|
// 4. 遍历处理每个店铺订单的分账
|
||||||
log.info("订单[{}]包含{}个子订单,开始逐一处理", orderId, totalCount);
|
log.info("[分账操作] 订单[{}]包含{}个子订单,开始逐一处理", orderId, totalCount);
|
||||||
for (ShopOrderLkl shopOrderLkl : shopOrderLklList) {
|
for (ShopOrderLkl shopOrderLkl : shopOrderLklList) {
|
||||||
log.debug("处理子订单:storeId={}, splitLogNo={}", shopOrderLkl.getStore_id(), shopOrderLkl.getLkl_split_log_no());
|
log.debug("[分账操作] 处理子订单:storeId={}, subLogNo={}, receive_log_no={}", shopOrderLkl.getStore_id(), shopOrderLkl.getLkl_sub_log_no(), shopOrderLkl.getLkl_receive_log_no());
|
||||||
|
|
||||||
|
if (!CommonConstant.Enable.equals(shopOrderLkl.getReceive_status()) || StrUtil.isBlank(shopOrderLkl.getLkl_receive_log_no())) {
|
||||||
|
log.warn("[分账操作] 订单[{}]对账流水号[{}]未被确认收货,跳过处理", orderId, shopOrderLkl.getLkl_receive_log_no());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// 5. 检查分账状态,避免重复处理
|
// 5. 检查分账状态,避免重复处理
|
||||||
LklOrderSeparate lklOrderSeparateExist = lklOrderSeparateService.getByOutTradeNo(shopOrderLkl.getLkl_split_log_no(), orderId);
|
LklOrderSeparate existingSeparateRecord = lklOrderSeparateService.getByOutTradeNo(shopOrderLkl.getLkl_sub_log_no(), orderId);
|
||||||
if (lklOrderSeparateExist != null) {
|
if (existingSeparateRecord != null) {
|
||||||
String status = lklOrderSeparateExist.getStatus();
|
String status = existingSeparateRecord.getStatus();
|
||||||
if ("SUCCESS".equals(status)) {
|
if ("SUCCESS".equals(status)) {
|
||||||
log.info("订单[{}]子订单[{}]已完成分账,跳过处理", orderId, shopOrderLkl.getLkl_log_no());
|
log.info("[分账操作] 订单[{}]子订单[{}]已完成分账,跳过处理", orderId, shopOrderLkl.getLkl_log_no());
|
||||||
successCount++;
|
successCount++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ("PROCESSING".equals(status) || "ACCEPTED".equals(status)) {
|
if ("PROCESSING".equals(status) || "ACCEPTED".equals(status)) {
|
||||||
log.info("订单[{}]子订单[{}]分账处理中或已受理,跳过处理", orderId, shopOrderLkl.getLkl_log_no());
|
log.info("[分账操作] 订单[{}]子订单[{}]分账处理中或已受理,跳过处理", orderId, shopOrderLkl.getLkl_log_no());
|
||||||
successCount++;
|
successCount++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1653,21 +1756,21 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
|
|
||||||
// 7. 分账金额校验
|
// 7. 分账金额校验
|
||||||
if (splitAmount < 1) {
|
if (splitAmount < 1) {
|
||||||
String errorMsg = String.format("店铺[%s]订单[%s]分账金额[%d]低于1分钱,跳过分账",
|
String errorMsg = String.format("[分账操作] 店铺[%s]订单[%s]分账金额[%d]低于1分钱,跳过分账",
|
||||||
shopOrderLkl.getStore_id(), orderId, splitAmount);
|
shopOrderLkl.getStore_id(), orderId, splitAmount);
|
||||||
log.error(errorMsg);
|
log.error(errorMsg);
|
||||||
errorMessages.append(errorMsg).append("; ");
|
errorMessages.append(errorMsg).append("; ");
|
||||||
if (lklOrderSeparateExist != null) {
|
if (existingSeparateRecord != null) {
|
||||||
lklOrderSeparateService.updateRemark(lklOrderSeparateExist.getId(), errorMsg);
|
lklOrderSeparateService.updateRemark(existingSeparateRecord.getId(), errorMsg);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取分账平台接收方信息
|
// 获取分账平台接收方信息
|
||||||
LklLedgerMerReceiverBind platform = lklLedgerMerReceiverBindService.getPlatformByMerCupNo(merchantNo);
|
LklLedgerMerReceiverBind platformReceiver = lklLedgerMerReceiverBindService.getPlatformByMerCupNo(merchantNo);
|
||||||
|
|
||||||
if (platform == null) {
|
if (platformReceiver == null) {
|
||||||
String errorMsg = String.format("店铺[%s]未绑定平台方接收账户,跳过分账", shopOrderLkl.getStore_id());
|
String errorMsg = String.format("[分账操作] 店铺[%s]未绑定平台方接收账户,跳过分账", shopOrderLkl.getStore_id());
|
||||||
log.error(errorMsg);
|
log.error(errorMsg);
|
||||||
errorMessages.append(errorMsg).append("; ");
|
errorMessages.append(errorMsg).append("; ");
|
||||||
continue;
|
continue;
|
||||||
@ -1677,43 +1780,43 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
List<V3SacsSeparateRecvDatas> recvDatas = new ArrayList<>();
|
List<V3SacsSeparateRecvDatas> recvDatas = new ArrayList<>();
|
||||||
|
|
||||||
// 9. 获取商家分账比例并校验
|
// 9. 获取商家分账比例并校验
|
||||||
BigDecimal splitRatioValMch = shopOrderLkl.getSplit_ratio(); // 如:94 代表94%
|
BigDecimal merchantSplitRatioRaw = shopOrderLkl.getSplit_ratio(); // 如:94 代表94%
|
||||||
// 判断商家分账比例是否有效(必须在(0, 100]范围内)
|
// 判断商家分账比例是否有效(必须在(0, 100]范围内)
|
||||||
boolean canSplitForMch = splitRatioValMch != null
|
boolean canSplitForMerchant = merchantSplitRatioRaw != null
|
||||||
&& splitRatioValMch.compareTo(BigDecimal.ZERO) > 0
|
&& merchantSplitRatioRaw.compareTo(BigDecimal.ZERO) > 0
|
||||||
&& splitRatioValMch.compareTo(new BigDecimal(100)) <= 0;
|
&& merchantSplitRatioRaw.compareTo(new BigDecimal(100)) <= 0;
|
||||||
if (!canSplitForMch) {
|
if (!canSplitForMerchant) {
|
||||||
String errorMsg = String.format("店铺[%s]商家分账比例[%s]不在(0-100]范围内,无法分账",
|
String errorMsg = String.format("[分账操作] 店铺[%s]商家分账比例[%s]不在(0-100]范围内,无法分账",
|
||||||
shopOrderLkl.getStore_id(), splitRatioValMch);
|
shopOrderLkl.getStore_id(), merchantSplitRatioRaw);
|
||||||
log.error(errorMsg);
|
log.error(errorMsg);
|
||||||
errorMessages.append(errorMsg).append("; ");
|
errorMessages.append(errorMsg).append("; ");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// 商家分账
|
// 商家分账
|
||||||
BigDecimal mchRatio = splitRatioValMch.divide(new BigDecimal(100)); // 比如:94%
|
BigDecimal merchantSplitRatio = merchantSplitRatioRaw.divide(new BigDecimal(100)); // 比如:94%
|
||||||
|
|
||||||
BigDecimal distributorRatio = BigDecimal.ZERO;
|
BigDecimal distributorSplitRatio = BigDecimal.ZERO;
|
||||||
BigDecimal platformRatio = BigDecimal.ONE;
|
BigDecimal platformSplitRatio = BigDecimal.ONE;
|
||||||
// 分账代理商接收方信息
|
// 分账代理商接收方信息
|
||||||
List<LklLedgerMerReceiverBind> distributors = lklLedgerMerReceiverBindService.selectDistributorByMerCupNo(merchantNo);
|
List<LklLedgerMerReceiverBind> distributorReceivers = lklLedgerMerReceiverBindService.selectDistributorByMerCupNo(merchantNo);
|
||||||
if (distributors != null && distributors.size() > 0) {
|
if (distributorReceivers != null && !distributorReceivers.isEmpty()) {
|
||||||
distributorRatio = new BigDecimal("0.8");
|
distributorSplitRatio = new BigDecimal("0.8");
|
||||||
platformRatio = new BigDecimal("0.2");
|
platformSplitRatio = new BigDecimal("0.2");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 记录关键分账参数,便于问题排查
|
// 记录关键分账参数,便于问题排查
|
||||||
log.info("分账参数信息:订单={}, 商户={}, 总金额={}分, 商家比例={}, 平台比例={}, 代理商比例={}, 是否有代理商={}",
|
log.info("[分账操作] 参数信息:订单={}, 商户={}, 总金额={}分, 商家比例={}, 平台比例={}, 代理商比例={}, 是否有代理商={}",
|
||||||
orderId, merchantNo, splitAmount, mchRatio, platformRatio, distributorRatio,
|
orderId, merchantNo, splitAmount, merchantSplitRatio, platformSplitRatio, distributorSplitRatio,
|
||||||
(distributors != null && !distributors.isEmpty()));
|
(distributorReceivers != null && !distributorReceivers.isEmpty()));
|
||||||
|
|
||||||
// 返回值如下:{platformAmount=6, merchantAmount=94, agentAmount=0}
|
// 返回值如下:{platformAmount=6, merchantAmount=94, agentAmount=0}
|
||||||
Map<String, Integer> splitAmountMap = CommonUtil.calculateProfitSharing(splitAmount, mchRatio, platformRatio, distributorRatio);
|
Map<String, Integer> splitAmountMap = CommonUtil.calculateProfitSharing(splitAmount, merchantSplitRatio, platformSplitRatio, distributorSplitRatio);
|
||||||
Integer merchantAmount = splitAmountMap.get("merchantAmount");
|
Integer merchantAmount = splitAmountMap.get("merchantAmount");
|
||||||
Integer platformAmount = splitAmountMap.get("platformAmount");
|
Integer platformAmount = splitAmountMap.get("platformAmount");
|
||||||
Integer agentAmount = splitAmountMap.get("agentAmount");
|
Integer agentAmount = splitAmountMap.get("agentAmount");
|
||||||
|
|
||||||
// 记录分账结果,便于问题排查
|
// 记录分账结果,便于问题排查
|
||||||
log.info("分账金额计算结果:订单={}, 商户={}, 总金额={}分, 商家分得={}分, 平台分得={}分, 代理商分得={}分",
|
log.info("[分账操作] 金额计算结果:订单={}, 商户={}, 总金额={}分, 商家分得={}分, 平台分得={}分, 代理商分得={}分",
|
||||||
orderId, merchantNo, splitAmount, merchantAmount, platformAmount, agentAmount);
|
orderId, merchantNo, splitAmount, merchantAmount, platformAmount, agentAmount);
|
||||||
|
|
||||||
if (merchantAmount > 0) {
|
if (merchantAmount > 0) {
|
||||||
@ -1725,55 +1828,55 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
|
|
||||||
if (platformAmount > 0) {
|
if (platformAmount > 0) {
|
||||||
V3SacsSeparateRecvDatas receiver = new V3SacsSeparateRecvDatas();
|
V3SacsSeparateRecvDatas receiver = new V3SacsSeparateRecvDatas();
|
||||||
receiver.setRecvNo(platform.getReceiver_no());
|
receiver.setRecvNo(platformReceiver.getReceiver_no());
|
||||||
receiver.setSeparateValue(platformAmount.toString());
|
receiver.setSeparateValue(platformAmount.toString());
|
||||||
recvDatas.add(receiver);
|
recvDatas.add(receiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (agentAmount > 0 && distributors != null && !distributors.isEmpty()) {
|
if (agentAmount > 0 && distributorReceivers != null && !distributorReceivers.isEmpty()) {
|
||||||
V3SacsSeparateRecvDatas receiver = new V3SacsSeparateRecvDatas();
|
V3SacsSeparateRecvDatas receiver = new V3SacsSeparateRecvDatas();
|
||||||
receiver.setRecvNo(distributors.get(0).getReceiver_no());
|
receiver.setRecvNo(distributorReceivers.get(0).getReceiver_no());
|
||||||
receiver.setSeparateValue(agentAmount.toString());
|
receiver.setSeparateValue(agentAmount.toString());
|
||||||
recvDatas.add(receiver);
|
recvDatas.add(receiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 14. 构建分账请求对象
|
// 14. 构建分账请求对象
|
||||||
V3SacsSeparateRequest request = new V3SacsSeparateRequest();
|
V3SacsSeparateRequest separateRequest = new V3SacsSeparateRequest();
|
||||||
request.setMerchantNo(merchantNo);
|
separateRequest.setMerchantNo(merchantNo);
|
||||||
request.setLogNo(shopOrderLkl.getLkl_split_log_no()); // 合单和非合单的流水号保存在此字段
|
separateRequest.setLogNo(shopOrderLkl.getLkl_receive_log_no()); // 合单和非合单的流水号保存在此字段
|
||||||
request.setLogDate(shopOrderLkl.getLkl_log_date());
|
separateRequest.setLogDate(shopOrderLkl.getLkl_log_date());
|
||||||
request.setOutSeparateNo(shopOrderLkl.getOut_separate_no());
|
separateRequest.setOutSeparateNo(shopOrderLkl.getOut_separate_no());
|
||||||
request.setTotalAmt(splitAmount.toString());
|
separateRequest.setTotalAmt(splitAmount.toString());
|
||||||
request.setLklOrgNo(orgCode);
|
separateRequest.setLklOrgNo(orgCode);
|
||||||
request.setCalType("0"); // 0- 按照指定金额,1- 按照指定比例。默认 0
|
separateRequest.setCalType("0"); // 0- 按照指定金额,1- 按照指定比例。默认 0
|
||||||
request.setNotifyUrl(projectDomain + "/api/mobile/shop/lakala/sacs/separateNotify");
|
separateRequest.setNotifyUrl(projectDomain + "/api/mobile/shop/lakala/sacs/separateNotify");
|
||||||
|
|
||||||
// 15. 设置分账接收方列表
|
// 15. 设置分账接收方列表
|
||||||
request.setRecvDatas(recvDatas);
|
separateRequest.setRecvDatas(recvDatas);
|
||||||
log.info("分账请求参数: 订单={}, 商户={}, 金额={}分, 分账接收方数量={}",
|
log.info("[分账操作] 请求参数: 订单={}, 商户={}, 金额={}分, 分账接收方数量={}",
|
||||||
orderId, merchantNo, splitAmount, recvDatas.size());
|
orderId, merchantNo, splitAmount, recvDatas.size());
|
||||||
|
|
||||||
log.debug("分账请求详细参数: {}", JSONUtil.toJsonStr(request));
|
log.debug("[分账操作] 请求详细参数: {}", JSONUtil.toJsonStr(separateRequest));
|
||||||
|
|
||||||
// 16. 发送分账请求
|
// 16. 发送分账请求
|
||||||
log.info("向拉卡拉发送分账请求:订单={}, 商户={}, 分账流水号={}",
|
log.info("[分账操作] 向拉卡拉发送分账请求:订单={}, 商户={}, 分账流水号={}",
|
||||||
orderId, merchantNo, shopOrderLkl.getLkl_split_log_no());
|
orderId, merchantNo, shopOrderLkl.getLkl_sub_log_no());
|
||||||
String response = LKLSDK.httpPost(request);
|
String response = LKLSDK.httpPost(separateRequest);
|
||||||
if (StrUtil.isBlank(response)) {
|
if (StrUtil.isBlank(response)) {
|
||||||
String errorMsg = String.format("拉卡拉无响应,订单=%s,商户=%s,分账流水号=%s",
|
String errorMsg = String.format("[分账操作] 拉卡拉无响应,订单=%s,商户=%s,分账流水号=%s",
|
||||||
orderId, merchantNo, shopOrderLkl.getLkl_split_log_no());
|
orderId, merchantNo, shopOrderLkl.getLkl_sub_log_no());
|
||||||
log.error(errorMsg);
|
log.error(errorMsg);
|
||||||
errorMessages.append(errorMsg).append("; ");
|
errorMessages.append(errorMsg).append("; ");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
log.debug("分账响应结果: {}", response);
|
log.debug("[分账操作] 响应结果: {}", response);
|
||||||
|
|
||||||
// 17. 解析响应结果
|
// 17. 解析响应结果
|
||||||
JSONObject respJson = JSONUtil.parseObj(response);
|
JSONObject respJson = JSONUtil.parseObj(response);
|
||||||
if (respJson == null || !lklSacsSuccessCode.equals(respJson.getStr("code")) || respJson.getJSONObject("resp_data") == null) {
|
if (respJson == null || !lklSacsSuccessCode.equals(respJson.getStr("code")) || respJson.getJSONObject("resp_data") == null) {
|
||||||
String errorMsg = String.format("拉卡拉返回格式异常,订单=%s,商户=%s,分账流水号=%s,响应=%s,respJson=%s",
|
String errorMsg = String.format("[分账操作] 拉卡拉返回格式异常,订单=%s,商户=%s,分账流水号=%s,响应=%s,respJson=%s",
|
||||||
orderId, merchantNo, shopOrderLkl.getLkl_split_log_no(), response, respJson);
|
orderId, merchantNo, shopOrderLkl.getLkl_sub_log_no(), response, respJson);
|
||||||
log.error(errorMsg);
|
log.error(errorMsg);
|
||||||
errorMessages.append(errorMsg).append("; ");
|
errorMessages.append(errorMsg).append("; ");
|
||||||
continue;
|
continue;
|
||||||
@ -1781,37 +1884,37 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
|
|
||||||
// 18. 保存分账记录
|
// 18. 保存分账记录
|
||||||
JSONObject respData = respJson.getJSONObject("resp_data");
|
JSONObject respData = respJson.getJSONObject("resp_data");
|
||||||
LklOrderSeparate lklOrderSeparate = new LklOrderSeparate();
|
LklOrderSeparate separateRecord = new LklOrderSeparate();
|
||||||
lklOrderSeparate.setSeparate_no(respData.getStr("separate_no"));
|
separateRecord.setSeparate_no(respData.getStr("separate_no"));
|
||||||
lklOrderSeparate.setOut_separate_no(request.getOutSeparateNo());
|
separateRecord.setOut_separate_no(separateRequest.getOutSeparateNo());
|
||||||
lklOrderSeparate.setMerchant_no(merchantNo);
|
separateRecord.setMerchant_no(merchantNo);
|
||||||
lklOrderSeparate.setLog_no(request.getLogNo());
|
separateRecord.setLog_no(separateRequest.getLogNo()); // 发货完成交易流水号后14位 。分账商户用该流水号发起分账
|
||||||
lklOrderSeparate.setLog_date(request.getLogDate());
|
separateRecord.setLog_date(separateRequest.getLogDate());
|
||||||
lklOrderSeparate.setOrder_id(shopOrderLkl.getOrder_id());
|
separateRecord.setOrder_id(shopOrderLkl.getOrder_id());
|
||||||
lklOrderSeparate.setTotal_amt(request.getTotalAmt());
|
separateRecord.setTotal_amt(separateRequest.getTotalAmt());
|
||||||
lklOrderSeparate.setNotify_url(request.getNotifyUrl());
|
separateRecord.setNotify_url(separateRequest.getNotifyUrl());
|
||||||
lklOrderSeparate.setLkl_org_no(request.getLklOrgNo());
|
separateRecord.setLkl_org_no(separateRequest.getLklOrgNo());
|
||||||
lklOrderSeparate.setRecv_datas(JSONUtil.toJsonStr(request.getRecvDatas()));
|
separateRecord.setRecv_datas(JSONUtil.toJsonStr(separateRequest.getRecvDatas()));
|
||||||
lklOrderSeparate.setStatus(respData.getStr("status"));
|
separateRecord.setStatus(respData.getStr("status"));
|
||||||
lklOrderSeparate.setTotal_separate_value(platformAmount + agentAmount);
|
separateRecord.setTotal_separate_value(platformAmount + agentAmount);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (lklOrderSeparateService.addOrUpdateByReceiverNo(lklOrderSeparate)) {
|
if (lklOrderSeparateService.addOrUpdateByReceiverNo(separateRecord)) {
|
||||||
log.info("分账记录保存成功:订单={}, 分账单号={}, 状态={}, 分账流水号={}",
|
log.info("[分账操作] 记录保存成功:订单={}, 分账单号={}, 状态={}, 分账流水号={}",
|
||||||
orderId, lklOrderSeparate.getSeparate_no(), lklOrderSeparate.getStatus(), lklOrderSeparate.getLog_no());
|
orderId, separateRecord.getSeparate_no(), separateRecord.getStatus(), separateRecord.getLog_no());
|
||||||
successCount++;
|
successCount++;
|
||||||
} else {
|
} else {
|
||||||
String errorMsg = String.format("保存分账记录失败,订单=%s,分账单号=%s,分账流水号=%s",
|
String errorMsg = String.format("[分账操作] 保存分账记录失败,订单=%s,分账单号=%s,分账流水号=%s",
|
||||||
orderId, lklOrderSeparate.getSeparate_no(), lklOrderSeparate.getLog_no());
|
orderId, separateRecord.getSeparate_no(), separateRecord.getLog_no());
|
||||||
log.error(errorMsg);
|
log.error(errorMsg);
|
||||||
lklOrderSeparateService.updateRemark(lklOrderSeparate.getLog_no(), lklOrderSeparate.getSeparate_no(), errorMsg);
|
lklOrderSeparateService.updateRemark(separateRecord.getLog_no(), separateRecord.getSeparate_no(), errorMsg);
|
||||||
errorMessages.append(errorMsg).append("; ");
|
errorMessages.append(errorMsg).append("; ");
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
String errorMsg = String.format("保存分账记录异常,订单=%s,分账单号=%s,流水号=%s,错误=%s",
|
String errorMsg = String.format("[分账操作] 保存分账记录异常,订单=%s,分账单号=%s,流水号=%s,错误=%s",
|
||||||
orderId,
|
orderId,
|
||||||
lklOrderSeparate.getSeparate_no(),
|
separateRecord.getSeparate_no(),
|
||||||
lklOrderSeparate.getLog_no(),
|
separateRecord.getLog_no(),
|
||||||
e.getMessage());
|
e.getMessage());
|
||||||
log.error(errorMsg, e);
|
log.error(errorMsg, e);
|
||||||
errorMessages.append(errorMsg).append("; ");
|
errorMessages.append(errorMsg).append("; ");
|
||||||
@ -1819,27 +1922,284 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 19. 返回最终处理结果
|
// 19. 返回最终处理结果
|
||||||
log.info("订单[{}]分账处理完成:总订单数={},成功处理数={}", orderId, totalCount, successCount);
|
log.info("[分账操作] 处理完成:总订单数={},成功处理数={}", orderId, totalCount, successCount);
|
||||||
if (successCount == 0) {
|
if (successCount == 0) {
|
||||||
String result = "分账全部失败: " + errorMessages;
|
String result = "分账全部失败: " + errorMessages;
|
||||||
log.warn("订单[{}]分账结果:{}", orderId, result);
|
log.warn("[分账操作] 结果:订单[{}] {}", orderId, result);
|
||||||
return Pair.of(false, result);
|
return Pair.of(false, result);
|
||||||
} else if (successCount < totalCount) {
|
} else if (successCount < totalCount) {
|
||||||
String result = "部分分账成功,处理中: " + errorMessages;
|
String result = "部分分账成功,处理中: " + errorMessages;
|
||||||
log.info("订单[{}]分账结果:{}", orderId, result);
|
log.info("[分账操作] 结果:订单[{}] {}", orderId, result);
|
||||||
return Pair.of(true, result);
|
return Pair.of(true, result);
|
||||||
} else {
|
} else {
|
||||||
String result = "全部订单分账已提交处理";
|
String result = "全部订单分账已提交处理";
|
||||||
log.info("订单[{}]分账结果:{}", orderId, result);
|
log.info("[分账操作] 结果:订单[{}] {}", orderId, result);
|
||||||
return Pair.of(true, result);
|
return Pair.of(true, result);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
String errorMsg = String.format("分账系统异常,订单=%s,错误=%s", orderId, e.getMessage());
|
String errorMsg = String.format("[分账操作] 系统异常,订单=%s,错误=%s", orderId, e.getMessage());
|
||||||
log.error(errorMsg, e);
|
log.error(errorMsg, e);
|
||||||
return Pair.of(false, "系统异常,请稍后重试");
|
return Pair.of(false, "系统异常,请稍后重试");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据商户号、交易号和收货流水号执行订单分账操作
|
||||||
|
* <p>
|
||||||
|
* 该方法用于处理拉卡拉订单的分账逻辑。在用户确认收货后,系统会根据订单信息执行分账操作,
|
||||||
|
* 将订单金额按照预设比例分配给平台、商家和代理商(如果存在)。
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* 分账操作流程:
|
||||||
|
* 1. 参数校验和订单查询
|
||||||
|
* 2. 检查订单状态(是否已确认收货)
|
||||||
|
* 3. 检查是否已分账,避免重复处理
|
||||||
|
* 4. 计算分账金额
|
||||||
|
* 5. 构建分账请求并发送至拉卡拉
|
||||||
|
* 6. 保存分账结果
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param lklMerchantNo 拉卡拉商户号
|
||||||
|
* @param receiveTradeNo 收货交易号(对应拉卡拉的trade_no)
|
||||||
|
* @param receiveLogNo 收货流水号(对应拉卡拉的log_no)
|
||||||
|
* @return Pair<Boolean, String> 处理结果对,first为是否成功,second为结果描述信息
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public Pair<Boolean, String> innerDoOrderSeparateByMerchantAndLogNo(String lklMerchantNo, String receiveTradeNo, String receiveLogNo) {
|
||||||
|
// 1. 输入参数校验
|
||||||
|
if (StrUtil.isBlank(lklMerchantNo) || StrUtil.isBlank(receiveTradeNo) || StrUtil.isBlank(receiveLogNo)) {
|
||||||
|
log.warn("[分账操作] 参数校验失败:缺少必要参数, merchantNo={}, tradeNo={}, logNo={}",
|
||||||
|
lklMerchantNo, receiveTradeNo, receiveLogNo);
|
||||||
|
return Pair.of(false, "缺少必要参数");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
log.info("[分账操作] 开始处理分账请求, merchantNo={}, tradeNo={}, logNo={}",
|
||||||
|
lklMerchantNo, receiveTradeNo, receiveLogNo);
|
||||||
|
|
||||||
|
// TODO 检查可分账余额是否足够?
|
||||||
|
|
||||||
|
// 2. 查询订单信息
|
||||||
|
ShopOrderLkl shopOrderLkl = shopOrderLklService.getByMerchantNoAndTradeNoAndSubLogNo(lklMerchantNo, receiveTradeNo, receiveLogNo);
|
||||||
|
if (shopOrderLkl == null) {
|
||||||
|
log.warn("[分账操作] 失败:对账流水号[{}]不存在", receiveLogNo);
|
||||||
|
return Pair.of(false, "订单不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
String orderId = shopOrderLkl.getOrder_id();
|
||||||
|
log.info("[分账操作] 开始处理订单[{}]的分账", orderId);
|
||||||
|
|
||||||
|
log.debug("[分账操作] 处理子订单:storeId={}, receive_log_no={}", shopOrderLkl.getStore_id(), shopOrderLkl.getLkl_receive_log_no());
|
||||||
|
|
||||||
|
// 3. 检查是否已确认收货
|
||||||
|
if (!CommonConstant.Enable.equals(shopOrderLkl.getReceive_status()) || StrUtil.isBlank(shopOrderLkl.getLkl_receive_log_no())) {
|
||||||
|
log.warn("[分账操作] 订单[{}]对账流水号[{}]未被确认收货,跳过处理", orderId, shopOrderLkl.getLkl_receive_log_no());
|
||||||
|
return Pair.of(false, "订单未确认收货");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 检查分账状态,避免重复处理
|
||||||
|
LklOrderSeparate existingSeparateRecord = lklOrderSeparateService.getByOutTradeNo(shopOrderLkl.getLkl_sub_log_no(), shopOrderLkl.getOut_separate_no());
|
||||||
|
if (existingSeparateRecord != null) {
|
||||||
|
String status = existingSeparateRecord.getStatus();
|
||||||
|
if ("SUCCESS".equals(status)) {
|
||||||
|
log.info("[分账操作] 订单[{}]子订单[{}]已完成分账,跳过处理", orderId, shopOrderLkl.getLkl_log_no());
|
||||||
|
return Pair.of(true, "订单已处理");
|
||||||
|
}
|
||||||
|
if ("PROCESSING".equals(status) || "ACCEPTED".equals(status)) {
|
||||||
|
log.info("[分账操作] 订单[{}]子订单[{}]分账处理中或已受理,跳过处理", orderId, shopOrderLkl.getLkl_log_no());
|
||||||
|
return Pair.of(true, "订单已处理中或已受理");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 获取订单分账相关参数
|
||||||
|
String merchantNo = shopOrderLkl.getLkl_merchant_no();
|
||||||
|
|
||||||
|
// 分账金额 = 应付总金额-运费(支付时已计算好)
|
||||||
|
Integer splitAmount = shopOrderLkl.getSplit_amt();
|
||||||
|
splitAmount = CheckUtil.isEmpty(splitAmount) ? 0 : splitAmount;
|
||||||
|
|
||||||
|
// 6. 分账金额校验
|
||||||
|
if (splitAmount < 1) {
|
||||||
|
String errorMsg = String.format("[分账操作] 店铺[%s]订单[%s]分账金额[%d]低于1分钱,跳过分账",
|
||||||
|
shopOrderLkl.getStore_id(), orderId, splitAmount);
|
||||||
|
log.error(errorMsg);
|
||||||
|
if (existingSeparateRecord != null) {
|
||||||
|
lklOrderSeparateService.updateRemark(existingSeparateRecord.getId(), errorMsg);
|
||||||
|
}
|
||||||
|
return Pair.of(false, "订单分账金额低于1分钱");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7. 获取分账平台接收方信息
|
||||||
|
LklLedgerMerReceiverBind platformReceiver = lklLedgerMerReceiverBindService.getPlatformByMerCupNo(merchantNo);
|
||||||
|
if (platformReceiver == null) {
|
||||||
|
String errorMsg = String.format("[分账操作] 店铺[%s]未绑定平台方接收账户,跳过分账", shopOrderLkl.getStore_id());
|
||||||
|
log.error(errorMsg);
|
||||||
|
return Pair.of(false, "平台方未绑定账户");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 8. 构建分账接收方列表
|
||||||
|
List<V3SacsSeparateRecvDatas> recvDatas = new ArrayList<>();
|
||||||
|
|
||||||
|
// 9. 获取商家分账比例并校验
|
||||||
|
BigDecimal merchantSplitRatioRaw = shopOrderLkl.getSplit_ratio();
|
||||||
|
// 判断商家分账比例是否有效(必须在(0, 100]范围内)
|
||||||
|
boolean canSplitForMerchant = merchantSplitRatioRaw != null
|
||||||
|
&& merchantSplitRatioRaw.compareTo(BigDecimal.ZERO) > 0
|
||||||
|
&& merchantSplitRatioRaw.compareTo(new BigDecimal(100)) <= 0;
|
||||||
|
if (!canSplitForMerchant) {
|
||||||
|
String errorMsg = String.format("[分账操作] 店铺[%s]商家分账比例[%s]不在(0-100]范围内,无法分账",
|
||||||
|
shopOrderLkl.getStore_id(), merchantSplitRatioRaw);
|
||||||
|
log.error(errorMsg);
|
||||||
|
return Pair.of(false, "商家分账比例无效");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 10. 计算商家分账比例(转换为小数)
|
||||||
|
BigDecimal merchantSplitRatio = merchantSplitRatioRaw.divide(new BigDecimal(100));
|
||||||
|
|
||||||
|
// 11. 获取代理商分账信息
|
||||||
|
BigDecimal distributorSplitRatio = BigDecimal.ZERO;
|
||||||
|
BigDecimal platformSplitRatio = BigDecimal.ONE;
|
||||||
|
List<LklLedgerMerReceiverBind> distributorReceivers = lklLedgerMerReceiverBindService.selectDistributorByMerCupNo(merchantNo);
|
||||||
|
if (distributorReceivers != null && !distributorReceivers.isEmpty()) {
|
||||||
|
distributorSplitRatio = new BigDecimal("0.8");
|
||||||
|
platformSplitRatio = new BigDecimal("0.2");
|
||||||
|
log.debug("[分账操作] 检测到代理商存在,调整分账比例: 代理商比例={}, 平台比例={}", distributorSplitRatio, platformSplitRatio);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 12. 记录关键分账参数,便于问题排查
|
||||||
|
log.info("[分账操作] 参数信息:订单={}, 商户={}, 总金额={}分, 商家比例={}, 平台比例={}, 代理商比例={}, 是否有代理商={}",
|
||||||
|
orderId, merchantNo, splitAmount, merchantSplitRatio, platformSplitRatio, distributorSplitRatio,
|
||||||
|
(distributorReceivers != null && !distributorReceivers.isEmpty()));
|
||||||
|
|
||||||
|
// 13. 计算各参与方分账金额
|
||||||
|
Map<String, Integer> splitAmountMap = CommonUtil.calculateProfitSharing(splitAmount, merchantSplitRatio, platformSplitRatio, distributorSplitRatio);
|
||||||
|
Integer merchantAmount = splitAmountMap.get("merchantAmount");
|
||||||
|
Integer platformAmount = splitAmountMap.get("platformAmount");
|
||||||
|
Integer agentAmount = splitAmountMap.get("agentAmount");
|
||||||
|
|
||||||
|
// 14. 记录分账结果,便于问题排查
|
||||||
|
log.info("[分账操作] 金额计算结果:订单={}, 商户={}, 总金额={}分, 商家分得={}分, 平台分得={}分, 代理商分得={}分",
|
||||||
|
orderId, merchantNo, splitAmount, merchantAmount, platformAmount, agentAmount);
|
||||||
|
|
||||||
|
// 15. 构建分账接收方列表
|
||||||
|
if (merchantAmount > 0) {
|
||||||
|
V3SacsSeparateRecvDatas receiver = new V3SacsSeparateRecvDatas();
|
||||||
|
receiver.setRecvMerchantNo(merchantNo);
|
||||||
|
receiver.setSeparateValue(merchantAmount.toString());
|
||||||
|
recvDatas.add(receiver);
|
||||||
|
log.debug("[分账操作] 添加商家接收方: merchantNo={}, amount={}", merchantNo, merchantAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (platformAmount > 0) {
|
||||||
|
V3SacsSeparateRecvDatas receiver = new V3SacsSeparateRecvDatas();
|
||||||
|
receiver.setRecvNo(platformReceiver.getReceiver_no());
|
||||||
|
receiver.setSeparateValue(platformAmount.toString());
|
||||||
|
recvDatas.add(receiver);
|
||||||
|
log.debug("[分账操作] 添加平台接收方: receiverNo={}, amount={}", platformReceiver.getReceiver_no(), platformAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (agentAmount > 0 && distributorReceivers != null && !distributorReceivers.isEmpty()) {
|
||||||
|
V3SacsSeparateRecvDatas receiver = new V3SacsSeparateRecvDatas();
|
||||||
|
receiver.setRecvNo(distributorReceivers.get(0).getReceiver_no());
|
||||||
|
receiver.setSeparateValue(agentAmount.toString());
|
||||||
|
recvDatas.add(receiver);
|
||||||
|
log.debug("[分账操作] 添加代理商接收方: receiverNo={}, amount={}", distributorReceivers.get(0).getReceiver_no(), agentAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 16. 初始化拉卡拉SDK
|
||||||
|
log.debug("[分账操作] 初始化拉卡拉SDK");
|
||||||
|
initLKLSDK();
|
||||||
|
|
||||||
|
// 17. 构建分账请求对象
|
||||||
|
V3SacsSeparateRequest separateRequest = new V3SacsSeparateRequest();
|
||||||
|
separateRequest.setMerchantNo(merchantNo);
|
||||||
|
separateRequest.setLogNo(shopOrderLkl.getLkl_receive_log_no()); // 使用收货流水号作为分账流水号
|
||||||
|
separateRequest.setLogDate(shopOrderLkl.getLkl_log_date());
|
||||||
|
separateRequest.setOutSeparateNo(shopOrderLkl.getOut_separate_no());
|
||||||
|
separateRequest.setTotalAmt(splitAmount.toString());
|
||||||
|
separateRequest.setLklOrgNo(orgCode);
|
||||||
|
separateRequest.setCalType("0"); // 0- 按照指定金额,1- 按照指定比例。默认 0
|
||||||
|
separateRequest.setNotifyUrl(projectDomain + "/api/mobile/shop/lakala/sacs/separateNotify");
|
||||||
|
|
||||||
|
// 18. 设置分账接收方列表
|
||||||
|
separateRequest.setRecvDatas(recvDatas);
|
||||||
|
log.info("[分账操作] 请求参数: 订单={}, 商户={}, 金额={}分, 分账接收方数量={}",
|
||||||
|
orderId, merchantNo, splitAmount, recvDatas.size());
|
||||||
|
|
||||||
|
log.debug("[分账操作] 请求详细参数: {}", JSONUtil.toJsonStr(separateRequest));
|
||||||
|
|
||||||
|
// 19. 发送分账请求
|
||||||
|
log.info("[分账操作] 向拉卡拉发送分账请求:订单={}, 商户={}, 分账流水号={}",
|
||||||
|
orderId, merchantNo, shopOrderLkl.getLkl_receive_log_no());
|
||||||
|
String response = LKLSDK.httpPost(separateRequest);
|
||||||
|
if (StrUtil.isBlank(response)) {
|
||||||
|
String errorMsg = String.format("[分账操作] 拉卡拉无响应,订单=%s,商户=%s,分账流水号=%s",
|
||||||
|
orderId, merchantNo, shopOrderLkl.getLkl_receive_log_no());
|
||||||
|
log.error(errorMsg);
|
||||||
|
return Pair.of(false, "拉卡拉无响应");
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("[分账操作] 响应结果: {}", response);
|
||||||
|
|
||||||
|
// 20. 解析响应结果
|
||||||
|
JSONObject respJson = JSONUtil.parseObj(response);
|
||||||
|
if (respJson == null || !lklSacsSuccessCode.equals(respJson.getStr("code")) || respJson.getJSONObject("resp_data") == null) {
|
||||||
|
String errorMsg = String.format("[分账操作] 拉卡拉返回格式异常,订单=%s,商户=%s,分账流水号=%s,响应=%s,respJson=%s",
|
||||||
|
orderId, merchantNo, shopOrderLkl.getLkl_receive_log_no(), response, respJson);
|
||||||
|
log.error(errorMsg);
|
||||||
|
return Pair.of(false, "拉卡拉返回格式异常");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 21. 保存分账记录
|
||||||
|
JSONObject respData = respJson.getJSONObject("resp_data");
|
||||||
|
LklOrderSeparate separateRecord = new LklOrderSeparate();
|
||||||
|
separateRecord.setSeparate_no(respData.getStr("separate_no"));
|
||||||
|
separateRecord.setOut_separate_no(separateRequest.getOutSeparateNo());
|
||||||
|
separateRecord.setMerchant_no(merchantNo);
|
||||||
|
separateRecord.setLog_no(separateRequest.getLogNo());
|
||||||
|
separateRecord.setLog_date(separateRequest.getLogDate());
|
||||||
|
separateRecord.setOrder_id(shopOrderLkl.getOrder_id());
|
||||||
|
separateRecord.setTotal_amt(separateRequest.getTotalAmt());
|
||||||
|
separateRecord.setNotify_url(separateRequest.getNotifyUrl());
|
||||||
|
separateRecord.setLkl_org_no(separateRequest.getLklOrgNo());
|
||||||
|
separateRecord.setRecv_datas(JSONUtil.toJsonStr(separateRequest.getRecvDatas()));
|
||||||
|
separateRecord.setStatus(respData.getStr("status"));
|
||||||
|
separateRecord.setTotal_separate_value(platformAmount + agentAmount);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (lklOrderSeparateService.addOrUpdateByReceiverNo(separateRecord)) {
|
||||||
|
log.info("[分账操作] 记录保存成功:订单={}, 分账单号={}, 状态={}, 分账流水号={}",
|
||||||
|
orderId, separateRecord.getSeparate_no(), separateRecord.getStatus(), separateRecord.getLog_no());
|
||||||
|
} else {
|
||||||
|
String errorMsg = String.format("[分账操作] 保存分账记录失败,订单=%s,分账单号=%s,分账流水号=%s",
|
||||||
|
orderId, separateRecord.getSeparate_no(), separateRecord.getLog_no());
|
||||||
|
log.error(errorMsg);
|
||||||
|
lklOrderSeparateService.updateRemark(separateRecord.getLog_no(), separateRecord.getSeparate_no(), errorMsg);
|
||||||
|
return Pair.of(false, "保存分账记录失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
String result = "订单分账已提交处理";
|
||||||
|
log.info("[分账操作] 结果:订单[{}] {}", orderId, result);
|
||||||
|
return Pair.of(true, result);
|
||||||
|
} catch (Exception e) {
|
||||||
|
String errorMsg = String.format("[分账操作] 保存分账记录异常,订单=%s,分账单号=%s,流水号=%s,错误=%s",
|
||||||
|
orderId,
|
||||||
|
separateRecord.getSeparate_no(),
|
||||||
|
separateRecord.getLog_no(),
|
||||||
|
e.getMessage());
|
||||||
|
log.error(errorMsg, e);
|
||||||
|
return Pair.of(false, "保存分账记录异常");
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
String errorMsg = String.format("[分账操作] 系统异常,分账对账流水号=%s,错误=%s", receiveLogNo, e.getMessage());
|
||||||
|
log.error(errorMsg, e);
|
||||||
|
return Pair.of(false, "系统异常,请稍后重试");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 拉卡拉分账结果通知处理
|
* 拉卡拉分账结果通知处理
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
@ -63,4 +63,14 @@ public interface ShopOrderLklService extends IBaseService<ShopOrderLkl> {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
List<ShopOrderLkl> selectByOrderId(String orderId, String lklLogNo, String storeId);
|
List<ShopOrderLkl> selectByOrderId(String orderId, String lklLogNo, String storeId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据商户号、商户订单号、子商户订单号查询一条记录
|
||||||
|
*
|
||||||
|
* @param lklMerchantNo
|
||||||
|
* @param lklTradeNo
|
||||||
|
* @param lklSubLogNo
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
ShopOrderLkl getByMerchantNoAndTradeNoAndSubLogNo(String lklMerchantNo, String lklTradeNo, String lklSubLogNo);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4961,10 +4961,10 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 重要;拉卡拉给平台和代理商分账
|
// 重要;拉卡拉给平台和代理商分账
|
||||||
Pair<Boolean, String> retOrderSeparateRet = lakalaApiService.innerDoOrderSeparate(order_row.getOrder_id(), Convert.toStr(order_row.getStore_id()));
|
// Pair<Boolean, String> retOrderSeparateRet = lakalaApiService.innerDoOrderSeparate(order_row.getOrder_id(), Convert.toStr(order_row.getStore_id()));
|
||||||
if (!retOrderSeparateRet.getFirst()) {
|
// if (!retOrderSeparateRet.getFirst()) {
|
||||||
throw new ApiException(I18nUtil._("平台或代理商分账失败: " + retOrderSeparateRet.getSecond()));
|
// throw new ApiException(I18nUtil._("平台或代理商分账失败: " + retOrderSeparateRet.getSecond()));
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 统计总营业额
|
// 统计总营业额
|
||||||
ShopStoreAnalytics analytics_row = shopStoreAnalyticsService.get(store_id);
|
ShopStoreAnalytics analytics_row = shopStoreAnalyticsService.get(store_id);
|
||||||
|
|||||||
@ -183,6 +183,7 @@ public class ShopOrderLklServiceImpl extends BaseServiceImpl<ShopOrderLklMapper,
|
|||||||
record.setAccount_type(JsonUtil.getJsonValueSmart(reqDataJson, "accountType"));
|
record.setAccount_type(JsonUtil.getJsonValueSmart(reqDataJson, "accountType"));
|
||||||
record.setTrans_type(JsonUtil.getJsonValueSmart(reqDataJson, "transType"));
|
record.setTrans_type(JsonUtil.getJsonValueSmart(reqDataJson, "transType"));
|
||||||
record.setNotify_url(JsonUtil.getJsonValueSmart(reqDataJson, "notifyUrl"));
|
record.setNotify_url(JsonUtil.getJsonValueSmart(reqDataJson, "notifyUrl"));
|
||||||
|
record.setReceive_notify_url(JsonUtil.getJsonValueSmart(reqDataJson, "complete_notify_url"));
|
||||||
record.setLkl_merchant_no(JsonUtil.getJsonValueSmart(reqDataJson, "merchantNo"));
|
record.setLkl_merchant_no(JsonUtil.getJsonValueSmart(reqDataJson, "merchantNo"));
|
||||||
record.setLkl_term_no(JsonUtil.getJsonValueSmart(reqDataJson, "termNo"));
|
record.setLkl_term_no(JsonUtil.getJsonValueSmart(reqDataJson, "termNo"));
|
||||||
record.setLkl_req(JSONUtil.toJsonStr(reqDataJson));
|
record.setLkl_req(JSONUtil.toJsonStr(reqDataJson));
|
||||||
@ -235,10 +236,10 @@ public class ShopOrderLklServiceImpl extends BaseServiceImpl<ShopOrderLklMapper,
|
|||||||
record.setLkl_trade_no(lklPayNotifyDataJson.getStr("trade_no"));
|
record.setLkl_trade_no(lklPayNotifyDataJson.getStr("trade_no"));
|
||||||
record.setTrade_status(lklPayNotifyDataJson.getStr("trade_status"));
|
record.setTrade_status(lklPayNotifyDataJson.getStr("trade_status"));
|
||||||
|
|
||||||
// 新增的订单字段,lkl_split_log_no,out_separate_no,split_amt 三字段无值,就给主单的值
|
// 新增的订单字段,lkl_sub_log_no,out_separate_no,split_amt 三字段无值,就给主单的值
|
||||||
record.setLkl_split_log_no(JsonUtil.getJsonValueSmart(lklPayNotifyDataJson, "split_log_no"));
|
record.setLkl_sub_log_no(JsonUtil.getJsonValueSmart(lklPayNotifyDataJson, "split_log_no"));
|
||||||
if (CheckUtil.isEmpty(record.getLkl_split_log_no())) {
|
if (CheckUtil.isEmpty(record.getLkl_sub_log_no())) {
|
||||||
record.setLkl_split_log_no(logNo);
|
record.setLkl_sub_log_no(logNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
record.setOut_separate_no(JsonUtil.getJsonValueSmart(lklPayNotifyDataJson, "out_separate_no"));
|
record.setOut_separate_no(JsonUtil.getJsonValueSmart(lklPayNotifyDataJson, "out_separate_no"));
|
||||||
@ -292,4 +293,56 @@ public class ShopOrderLklServiceImpl extends BaseServiceImpl<ShopOrderLklMapper,
|
|||||||
return CollectionUtil.newArrayList();
|
return CollectionUtil.newArrayList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据商户号、商户订单号、子商户订单号查询一条记录
|
||||||
|
*
|
||||||
|
* @param lklMerchantNo 拉卡拉商户号
|
||||||
|
* @param lklTradeNo 拉卡拉交易号
|
||||||
|
* @param lklSubLogNo 拉卡拉子订单流水号
|
||||||
|
* @return ShopOrderLkl 拉卡拉订单记录
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ShopOrderLkl getByMerchantNoAndTradeNoAndSubLogNo(String lklMerchantNo, String lklTradeNo, String lklSubLogNo) {
|
||||||
|
// 检查参数是否全部为空
|
||||||
|
if (StringUtils.isAllBlank(lklMerchantNo, lklTradeNo, lklSubLogNo)) {
|
||||||
|
log.warn("[拉卡拉订单查询] 参数校验失败:所有查询条件均为空");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
log.debug("[拉卡拉订单查询] 开始查询, merchantNo={}, tradeNo={}, subLogNo={}",
|
||||||
|
lklMerchantNo, lklTradeNo, lklSubLogNo);
|
||||||
|
|
||||||
|
QueryWrapper<ShopOrderLkl> queryWrapper = new QueryWrapper<>();
|
||||||
|
queryWrapper.orderByAsc("id");
|
||||||
|
|
||||||
|
// 根据非空参数构建查询条件
|
||||||
|
if (StrUtil.isNotBlank(lklMerchantNo)) {
|
||||||
|
queryWrapper.eq("lkl_merchant_no", lklMerchantNo);
|
||||||
|
log.debug("[拉卡拉订单查询] 添加商户号查询条件: {}", lklMerchantNo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isNotBlank(lklTradeNo)) {
|
||||||
|
queryWrapper.eq("lkl_trade_no", lklTradeNo);
|
||||||
|
log.debug("[拉卡拉订单查询] 添加交易号查询条件: {}", lklTradeNo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isNotBlank(lklSubLogNo)) {
|
||||||
|
queryWrapper.eq("lkl_sub_log_no", lklSubLogNo);
|
||||||
|
log.debug("[拉卡拉订单查询] 添加子订单流水号查询条件: {}", lklSubLogNo);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShopOrderLkl result = findOne(queryWrapper);
|
||||||
|
|
||||||
|
log.debug("[拉卡拉订单查询] 查询完成, merchantNo={}, tradeNo={}, subLogNo={}, found={}",
|
||||||
|
lklMerchantNo, lklTradeNo, lklSubLogNo, result != null);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("[拉卡拉订单查询] 系统异常, merchantNo={}, tradeNo={}, subLogNo={}",
|
||||||
|
lklMerchantNo, lklTradeNo, lklSubLogNo, e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1011,9 +1011,9 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
|
|||||||
return new ThirdApiRes().fail(-1, "返回数据转换失败!");
|
return new ThirdApiRes().fail(-1, "返回数据转换失败!");
|
||||||
}
|
}
|
||||||
|
|
||||||
String orderId = shopStoreSfOrder.getShop_order_id();
|
|
||||||
|
|
||||||
ShopStoreSfOrder order = shopStoreSfOrderService.getBySfOrderId(orderId);
|
String sfOrderId = shopStoreSfOrder.getSf_order_id();
|
||||||
|
ShopStoreSfOrder order = shopStoreSfOrderService.getBySfOrderId(sfOrderId);
|
||||||
if (order == null) {
|
if (order == null) {
|
||||||
return new ThirdApiRes().fail(-1, "订单不存在!");
|
return new ThirdApiRes().fail(-1, "订单不存在!");
|
||||||
}
|
}
|
||||||
@ -1067,6 +1067,8 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
|
|||||||
// 订单确认收货
|
// 订单确认收货
|
||||||
shopOrderBaseService.receive(shopStoreSfOrder.getShop_order_id(), null);
|
shopOrderBaseService.receive(shopStoreSfOrder.getShop_order_id(), null);
|
||||||
|
|
||||||
|
String orderId = shopStoreSfOrder.getShop_order_id();
|
||||||
|
|
||||||
// 消息推送
|
// 消息推送
|
||||||
JSONObject payload = new JSONObject();
|
JSONObject payload = new JSONObject();
|
||||||
payload.put("category", CommonConstant.PUSH_MSG_CATE_MCH_ORDER_DETAIL);
|
payload.put("category", CommonConstant.PUSH_MSG_CATE_MCH_ORDER_DETAIL);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user