fix 入驻潜在空指针问题

This commit is contained in:
Jack 2025-09-25 00:04:34 +08:00
parent a25e511404
commit 5efd10b87a
3 changed files with 130 additions and 110 deletions

View File

@ -601,7 +601,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
// 参数校验
if (StringUtils.isBlank(merCupNo)) {
log.warn("商户分账业务申请失败:商户号不能为空");
return Pair.of(false, I18nUtil._("商户号不能为空!"));
return Pair.of(false, "商户号不能为空!");
}
// 获取商户入驻记录
@ -609,7 +609,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
ShopMchEntry shopMchEntry = shopMchEntryService.getShopMerchEntryByMerCupNo(merCupNo);
if (shopMchEntry == null) {
log.warn("商户分账业务申请失败:商家入驻信息不存在,商户号: {}", merCupNo);
return Pair.of(false, I18nUtil._("商家入驻信息不存在!"));
return Pair.of(false, "商家入驻信息不存在!");
}
// 商户是否已经已申请过分账业务
@ -627,18 +627,10 @@ public class LakalaApiServiceImpl implements LakalaApiService {
if (!Boolean.TRUE.equals(forceReApply)) {
log.info("商户{}已申请过分账业务,无需重复申请", merCupNo);
// 检查绑定关系
return Pair.of(true, I18nUtil._("商家已经申请过了!"));
return Pair.of(true, "商家分账业务已申请过!");
}
}
// 检查更新店铺初始化状态
// log.debug("检查并更新店铺初始化状态商户ID: {}", shopMchEntry.getId());
// shopMchEntryService.checkMchEntryStoreStatus(shopMchEntry.getId(), shopMchEntry);
try {
// 1. 配置初始化
log.debug("初始化拉卡拉SDK");
@ -646,24 +638,35 @@ public class LakalaApiServiceImpl implements LakalaApiService {
//2. 装配数据
log.debug("装配分账业务申请请求参数");
String splitEntrustFilePath = shopMchEntry.getLkl_ec_file_path(); //fileUploadResp.getStr("attFileId");
String splitEntrustFilePath = shopMchEntry.getLkl_ec_file_path();
if (StringUtils.isBlank(splitEntrustFilePath)) {
log.warn("商户分账业务申请失败:电子合同文件路径为空,商户号: {}", merCupNo);
return Pair.of(false, "电子合同文件路径为空");
}
// 给拉卡拉通知的回调地址
String notifyUrl = projectDomain + "/api/mobile/shop/lakala/ledger/applyLedgerMerNotify";
String orderNo = StringUtils.genLklOrderNo(8); // 14位年月日时24小时制分秒+8位的随机数
String merCupNoValue = shopMchEntry.getLkl_mer_cup_no(); // 从进件申请返回的商户号不要传入内部商户号传银联商户号才有效
String contactMobile = shopMchEntry.getLogin_mobile(); // 商户入驻注册的手机号
String fileName = "商家分账授权委托书.pdf";
if (StringUtils.isBlank(merCupNoValue)) {
log.warn("商户分账业务申请失败商户cup号为空商户号: {}", merCupNo);
return Pair.of(false, "商户cup号为空");
}
String contactMobile = shopMchEntry.getLogin_mobile(); // 商户入驻注册的手机号
if (StringUtils.isBlank(contactMobile)) {
log.warn("商户分账业务申请失败:联系人手机号为空,商户号: {}", merCupNo);
return Pair.of(false, "联系人手机号为空");
}
String fileName = "商家分账授权委托书.pdf";
JSONObject reqData = new JSONObject();
reqData.put("version", "1.0");
reqData.put("orderNo", orderNo);
reqData.put("orgCode", orgCode);
// reqData.put("merInnerNo", merCupNoValue);
reqData.put("merCupNo", merCupNoValue);
reqData.put("contactMobile", contactMobile);
@ -680,16 +683,13 @@ public class LakalaApiServiceImpl implements LakalaApiService {
reqData.put("splitLowestRatio", splitLowestRatio); // 商家最低分账比例不低于 20%
reqData.put("splitRange", "ALL");
reqData.put("settleType", "01"); //01主动提款 03交易自动结算 不填默认01
// paramsJSON.put("splitLaunchMode", "MANUAL");
// paramsJSON.put("splitRuleSource", "MER");
// paramsJSON.put("sepFundSource", "TR");
String postUrl = "";
String operationType = ""; // 操作类型用于日志记录和提示信息
// 确保serverUrl不为null
String effectiveServerUrl = serverUrl != null ? serverUrl : "";
if (!isLklProd) {
if (Boolean.FALSE.equals(isLklProd)) {
effectiveServerUrl = effectiveServerUrl + "/sit";
}
@ -712,14 +712,14 @@ public class LakalaApiServiceImpl implements LakalaApiService {
log.debug("商户分账业务{}申请请求参数: 请求地址:{}\n {}\n 响应数据:{}", operationType, postUrl, reqData, responseStr);
if (StrUtil.isBlank(responseStr)) {
log.error("申请拉卡拉分账业务{}无返回值,商户号: {}", operationType, merCupNo);
return Pair.of(false, I18nUtil._("申请拉卡拉分账业务无返回值!"));
return Pair.of(false, "申请拉卡拉分账业务无返回值!");
}
// 成功返回示例{'retCode':'000000','retMsg':'申请已受理请等待审核结果','respData':{'version':'1.0','orderNo':'KFPT20230223181025407788734','orgCode':'1','applyId':681201215598657536}}
JSONObject lakalaRespJSON = JSONUtil.parseObj(responseStr);
if (lakalaRespJSON == null) {
log.error("申请拉卡拉分账业务{}返回值异常,商户号: {}", operationType, merCupNo);
return Pair.of(false, I18nUtil._("申请拉卡拉分账业务返回值异常!"));
return Pair.of(false, "申请拉卡拉分账业务返回值异常!");
}
Object applyId = lakalaRespJSON.getByPath("respData.applyId");
@ -736,7 +736,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
reqData.set("applyId", applyId);
String retMsg = lakalaRespJSON.getStr("retMsg");
reqData.set("remark", retMsg);
reqData.set("auditStatusText", retMsg); // 直接使用retMsg避免null值
reqData.set("auditStatusText", retMsg);
reqData.set("mchId", shopMchEntry.getId());
// 新增数据
@ -745,24 +745,24 @@ public class LakalaApiServiceImpl implements LakalaApiService {
String snakeCaseJson = StringUtils.convertCamelToSnake(reqData.toString());
if (StringUtils.isBlank(snakeCaseJson)) {
log.error("JSON转换为下划线命名格式失败商户号: {}", merCupNo);
return Pair.of(false, I18nUtil._("数据格式转换失败!"));
return Pair.of(false, "数据格式转换失败!");
}
LklLedgerMember lklLedgerMemberNew = JSONUtil.toBean(snakeCaseJson, LklLedgerMember.class);
// 根据 mchId 商户号更新记录
if (lklLedgerMemberNew == null || !lklLedgerMemberService.addOrUpdateByMerCupNo(lklLedgerMemberNew)) {
log.error("新增或更改拉卡拉分账业务申请信息失败,订单号: {}", orderNo);
return Pair.of(false, I18nUtil._("新增或更改拉卡拉分账业务申请信息失败!"));
return Pair.of(false, "新增或更改拉卡拉分账业务申请信息失败!");
}
log.info("商户分账业务{}申请提交成功,等待审核,商户号: {}申请ID: {}", operationType, merCupNo, applyId);
return Pair.of(true, I18nUtil._("商户分账业务" + operationType + "申请已提交成功,请耐心等待拉卡拉审核!"));
return Pair.of(true, "商户分账业务" + operationType + "申请已提交成功,请耐心等待拉卡拉审核!");
} catch (SDKException e) {
log.error("申请拉卡拉分账业务出错,商户号: {}", merCupNo, e);
return Pair.of(false, I18nUtil._("申请拉卡拉分账业务出错!"));
return Pair.of(false, "申请拉卡拉分账业务出错!");
} catch (Exception e) {
log.error("申请拉卡拉分账业务出现未预期异常,商户号: {}", merCupNo, e);
return Pair.of(false, I18nUtil._("申请拉卡拉分账业务出现未预期异常!"));
return Pair.of(false, "申请拉卡拉分账业务出现未预期异常!");
}
}
@ -921,7 +921,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
Pair<Boolean, String> checkResult = LakalaUtil.chkLklApiNotifySign(request, lklNotifyCerPath, false);
if (!checkResult.getFirst()) {
log.warn("商户入网电子合同申请回调验签失败: {}", checkResult.getSecond());
return JSONUtil.createObj().set("code", "FAIL").set("retMsg", checkResult.getSecond());
return JSONUtil.createObj().set("code", "FAIL").set("message", checkResult.getSecond());
}
// 2. 初始化响应对象
@ -1167,7 +1167,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
public CommonResult applyLedgerMer(JSONObject paramsJSON) {
// 检查参数
if (ObjectUtil.isEmpty(paramsJSON) || StrUtil.isBlank(paramsJSON.getStr("merCupNo"))) {
return CommonResult.failed("请填写商户号");
return CommonResult.failed("缺少商户号 merCupNo");
}
String merCupNo = paramsJSON.getStr("merCupNo");
@ -1213,7 +1213,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
// 验签
Pair<Boolean, String> checkResult = LakalaUtil.chkLklApiNotifySign(request, lklNotifyCerPath, false);
if (!checkResult.getFirst()) {
return JSONUtil.createObj().set("code", "FAIL").set("retMsg", checkResult.getSecond());
return JSONUtil.createObj().set("code", "FAIL").set("message", checkResult.getSecond());
}
// 异步通知返回的数据
@ -1622,11 +1622,11 @@ public class LakalaApiServiceImpl implements LakalaApiService {
continue; // 单个失败不影响其他接收方处理
}
Object applyId = respJson.getByPath("respData.applyId");
String applyId = Convert.toStr(respJson.getByPath("respData.applyId"));
log.info("拉卡拉分账接收方绑定申请提交成功,订单号: {},商户号: {},接收方: {}申请ID: {}",
orderNo, merCupNo, receiverNo, applyId);
if (ObjectUtil.isEmpty(applyId)) {
if (StrUtil.isBlank(applyId)) {
log.error("拉卡拉分账接收方绑定申请提交失败,订单号: {},商户号: {},接收方: {} 申请ID为空", orderNo, merCupNo, receiverNo);
continue;
}
@ -1638,8 +1638,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
paramsJSON.set("receiver_no", receiverNo);
paramsJSON.set("ret_url", retUrl);
paramsJSON.set("remark", respJson.getStr("retMsg"));
// 处理可能为null的platform_id
paramsJSON.set("platform_id", receiver.getPlatform_id() != null ? receiver.getPlatform_id().toString() : "");
paramsJSON.set("platform_id", receiver.getPlatform_id());
paramsJSON.set("mch_id", shopMchEntry.getId());
// 转换JSON键名格式并保存
@ -1783,29 +1782,24 @@ public class LakalaApiServiceImpl implements LakalaApiService {
// 8. 成功后更新商户绑定状态为已绑定
shopMchEntryService.updateMulStatus(mchId, merCupNo, 0, 0, 0, 0, 0, 1, CommonConstant.MCH_APPR_STA_PASS);
try {
// 9. 判断是否可以创建店铺了
if (shopMchEntryService.canBuildingShopStore(mchId)) {
// 创建店铺并初始化
// 新建一个正式的已审核通过的店铺不要抛异常使用补偿机制可以独立初始化店铺
// 重要包含了更改 merchEntryInfo 的状态 使用法人小微个人的手机号注册商家账号作为店铺的管理员
Pair<Integer, String> retPair = shopStoreBaseService.covMerchEntryInfo2StoreInfo(mchId, false);
if (retPair.getFirst() <= 0) {
shopMchEntryService.updateMerchEntryApprovalByMchId(mchId, null, "创建并初始化店铺失败:" + retPair.getSecond());
log.error("进件成功,但初始化店铺失败: mchId={}, reason={}", mchId, retPair.getSecond());
} else {
shopMchEntryService.updateMulStatus(mchId, merCupNo, 0, 0, 1, 0, 0, 0, 0);
log.info("进件成功创建并初始化店铺成功mchId={}", mchId);
}
// 9. 判断是否可以创建店铺了
if (shopMchEntryService.canBuildingShopStore(mchId)) {
// 创建店铺并初始化
// 新建一个正式的已审核通过的店铺不要抛异常使用补偿机制可以独立初始化店铺
// 重要包含了更改 merchEntryInfo 的状态 使用法人小微个人的手机号注册商家账号作为店铺的管理员
Pair<Integer, String> retPair = shopStoreBaseService.covMerchEntryInfo2StoreInfo(mchId, false);
if (retPair.getFirst() <= 0) {
shopMchEntryService.updateMerchEntryApprovalByMchId(mchId, null, "创建并初始化店铺失败:" + retPair.getSecond());
log.error("进件成功,但初始化店铺失败: mchId={}, reason={}", mchId, retPair.getSecond());
} else {
shopMchEntryService.updateMulStatus(mchId, merCupNo, 0, 0, 1, 0, 0, 0, 0);
log.info("进件成功创建并初始化店铺成功mchId={}", mchId);
}
// 10. 检查商户绑定状态是否完成 更改总的审核状态
shopMchEntryService.checkMerchEntryFinished(mchId);
} catch (Exception e) {
log.error("处理商户店铺创建或状态检查时发生异常mchId: {}", mchId, e);
// 不中断主流程继续返回成功
}
// 10. 检查商户绑定状态是否完成 更改总的审核状态
shopMchEntryService.checkMerchEntryFinished(mchId);
// 11. 日志记录并返回成功响应
log.info("商家绑定分账接收方异步通知处理完成mchId:{} merCupNo{}", mchId, merCupNo);
return JSONUtil.createObj().set("code", "SUCCESS").set("message", "分账接收方绑定成功");

View File

@ -779,6 +779,12 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
return fixCount > 0;
}
/**
* 重要补偿机制检查修复商户入驻店铺信息(商家账号关联入驻店铺Id给商家账户创立公司员工账号和权限)
*
* @param mchId 商户入驻ID必填
* @return boolean 是否成功修复商户信息
*/
public Boolean checkAndFixMchStoreInfo(Long mchId) {
// 1. 参数校验
if (CheckUtil.isEmpty(mchId)) {
@ -787,70 +793,67 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
}
try {
// 2. 获取当前商户用户信息
UserDto currentUser = getCurrentUser();
if (currentUser == null || !currentUser.isMerchant()) {
log.warn("当前用户非商户账号");
return false;
}
// 4.3 获取用户基础信息
AccountUserBase userBase = accountService.getUserBase(currentUser.getId());
if (userBase == null) {
log.warn("商户用户基础信息不存在用户ID: {}", currentUser.getId());
return false;
}
// 3. 查询商户入驻记录
// 2. 查询商户入驻记录
ShopMchEntry shopMchEntry = get(mchId);
if (shopMchEntry == null) {
log.debug("未找到商户入驻记录 mchId {}", mchId);
return false;
}
// 4.2 检查入驻状态
// 3. 检查入驻状态
boolean isValidStatus = CommonConstant.Enable.equals(shopMchEntry.getHas_ec_signed())
&& CommonConstant.Enable.equals(shopMchEntry.getHas_apply_mer())
&& CommonConstant.Enable.equals(shopMchEntry.getHas_apply_split())
&& CommonConstant.Enable.equals(shopMchEntry.getHas_apply_receiver())
&& CommonConstant.Enable.equals(shopMchEntry.getHas_bind_receiver());
if (isValidStatus) {
log.debug("入驻记录状态都通过了审核进一步验证修复条件入驻ID: {}", mchId);
} else {
log.debug("入驻记录状态个别未通过审核接着检查验证修复条件入驻ID: {}", mchId);
if (!isValidStatus) {
log.debug("入驻记录状态未全部通过审核不能创建店铺入驻ID: {}", mchId);
return false;
}
// 4. 获取当前商户用户信息
UserDto currentUser = getCurrentUser();
if (currentUser == null || CheckUtil.isEmpty(currentUser.getId())) {
log.warn("当前用户未登录入驻ID: {}", mchId);
return false;
}
// 4.4 获取店铺员工信息
// 5. 获取用户基础信息
AccountUserBase userBase = accountService.getUserBase(currentUser.getId());
if (userBase == null) {
log.warn("商户用户基础信息不存在用户ID: {}", currentUser.getId());
return false;
}
// 6. 检查店铺关联关系
boolean hasStoreRelation = false;
if (StrUtil.isNotBlank(shopMchEntry.getStore_id()) && StrUtil.isNotBlank(userBase.getStore_ids())) {
hasStoreRelation = userBase.getStore_ids().contains(shopMchEntry.getStore_id());
}
// 7. 获取店铺员工信息
ShopStoreEmployee storeEmployee = null;
if (StrUtil.isNotBlank(shopMchEntry.getStore_id())) {
storeEmployee = shopStoreEmployeeService.getStoreEmployeeByUserId(
Convert.toInt(shopMchEntry.getStore_id()),
currentUser.getId()
);
Integer storeId = Convert.toInt(shopMchEntry.getStore_id());
if (CheckUtil.isNotEmpty(storeId)) {
storeEmployee = shopStoreEmployeeService.getStoreEmployeeByUserId(
storeId,
currentUser.getId()
);
}
}
// 4.5 检查店铺关联关系
boolean hasStoreRelation = StrUtil.isNotBlank(userBase.getStore_ids()) &&
userBase.getStore_ids().contains(shopMchEntry.getStore_id());
// 8. 检查权限组信息
boolean hasRoles = storeEmployee != null && StrUtil.isNotBlank(storeEmployee.getRights_group_id());
// 4.6 检查权限组信息
boolean hasRoles = storeEmployee != null &&
StrUtil.isNotBlank(storeEmployee.getRights_group_id());
// 4.7 当以下任一条件满足时需要进行修复
// - 无店铺员工信息
// - 无权限组信息
// - 无店铺关联
if (storeEmployee == null ||
!hasRoles ||
!hasStoreRelation) {
// 4.8 补偿创建初始化店铺部分赋值
// 10. 当满足创建店铺条件且存在信息缺失时需要进行修复
if (storeEmployee == null || !hasRoles || !hasStoreRelation) {
// 补偿创建初始化店铺部分赋值
Pair<Integer, String> result = shopStoreBaseService.covMerchEntryInfo2StoreInfo(mchId, false);
if (result != null && result.getFirst() > 0) {
log.warn("商户信息修复成功入驻ID: {}", mchId);
log.info("商户信息修复成功入驻ID: {}", mchId);
return true;
} else {
log.error("商户信息修复失败入驻ID: {}, 错误信息:{}", mchId, result != null ? result.getSecond() : "未知错误");
return false;
@ -1428,21 +1431,45 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
/**
* 更新商家入驻申请的店铺 ID
*
* @param id
* @param storeId
* @return
* @param mchId 商户ID
* @param storeId 店铺ID
* @return 更新成功返回 true否则返回 false
*/
@Override
public Boolean updateMerchEntryStoreStatus(Long id, Integer storeId) {
if (ObjectUtil.isEmpty(id) && ObjectUtil.isEmpty(storeId)) {
public Boolean updateMerchEntryStoreStatus(Long mchId, Integer storeId) {
// 1. 参数校验mchId 不能为空
if (CheckUtil.isEmpty(mchId) || CheckUtil.isEmpty(storeId)) {
log.warn("更新商户店铺状态失败商户ID不能为空");
return false;
}
return update(new UpdateWrapper<ShopMchEntry>()
.eq("id", id)
.set("store_id", storeId).set("store_status", CommonConstant.Enable));
try {
// 2. 构建更新条件
UpdateWrapper<ShopMchEntry> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("id", mchId)
.set("store_id", storeId)
.set("store_status", CommonConstant.Enable)
.set("updated_at", new Date()); // 更新时间戳
// 3. 执行更新操作并返回结果
boolean result = update(updateWrapper);
if (result) {
log.info("商户店铺状态更新成功mchId: {}, storeId: {}", mchId, storeId);
} else {
log.warn("商户店铺状态更新失败未找到匹配记录mchId: {}", mchId);
}
return result;
} catch (Exception e) {
// 4. 异常处理记录异常信息
log.error("更新商户店铺状态时发生异常mchId: {}, storeId: {}", mchId, storeId, e);
return false;
}
}
// /**
// * 更新拉卡拉入网电子合同和签署地址
// *

View File

@ -3185,9 +3185,8 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
ShopStoreBase shopStoreBase = findOneByStoreName(shopMchEntry.getStore_name());
if (shopStoreBase != null
&& StrUtil.isNotBlank(shopStoreBase.getLkl_merchant_no())
&& StrUtil.isNotBlank(shopStoreBase.getLkl_term_no())
&& shopMchEntry.getStore_id() != null // 添加null检查
&& !shopStoreBase.getStore_id().toString().equals(shopMchEntry.getStore_id())) {
&& StrUtil.isNotBlank(shopMchEntry.getLkl_mer_cup_no())
&& !shopStoreBase.getLkl_merchant_no().equals(shopMchEntry.getLkl_mer_cup_no())) {
logger.error("生成店铺:店铺名称已存在");
return Pair.of(0, "店铺名称已存在,请使用另一名称");
}
@ -3260,7 +3259,7 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
// 获取店铺ID
Integer storeId = shopStoreBase.getStore_id();
if (storeId == null) {
if (CheckUtil.isEmpty(storeId)) {
logger.error("生成店铺店铺ID获取失败");
return Pair.of(0, "店铺ID获取失败");
}
@ -3411,7 +3410,7 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
// 初始化店铺额外信息
initStoreExtraInfo(userId, storeId, allowThrown);
// 更新商家入驻状态
// 更新商家入驻状态和新建的店铺ID
if (shopMchEntry.getId() != null) {
shopMchEntryService.updateMerchEntryStoreStatus(shopMchEntry.getId(), storeId);
}