Commit 87e5b2bed13cc6558e538739914ffb81dc82fcc4

Authored by YunaiV
1 parent 41533315

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

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 { @@ -12,6 +12,7 @@ public interface ErrorCodeConstants {
12 // ========== 用户相关 1004001000============ 12 // ========== 用户相关 1004001000============
13 ErrorCode USER_NOT_EXISTS = new ErrorCode(1004001000, "用户不存在"); 13 ErrorCode USER_NOT_EXISTS = new ErrorCode(1004001000, "用户不存在");
14 ErrorCode USER_PASSWORD_FAILED = new ErrorCode(1004001001, "密码校验失败"); 14 ErrorCode USER_PASSWORD_FAILED = new ErrorCode(1004001001, "密码校验失败");
  15 + ErrorCode USER_MOBILE_USED = new ErrorCode(1004001002, "修改手机失败,该手机号({})已经被使用");
15 16
16 // ========== AUTH 模块 1004003000 ========== 17 // ========== AUTH 模块 1004003000 ==========
17 ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1004003000, "登录失败,账号密码不正确"); 18 ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1004003000, "登录失败,账号密码不正确");
@@ -19,6 +20,7 @@ public interface ErrorCodeConstants { @@ -19,6 +20,7 @@ public interface ErrorCodeConstants {
19 ErrorCode AUTH_TOKEN_EXPIRED = new ErrorCode(1004003004, "Token 已经过期"); 20 ErrorCode AUTH_TOKEN_EXPIRED = new ErrorCode(1004003004, "Token 已经过期");
20 ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1004003005, "未绑定账号,需要进行绑定"); 21 ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1004003005, "未绑定账号,需要进行绑定");
21 ErrorCode AUTH_WEIXIN_MINI_APP_PHONE_CODE_ERROR = new ErrorCode(1004003006, "获得手机号失败"); 22 ErrorCode AUTH_WEIXIN_MINI_APP_PHONE_CODE_ERROR = new ErrorCode(1004003006, "获得手机号失败");
  23 + ErrorCode AUTH_MOBILE_USED = new ErrorCode(1004003007, "手机号已经被使用");
22 24
23 // ========== 用户收件地址 1004004000 ========== 25 // ========== 用户收件地址 1004004000 ==========
24 ErrorCode ADDRESS_NOT_EXISTS = new ErrorCode(1004004000, "用户收件地址不存在"); 26 ErrorCode ADDRESS_NOT_EXISTS = new ErrorCode(1004004000, "用户收件地址不存在");
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 { @@ -77,6 +77,13 @@ public class AppAuthController {
77 return success(true); 77 return success(true);
78 } 78 }
79 79
  80 + @PostMapping("/validate-sms-code")
  81 + @Operation(summary = "校验手机验证码")
  82 + public CommonResult<Boolean> validateSmsCode(@RequestBody @Valid AppAuthSmsValidateReqVO reqVO) {
  83 + authService.validateSmsCode(getLoginUserId(), reqVO);
  84 + return success(true);
  85 + }
  86 +
