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);
}
}