feat: 新增微信公众号扫码注册功能及幂等处理

- 新增 `FuwuhaoConst` 常量类,统一缓存 Key 前缀管理
- `FuwuhaoOptions` 增加 FromUser、RedirectUri、PicUrl 配置项
- `FuwuhaoManager` 新增 `BuildRegisterMessage` 方法,构建注册引导图文消息
- `FuwuhaoService`
  - 增加 OpenId 与 Scene 绑定缓存,支持扫码注册有效期管理
  - 回调处理支持注册场景,返回图文消息引导用户注册
  - 新增注册接口 `RegisterByCodeAsync`,根据微信授权信息自动注册账号并更新场景状态
- `AccountManager` 注册方法增加分布式锁,防止重复注册,并校验用户名唯一性
This commit is contained in:
chenchun
2025-08-29 11:01:09 +08:00
parent d2c6238df1
commit 6bd561b094
5 changed files with 146 additions and 31 deletions

View File

@@ -2,6 +2,7 @@
using System.Security.Claims;
using System.Text;
using Mapster;
using Medallion.Threading;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
@@ -36,6 +37,13 @@ namespace Yi.Framework.Rbac.Domain.Managers
private UserManager _userManager;
private ISqlSugarRepository<RoleAggregateRoot> _roleRepository;
private RefreshJwtOptions _refreshJwtOptions;
/// <summary>
/// 缓存前缀
/// </summary>
private string CacheKeyPrefix => LazyServiceProvider.LazyGetRequiredService<IOptions<AbpDistributedCacheOptions>>()
.Value.KeyPrefix;
public IDistributedLockProvider DistributedLock =>
LazyServiceProvider.LazyGetService<IDistributedLockProvider>();
public AccountManager(IUserRepository repository
, IOptions<JwtOptions> jwtOptions
@@ -288,17 +296,32 @@ namespace Yi.Framework.Rbac.Domain.Managers
/// <param name="icon"></param>
/// <returns></returns>
public async Task<Guid> RegisterAsync(string userName, string password, long? phone, string? email,
string? nick,string? icon)
string? nick, string? icon)
{
if (phone is null && string.IsNullOrWhiteSpace(email))
if (userName is null)
{
throw new UserFriendlyException("注册时,电话与邮箱不能同时为空");
throw new UserFriendlyException("注册时,用户名不能为空");
}
var user = new UserAggregateRoot(userName, password, phone, email, nick);
var userId = await _userManager.CreateAsync(user);
await _userManager.SetDefautRoleAsync(user.Id);
return userId;
//制作幂等
await using (var handle = await DistributedLock.TryAcquireLockAsync($"{CacheKeyPrefix}Register:Lock:{userName}", TimeSpan.FromSeconds(60)))
{
if (handle is null)
{
throw new UserFriendlyException($"{userName}用户正在注册中,请稍等");
}
var userUpName = userName.ToUpper();
if (await _userManager._repository._DbQueryable.Where(x => x.UserName.ToUpper() == userUpName).AnyAsync())
{
throw new UserFriendlyException($"{userName}用户已注册");
}
var user = new UserAggregateRoot(userName, password, phone, email, nick);
var userId = await _userManager.CreateAsync(user);
await _userManager.SetDefautRoleAsync(user.Id);
return userId;
}
}
}
}