80 @PostMapping("/reset-password") 87 @PostMapping("/reset-password")
81 @Operation(summary = "重置密码", description = "用户忘记密码时使用") 88 @Operation(summary = "重置密码", description = "用户忘记密码时使用")
82 @PreAuthenticated 89 @PreAuthenticated
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSmsValidateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.member.controller.app.auth.vo;
  2 +
  3 +import cn.iocoder.yudao.framework.common.validation.InEnum;
  4 +import cn.iocoder.yudao.framework.common.validation.Mobile;
  5 +import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum;
  6 +import io.swagger.v3.oas.annotations.media.Schema;
  7 +import lombok.Data;
  8 +import lombok.experimental.Accessors;
  9 +import org.hibernate.validator.constraints.Length;
  10 +
  11 +import javax.validation.constraints.NotEmpty;
  12 +import javax.validation.constraints.NotNull;
  13 +import javax.validation.constraints.Pattern;
  14 +
  15 +@Schema(description = "用户 APP - 校验手机验证码 Request VO")
  16 +@Data
  17 +@Accessors(chain = true)
  18 +public class AppAuthSmsValidateReqVO {
  19 +
  20 + @Schema(description = "手机号", example = "15601691234")
  21 + @Mobile
  22 + private String mobile;
  23 +
  24 + @Schema(description = "发送场景,对应 SmsSceneEnum 枚举", example = "1")
  25 + @NotNull(message = "发送场景不能为空")
  26 + @InEnum(SmsSceneEnum.class)
  27 + private Integer scene;
  28 +
  29 + @Schema(description = "手机验证码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  30 + @NotEmpty(message = "手机验证码不能为空")
  31 + @Length(min = 4, max = 6, message = "手机验证码长度为 4-6 位")
  32 + @Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字")
  33 + private String code;
  34 +
  35 +}
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 { @@ -30,14 +30,6 @@ public class AppMemberUserController {
30 @Resource 30 @Resource
31 private MemberUserService userService; 31 private MemberUserService userService;
32 32
33 - @PutMapping("/update")  
34 - @Operation(summary = "修改基本信息")  
35 - @PreAuthenticated  
36 - public CommonResult<Boolean> updateUser(@RequestBody @Valid AppMemberUserUpdateReqVO reqVO) {  
37 - userService.updateUser(getLoginUserId(), reqVO);  
38 - return success(true);  
39 - }  
40 -  
41 @GetMapping("/get") 33 @GetMapping("/get")
42 @Operation(summary = "获得基本信息") 34 @Operation(summary = "获得基本信息")
43 @PreAuthenticated 35 @PreAuthenticated
@@ -46,10 +38,18 @@ public class AppMemberUserController { @@ -46,10 +38,18 @@ public class AppMemberUserController {
46 return success(MemberUserConvert.INSTANCE.convert(user)); 38 return success(MemberUserConvert.INSTANCE.convert(user));
47 } 39 }
48 40
49 - @PostMapping("/update-mobile") 41 + @PutMapping("/update")
  42 + @Operation(summary = "修改基本信息")
  43 + @PreAuthenticated
  44 + public CommonResult<Boolean> updateUser(@RequestBody @Valid AppMemberUserUpdateReqVO reqVO) {
  45 + userService.updateUser(getLoginUserId(), reqVO);
  46 + return success(true);
  47 + }
  48 +
  49 + @PutMapping("/update-mobile")
50 @Operation(summary = "修改用户手机") 50 @Operation(summary = "修改用户手机")
51 @PreAuthenticated 51 @PreAuthenticated
52 - public CommonResult<Boolean> updateMobile(@RequestBody @Valid AppUserUpdateMobileReqVO reqVO) { 52 + public CommonResult<Boolean> updateUserMobile(@RequestBody @Valid AppUserUpdateMobileReqVO reqVO) {
53 userService.updateUserMobile(getLoginUserId(), reqVO); 53 userService.updateUserMobile(getLoginUserId(), reqVO);
54 return success(true); 54 return success(true);
55 } 55 }
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 { @@ -37,12 +37,4 @@ public class AppUserUpdateMobileReqVO {
37 @Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字") 37 @Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字")
38 private String oldCode; 38 private String oldCode;
39 39
40 - // TODO @芋艿:oldMobile 应该不用传递  
41 -  
42 - @Schema(description = "原手机号",requiredMode = Schema.RequiredMode.REQUIRED,example = "15823654487")  
43 - @NotBlank(message = "手机号不能为空")  
44 - @Length(min = 8, max = 11, message = "手机号码长度为 8-11 位")  
45 - @Mobile  
46 - private String oldMobile;  
47 -  
48 } 40 }
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 @@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserUnbi
5 import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenRespDTO; 5 import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenRespDTO;
6 import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeSendReqDTO; 6 import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
7 import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO; 7 import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
  8 +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeValidateReqDTO;
8 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; 9 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
9 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO; 10 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO;
10 import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; 11 import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum;
@@ -25,4 +26,6 @@ public interface AuthConvert { @@ -25,4 +26,6 @@ public interface AuthConvert {
25 26
26 AppAuthLoginRespVO convert(OAuth2AccessTokenRespDTO bean); 27 AppAuthLoginRespVO convert(OAuth2AccessTokenRespDTO bean);
27 28
  29 + SmsCodeValidateReqDTO convert(AppAuthSmsValidateReqVO bean);
  30 +
28 } 31 }
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthService.java
@@ -83,6 +83,14 @@ public interface MemberAuthService { @@ -83,6 +83,14 @@ public interface MemberAuthService {
83 void sendSmsCode(Long userId, AppAuthSmsSendReqVO reqVO); 83 void sendSmsCode(Long userId, AppAuthSmsSendReqVO reqVO);
84 84
85 /** 85 /**
  86 + * 校验短信验证码是否正确
  87 + *
  88 + * @param userId 用户编号
  89 + * @param reqVO 校验信息
  90 + */
  91 + void validateSmsCode(Long userId, AppAuthSmsValidateReqVO reqVO);
  92 +
  93 + /**
86 * 刷新访问令牌 94 * 刷新访问令牌
87 * 95 *
88 * @param refreshToken 刷新令牌 96 * @param refreshToken 刷新令牌
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 { @@ -236,13 +236,27 @@ public class MemberAuthServiceImpl implements MemberAuthService {
236 236
237 @Override 237 @Override
238 public void sendSmsCode(Long userId, AppAuthSmsSendReqVO reqVO) { 238 public void sendSmsCode(Long userId, AppAuthSmsSendReqVO reqVO) {
239 - // TODO 要根据不同的场景,校验是否有用户 239 + // 如果是修改手机场景,需要校验新手机号是否已经注册,说明不能使用该手机了
  240 + if (Objects.equals(reqVO.getScene(), SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene())) {
  241 + MemberUserDO user = userMapper.selectByMobile(reqVO.getMobile());
  242 + if (user != null && !Objects.equals(user.getId(), userId)) {
  243 + throw exception(AUTH_MOBILE_USED);
  244 + }
  245 + }
  246 +
  247 + // 执行发送
240 smsCodeApi.sendSmsCode(AuthConvert.INSTANCE.convert(reqVO).setCreateIp(getClientIP())); 248 smsCodeApi.sendSmsCode(AuthConvert.INSTANCE.convert(reqVO).setCreateIp(getClientIP()));
241 } 249 }
242 250
243 @Override 251 @Override
  252 + public void validateSmsCode(Long userId, AppAuthSmsValidateReqVO reqVO) {
  253 + smsCodeApi.validateSmsCode(AuthConvert.INSTANCE.convert(reqVO));
  254 + }
  255 +
  256 + @Override
244 public AppAuthLoginRespVO refreshToken(String refreshToken) { 257 public AppAuthLoginRespVO refreshToken(String refreshToken) {
245 - OAuth2AccessTokenRespDTO accessTokenDO = oauth2TokenApi.refreshAccessToken(refreshToken, OAuth2ClientConstants.CLIENT_ID_DEFAULT); 258 + OAuth2AccessTokenRespDTO accessTokenDO = oauth2TokenApi.refreshAccessToken(refreshToken,
  259 + OAuth2ClientConstants.CLIENT_ID_DEFAULT);
246 return AuthConvert.INSTANCE.convert(accessTokenDO); 260 return AuthConvert.INSTANCE.convert(accessTokenDO);
247 } 261 }
248 262
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; @@ -29,8 +29,7 @@ import java.util.List;
29 29
30 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 30 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
31 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; 31 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
32 -import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.USER_NOT_EXISTS;  
33 -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_MOBILE_EXISTS; 32 +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*;
34 33
35 /** 34 /**
36 * 会员 User Service 实现类 35 * 会员 User Service 实现类
@@ -113,11 +112,12 @@ public class MemberUserServiceImpl implements MemberUserService { @@ -113,11 +112,12 @@ public class MemberUserServiceImpl implements MemberUserService {
113 @Transactional(rollbackFor = Exception.class) 112 @Transactional(rollbackFor = Exception.class)
114 public void updateUserMobile(Long userId, AppUserUpdateMobileReqVO reqVO) { 113 public void updateUserMobile(Long userId, AppUserUpdateMobileReqVO reqVO) {
115 // 检测用户是否存在 114 // 检测用户是否存在
116 - validateUserExists(userId);  
117 - // TODO 芋艿:oldMobile 应该不用传递 115 + MemberUserDO user = validateUserExists(userId);
  116 + // 校验新手机是否已经被绑定
  117 + validateMobileUnique(null, reqVO.getMobile());
118 118
119 // 校验旧手机和旧验证码 119 // 校验旧手机和旧验证码
120 - smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(reqVO.getOldMobile()).setCode(reqVO.getOldCode()) 120 + smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(user.getMobile()).setCode(reqVO.getOldCode())
121 .setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP())); 121 .setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP()));
122 // 使用新验证码 122 // 使用新验证码
123 smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(reqVO.getMobile()).setCode(reqVO.getCode()) 123 smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(reqVO.getMobile()).setCode(reqVO.getCode())
@@ -177,10 +177,10 @@ public class MemberUserServiceImpl implements MemberUserService { @@ -177,10 +177,10 @@ public class MemberUserServiceImpl implements MemberUserService {
177 } 177 }
178 // 如果 id 为空,说明不用比较是否为相同 id 的用户 178 // 如果 id 为空,说明不用比较是否为相同 id 的用户
179 if (id == null) { 179 if (id == null) {
180 - throw exception(USER_MOBILE_EXISTS); 180 + throw exception(USER_MOBILE_USED);
181 } 181 }
182 if (!user.getId().equals(id)) { 182 if (!user.getId().equals(id)) {
183 - throw exception(USER_MOBILE_EXISTS); 183 + throw exception(USER_MOBILE_USED);
184 } 184 }
185 } 185 }
186 186
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; @@ -17,8 +17,8 @@ import java.util.Arrays;
17 public enum SmsSceneEnum implements IntArrayValuable { 17 public enum SmsSceneEnum implements IntArrayValuable {
18 18
19 MEMBER_LOGIN(1, "user-sms-login", "会员用户 - 手机号登陆"), 19 MEMBER_LOGIN(1, "user-sms-login", "会员用户 - 手机号登陆"),
20 - MEMBER_UPDATE_MOBILE(2, "user-sms-reset-password", "会员用户 - 修改手机"),  
21 - MEMBER_FORGET_PASSWORD(3, "user-sms-update-mobile", "会员用户 - 忘记密码"), 20 + MEMBER_UPDATE_MOBILE(2, "user-sms-update-mobile", "会员用户 - 修改手机"),
  21 + MEMBER_FORGET_PASSWORD(3, "user-sms-forget-password", "会员用户 - 忘记密码"),
22 22
23 ADMIN_MEMBER_LOGIN(21, "admin-sms-login", "后台用户 - 手机号登录"); 23 ADMIN_MEMBER_LOGIN(21, "admin-sms-login", "后台用户 - 手机号登录");
24 24