208 lines
6.9 KiB
C#

using EasyCaching.Core;
using Microsoft.Extensions.Logging;
using YD_Event.Application.Client.Dtos;
namespace YD_Event.Application.Client;
/// <summary>
/// 微信小程序认证接口
/// </summary>
[ApiDescriptionSettings("微信小程序接口")]
public class OAuthController : IDynamicApiController
{
private readonly ISqlSugarRepository<YD_Event.Core.Entities.AppUser> _appUserRepository;
private readonly IEasyCachingProvider _cachingProvider;
private readonly IIdGenerator _idGenerator;
private readonly ILogger<OAuthController> _logger;
private const string SmsCodeCachePrefix = "sms:code:";
public OAuthController(
ISqlSugarRepository<YD_Event.Core.Entities.AppUser> appUserRepository,
IEasyCachingProvider cachingProvider,
IIdGenerator idGenerator,
ILogger<OAuthController> logger)
{
_appUserRepository = appUserRepository;
_cachingProvider = cachingProvider;
_idGenerator = idGenerator;
_logger = logger;
}
/// <summary>
/// 登录接口(支持账号密码登录和短信验证码登录两种方式)
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("login")]
[AllowAnonymous]
public async Task<MiniProgramLoginOutput> 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);
if (appUser == null)
{
throw Oops.Bah("用户不存在,请先注册");
}
if (isPasswordLogin)
{
if (string.IsNullOrEmpty(appUser.Password))
{
throw Oops.Bah("该用户未设置密码,请使用验证码登录");
}
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<string>(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
};
}
/// <summary>
/// 注册接口
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("register")]
[AllowAnonymous]
[UnitOfWork]
public async Task<MiniProgramRegisterOutput> Register([FromBody] MiniProgramRegisterInput input)
{
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);
if (await _appUserRepository.IsAnyAsync(x => x.Mobile == input.Mobile))
{
throw Oops.Bah("该手机号已注册");
}
long appUserId = _idGenerator.NewLong();
var encryptedPassword = MD5Encryption.Encrypt($"{_idGenerator.Encode(appUserId)}{input.Password}");
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,
Status = AvailabilityStatus.Enable,
AuditStatus = AuditStatus.Pass,
CreatedTime = DateTime.Now,
CreatedUserId = appUserId
};
await _appUserRepository.InsertAsync(appUser);
return new MiniProgramRegisterOutput
{
UserId = appUser.Id,
Mobile = appUser.Mobile,
NickName = appUser.NickName,
RegisterTime = appUser.CreatedTime
};
}
/// <summary>
/// 重置密码接口
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("reset-password")]
[AllowAnonymous]
public async Task ResetPassword([FromBody] MiniProgramResetPasswordInput input)
{
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);
var appUser = await _appUserRepository.GetFirstAsync(x => x.Mobile == input.Mobile);
if (appUser == null)
{
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);
}
/// <summary>
/// 生成自定义 Token
/// </summary>
private (string AccessToken, string RefreshToken) GenerateTokens(YD_Event.Core.Entities.AppUser appUser)
{
long uniqueId = _idGenerator.NewLong();
string accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>()
{
[AuthClaimsConst.AuthIdKey] = appUser.Id,
[AuthClaimsConst.AccountKey] = appUser.Mobile,
[AuthClaimsConst.UuidKey] = uniqueId,
[AuthClaimsConst.AuthPlatformTypeKey] = AuthPlatformType.WeChatApplet
});
string refreshToken = JWTEncryption.GenerateRefreshToken(accessToken);
return (accessToken, refreshToken);
}
}