diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/controller/mobile/LakalaController.java b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/controller/mobile/LakalaController.java index 4c11a08c..ac07da3b 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/controller/mobile/LakalaController.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/controller/mobile/LakalaController.java @@ -116,7 +116,9 @@ public class LakalaController extends BaseControllerImpl { // return sfExpressApiService.createSfExpressShop(66, "能辉超市", "桂平市", "广西壮族自治区贵港市桂平市广佰汇超市(桂平店)", "谢能坤", "17777525395", "110.07165452271", "23.369069486251"); - return lakalaApiService.sacsQuery("8226330541100GU", "20250918770188017227140800").toString(); +// return lakalaApiService.sacsQuery("8226330541100GU", "20250918770188017227140800").toString(); + + return lakalaApiService.queryLedgerMer("8226330541100HA"); } @ApiOperation(value = "批量发送推送消息 - 测试案例", notes = "批量发送推送消息 - 测试案例") diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LakalaApiService.java b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LakalaApiService.java index 598e1be4..1b28f065 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LakalaApiService.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LakalaApiService.java @@ -10,6 +10,7 @@ package com.suisung.mall.shop.lakala.service; import cn.hutool.json.JSONObject; import com.suisung.mall.common.api.CommonResult; +import com.suisung.mall.common.modules.store.ShopMchEntry; import org.springframework.data.util.Pair; import javax.servlet.http.HttpServletRequest; @@ -268,6 +269,18 @@ public interface LakalaApiService { */ JSONObject sacsQuery(String merchantNo, String separateNo); + + /** + * 商户分账业务信息查询 + * 参考:https://o.lakala.com/#/home/document/detail?id=381 + * + * @param merCupNo 银联商户号 + * @return 分账业务信息,查询失败时返回null + *

+ * 返回:{"merInnerNo":"4002025092404043540","merCupNo":"8226330541100HA","splitLowestRatio":20.0,"orgId":"980688","orgName":"桂平发发","splitStatus":"VALID","splitStatusText":"启用","splitRange":"ALL","sepFundSource":"TR","bindRelations":[{"merInnerNo":"4002025092404043540","merCupNo":"8226330541100HA","receiverNo":"SR2024000129789","receiverName":"桂平发发网络有限公司"}],"platformId":null,"splitLaunchMode":"MANUAL","splitRuleSource":null,"eleContractNo":"QY20250924613672961"} + */ + JSONObject queryLedgerMer(String merCupNo); + /** * 订单分账撤销 * 参考:https://o.lakala.com/#/home/document/detail?id=390 @@ -288,4 +301,13 @@ public interface LakalaApiService { */ Integer fixedUnSuccessSeparateStatusJob(); + /** + * 检测修复补全商户的商户分账业务信息及分账接收方绑定关系(分账业务申请异步通知的补偿机制) + * + * @param shopMchEntry 商户入驻信息实例 + * @return + */ + Boolean checkAndFixLedgerMerApplyAndBindRelations(ShopMchEntry shopMchEntry); + + } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LklLedgerMemberService.java b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LklLedgerMemberService.java index d0a6aa46..6f407c5a 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LklLedgerMemberService.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LklLedgerMemberService.java @@ -50,8 +50,9 @@ public interface LklLedgerMemberService extends IBaseService { * @param auditStatus * @param auditStatusText * @param remark + * @param notifyResp * @return */ - Boolean updateAuditResult(String applyId, String merInnerNo, String merCupNo, String entrustFileName, String entrustFilePath, String auditStatus, String auditStatusText, String remark); + Boolean updateAuditResult(String applyId, String merInnerNo, String merCupNo, String entrustFileName, String entrustFilePath, String auditStatus, String auditStatusText, String remark, String notifyResp); } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LakalaApiServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LakalaApiServiceImpl.java index d0a82218..7aa8e6e9 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LakalaApiServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LakalaApiServiceImpl.java @@ -1266,7 +1266,7 @@ public class LakalaApiServiceImpl implements LakalaApiService { try { Boolean updateSuccess = lklLedgerMemberService.updateAuditResult( applyId, merInnerNo, merCupNo, entrustFileName, entrustFilePath, - auditStatus, auditStatusText, remark + auditStatus, auditStatusText, remark, checkResult.getSecond() ); if (!updateSuccess) { @@ -2070,6 +2070,80 @@ public class LakalaApiServiceImpl implements LakalaApiService { } } + /** + * 商户分账业务信息查询 + * 参考:https://o.lakala.com/#/home/document/detail?id=381 + * + * @param merCupNo 银联商户号 + * @return 分账业务信息,查询失败时返回null + *

+ * 返回:{"merInnerNo":"4002025092404043540","merCupNo":"8226330541100HA","splitLowestRatio":20.0,"orgId":"980688","orgName":"桂平发发","splitStatus":"VALID","splitStatusText":"启用","splitRange":"ALL","sepFundSource":"TR","bindRelations":[{"merInnerNo":"4002025092404043540","merCupNo":"8226330541100HA","receiverNo":"SR2024000129789","receiverName":"桂平发发网络有限公司"}],"platformId":null,"splitLaunchMode":"MANUAL","splitRuleSource":null,"eleContractNo":"QY20250924613672961"} + */ + @Override + public JSONObject queryLedgerMer(String merCupNo) { + // 1. 参数校验 + if (StrUtil.isBlank(merCupNo)) { + log.warn("[分账商户查询] 参数校验失败:银联商户号为空"); + return null; + } + + // 2. 初始化拉卡拉SDK配置 + initLKLSDK(); + + try { + // 3. 构造请求参数 + String orderNo = StringUtils.genLklOrderNo(8); + V2MmsOpenApiLedgerQueryLedgerMerRequest request = new V2MmsOpenApiLedgerQueryLedgerMerRequest(); + request.setVersion("1.0"); + request.setOrderNo(orderNo); + request.setOrgCode(orgCode); + request.setMerCupNo(merCupNo); + + log.debug("[分账商户查询] 开始查询商户分账信息,商户号: {}", merCupNo); + + // 4. 发送HTTP请求到拉卡拉服务器 + String responseStr = LKLSDK.httpPost(request); + + // 5. 检查响应结果 + if (StrUtil.isBlank(responseStr)) { + log.warn("[分账商户查询] 服务器无返回值,商户号: {}", merCupNo); + return null; + } + + // 6. 解析响应JSON + JSONObject lakalaRespJSON = JSONUtil.parseObj(responseStr); + if (lakalaRespJSON == null) { + log.warn("[分账商户查询] 响应数据解析失败,商户号: {},响应内容: {}", merCupNo, responseStr); + return null; + } + + // 7. 检查业务状态码 + String code = lakalaRespJSON.getStr("retCode"); + if (!"000000".equals(code)) { + log.warn("[分账商户查询] 业务处理失败,商户号: {},错误码: {},错误信息: {}", + merCupNo, code, lakalaRespJSON.getStr("retMsg")); + return null; + } + + // 8. 检查响应数据 + JSONObject respData = lakalaRespJSON.getJSONObject("respData"); + if (respData == null) { + log.warn("[分账商户查询] 响应数据为空,商户号: {},完整响应: {}", merCupNo, responseStr); + return null; + } + + log.info("[分账商户查询] 查询成功,商户号: {}", merCupNo); + return respData; + + } catch (SDKException e) { + log.error("[分账商户查询] SDK调用异常,商户号: {}", merCupNo, e); + return null; + } catch (Exception e) { + log.error("[分账商户查询] 查询过程中发生未知异常,商户号: {}", merCupNo, e); + return null; + } + } + /** * 执行拉卡拉订单分账操作 @@ -2950,4 +3024,229 @@ public class LakalaApiServiceImpl implements LakalaApiService { return totalSuccessCount; } + /** + * 检测修复补全商户的商户分账业务信息及分账接收方绑定关系(分账业务申请异步通知的补偿机制) + * + * @param shopMchEntry 商户入驻信息实例 + * @return 是否处理成功 + */ + @Override + public Boolean checkAndFixLedgerMerApplyAndBindRelations(ShopMchEntry shopMchEntry) { + // 1. 输入参数校验 + if (shopMchEntry == null) { + log.warn("[分账业务补偿机制] 商户入驻信息为空"); + return false; + } + + String merCupNo = shopMchEntry.getLkl_mer_cup_no(); + if (CheckUtil.isEmpty(merCupNo)) { + log.warn("[分账业务补偿机制] 商户未进件成功,停止执行,mchId: {}", shopMchEntry.getId()); + return false; + } + + // 2. 查询商户分账业务信息 + JSONObject ledgerMerInfo; + try { + ledgerMerInfo = queryLedgerMer(merCupNo); + } catch (Exception e) { + log.error("[分账业务补偿机制] 查询商户分账业务信息异常,merCupNo: {}", merCupNo, e); + return false; + } + + // 检查返回结果是否为空 + if (ObjectUtil.isEmpty(ledgerMerInfo)) { + log.warn("[分账业务补偿机制] 查询商户分账业务信息返回空,merCupNo: {}", merCupNo); + return false; + } + + String splitStatus = ledgerMerInfo.getStr("splitStatus"); + if (StrUtil.isBlank(splitStatus)) { + splitStatus = ""; + } + + if (!"VALID".equals(splitStatus)) { + log.warn("[分账业务补偿机制] 商户分账业务未通过或未申请,停止执行,merCupNo: {}, splitStatus: {}", merCupNo, splitStatus); + return false; + } + + log.info("[分账业务补偿机制] 开始处理商户分账信息修复,merCupNo: {}", merCupNo); + + // 3. 处理分账业务申请记录 + Long mchId = shopMchEntry.getId(); + String merInnerNo = ledgerMerInfo.getStr("merInnerNo"); + String orderNo = StringUtils.genLklOrderNo(8); + boolean memberUpdated = false; + + LklLedgerMember ledgerMember = lklLedgerMemberService.getByMerCupNo(merCupNo); + + try { + if (ObjectUtil.isEmpty(ledgerMember)) { + // 情况1: 分账业务申请记录不存在,创建新记录 + log.debug("[分账业务补偿机制] 分账业务申请记录不存在,创建新记录,merCupNo: {}", merCupNo); + + ledgerMember = new LklLedgerMember(); + ledgerMember.setOrg_code(ledgerMerInfo.getStr("orgId", orgCode)); + ledgerMember.setOrder_no(orderNo); + ledgerMember.setMer_cup_no(merCupNo); + ledgerMember.setMer_inner_no(StrUtil.blankToDefault(merInnerNo, "")); + ledgerMember.setContact_mobile(shopMchEntry.getLogin_mobile()); + ledgerMember.setSplit_lowest_ratio(ledgerMerInfo.getStr("splitLowestRatio", splitLowestRatio)); + ledgerMember.setSplit_entrust_file_name("商家分账授权委托书.pdf"); + ledgerMember.setSplit_entrust_file_path(StrUtil.blankToDefault(shopMchEntry.getLkl_ec_file_path(), "")); + ledgerMember.setSplit_range(ledgerMerInfo.getStr("splitRange", "ALL")); + ledgerMember.setEle_contract_no(ledgerMerInfo.getStr("eleContractNo", StrUtil.blankToDefault(shopMchEntry.getLkl_ec_no(), ""))); + ledgerMember.setSep_fund_source(ledgerMerInfo.getStr("sepFundSource", "TR")); + ledgerMember.setSplit_launch_mode(ledgerMerInfo.getStr("splitLaunchMode", "MANUAL")); + ledgerMember.setSettle_type("01"); + ledgerMember.setSplit_rule_source(""); + ledgerMember.setRet_url(projectDomain + "/api/mobile/shop/lakala/ledger/applyLedgerMerNotify"); + ledgerMember.setApply_id(orderNo); + ledgerMember.setAudit_status(CommonConstant.Enable); + ledgerMember.setAudit_status_text("审核通过"); + ledgerMember.setAudit_resp(ledgerMerInfo.toString()); + ledgerMember.setRemark("审核通过(补偿机制)"); + ledgerMember.setMch_id(mchId); + ledgerMember.setVersion("1.0"); + + memberUpdated = lklLedgerMemberService.addOrUpdateByMerCupNo(ledgerMember); + if (memberUpdated) { + log.info("[分账业务补偿机制] 成功创建分账业务申请记录,merCupNo: {}", merCupNo); + } else { + log.error("[分账业务补偿机制] 创建分账业务申请记录失败,merCupNo: {}", merCupNo); + return false; + } + + } else if (!CommonConstant.Enable.equals(ledgerMember.getAudit_status())) { + // 情况2: 分账业务申请记录存在但未审核通过,更新状态 + log.debug("[分账业务补偿机制] 分账业务申请记录存在但未审核通过,更新状态,merCupNo: {}", merCupNo); + + ledgerMember.setAudit_status(CommonConstant.Enable); + ledgerMember.setAudit_status_text("审核通过"); + ledgerMember.setAudit_resp(ledgerMerInfo.toString()); + ledgerMember.setRemark("审核通过(补偿机制)"); + ledgerMember.setMch_id(mchId); // 确保mch_id设置正确 + + memberUpdated = lklLedgerMemberService.addOrUpdateByMerCupNo(ledgerMember); + if (memberUpdated) { + log.info("[分账业务补偿机制] 成功更新分账业务申请记录状态,merCupNo: {}", merCupNo); + } else { + log.error("[分账业务补偿机制] 更新分账业务申请记录状态失败,merCupNo: {}", merCupNo); + return false; + } + } else { + // 情况3: 分账业务申请记录已审核通过 + log.debug("[分账业务补偿机制] 分账业务申请记录已审核通过,merCupNo: {}", merCupNo); + memberUpdated = true; + } + } catch (Exception e) { + log.error("[分账业务补偿机制] 处理分账业务申请记录异常,merCupNo: {}", merCupNo, e); + return false; + } + + // 4. 更新商户分账申请状态 + if (memberUpdated && !CommonConstant.Enable.equals(shopMchEntry.getHas_apply_split())) { + boolean updateResult = shopMchEntryService.updateMulStatus(mchId, merCupNo, 0, 0, 0, 1, 0, 0, CommonConstant.MCH_APPR_STA_LKL_PADDING); + if (updateResult) { + shopMchEntry.setHas_apply_split(CommonConstant.Enable); + log.info("[分账业务补偿机制] 成功更新商户分账申请状态,mchId: {}", mchId); + } else { + log.warn("[分账业务补偿机制] 更新商户分账申请状态失败,mchId: {}", mchId); + // 不返回false,因为这不影响主要流程 + } + } + + // 5. 处理分账接收方绑定关系 + int bindSuccessCount = 0; + JSONArray ledgerReceivers = ledgerMerInfo.getJSONArray("bindRelations"); + + if (CollUtil.isNotEmpty(ledgerReceivers)) { + log.debug("[分账业务补偿机制] 开始处理分账接收方绑定关系,绑定数量: {}", ledgerReceivers.size()); + + for (Object obj : ledgerReceivers) { + if (!(obj instanceof JSONObject)) { + continue; + } + + JSONObject ledgerReceiver = (JSONObject) obj; + if (ledgerReceiver == null) { + continue; + } + + String receiverMerCupNo = ledgerReceiver.getStr("merCupNo"); + String receiverNo = ledgerReceiver.getStr("receiverNo"); + + if (StrUtil.hasBlank(receiverMerCupNo, receiverNo)) { + log.warn("[分账业务补偿机制] 接收方信息不完整,跳过处理,receiverMerCupNo: {}, receiverNo: {}", receiverMerCupNo, receiverNo); + continue; + } + + LklLedgerMerReceiverBind ledgerMerReceiverBind = lklLedgerMerReceiverBindService.getByCondition(receiverMerCupNo, receiverNo); + boolean bindUpdated = false; + + try { + if (ObjectUtil.isEmpty(ledgerMerReceiverBind)) { + // 情况1: 绑定关系不存在,创建新记录 + log.debug("[分账业务补偿机制] 绑定关系不存在,创建新记录,merCupNo: {}, receiverNo: {}", receiverMerCupNo, receiverNo); + + ledgerMerReceiverBind = new LklLedgerMerReceiverBind(); + ledgerMerReceiverBind.setOrder_no(orderNo); + ledgerMerReceiverBind.setOrg_code(ledgerMerInfo.getStr("orgId", orgCode)); + ledgerMerReceiverBind.setMer_inner_no(ledgerReceiver.getStr("merInnerNo", "")); + ledgerMerReceiverBind.setMer_cup_no(receiverMerCupNo); + ledgerMerReceiverBind.setEntrust_file_name("小发同城合作协议书.pdf"); + ledgerMerReceiverBind.setEntrust_file_path(StrUtil.blankToDefault(shopMchEntry.getLkl_ec_file_path(), "")); + ledgerMerReceiverBind.setRet_url(projectDomain + "/api/mobile/shop/lakala/ledger/applyLedgerMerReceiverBindNotify"); + ledgerMerReceiverBind.setApply_id(orderNo); + ledgerMerReceiverBind.setPlatform_id(0L); + ledgerMerReceiverBind.setMch_id(mchId); + ledgerMerReceiverBind.setAudit_status("1"); + ledgerMerReceiverBind.setAudit_status_text("审核通过"); + ledgerMerReceiverBind.setRemark("审核通过(补偿机制)"); + ledgerMerReceiverBind.setVersion("1.0"); + + bindUpdated = lklLedgerMerReceiverBindService.addOrUpdateByMerCupNoReceiverNo(ledgerMerReceiverBind); + + } else if (!"1".equals(ledgerMerReceiverBind.getAudit_status())) { + // 情况2: 绑定关系存在但未审核通过,更新状态 + log.debug("[分账业务补偿机制] 绑定关系存在但未审核通过,更新状态,merCupNo: {}, receiverNo: {}", receiverMerCupNo, receiverNo); + + ledgerMerReceiverBind.setMch_id(mchId); + ledgerMerReceiverBind.setAudit_status("1"); + ledgerMerReceiverBind.setAudit_status_text("审核通过"); + ledgerMerReceiverBind.setRemark("审核通过(补偿机制)"); + + bindUpdated = lklLedgerMerReceiverBindService.addOrUpdateByMerCupNoReceiverNo(ledgerMerReceiverBind); + } else { + // 情况3: 绑定关系已审核通过 + log.debug("[分账业务补偿机制] 绑定关系已审核通过,merCupNo: {}, receiverNo: {}", receiverMerCupNo, receiverNo); + bindUpdated = true; + } + + if (bindUpdated) { + bindSuccessCount++; + } + } catch (Exception e) { + log.error("[分账业务补偿机制] 处理分账接收方绑定关系异常,merCupNo: {}, receiverNo: {}", receiverMerCupNo, receiverNo, e); + // 继续处理其他绑定关系 + } + } + } + + // 6. 更新商户分账接收方绑定状态 + if (bindSuccessCount > 0 && !CommonConstant.Enable.equals(shopMchEntry.getHas_bind_receiver())) { + boolean updateResult = shopMchEntryService.updateMulStatus(mchId, merCupNo, 0, 0, 0, 0, 0, 1, CommonConstant.MCH_APPR_STA_LKL_PADDING); + if (updateResult) { + shopMchEntry.setHas_bind_receiver(CommonConstant.Enable); + log.info("[分账业务补偿机制] 成功更新商户分账接收方绑定状态,mchId: {}, 成功处理数量: {}", mchId, bindSuccessCount); + } else { + log.warn("[分账业务补偿机制] 更新商户分账接收方绑定状态失败,mchId: {}", mchId); + // 不返回false,因为这不影响主要流程 + } + } + + log.info("[分账业务补偿机制] 处理完成,merCupNo: {}, memberUpdated: {}, bindSuccessCount: {}", merCupNo, memberUpdated, bindSuccessCount); + return true; + } + + } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklLedgerMemberServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklLedgerMemberServiceImpl.java index 66657a65..be33de34 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklLedgerMemberServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklLedgerMemberServiceImpl.java @@ -101,10 +101,11 @@ public class LklLedgerMemberServiceImpl extends BaseServiceImpl result = shopStoreBaseService.covMerchEntryInfo2StoreInfo(mchId, false); if (result != null && result.getFirst() > 0) { log.info("商户信息修复成功,入驻ID: {}", mchId); + // 修复成功后检查商户绑定状态是否完成,更改总的审核状态 + checkMerchEntryFinished(mchId); return true; } else { log.error("商户信息修复失败,入驻ID: {}, 错误信息:{}", mchId, result != null ? result.getSecond() : "未知错误"); @@ -860,6 +869,10 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl