From 497df1354074b3f88e2666b1a1ab2d980969852f Mon Sep 17 00:00:00 2001 From: Jack <46790855@qq.com> Date: Mon, 1 Sep 2025 17:34:24 +0800 Subject: [PATCH] =?UTF-8?q?=E5=95=86=E5=AE=B6=E7=94=A8=E6=88=B7=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E4=B9=8B=E5=90=8E=EF=BC=8C=E8=A1=A5=E5=81=BF=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=E5=BA=97=E9=93=BA=E9=81=97=E6=BC=8F=E7=9A=84=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/AccountUserBaseServiceImpl.java | 33 +++- .../mall/common/feignService/ShopService.java | 11 ++ .../common/utils/phone/PhoneNumberUtils.java | 81 +++++++++- .../admin/ShopMchEntryAdminController.java | 17 +- .../store/service/ShopMchEntryService.java | 16 ++ .../service/ShopStoreEmployeeService.java | 10 ++ .../service/impl/ShopMchEntryServiceImpl.java | 145 ++++++++++++++++-- .../impl/ShopStoreEmployeeServiceImpl.java | 42 +++++ 8 files changed, 332 insertions(+), 23 deletions(-) diff --git a/mall-account/src/main/java/com/suisung/mall/account/service/impl/AccountUserBaseServiceImpl.java b/mall-account/src/main/java/com/suisung/mall/account/service/impl/AccountUserBaseServiceImpl.java index 7c013fdf..b8051078 100644 --- a/mall-account/src/main/java/com/suisung/mall/account/service/impl/AccountUserBaseServiceImpl.java +++ b/mall-account/src/main/java/com/suisung/mall/account/service/impl/AccountUserBaseServiceImpl.java @@ -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 params) { Boolean hasKey = false; @@ -2975,7 +2977,13 @@ public class AccountUserBaseServiceImpl extends BaseServiceImpl 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); + } diff --git a/mall-common/src/main/java/com/suisung/mall/common/utils/phone/PhoneNumberUtils.java b/mall-common/src/main/java/com/suisung/mall/common/utils/phone/PhoneNumberUtils.java index deb3372c..454ae152 100644 --- a/mall-common/src/main/java/com/suisung/mall/common/utils/phone/PhoneNumberUtils.java +++ b/mall-common/src/main/java/com/suisung/mall/common/utils/phone/PhoneNumberUtils.java @@ -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 → 234567890123(3位国家码123) + * - +354123456789 → 123456789(3位国家码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")); + } } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/admin/ShopMchEntryAdminController.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/admin/ShopMchEntryAdminController.java index 062cee70..e177894e 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/admin/ShopMchEntryAdminController.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/admin/ShopMchEntryAdminController.java @@ -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); + } + } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopMchEntryService.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopMchEntryService.java index e9f68310..86b68d9b 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopMchEntryService.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopMchEntryService.java @@ -145,6 +145,14 @@ public interface ShopMchEntryService { */ ShopMchEntry getShopMerchEntryByMobileOrMerCupNo(String loginMobile, String merchantCupNo); + /** + * 根据手机号获取商户入驻信息(一个手机可以申请多个商家入驻) + * + * @param mobile 手机号 + * @return 商户入驻信息,如果不存在则返回 null + */ + List selectByMobile(String mobile); + /** * 根据商家注册的手机号,更新合同签署状态和合同下载地址 * @@ -312,4 +320,12 @@ public interface ShopMchEntryService { * @return */ CommonResult updateMerchEntry(ShopMchEntry record); + + /** + * 重要(补偿机制),检查修复商户入驻店铺信息(商家账号关联入驻店铺Id,给商家账户创立公司员工账号和权限) + * + * @param loginMobile 商户登录手机号(必填) + * @return boolean 是否成功修复至少一个商户信息 + */ + Boolean checkAndFixMchStoreInfo(String loginMobile); } \ No newline at end of file diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopStoreEmployeeService.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopStoreEmployeeService.java index fef8f900..22b36063 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopStoreEmployeeService.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopStoreEmployeeService.java @@ -48,4 +48,14 @@ public interface ShopStoreEmployeeService extends IBaseService selectEmployeeGeTuiCidByStoreId(Integer storeId, String orderId, Boolean isAdmin); + + /** + * 根据店铺Id和员工Id获取员工信息 + * + * @param storeId + * @param userId + * @return + */ + ShopStoreEmployee getStoreEmployeeByUserId(Integer storeId, Integer userId); + } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopMchEntryServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopMchEntryServiceImpl.java index 9fb53d41..fbf9be42 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopMchEntryServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopMchEntryServiceImpl.java @@ -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 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 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 selectByMobile(String mobile) { + if (StrUtil.isBlank(mobile)) { + return null; + } + + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("login_mobile", mobile).eq("status", CommonConstant.Enable).orderByAsc("id"); + return list(queryWrapper); + } + /** * 根据商家注册的手机号,更新合同签署状态和合同下载地址 * diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreEmployeeServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreEmployeeServiceImpl.java index 69bb25bd..4ac0df00 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreEmployeeServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreEmployeeServiceImpl.java @@ -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 implements ShopStoreEmployeeService { @@ -274,4 +276,44 @@ public class ShopStoreEmployeeServiceImpl extends BaseServiceImpl 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; + } + } + }