商家用户登录之后,补偿创建店铺遗漏的信息。

This commit is contained in:
Jack 2025-09-01 17:34:24 +08:00
parent c8b6ac2f4b
commit 497df13540
8 changed files with 332 additions and 23 deletions

View File

@ -68,6 +68,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.util.Pair;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -144,6 +145,7 @@ public class AccountUserBaseServiceImpl extends BaseServiceImpl<AccountUserBaseM
@Resource
private AccountUserBindGeTuiService accountUserBindGeTuiService;
@Override
public CommonResult login(Map<String, String> params) {
Boolean hasKey = false;
@ -2975,7 +2977,13 @@ public class AccountUserBaseServiceImpl extends BaseServiceImpl<AccountUserBaseM
// 找出手机对应的绑定用户
// 是否为手机号注册密码6位随机数
return doMobileBindLogin(verifyMobile, CommonConstant.USER_TYPE_MCH, cid, osType);
CommonResult result = doMobileBindLogin(verifyMobile, CommonConstant.USER_TYPE_MCH, cid, osType);
if (result.getStatus() == 200) {
// 登录成功之后异步检查并修复商户店铺信息
checkAndFixMchStoreInfo(PhoneNumberUtils.cleanPhoneNumber(user_mobile));
}
return result;
}
/**
@ -3789,5 +3797,28 @@ public class AccountUserBaseServiceImpl extends BaseServiceImpl<AccountUserBaseM
return new ThirdApiRes().fail(250, "保存异常");
}
/**
* 检查并修复商户店铺信息
* 重要补偿机制检查修复商户入驻店铺信息(商家账号关联入驻店铺Id给商家账户创立公司员工账号和权限)
*
* @param loginMobile 登录手机号
* @return 处理结果
*/
@Async
protected Boolean checkAndFixMchStoreInfo(String loginMobile) {
try {
// 调用shop服务检查并修复商户店铺信息
Boolean result = shopService.checkAndFixMchStoreInfo(loginMobile);
// 记录处理结果日志
logger.info("商户店铺信息检查与修复完成,手机号: {},结果: {}", loginMobile, result);
return result;
} catch (Exception e) {
// 捕获所有异常防止影响主流程
logger.error("检查并修复商户店铺信息时发生异常,手机号: {}", loginMobile, e);
// 发生异常时返回false不影响主流程
return false;
}
}
}

View File

