Răsfoiți Sursa

1. 会员用户的修改手机 API 的优化

YunaiV 1 an în urmă
părinte
comite
87e5b2bed1

+ 2 - 0
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java

@@ -12,6 +12,7 @@ public interface ErrorCodeConstants {
     // ========== 用户相关  1004001000============
     ErrorCode USER_NOT_EXISTS = new ErrorCode(1004001000, "用户不存在");
     ErrorCode USER_PASSWORD_FAILED = new ErrorCode(1004001001, "密码校验失败");
+    ErrorCode USER_MOBILE_USED = new ErrorCode(1004001002, "修改手机失败,该手机号({})已经被使用");
 
     // ========== AUTH 模块 1004003000 ==========
     ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1004003000, "登录失败,账号密码不正确");
@@ -19,6 +20,7 @@ public interface ErrorCodeConstants {
     ErrorCode AUTH_TOKEN_EXPIRED = new ErrorCode(1004003004, "Token 已经过期");
     ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1004003005, "未绑定账号,需要进行绑定");
     ErrorCode AUTH_WEIXIN_MINI_APP_PHONE_CODE_ERROR = new ErrorCode(1004003006, "获得手机号失败");
+    ErrorCode AUTH_MOBILE_USED = new ErrorCode(1004003007, "手机号已经被使用");
 
     // ========== 用户收件地址 1004004000 ==========
     ErrorCode ADDRESS_NOT_EXISTS = new ErrorCode(1004004000, "用户收件地址不存在");

+ 7 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.java

@@ -77,6 +77,13 @@ public class AppAuthController {
         return success(true);
     }
 
+    @PostMapping("/validate-sms-code")
+    @Operation(summary = "校验手机验证码")
+    public CommonResult<Boolean> validateSmsCode(@RequestBody @Valid AppAuthSmsValidateReqVO reqVO) {
+        authService.validateSmsCode(getLoginUserId(), reqVO);
+        return success(true);
+    }
+
     @PostMapping("/reset-password")
     @Operation(summary = "重置密码", description = "用户忘记密码时使用")
     @PreAuthenticated

+ 35 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSmsValidateReqVO.java

