Просмотр исходного кода

feat(customer): 新增客户注册功能

- 实现客户注册接口,包含验证码校验、密码确认、企业信息验证
- 集成企查查API验证企业真实性并获取工商信息
- 添加客户信息、工商信息、联系人信息的完整数据录入流程
- 创建对应的系统用户账户并设置商城用户类型
- 新增客户注册控制器和业务对象类
- 扩展认证策略接口支持客户登录功能
- 更新短信验证码为6位数字并优化发送配置
- 修复数据权限拦截器中的表名配置问题
肖路 2 месяцев назад
Родитель
Сommit
e50f88966d
14 измененных файлов с 316 добавлено и 8 удалено
  1. 26 0
      ruoyi-auth/src/main/java/org/dromara/auth/controller/TokenController.java
  2. 19 0
      ruoyi-auth/src/main/java/org/dromara/auth/service/IAuthStrategy.java
  3. 12 0
      ruoyi-auth/src/main/java/org/dromara/auth/service/impl/EmailAuthStrategy.java
  4. 12 0
      ruoyi-auth/src/main/java/org/dromara/auth/service/impl/PasswordAuthStrategy.java
  5. 12 0
      ruoyi-auth/src/main/java/org/dromara/auth/service/impl/SmsAuthStrategy.java
  6. 12 0
      ruoyi-auth/src/main/java/org/dromara/auth/service/impl/SocialAuthStrategy.java
  7. 12 0
      ruoyi-auth/src/main/java/org/dromara/auth/service/impl/XcxAuthStrategy.java
  8. 1 1
      ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/interceptor/PlatformDataScopeInterceptor.java
  9. 31 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/pc/CustomerRegisterController.java
  10. 35 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/CustomerRegisterBo.java
  11. 6 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/ICustomerInfoService.java
  12. 103 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerInfoServiceImpl.java
  13. 17 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/pc/DiyProductController.java
  14. 18 7
      ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/controller/SysSmsController.java

+ 26 - 0
ruoyi-auth/src/main/java/org/dromara/auth/controller/TokenController.java

@@ -228,4 +228,30 @@ public class TokenController {
         return R.ok(result);
     }
 
+    /**
+    * 客户登录
+    * */
+    @PostMapping("/client/login")
+    public R<LoginVo> clientLogin(@RequestBody String body) {
+        LoginBody loginBody = JsonUtils.parseObject(body, LoginBody.class);
+        ValidatorUtils.validate(loginBody);
+        // 授权类型和客户端id
+        String clientId = loginBody.getClientId();
+        String grantType = loginBody.getGrantType();
+        RemoteClientVo clientVo = remoteClientService.queryByClientId(clientId);
+
+        // 查询不到 client 或 client 内不包含 grantType
+        if (ObjectUtil.isNull(clientVo) || !StringUtils.contains(clientVo.getGrantType(), grantType)) {
+            log.info("客户端id: {} 认证类型:{} 异常!.", clientId, grantType);
+            return R.fail(MessageUtils.message("auth.grant.type.error"));
+        } else if (!SystemConstants.NORMAL.equals(clientVo.getStatus())) {
+            return R.fail(MessageUtils.message("auth.grant.type.blocked"));
+        }
+        // 登录
+        LoginVo loginVo = IAuthStrategy.clientLogin(body, clientVo, grantType);
+
+        Long userId = LoginHelper.getUserId();
+        return R.ok(loginVo);
+    }
+
 }

+ 19 - 0
ruoyi-auth/src/main/java/org/dromara/auth/service/IAuthStrategy.java

@@ -37,6 +37,16 @@ public interface IAuthStrategy {
         return instance.getToken(username,password);
     }
 
+    static LoginVo clientLogin(String body, RemoteClientVo client, String grantType) {
+        // 授权类型和客户端id
+        String beanName = grantType + BASE_NAME;
+        if (!SpringUtils.containsBean(beanName)) {
+            throw new ServiceException("授权类型不正确!");
+        }
+        IAuthStrategy instance = SpringUtils.getBean(beanName);
+        return instance.login(body, client);
+    }
+
     /**
      * 登录
      *
@@ -46,6 +56,15 @@ public interface IAuthStrategy {
      */
     LoginVo login(String body, RemoteClientVo client);
 
+    /**
+     * 客户登录
+     *
+     * @param body   登录对象
+     * @param client 授权管理视图对象
+     * @return 登录验证信息
+     */
+    LoginVo clientLogin(String body, RemoteClientVo client);
+
     LoginVo getToken(String username, String password);
 
 }

+ 12 - 0
ruoyi-auth/src/main/java/org/dromara/auth/service/impl/EmailAuthStrategy.java

@@ -71,6 +71,18 @@ public class EmailAuthStrategy implements IAuthStrategy {
         return loginVo;
     }
 