@ -281,6 +281,16 @@ public interface ShopService {
@PostMapping(value = "/mobile/shop/merch/approval/status")
Long shopMerchEntryApprovalStatus(@RequestBody Map<String, Object> params);
/**
* 重要补偿机制检查修复商户入驻店铺信息(商家账号关联入驻店铺Id给商家账户创立公司员工账号和权限)
*
* @param loginMobile
* @return
*/
@ApiOperation(value = "检查修复商户入驻店铺信息", notes = "重要(补偿机制),检查修复商户入驻店铺信息(商家账号关联入驻店铺Id给商家账户创立公司员工账号和权限)")
@PostMapping(value = "/admin/shop/merch/checkAndFixMchStoreInfo")
Boolean checkAndFixMchStoreInfo(@RequestParam(name = "loginMobile") String loginMobile);
/**
* 当拉卡拉支付时新增一个拉卡拉订单信息
@ -309,5 +319,6 @@ public interface ShopService {
@PostMapping(value = "/admin/shop/shop-order-data/getOrderShippingFee")
BigDecimal getOrderShippingFee(@RequestParam(name = "order_id") String order_id);
}

View File

@ -13,6 +13,7 @@ import java.util.Locale;
import java.util.regex.Pattern;
public class PhoneNumberUtils {
/**
* 直辖市
*/
@ -102,17 +103,78 @@ public class PhoneNumberUtils {
}
/**
* 去掉手机的国家码方法不严谨
* 去掉手机的国家码保留纯手机号优先处理+86开头的中国手机号
* 支持1-3位国际区号+86开头的格式做特殊优化
* - +8613128997057 13128997057优先提取2位国家码86
* - +1234567890123 2345678901233位国家码123
* - +354123456789 1234567893位国家码354
* - 13128997057 13128997057无国家码
* - +86 +86纯国家码保留
*
* @param phoneNumber
* @return
* @param phoneNumber 完整手机号可能包含国际区号和特殊字符
* @return 清理后的纯手机号或完整国家码
*/
public static String cleanPhoneNumber(String phoneNumber) {
if (phoneNumber.length() <= 3) {
if (StrUtil.isBlank(phoneNumber)) {
return phoneNumber;
}
return StrUtil.startWith(phoneNumber, "+") ? phoneNumber.substring(2) : phoneNumber;
// 预处理只保留+和数字移除其他所有字符-空格等
String processed = phoneNumber.replaceAll("[^+0-9]", "");
if (StrUtil.isBlank(processed)) {
return processed;
}
// 不包含国家码前缀+直接返回纯数字
if (!processed.startsWith("+")) {
return processed;
}
// ########## 优先处理+86开头的中国手机号核心优化##########
// 若以+86开头且后面至少有11位数字中国手机号标准长度则提取2位国家码
if (processed.startsWith("+86") && processed.length() >= 1 + 2 + 11) { // 1(+)+2(86)+11(手机号)
return processed.substring(3); // 从索引3开始跳过+86
}
// ########## 通用国家码处理1-3位##########
int len = processed.length();
int bestCountryCodeLength = 0;
int maxValidRemainingLength = -1;
// 检查3位国家码若剩余长度在7-15位国际通用手机号长度范围则记录
if (len >= 1 + 3) { // 至少有+和3位国家码
int remainingLength = len - (1 + 3); // 剩余长度=总长度 - (+1位) - (国家码3位)
if (remainingLength >= 7 && remainingLength <= 15) {
bestCountryCodeLength = 3;
maxValidRemainingLength = remainingLength;
}
}
// 检查2位国家码若剩余长度更合理更长则覆盖3位的判断
if (len >= 1 + 2) {
int remainingLength = len - (1 + 2);
if (remainingLength >= 7 && remainingLength <= 15 && remainingLength > maxValidRemainingLength) {
bestCountryCodeLength = 2;
maxValidRemainingLength = remainingLength;
}
}
// 检查1位国家码同样以剩余长度更合理为优先
if (len >= 1 + 1) {
int remainingLength = len - (1 + 1);
if (remainingLength >= 7 && remainingLength <= 15 && remainingLength > maxValidRemainingLength) {
bestCountryCodeLength = 1;
maxValidRemainingLength = remainingLength;
}
}
// 根据最佳国家码长度提取结果
if (bestCountryCodeLength > 0) {
return processed.substring(1 + bestCountryCodeLength); // 跳过+和国家码
} else {
// 无有效手机号部分纯国家码返回原处理结果保留+
return processed;
}
}
/**
@ -282,7 +344,14 @@ public class PhoneNumberUtils {
public static void main(String[] args) {
System.out.println(isValidNumber("13111111111"));
System.out.println(cleanPhoneNumber("+8613128997057")); // 期望输出: 13128997057
System.out.println(cleanPhoneNumber("13128997057")); // 期望输出: 13128997057
System.out.println(cleanPhoneNumber("+86")); // 期望输出: +86
System.out.println(cleanPhoneNumber("+1234567890123")); // 期望输出: 234567890123
System.out.println(cleanPhoneNumber("+3541234567")); // 期望输出: 1234567
System.out.println(cleanPhoneNumber("+85298765432"));
}
}

View File

@ -17,10 +17,7 @@ import com.suisung.mall.shop.store.service.ShopMchEntryService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@ -85,5 +82,17 @@ public class ShopMchEntryAdminController extends BaseControllerImpl {
}
}
/**
* 重要补偿机制检查修复商户入驻店铺信息(商家账号关联入驻店铺Id给商家账户创立公司员工账号和权限)
*
* @param loginMobile
* @return
*/
@ApiOperation(value = "检查修复商户入驻店铺信息", notes = "重要(补偿机制),检查修复商户入驻店铺信息(商家账号关联入驻店铺Id给商家账户创立公司员工账号和权限)")
@PostMapping(value = "/checkAndFixMchStoreInfo")
public Boolean checkAndFixMchStoreInfo(@RequestParam(name = "loginMobile") String loginMobile) {
return shopMchEntryService.checkAndFixMchStoreInfo(loginMobile);
}
}

View File

@ -145,6 +145,14 @@ public interface ShopMchEntryService {
*/
ShopMchEntry getShopMerchEntryByMobileOrMerCupNo(String loginMobile, String merchantCupNo);
/**
* 根据手机号获取商户入驻信息(一个手机可以申请多个商家入驻)
*
* @param mobile 手机号
* @return 商户入驻信息如果不存在则返回 null
*/
List<ShopMchEntry> selectByMobile(String mobile);
/**
* 根据商家注册的手机号更新合同签署状态和合同下载地址
*
@ -312,4 +320,12 @@ public interface ShopMchEntryService {
* @return
*/
CommonResult updateMerchEntry(ShopMchEntry record);
/**
* 重要补偿机制检查修复商户入驻店铺信息(商家账号关联入驻店铺Id给商家账户创立公司员工账号和权限)
*
* @param loginMobile 商户登录手机号必填
* @return boolean 是否成功修复至少一个商户信息
*/
Boolean checkAndFixMchStoreInfo(String loginMobile);
}

View File

@ -48,4 +48,14 @@ public interface ShopStoreEmployeeService extends IBaseService<ShopStoreEmployee
*/
List<String> selectEmployeeGeTuiCidByStoreId(Integer storeId, String orderId, Boolean isAdmin);
/**
* 根据店铺Id和员工Id获取员工信息
*
* @param storeId
* @param userId
* @return
*/
ShopStoreEmployee getStoreEmployeeByUserId(Integer storeId, Integer userId);
}

