208 lines
6.9 KiB
C#
Raw Normal View History

2026-03-31 15:54:27 +08:00
using EasyCaching.Core;
2026-03-14 06:13:06 +08:00
using Microsoft.Extensions.Logging;
2025-12-17 11:12:13 +08:00
using YD_Event.Application.Client.Dtos;
2025-12-17 10:32:52 +08:00
2025-12-17 11:12:13 +08:00
namespace YD_Event.Application.Client;
2026-03-14 06:13:06 +08:00
2025-12-17 10:32:52 +08:00
/// <summary>
2026-03-14 06:13:06 +08:00
/// 微信小程序认证接口
2025-12-17 10:32:52 +08:00
/// </summary>
2025-12-27 12:53:54 +08:00
[ApiDescriptionSettings("微信小程序接口")]
2025-12-17 10:32:52 +08:00
public class OAuthController : IDynamicApiController
{
2026-03-14 06:13:06 +08:00
private readonly ISqlSugarRepository<YD_Event.Core.Entities.AppUser> _appUserRepository;
2026-03-31 15:54:27 +08:00
private readonly IEasyCachingProvider _cachingProvider;
2025-12-17 10:32:52 +08:00
private readonly IIdGenerator _idGenerator;
2026-03-14 06:13:06 +08:00
private readonly ILogger<OAuthController> _logger;
private const string SmsCodeCachePrefix = "sms:code:";
2025-12-17 10:32:52 +08:00
2026-03-14 06:13:06 +08:00
public OAuthController(
ISqlSugarRepository<YD_Event.Core.Entities.AppUser> appUserRepository,
2026-03-31 15:54:27 +08:00
IEasyCachingProvider cachingProvider,
2026-03-14 06:13:06 +08:00
IIdGenerator idGenerator,
ILogger<OAuthController> logger)
2025-12-17 10:32:52 +08:00
{
2026-03-14 06:13:06 +08:00
_appUserRepository = appUserRepository;
2026-03-31 15:54:27 +08:00
_cachingProvider = cachingProvider;
2025-12-17 10:32:52 +08:00
_idGenerator = idGenerator;
2026-03-14 06:13:06 +08:00
_logger = logger;
2025-12-17 10:32:52 +08:00
}
/// <summary>
/// 登录接口(支持账号密码登录和短信验证码登录两种方式)
2025-12-17 10:32:52 +08:00
/// </summary>
2026-03-14 06:13:06 +08:00
/// <param name="input"></param>
2025-12-17 10:32:52 +08:00
/// <returns></returns>
2026-03-14 06:13:06 +08:00
[HttpPost("login")]
2025-12-17 10:32:52 +08:00
[AllowAnonymous]
public async Task<MiniProgramLoginOutput> Login([FromBody] MiniProgramLoginInput input)
2025-12-17 10:32:52 +08:00
{
var isPasswordLogin = !string.IsNullOrEmpty(input.Password);
var isSmsLogin = !string.IsNullOrEmpty(input.VerificationCode);
if (!isPasswordLogin && !isSmsLogin)
{
throw Oops.Bah("请选择密码登录或短信验证码登录");
}
if (isPasswordLogin && isSmsLogin)
{
throw Oops.Bah("请选择一种登录方式");
}
2026-03-14 06:13:06 +08:00
var appUser = await _appUserRepository.GetFirstAsync(x => x.Mobile == input.Mobile);
if (appUser == null)
{
throw Oops.Bah("用户不存在,请先注册");
}
2026-03-14 06:13:06 +08:00
if (isPasswordLogin)
2025-12-17 10:32:52 +08:00
{
if (string.IsNullOrEmpty(appUser.Password))
2026-03-14 06:13:06 +08:00
{
throw Oops.Bah("该用户未设置密码,请使用验证码登录");
2026-03-14 06:13:06 +08:00
}
var encryptedPassword = MD5Encryption.Encrypt($"{_idGenerator.Encode(appUser.Id)}{input.Password}");
if (appUser.Password != encryptedPassword)
2026-03-14 06:13:06 +08:00
{
throw Oops.Bah("密码错误");
2026-03-14 06:13:06 +08:00
}
}
else
{
var cacheKey = $"{SmsCodeCachePrefix}{input.Mobile}";
var cachedCodeResult = _cachingProvider.Get<string>(cacheKey);
string cachedCode = cachedCodeResult.Value;
if (!cachedCodeResult.HasValue || cachedCode != input.VerificationCode)
{
throw Oops.Bah("验证码错误或已过期");
}
_cachingProvider.Remove(cacheKey);
}
2026-03-14 06:13:06 +08:00
(string accessToken, string refreshToken) = GenerateTokens(appUser);
var userInfo = new
{
appUser.Name,
appUser.Id,
appUser.Mobile,
appUser.Avatar,
appUser.NickName
};
return new MiniProgramLoginOutput
2026-03-14 06:13:06 +08:00
{
AccessToken = accessToken,
RefreshToken = refreshToken,
ExpiresIn = 7200,
2026-03-14 06:13:06 +08:00
UserInfo = userInfo
2025-12-17 10:32:52 +08:00
};
}
/// <summary>
2026-03-14 06:13:06 +08:00
/// 注册接口
2025-12-17 10:32:52 +08:00
/// </summary>
2026-03-14 06:13:06 +08:00
/// <param name="input"></param>
2025-12-17 10:32:52 +08:00
/// <returns></returns>
2026-03-14 06:13:06 +08:00
[HttpPost("register")]
2025-12-17 10:32:52 +08:00
[AllowAnonymous]
2026-03-14 06:13:06 +08:00
[UnitOfWork]
public async Task<MiniProgramRegisterOutput> Register([FromBody] MiniProgramRegisterInput input)
2025-12-17 10:32:52 +08:00
{
var cacheKey = $"{SmsCodeCachePrefix}{input.Mobile}";
2026-03-31 15:54:27 +08:00
var cachedCodeResult = _cachingProvider.Get<string>(cacheKey);
string cachedCode = cachedCodeResult.Value;
if (!cachedCodeResult.HasValue || cachedCode != input.VerificationCode)
2025-12-17 10:32:52 +08:00
{
throw Oops.Bah("验证码错误或已过期");
2025-12-17 10:32:52 +08:00
}
2026-03-31 15:54:27 +08:00
_cachingProvider.Remove(cacheKey);
2026-03-14 06:13:06 +08:00
if (await _appUserRepository.IsAnyAsync(x => x.Mobile == input.Mobile))
2026-03-14 06:13:06 +08:00
{
throw Oops.Bah("该手机号已注册");
2026-03-14 06:13:06 +08:00
}
long appUserId = _idGenerator.NewLong();
var encryptedPassword = MD5Encryption.Encrypt($"{_idGenerator.Encode(appUserId)}{input.Password}");
2026-03-14 06:13:06 +08:00
var appUser = new YD_Event.Core.Entities.AppUser
{
Id = appUserId,
Name = input.NickName ?? input.Mobile,
NickName = input.NickName,
Avatar = input.Avatar,
Gender = Gender.Unknown,
Mobile = input.Mobile,
Password = encryptedPassword,
PersonType = PersonType.User,
2026-03-14 06:13:06 +08:00
Status = AvailabilityStatus.Enable,
AuditStatus = AuditStatus.Pass,
CreatedTime = DateTime.Now,
CreatedUserId = 0
2026-03-14 06:13:06 +08:00
};
await _appUserRepository.InsertAsync(appUser);
return new MiniProgramRegisterOutput
2026-03-14 06:13:06 +08:00
{
UserId = appUser.Id,
Mobile = appUser.Mobile,
NickName = appUser.NickName,
RegisterTime = appUser.CreatedTime
2026-03-14 06:13:06 +08:00
};
2025-12-17 10:32:52 +08:00
}
/// <summary>
/// 重置密码接口
2025-12-17 10:32:52 +08:00
/// </summary>
2026-03-14 06:13:06 +08:00
/// <param name="input"></param>
2025-12-17 10:32:52 +08:00
/// <returns></returns>
2026-03-14 06:13:06 +08:00
[HttpPost("reset-password")]
2025-12-17 10:32:52 +08:00
[AllowAnonymous]
public async Task ResetPassword([FromBody] MiniProgramResetPasswordInput input)
2025-12-17 10:32:52 +08:00
{
var cacheKey = $"{SmsCodeCachePrefix}{input.Mobile}";
2026-03-31 15:54:27 +08:00
var cachedCodeResult = _cachingProvider.Get<string>(cacheKey);
string cachedCode = cachedCodeResult.Value;
if (!cachedCodeResult.HasValue || cachedCode != input.VerificationCode)
2025-12-17 10:32:52 +08:00
{
throw Oops.Bah("验证码错误或已过期");
2026-03-14 06:13:06 +08:00
}
2026-03-31 15:54:27 +08:00
_cachingProvider.Remove(cacheKey);
2026-03-14 06:13:06 +08:00
var appUser = await _appUserRepository.GetFirstAsync(x => x.Mobile == input.Mobile);
if (appUser == null)
2026-03-14 06:13:06 +08:00
{
throw Oops.Bah("用户不存在");
2026-03-14 06:13:06 +08:00
}
var encryptedPassword = MD5Encryption.Encrypt($"{_idGenerator.Encode(appUser.Id)}{input.NewPassword}");
appUser.Password = encryptedPassword;
appUser.UpdatedTime = DateTime.Now;
appUser.UpdatedUserId = appUser.Id;
2025-12-17 10:32:52 +08:00
await _appUserRepository.UpdateAsync(appUser);
2026-03-14 06:13:06 +08:00
}
/// <summary>
/// 生成自定义 Token
/// </summary>
private (string AccessToken, string RefreshToken) GenerateTokens(YD_Event.Core.Entities.AppUser appUser)
2026-03-14 06:13:06 +08:00
{
long uniqueId = _idGenerator.NewLong();
string accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>()
{
[AuthClaimsConst.AuthIdKey] = appUser.Id,
[AuthClaimsConst.AccountKey] = appUser.Mobile,
2026-03-14 06:13:06 +08:00
[AuthClaimsConst.UuidKey] = uniqueId,
[AuthClaimsConst.AuthPlatformTypeKey] = AuthPlatformType.WeChatApplet
2026-04-04 22:09:43 +08:00
});
2026-03-14 06:13:06 +08:00
string refreshToken = JWTEncryption.GenerateRefreshToken(accessToken);
return (accessToken, refreshToken);
2025-12-17 10:32:52 +08:00
}
2026-03-02 11:19:25 +08:00
}