+    /**
+     * 客户登录
+     *
+     * @param body   登录对象
+     * @param client 授权管理视图对象
+     * @return 登录验证信息
+     */
+    @Override
+    public LoginVo clientLogin(String body, RemoteClientVo client) {
+        return null;
+    }
+
     @Override
     public LoginVo getToken(String username, String password) {
         return null;

+ 12 - 0
ruoyi-auth/src/main/java/org/dromara/auth/service/impl/PasswordAuthStrategy.java

@@ -90,6 +90,18 @@ public class PasswordAuthStrategy implements IAuthStrategy {
         return loginVo;
     }
 
+    /**
+     * 客户登录
+     *
+     * @param body   登录对象
+     * @param client 授权管理视图对象
+     * @return 登录验证信息
+     */
+    @Override
+    public LoginVo clientLogin(String body, RemoteClientVo client) {
+        return null;
+    }
+
     /**
      * 校验验证码
      *

+ 12 - 0
ruoyi-auth/src/main/java/org/dromara/auth/service/impl/SmsAuthStrategy.java

@@ -71,6 +71,18 @@ public class SmsAuthStrategy implements IAuthStrategy {
         return loginVo;
     }
 
+    /**
+     * 客户登录
+     *
+     * @param body   登录对象
+     * @param client 授权管理视图对象
+     * @return 登录验证信息
+     */
+    @Override
+    public LoginVo clientLogin(String body, RemoteClientVo client) {
+        return null;
+    }
+
     @Override
     public LoginVo getToken(String username, String password) {
         return null;

+ 12 - 0
ruoyi-auth/src/main/java/org/dromara/auth/service/impl/SocialAuthStrategy.java

@@ -99,6 +99,18 @@ public class SocialAuthStrategy implements IAuthStrategy {
         return loginVo;
     }
 
+    /**
+     * 客户登录
+     *
+     * @param body   登录对象
+     * @param client 授权管理视图对象
+     * @return 登录验证信息
+     */
+    @Override
+    public LoginVo clientLogin(String body, RemoteClientVo client) {
+        return null;
+    }
+
     @Override
     public LoginVo getToken(String username, String password) {
         return null;

+ 12 - 0
ruoyi-auth/src/main/java/org/dromara/auth/service/impl/XcxAuthStrategy.java

@@ -88,6 +88,18 @@ public class XcxAuthStrategy implements IAuthStrategy {
         return loginVo;
     }
 
+    /**
+     * 客户登录
+     *
+     * @param body   登录对象
+     * @param client 授权管理视图对象
+     * @return 登录验证信息
+     */
+    @Override
+    public LoginVo clientLogin(String body, RemoteClientVo client) {
+        return null;
+    }
+
     @Override
     public LoginVo getToken(String username, String password) {
         return null;

+ 1 - 1
ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/interceptor/PlatformDataScopeInterceptor.java

@@ -89,7 +89,7 @@ public class PlatformDataScopeInterceptor implements Interceptor {
         "partner_contacts",
         "partner_contract",
         "partner_warehouse",
-        "partner_qualification"
+        "partner_qualification",
         "address_area",
         "supplier_",
         "supply_area",

+ 31 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/pc/CustomerRegisterController.java

@@ -0,0 +1,31 @@
+package org.dromara.customer.controller.pc;
+
+/**
+ * @author
+ * @date 2026/1/29 上午10:15
+ */
+
+import lombok.RequiredArgsConstructor;
+import org.dromara.common.core.domain.R;
+import org.dromara.customer.domain.bo.CustomerRegisterBo;
+import org.dromara.customer.service.ICustomerInfoService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/customerContact")
+public class CustomerRegisterController {
+
+    private final ICustomerInfoService customerInfoService;
+
+    /**
+    * 企业注册
+    * */
+    public R<Void> register(CustomerRegisterBo bo) {
+        customerInfoService.register(bo);
+        return R.ok();
+    }
+}

+ 35 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/CustomerRegisterBo.java

@@ -0,0 +1,35 @@
+package org.dromara.customer.domain.bo;
+
+import lombok.Data;
+
+/**
+ * @author
+ * @date 2026/1/29 上午10:24
+ */
+@Data
+public class CustomerRegisterBo {
+    /**
+    * 客户名称
+    * */
+    private String customerName;
+    /**
+    * 采购人姓名
+    * */
+    private String purchaseName;
+    /**
+    * 采购人手机号
+    * */
+    private String purchasePhone;
+    /**
+    * 验证码
+    * */
+    private String code;
+    /**
+    * 密码
+    * */
+    private String password;
+    /**
+    * 确认密码
+    * */
+    private String confirmPassword;
+}

+ 6 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/ICustomerInfoService.java

@@ -3,6 +3,7 @@ package org.dromara.customer.service;
 import com.baomidou.mybatisplus.extension.service.IService;
 import org.dromara.customer.domain.CustomerInfo;
 import org.dromara.customer.domain.bo.CustomerListBo;
+import org.dromara.customer.domain.bo.CustomerRegisterBo;
 import org.dromara.customer.domain.bo.MessagePublishCustomerBo;
 import org.dromara.customer.domain.vo.*;
 import org.dromara.customer.domain.bo.CustomerInfoBo;
@@ -121,4 +122,9 @@ public interface ICustomerInfoService extends IService<CustomerInfo> {
      * @return 是否删除成功
      */
     Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+
+    /**
+    * 客户注册
+    * */
+    Boolean register(CustomerRegisterBo bo);
 }

+ 103 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerInfoServiceImpl.java

@@ -10,18 +10,24 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.dubbo.config.annotation.DubboReference;
+import org.dromara.common.core.constant.GlobalConstants;
 import org.dromara.common.core.context.PlatformContext;
 import org.dromara.common.core.enums.IsDefault;
+import org.dromara.common.core.exception.ServiceException;
+import org.dromara.common.core.utils.DateUtils;
 import org.dromara.common.core.utils.MapstructUtils;
 import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.mybatis.core.page.PageQuery;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.redis.utils.RedisUtils;
 import org.dromara.common.satoken.utils.LoginHelper;
 import org.dromara.customer.domain.*;
 import org.dromara.customer.domain.bo.*;
 import org.dromara.customer.domain.vo.*;
 import org.dromara.customer.mapper.*;
 import org.dromara.customer.service.ICustomerInfoService;
+import org.dromara.customer.utils.qcc.QccUtils;
+import org.dromara.customer.utils.qcc.domain.CompanyInfoResponse;
 import org.dromara.system.api.*;
 import org.dromara.system.api.domain.bo.RemoteUserBo;
 import org.dromara.system.api.domain.vo.RemoteDeptVo;
@@ -834,4 +840,101 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
         }
         return baseMapper.deleteByIds(ids) > 0;
     }
+
+    /**
+     * 客户注册
+     *
+     * @param bo
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean register(CustomerRegisterBo bo) {
+        //先校验验证码是否正确
+        String code = RedisUtils.getCacheObject(GlobalConstants.CAPTCHA_CODE_KEY + bo.getPurchasePhone());
+        code = "123456";
+        if (!code.equals(bo.getCode())) {
+            throw new ServiceException("验证码错误");
+        }
+
+        //校验密码与确认密码是否一致
+        if (!bo.getPassword().equals(bo.getConfirmPassword())) {
+            throw new ServiceException("密码与确认密码不一致");
+        }
+
+        //查询数据库是否存在企业,已存在则提示客户已存在
+        CustomerInfo customerInfo = baseMapper.selectOne(new LambdaQueryWrapper<CustomerInfo>()
+            .eq(CustomerInfo::getCustomerName, bo.getCustomerName())
+        );
+        if (customerInfo != null) {
+            throw new ServiceException("客户已存在");
+        }
+
+        //查询企查查是否存在企业,如果企查查不存在则提示企业不存在
+        CompanyInfoResponse companyInfo = QccUtils.getCompanyInfo(bo.getCustomerName());
+        if (companyInfo == null || companyInfo.getResult() == null) {
+            throw new ServiceException("请检查企业名是否正确");
+        }
+
+        //构建客户信息实体
+        CustomerInfo customerEntity = new CustomerInfo();
+        customerEntity.setCustomerName(bo.getCustomerName());
+        customerEntity.setBusinessCustomerName(companyInfo.getResult().getName());
+        customerEntity.setShortName(companyInfo.getResult().getName());
+        customerEntity.setStatus("0"); // 正常状态
+        customerEntity.setDelFlag("0"); // 未删除
+
+        // 设置其他工商信息
+        if (baseMapper.insert(customerEntity) <= 0) {
+            throw new ServiceException("客户信息新增失败");
+        }
+
+        Long customerId = customerEntity.getId();
+
+        // 添加客户工商信息
+        CustomerBusinessInfo businessInfo = new CustomerBusinessInfo();
+        businessInfo.setCustomerId(customerId);
+        businessInfo.setBusinessCustomerName(companyInfo.getResult().getName());
+        businessInfo.setSocialCreditCode(companyInfo.getResult().getCreditCode());
+        businessInfo.setLegalPersonName(companyInfo.getResult().getOperName());
+        businessInfo.setRegisteredCapital(companyInfo.getResult().getRegistCapi());
+        businessInfo.setEstablishmentDate(DateUtils.parseDate((companyInfo.getResult().getStartDate())));
+        businessInfo.setRegistrationStatus(companyInfo.getResult().getStatus());
+        businessInfo.setBusinessAddress(companyInfo.getResult().getAddress());
+        businessInfo.setBussinessRange(companyInfo.getResult().getScope());
+        businessInfo.setStatus("0");
+        businessInfo.setDelFlag("0");
+
+        if (customerBusinessInfoMapper.insert(businessInfo) <= 0) {
+            throw new ServiceException("客户工商信息新增失败");
+        }
+
+        // 添加客户联系人信息
+        CustomerContact contact = new CustomerContact();
+        contact.setCustomerId(customerId);
+        contact.setContactName(bo.getPurchaseName());
+        contact.setPhone(bo.getPurchasePhone());
+        contact.setCustomLoginName(bo.getPurchasePhone());
+        contact.setIsPrimary("0"); // 设为主联系人
+        contact.setStatus("0");
+        contact.setDelFlag("0");
+
+        if (customerContactMapper.insert(contact) <= 0) {
+            throw new ServiceException("客户联系人信息新增失败");
+        }
+
+        // 创建系统用户
+        RemoteUserBo remoteUserBo = new RemoteUserBo();
+        remoteUserBo.setUserName(bo.getPurchasePhone());
+        remoteUserBo.setNickName(bo.getCustomerName());
+        remoteUserBo.setPhonenumber(bo.getPurchasePhone());
+        remoteUserBo.setPassword(BCrypt.hashpw(bo.getPassword()));
+        remoteUserBo.setUserSonType("3"); // 商城用户
+        remoteUserBo.setTenantId(LoginHelper.getTenantId());
+        remoteUserBo.setStatus("0"); // 正常状态
+
+        remoteUserService.addUser(remoteUserBo);
+
+        log.info("客户注册成功,客户ID:{},客户名称:{}", customerId, bo.getCustomerName());
+        return true;
+    }
 }

+ 17 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/pc/DiyProductController.java

@@ -0,0 +1,17 @@
+package org.dromara.product.controller.pc;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author
+ * @date 2026/1/28 下午3:37
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/diyProduct")
+public class DiyProductController {
+}

+ 18 - 7
ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/controller/SysSmsController.java

@@ -2,6 +2,7 @@ package org.dromara.resource.controller;
 
 
 import cn.hutool.core.util.RandomUtil;
+import cn.hutool.http.HttpUtil;
 import jakarta.validation.constraints.NotBlank;
 import jakarta.validation.constraints.NotEmpty;
 import lombok.Data;
@@ -20,8 +21,10 @@ import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import java.time.Duration;
+import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * 短信功能
@@ -40,17 +43,17 @@ public class SysSmsController extends BaseController {
      *
      * @param phonenumber 用户手机号
      */
-    @RateLimiter(key = "#phonenumber", time = 60, count = 1)
+//    @RateLimiter(key = "#phonenumber", time = 60, count = 1)
     @GetMapping("/code")
     public R<Void> smsCaptcha(@NotBlank(message = "{user.phonenumber.not.blank}") String phonenumber) {
         String key = GlobalConstants.CAPTCHA_CODE_KEY + phonenumber;
-        String code = RandomUtil.randomNumbers(4);
+        String code = RandomUtil.randomNumbers(6);
         RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
         // 验证码模板id 自行处理 (查数据库或写死均可)
-        String templateId = "";
+        String templateId = "SMS_482795341";
         LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
         map.put("code", code);
-        SmsBlend smsBlend = SmsFactory.getSmsBlend("tx1");
+        SmsBlend smsBlend = SmsFactory.getSmsBlend("config1");
         SmsResponse smsResponse = smsBlend.sendMessage(phonenumber, templateId, map);
         if (!smsResponse.isSuccess()) {
             log.error("验证码短信发送异常 => {}", smsResponse);
@@ -59,6 +62,14 @@ public class SysSmsController extends BaseController {
         return R.ok();
     }
 
+    public static void main(String[] args) {
+        Map<String, Object> map = new HashMap<>();
+        map.put("phonenumber", "17683851082");
+        String string = HttpUtil.get("http://127.0.0.1:8080/resource/sms/code",map);
+        System.out.println(string);
+
+    }
+
     /**
      * 群发短信
      *
@@ -68,16 +79,16 @@ public class SysSmsController extends BaseController {
     public R<Void> batchSend(@Validated @RequestBody SmsBatchRequest request) {
         List<String> phones = request.getPhones();
         String message = request.getMessage();
-        
+
         if (phones.isEmpty()) {
             return R.fail("手机号列表不能为空");
         }
         if (phones.size() > 1000) {
             return R.fail("单次群发不能超过1000个手机号");
         }
-        
+
         log.info("群发短信 => 手机号数量: {}, 内容: {}", phones.size(), message);
-        
+
         try {
             SmsBlend smsBlend = SmsFactory.getSmsBlend("config1");
             SmsResponse smsResponse = smsBlend.massTexting(phones, message);