View File

@ -9,7 +9,9 @@
package com.suisung.mall.shop.store.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
@ -22,8 +24,11 @@ import com.suisung.mall.common.api.CommonResult;
import com.suisung.mall.common.api.ResultCode;
import com.suisung.mall.common.constant.CommonConstant;
import com.suisung.mall.common.domain.UserDto;
import com.suisung.mall.common.feignService.AccountService;
import com.suisung.mall.common.modules.account.AccountUserBase;
import com.suisung.mall.common.modules.lakala.LklLedgerEc;
import com.suisung.mall.common.modules.store.ShopMchEntry;
import com.suisung.mall.common.modules.store.ShopStoreEmployee;
import com.suisung.mall.common.utils.BankUtil;
import com.suisung.mall.common.utils.CheckUtil;
import com.suisung.mall.common.utils.DateTimeUtils;
@ -32,9 +37,6 @@ import com.suisung.mall.common.utils.phone.PhoneNumberUtils;
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
import com.suisung.mall.shop.base.service.AccountBaseConfigService;
import com.suisung.mall.shop.base.service.ShopBaseStoreCategoryService;
import com.suisung.mall.shop.components.TaskService;
import com.suisung.mall.shop.esign.service.EsignContractFillingFileService;
import com.suisung.mall.shop.esign.service.EsignContractService;
import com.suisung.mall.shop.esign.service.EsignPlatformInfoService;
import com.suisung.mall.shop.lakala.service.LklLedgerEcService;
import com.suisung.mall.shop.lakala.service.impl.LakalaApiServiceImpl;
@ -42,8 +44,8 @@ import com.suisung.mall.shop.message.service.ShopMessageTemplateService;
import com.suisung.mall.shop.store.mapper.ShopMchEntryMapper;
import com.suisung.mall.shop.store.service.ShopMchEntryService;
import com.suisung.mall.shop.store.service.ShopStoreBaseService;
import com.suisung.mall.shop.store.service.ShopStoreEmployeeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.util.Pair;
import org.springframework.scheduling.annotation.Async;
@ -71,12 +73,12 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
@Resource
private EsignPlatformInfoService esignPlatformInfoService;
@Resource
private EsignContractFillingFileService esignContractFillingFileService;
@Lazy
@Resource
private EsignContractService esignContractService;
// @Resource
// private EsignContractFillingFileService esignContractFillingFileService;
//
// @Lazy
// @Resource
// private EsignContractService esignContractService;
@Lazy
@Resource
@ -89,13 +91,19 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
@Resource
private LklLedgerEcService lklLedgerEcService;
@Autowired
private TaskService taskService;
// @Autowired
// private TaskService taskService;
@Lazy
@Resource
private LakalaApiServiceImpl lakalaApiService;
@Resource
private ShopStoreEmployeeService shopStoreEmployeeService;
@Resource
private AccountService accountService;
/**
* 获取店铺的经营类目列表
@ -708,6 +716,103 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
return CommonResult.success();
}
/**
* 重要补偿机制检查修复商户入驻店铺信息(商家账号关联入驻店铺Id给商家账户创立公司员工账号和权限)
*
* @param loginMobile 商户登录手机号必填
* @return boolean 是否成功修复至少一个商户信息
*/
@Override
public Boolean checkAndFixMchStoreInfo(String loginMobile) {
// 1. 参数校验
if (StrUtil.isBlank(loginMobile)) {
log.warn("商户登录手机号为空");
return false;
}
try {
// 2. 获取当前商户用户信息
UserDto currentUser = getCurrentUser();
if (currentUser == null || !currentUser.isMerchant()) {
log.warn("当前用户非商户账号");
return false;
}
// 3. 查询商户入驻记录
List<ShopMchEntry> entryRecords = selectByMobile(loginMobile);
if (CollUtil.isEmpty(entryRecords)) {
log.debug("未找到商户入驻记录,手机号: {}", loginMobile);
return false;
}
int fixCount = 0;
// 4. 遍历处理每个入驻记录
for (ShopMchEntry entry : entryRecords) {
// 4.1 验证入驻记录有效性
if (entry == null || entry.getId() == null) {
log.warn("无效的入驻记录");
continue;
}
// 4.2 检查入驻状态
boolean isValidStatus =
CommonConstant.MCH_APPR_STA_PASS.equals(entry.getApproval_status()) ||
CommonConstant.Enable.equals(entry.getHas_ec_signed()) ||
CommonConstant.Enable.equals(entry.getHas_apply_mer());
if (!isValidStatus) {
log.debug("入驻记录状态不满足修复条件入驻ID: {}", entry.getId());
continue;
}
// 4.3 获取用户基础信息
AccountUserBase userBase = accountService.getUserBase(currentUser.getId());
if (userBase == null) {
log.warn("商户用户基础信息不存在用户ID: {}", currentUser.getId());
continue;
}
// 4.4 获取店铺员工信息
ShopStoreEmployee storeEmployee = shopStoreEmployeeService.getStoreEmployeeByUserId(
Convert.toInt(entry.getStore_id()),
currentUser.getId()
);
// 4.5 检查店铺关联关系
boolean hasStoreRelation = userBase.getStore_ids() != null &&
userBase.getStore_ids().contains(entry.getStore_id());
// 4.6 检查权限组信息
boolean hasPermission = storeEmployee != null &&
StrUtil.isNotBlank(storeEmployee.getRights_group_id());
// 4.7 只有当不满足以下条件时才需要修复
// - 无店铺员工信息
// - 无权限组信息
// - 无店铺关联
if (storeEmployee == null ||
!hasPermission ||
!hasStoreRelation) {
// 4.8 补偿创建初始化店铺部分赋值
Pair<Integer, String> result = shopStoreBaseService.covMerchEntryInfo2StoreInfo(entry.getId(), false);
if (result != null && result.getFirst() > 0) {
fixCount++;
log.warn("商户信息修复成功入驻ID: {}", entry.getId());
} else {
log.error("商户信息修复失败入驻ID: {}, 错误信息:{}", entry.getId(), result.getSecond());
}
}
}
return fixCount > 0;
} catch (Exception e) {
log.error("商户信息修复异常,手机号: {}", loginMobile, e);
return false;
}
}
/**
* 商家入驻审批
*
@ -1099,6 +1204,22 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
return CollectionUtil.isNotEmpty(recordList) ? recordList.get(0) : null;
}
/**
* 根据手机号获取商户入驻信息(一个手机可以申请多个商家入驻)
*
* @param mobile 手机号
* @return 商户入驻信息如果不存在则返回 null
*/
public List<ShopMchEntry> selectByMobile(String mobile) {
if (StrUtil.isBlank(mobile)) {
return null;
}
QueryWrapper<ShopMchEntry> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("login_mobile", mobile).eq("status", CommonConstant.Enable).orderByAsc("id");
return list(queryWrapper);
}
/**
* 根据商家注册的手机号更新合同签署状态和合同下载地址
*

View File

@ -26,6 +26,7 @@ import com.suisung.mall.shop.store.mapper.ShopStoreEmployeeMapper;
import com.suisung.mall.shop.store.service.ShopStoreEmployeeRightsGroupService;
import com.suisung.mall.shop.store.service.ShopStoreEmployeeService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
@ -45,6 +46,7 @@ import static com.suisung.mall.common.utils.ContextUtil.getCurrentUser;
* @author Xinze
* @since 2021-06-21
*/
@Slf4j
@Service
public class ShopStoreEmployeeServiceImpl extends BaseServiceImpl<ShopStoreEmployeeMapper, ShopStoreEmployee> implements ShopStoreEmployeeService {
@ -274,4 +276,44 @@ public class ShopStoreEmployeeServiceImpl extends BaseServiceImpl<ShopStoreEmplo
return employeeGeTuiCids;
}
/**
* 根据店铺Id和员工Id获取员工信息
*
* @param storeId 店铺ID必填
* @param userId 用户ID必填
* @return ShopStoreEmployee 员工信息若未找到返回null
* @throws ApiException 参数校验失败或系统异常时抛出
*/
@Override
public ShopStoreEmployee getStoreEmployeeByUserId(Integer storeId, Integer userId) throws ApiException {
// 参数校验
if (storeId == null || storeId <= 0) {
log.warn("无效的店铺ID{}", storeId);
return null;
}
if (userId == null || userId <= 0) {
log.warn("无效的用户ID{}", userId);
return null;
}
try {
QueryWrapper<ShopStoreEmployee> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("store_id", storeId)
.eq("user_id", userId);
ShopStoreEmployee employee = getOne(queryWrapper);
if (employee == null) {
log.info("未找到店铺员工信息 - 店铺ID: {}, 用户ID: {}", storeId, userId);
}
return employee;
} catch (Exception e) {
log.error("查询店铺员工信息异常 - 店铺ID: {}, 用户ID: {}", storeId, userId, e);
return null;
}
}
}