@@ -0,0 +1,35 @@
+package cn.iocoder.yudao.module.member.controller.app.auth.vo;
+
+import cn.iocoder.yudao.framework.common.validation.InEnum;
+import cn.iocoder.yudao.framework.common.validation.Mobile;
+import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.experimental.Accessors;
+import org.hibernate.validator.constraints.Length;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+
+@Schema(description = "用户 APP - 校验手机验证码 Request VO")
+@Data
+@Accessors(chain = true)
+public class AppAuthSmsValidateReqVO {
+
+    @Schema(description = "手机号", example = "15601691234")
+    @Mobile
+    private String mobile;
+
+    @Schema(description = "发送场景,对应 SmsSceneEnum 枚举", example = "1")
+    @NotNull(message = "发送场景不能为空")
+    @InEnum(SmsSceneEnum.class)
+    private Integer scene;
+
+    @Schema(description = "手机验证码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+    @NotEmpty(message = "手机验证码不能为空")
+    @Length(min = 4, max = 6, message = "手机验证码长度为 4-6 位")
+    @Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字")
+    private String code;
+
+}

+ 10 - 10
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java

@@ -30,14 +30,6 @@ public class AppMemberUserController {
     @Resource
     private MemberUserService userService;
 
-    @PutMapping("/update")
-    @Operation(summary = "修改基本信息")
-    @PreAuthenticated
-    public CommonResult<Boolean> updateUser(@RequestBody @Valid AppMemberUserUpdateReqVO reqVO) {
-        userService.updateUser(getLoginUserId(), reqVO);
-        return success(true);
-    }
-
     @GetMapping("/get")
     @Operation(summary = "获得基本信息")
     @PreAuthenticated
@@ -46,10 +38,18 @@ public class AppMemberUserController {
         return success(MemberUserConvert.INSTANCE.convert(user));
     }
 
-    @PostMapping("/update-mobile")
+    @PutMapping("/update")
+    @Operation(summary = "修改基本信息")
+    @PreAuthenticated
+    public CommonResult<Boolean> updateUser(@RequestBody @Valid AppMemberUserUpdateReqVO reqVO) {
+        userService.updateUser(getLoginUserId(), reqVO);
+        return success(true);
+    }
+
+    @PutMapping("/update-mobile")
     @Operation(summary = "修改用户手机")
     @PreAuthenticated
-    public CommonResult<Boolean> updateMobile(@RequestBody @Valid AppUserUpdateMobileReqVO reqVO) {
+    public CommonResult<Boolean> updateUserMobile(@RequestBody @Valid AppUserUpdateMobileReqVO reqVO) {
         userService.updateUserMobile(getLoginUserId(), reqVO);
         return success(true);
     }

+ 0 - 8
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppUserUpdateMobileReqVO.java

@@ -37,12 +37,4 @@ public class AppUserUpdateMobileReqVO {
     @Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字")
     private String oldCode;
 
-    // TODO @芋艿:oldMobile 应该不用传递
-
-    @Schema(description = "原手机号",requiredMode = Schema.RequiredMode.REQUIRED,example = "15823654487")
-    @NotBlank(message = "手机号不能为空")
-    @Length(min = 8, max = 11, message = "手机号码长度为 8-11 位")
-    @Mobile
-    private String oldMobile;
-
 }

+ 3 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/auth/AuthConvert.java

@@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserUnbi
 import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenRespDTO;
 import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
 import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
+import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeValidateReqDTO;
 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO;
 import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum;
@@ -25,4 +26,6 @@ public interface AuthConvert {
 
     AppAuthLoginRespVO convert(OAuth2AccessTokenRespDTO bean);
 
+    SmsCodeValidateReqDTO convert(AppAuthSmsValidateReqVO bean);
+
 }

+ 8 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthService.java

@@ -82,6 +82,14 @@ public interface MemberAuthService {
      */
     void sendSmsCode(Long userId, AppAuthSmsSendReqVO reqVO);
 
+    /**
+     * 校验短信验证码是否正确
+     *
+     * @param userId 用户编号
+     * @param reqVO 校验信息
+     */
+    void validateSmsCode(Long userId, AppAuthSmsValidateReqVO reqVO);
+
     /**
      * 刷新访问令牌
      *

+ 16 - 2
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java

@@ -236,13 +236,27 @@ public class MemberAuthServiceImpl implements MemberAuthService {
 
     @Override
     public void sendSmsCode(Long userId, AppAuthSmsSendReqVO reqVO) {
-        // TODO 要根据不同的场景,校验是否有用户
+        // 如果是修改手机场景,需要校验新手机号是否已经注册,说明不能使用该手机了
+        if (Objects.equals(reqVO.getScene(), SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene())) {
+            MemberUserDO user = userMapper.selectByMobile(reqVO.getMobile());
+            if (user != null && !Objects.equals(user.getId(), userId)) {
+                throw exception(AUTH_MOBILE_USED);
+            }
+        }
+
+        // 执行发送
         smsCodeApi.sendSmsCode(AuthConvert.INSTANCE.convert(reqVO).setCreateIp(getClientIP()));
     }
 
+    @Override
+    public void validateSmsCode(Long userId, AppAuthSmsValidateReqVO reqVO) {
+        smsCodeApi.validateSmsCode(AuthConvert.INSTANCE.convert(reqVO));
+    }
+
     @Override
     public AppAuthLoginRespVO refreshToken(String refreshToken) {
-        OAuth2AccessTokenRespDTO accessTokenDO = oauth2TokenApi.refreshAccessToken(refreshToken, OAuth2ClientConstants.CLIENT_ID_DEFAULT);
+        OAuth2AccessTokenRespDTO accessTokenDO = oauth2TokenApi.refreshAccessToken(refreshToken,
+                OAuth2ClientConstants.CLIENT_ID_DEFAULT);
         return AuthConvert.INSTANCE.convert(accessTokenDO);
     }
 

+ 7 - 7
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java

@@ -29,8 +29,7 @@ import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
-import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.USER_NOT_EXISTS;
-import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_MOBILE_EXISTS;
+import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*;
 
 /**
  * 会员 User Service 实现类
@@ -113,11 +112,12 @@ public class MemberUserServiceImpl implements MemberUserService {
     @Transactional(rollbackFor = Exception.class)
     public void updateUserMobile(Long userId, AppUserUpdateMobileReqVO reqVO) {
         // 检测用户是否存在
-        validateUserExists(userId);
-        // TODO 芋艿:oldMobile 应该不用传递
+        MemberUserDO user = validateUserExists(userId);
+        // 校验新手机是否已经被绑定
+        validateMobileUnique(null, reqVO.getMobile());
 
         // 校验旧手机和旧验证码
-        smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(reqVO.getOldMobile()).setCode(reqVO.getOldCode())
+        smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(user.getMobile()).setCode(reqVO.getOldCode())
                 .setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP()));
         // 使用新验证码
         smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(reqVO.getMobile()).setCode(reqVO.getCode())
@@ -177,10 +177,10 @@ public class MemberUserServiceImpl implements MemberUserService {
         }
         // 如果 id 为空,说明不用比较是否为相同 id 的用户
         if (id == null) {
-            throw exception(USER_MOBILE_EXISTS);
+            throw exception(USER_MOBILE_USED);
         }
         if (!user.getId().equals(id)) {
-            throw exception(USER_MOBILE_EXISTS);
+            throw exception(USER_MOBILE_USED);
         }
     }
 

+ 2 - 2
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/sms/SmsSceneEnum.java

@@ -17,8 +17,8 @@ import java.util.Arrays;
 public enum SmsSceneEnum implements IntArrayValuable {
 
     MEMBER_LOGIN(1, "user-sms-login", "会员用户 - 手机号登陆"),
-    MEMBER_UPDATE_MOBILE(2, "user-sms-reset-password", "会员用户 - 修改手机"),
-    MEMBER_FORGET_PASSWORD(3, "user-sms-update-mobile", "会员用户 - 忘记密码"),
+    MEMBER_UPDATE_MOBILE(2, "user-sms-update-mobile", "会员用户 - 修改手机"),
+    MEMBER_FORGET_PASSWORD(3, "user-sms-forget-password", "会员用户 - 忘记密码"),
 
     ADMIN_MEMBER_LOGIN(21, "admin-sms-login", "后台用户 - 手机号登录");