using EasyCaching.Core; using Microsoft.Extensions.Logging; using YD_Event.Application.Client.Dtos; namespace YD_Event.Application.Client; /// /// 微信小程序认证接口 /// [ApiDescriptionSettings("微信小程序接口")] public class OAuthController : IDynamicApiController { private readonly ISqlSugarRepository _appUserRepository; private readonly IEasyCachingProvider _cachingProvider; private readonly IIdGenerator _idGenerator; private readonly ILogger _logger; private const string SmsCodeCachePrefix = "sms:code:"; public OAuthController( ISqlSugarRepository appUserRepository, IEasyCachingProvider cachingProvider, IIdGenerator idGenerator, ILogger logger) { _appUserRepository = appUserRepository; _cachingProvider = cachingProvider; _idGenerator = idGenerator; _logger = logger; } /// /// 登录接口(支持账号密码登录和短信验证码登录两种方式) /// /// /// [HttpPost("login")] [AllowAnonymous] public async Task Login([FromBody] MiniProgramLoginInput input) { var isPasswordLogin = !string.IsNullOrEmpty(input.Password); var isSmsLogin = !string.IsNullOrEmpty(input.VerificationCode); if (!isPasswordLogin && !isSmsLogin) { throw Oops.Bah("请选择密码登录或短信验证码登录"); } if (isPasswordLogin && isSmsLogin) { throw Oops.Bah("请选择一种登录方式"); } var appUser = await _appUserRepository.GetFirstAsync(x => x.Mobile == input.Mobile); // 统一的未注册账户判断逻辑 bool isRegistered = appUser != null && !string.IsNullOrEmpty(appUser.Password); if (!isRegistered) { if (appUser == null || string.IsNullOrEmpty(appUser.Password)) { throw Oops.Bah("未注册过账户"); } } // 检查用户类型 - 仅允许运动员登录 if (appUser.PersonType != PersonType.Athlete) { throw Oops.Bah("未注册用户"); } if (isPasswordLogin) { var encryptedPassword = MD5Encryption.Encrypt($"{_idGenerator.Encode(appUser.Id)}{input.Password}"); if (appUser.Password != encryptedPassword) { 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); var userInfo = new { appUser.Name, appUser.Id, appUser.Mobile, appUser.Avatar, appUser.NickName }; return new MiniProgramLoginOutput { AccessToken = accessToken, RefreshToken = refreshToken, ExpiresIn = 7200, UserInfo = userInfo }; } /// /// 注册接口 /// /// /// [HttpPost("register")] [AllowAnonymous] [UnitOfWork] public async Task Register([FromBody] MiniProgramRegisterInput input) { 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); // 检查手机号是否已存在 var existingUser = await _appUserRepository.GetFirstAsync(x => x.Mobile == input.Mobile && !x.DeleteMark); YD_Event.Core.Entities.AppUser appUser; bool isNewUser = false; if (existingUser != null) { // 手机号已存在,检查是否已设置密码 if (!string.IsNullOrEmpty(existingUser.Password)) { throw Oops.Bah("该手机号已注册"); } // 未设置密码,更新现有记录 appUser = existingUser; var encryptedPassword = MD5Encryption.Encrypt($"{_idGenerator.Encode(appUser.Id)}{input.Password}"); appUser.Password = encryptedPassword; appUser.UpdatedTime = DateTime.Now; } else { // 手机号不存在,创建新用户 isNewUser = true; long appUserId = _idGenerator.NewLong(); var encryptedPassword = MD5Encryption.Encrypt($"{_idGenerator.Encode(appUserId)}{input.Password}"); appUser = new YD_Event.Core.Entities.AppUser { Id = appUserId, Name = input.NickName ?? input.Mobile, NickName = input.NickName, Avatar = input.Avatar, Mobile = input.Mobile, Password = encryptedPassword, PersonType = PersonType.Athlete, Status = AvailabilityStatus.Enable, AuditStatus = AuditStatus.PendingSubmission, CreatedTime = DateTime.Now, CreatedUserId = 0 }; } if (isNewUser) { await _appUserRepository.InsertAsync(appUser); } else { await _appUserRepository.UpdateAsync(appUser); } return new MiniProgramRegisterOutput { UserId = appUser.Id, Mobile = appUser.Mobile, NickName = appUser.NickName, RegisterTime = isNewUser ? appUser.CreatedTime : (appUser.UpdatedTime ?? appUser.CreatedTime) }; } /// /// 重置密码接口 /// /// /// [HttpPost("reset-password")] [AllowAnonymous] public async Task ResetPassword([FromBody] MiniProgramResetPasswordInput input) { 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); var appUser = await _appUserRepository.GetFirstAsync(x => x.Mobile == input.Mobile); if (appUser == null) { throw Oops.Bah("用户不存在"); } // 检查用户类型 - 仅允许运动员重置密码 if (appUser.PersonType != PersonType.Athlete) { throw Oops.Bah("用户不存在"); } var encryptedPassword = MD5Encryption.Encrypt($"{_idGenerator.Encode(appUser.Id)}{input.NewPassword}"); appUser.Password = encryptedPassword; appUser.UpdatedTime = DateTime.Now; appUser.UpdatedUserId = appUser.Id; await _appUserRepository.UpdateAsync(appUser); } /// /// 生成自定义 Token /// private (string AccessToken, string RefreshToken) GenerateTokens(YD_Event.Core.Entities.AppUser appUser) { long uniqueId = _idGenerator.NewLong(); string accessToken = JWTEncryption.Encrypt(new Dictionary() { [AuthClaimsConst.AuthIdKey] = appUser.Id, [AuthClaimsConst.AccountKey] = appUser.Mobile, [AuthClaimsConst.UuidKey] = uniqueId, [AuthClaimsConst.AuthPlatformTypeKey] = AuthPlatformType.WeChatApplet }); string refreshToken = JWTEncryption.GenerateRefreshToken(accessToken); return (accessToken, refreshToken); } }