diff --git a/YD_Event.Application/AppUser/AppUserService.cs b/YD_Event.Application/AppUser/AppUserService.cs index c85858a..5ece55a 100644 --- a/YD_Event.Application/AppUser/AppUserService.cs +++ b/YD_Event.Application/AppUser/AppUserService.cs @@ -4,6 +4,7 @@ using YD_Event.Core.Entities; using AppUserEntity = YD_Event.Core.Entities.AppUser; using YD_Event.Core.Enum; using Mapster; +using EasyCaching.Core; namespace YD_Event.Application.AppUser; @@ -15,14 +16,17 @@ public class AppUserService : BaseService, ITransient private readonly ISqlSugarRepository _appUserRep; private readonly ISqlSugarClient _db; private readonly AuthManager _authManager; + private readonly IEasyCachingProvider _cachingProvider; public AppUserService(ISqlSugarRepository appUserRep, ISqlSugarClient db, - AuthManager authManager) : base(appUserRep) + AuthManager authManager, + IEasyCachingProvider cachingProvider) : base(appUserRep) { _appUserRep = appUserRep; _db = db; _authManager = authManager; + _cachingProvider = cachingProvider; } /// @@ -133,6 +137,23 @@ public class AppUserService : BaseService, ITransient [DisplayName("统一新增/编辑成员")] public async Task SaveUnifiedMember(CreateOrUpdateMemberInput input) { + // 仅在新增领队/教练时验证验证码 + if (!input.Id.HasValue && (input.PersonType == PersonType.Leader || input.PersonType == PersonType.Coach)) + { + if (string.IsNullOrWhiteSpace(input.VerificationCode)) + { + throw Oops.Bah("验证码不能为空"); + } + + var cacheKey = $"sms:code:{input.Mobile}"; + var cachedCodeResult = _cachingProvider.Get(cacheKey); + string? cachedCode = cachedCodeResult.Value; + if (!cachedCodeResult.HasValue || cachedCode != input.VerificationCode) + { + throw Oops.Bah("验证码错误或已过期"); + } + } + var (userId, merchantCertificationId) = await GetCurrentUserAndMerchantCertificationId(); // 校验唯一性 (手机号或身份证号,具体根据角色定) diff --git a/YD_Event.Application/AppUser/Dtos/AppUserDtos.cs b/YD_Event.Application/AppUser/Dtos/AppUserDtos.cs index 50528fb..6824c33 100644 --- a/YD_Event.Application/AppUser/Dtos/AppUserDtos.cs +++ b/YD_Event.Application/AppUser/Dtos/AppUserDtos.cs @@ -190,6 +190,11 @@ public class CreateOrUpdateMemberInput /// 备注 /// public string? Remark { get; set; } + + /// + /// 验证码(仅新增领队/教练时需要) + /// + public string? VerificationCode { get; set; } } /// diff --git a/YD_Event.Application/Client/Dtos/MiniProgramDtos.cs b/YD_Event.Application/Client/Dtos/MiniProgramDtos.cs index 85aaf07..9566c07 100644 --- a/YD_Event.Application/Client/Dtos/MiniProgramDtos.cs +++ b/YD_Event.Application/Client/Dtos/MiniProgramDtos.cs @@ -15,9 +15,14 @@ public class MiniProgramLoginInput public string Mobile { get; set; } /// - /// 密码 + /// 密码(账号登录时必填) /// public string Password { get; set; } + + /// + /// 验证码(短信登录时必填) + /// + public string VerificationCode { get; set; } } /// diff --git a/YD_Event.Application/Client/OAuthController.cs b/YD_Event.Application/Client/OAuthController.cs index d5e244c..40cbe2c 100644 --- a/YD_Event.Application/Client/OAuthController.cs +++ b/YD_Event.Application/Client/OAuthController.cs @@ -30,7 +30,7 @@ public class OAuthController : IDynamicApiController } /// - /// 登录接口 + /// 登录接口(支持账号密码登录和短信验证码登录两种方式) /// /// /// @@ -38,9 +38,17 @@ public class OAuthController : IDynamicApiController [AllowAnonymous] public async Task Login([FromBody] MiniProgramLoginInput input) { - if (string.IsNullOrEmpty(input.Password) ) + var isPasswordLogin = !string.IsNullOrEmpty(input.Password); + var isSmsLogin = !string.IsNullOrEmpty(input.VerificationCode); + + if (!isPasswordLogin && !isSmsLogin) { - throw Oops.Bah("密码必填"); + throw Oops.Bah("请选择密码登录或短信验证码登录"); + } + + if (isPasswordLogin && isSmsLogin) + { + throw Oops.Bah("请选择一种登录方式"); } var appUser = await _appUserRepository.GetFirstAsync(x => x.Mobile == input.Mobile); @@ -49,7 +57,7 @@ public class OAuthController : IDynamicApiController throw Oops.Bah("用户不存在,请先注册"); } - if (!string.IsNullOrEmpty(input.Password)) + if (isPasswordLogin) { if (string.IsNullOrEmpty(appUser.Password)) { @@ -61,6 +69,17 @@ public class OAuthController : IDynamicApiController throw Oops.Bah("密码错误"); } } + else + { + var cacheKey = $"{SmsCodeCachePrefix}{input.Mobile}"; + var cachedCodeResult = _cachingProvider.Get(cacheKey); + string cachedCode = cachedCodeResult.Value; + if (!cachedCodeResult.HasValue || cachedCode != input.VerificationCode) + { + throw Oops.Bah("验证码错误或已过期"); + } + _cachingProvider.Remove(cacheKey); + } (string accessToken, string refreshToken) = GenerateTokens(appUser); diff --git a/YD_Event.Application/YD_Event.Application.xml b/YD_Event.Application/YD_Event.Application.xml index 4f636ee..86d3699 100644 --- a/YD_Event.Application/YD_Event.Application.xml +++ b/YD_Event.Application/YD_Event.Application.xml @@ -282,6 +282,11 @@ 备注 + + + 验证码(仅新增领队/教练时需要) + + 成员状态变更输入 @@ -2092,7 +2097,12 @@ - 密码 + 密码(账号登录时必填) + + + + + 验证码(短信登录时必填) @@ -2601,7 +2611,7 @@ - 登录接口 + 登录接口(支持账号密码登录和短信验证码登录两种方式)