165 lines
5.4 KiB
C#
165 lines
5.4 KiB
C#
using System.Text;
|
|
using Microsoft.Extensions.Logging;
|
|
using Volo.Abp;
|
|
using Volo.Abp.Domain.Services;
|
|
using Yi.Framework.AiHub.Domain.Entities;
|
|
using Yi.Framework.AiHub.Domain.Shared.Enums;
|
|
using Yi.Framework.SqlSugarCore.Abstractions;
|
|
|
|
namespace Yi.Framework.AiHub.Domain.Managers;
|
|
|
|
public class ActivationCodeRedeemContext
|
|
{
|
|
public ActivationCodeAggregateRoot ActivationCode { get; set; } = default!;
|
|
public string PackageName { get; set; } = string.Empty;
|
|
public ActivationCodeGoodsAttribute Goods { get; set; } = default!;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 激活码管理器
|
|
/// </summary>
|
|
public class ActivationCodeManager : DomainService
|
|
{
|
|
private readonly ISqlSugarRepository<ActivationCodeAggregateRoot, Guid> _activationCodeRepository;
|
|
private readonly ISqlSugarRepository<ActivationCodeRecordAggregateRoot, Guid> _activationCodeRecordRepository;
|
|
private readonly ILogger<ActivationCodeManager> _logger;
|
|
|
|
public ActivationCodeManager(
|
|
ISqlSugarRepository<ActivationCodeAggregateRoot, Guid> activationCodeRepository,
|
|
ISqlSugarRepository<ActivationCodeRecordAggregateRoot, Guid> activationCodeRecordRepository,
|
|
ILogger<ActivationCodeManager> logger)
|
|
{
|
|
_activationCodeRepository = activationCodeRepository;
|
|
_activationCodeRecordRepository = activationCodeRecordRepository;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task<List<ActivationCodeAggregateRoot>> CreateBatchAsync(ActivationCodeGoodsTypeEnum goodsType,
|
|
int count, bool isReusable, bool isSameTypeOnce, string? remark)
|
|
{
|
|
if (count <= 0)
|
|
{
|
|
throw new UserFriendlyException("生成数量必须大于0");
|
|
}
|
|
|
|
var entities = new List<ActivationCodeAggregateRoot>();
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
var code = await GenerateUniqueActivationCodeAsync();
|
|
entities.Add(new ActivationCodeAggregateRoot
|
|
{
|
|
Code = code,
|
|
GoodsType = goodsType,
|
|
IsReusable = isReusable,
|
|
IsSameTypeOnce = isSameTypeOnce,
|
|
UsedCount = 0,
|
|
Remark = remark
|
|
});
|
|
}
|
|
|
|
await _activationCodeRepository.InsertRangeAsync(entities);
|
|
return entities;
|
|
}
|
|
|
|
public async Task<ActivationCodeRedeemContext> RedeemAsync(Guid userId, string code)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(code))
|
|
{
|
|
throw new UserFriendlyException("激活码不能为空");
|
|
}
|
|
|
|
var trimmedCode = code.Trim();
|
|
var activationCode = await _activationCodeRepository._DbQueryable
|
|
.Where(x => x.Code == trimmedCode)
|
|
.FirstAsync();
|
|
|
|
if (activationCode == null)
|
|
{
|
|
throw new UserFriendlyException("激活码不存在");
|
|
}
|
|
|
|
var hasUsedCurrentCode = await _activationCodeRecordRepository._DbQueryable
|
|
.Where(x => x.UserId == userId && x.ActivationCodeId == activationCode.Id)
|
|
.AnyAsync();
|
|
|
|
if (hasUsedCurrentCode)
|
|
{
|
|
throw new UserFriendlyException("该激活码已被你使用过");
|
|
}
|
|
|
|
if (!activationCode.IsReusable && activationCode.UsedCount > 0)
|
|
{
|
|
throw new UserFriendlyException("该激活码已被使用");
|
|
}
|
|
|
|
if (activationCode.IsSameTypeOnce)
|
|
{
|
|
var hasUsedSameType = await _activationCodeRecordRepository._DbQueryable
|
|
.Where(x => x.UserId == userId && x.GoodsType == activationCode.GoodsType)
|
|
.AnyAsync();
|
|
|
|
if (hasUsedSameType)
|
|
{
|
|
throw new UserFriendlyException("该类型激活码每个用户只能兑换一次");
|
|
}
|
|
}
|
|
|
|
var goods = activationCode.GoodsType.GetGoods();
|
|
if (goods == null)
|
|
{
|
|
throw new UserFriendlyException("激活码商品类型无效");
|
|
}
|
|
|
|
var packageName = string.IsNullOrWhiteSpace(goods.Content)
|
|
? goods.DisplayName
|
|
: $"{goods.DisplayName} {goods.Content}";
|
|
|
|
activationCode.UsedCount += 1;
|
|
await _activationCodeRepository.UpdateAsync(activationCode);
|
|
|
|
var record = new ActivationCodeRecordAggregateRoot
|
|
{
|
|
ActivationCodeId = activationCode.Id,
|
|
Code = activationCode.Code,
|
|
UserId = userId,
|
|
GoodsType = activationCode.GoodsType,
|
|
RedeemTime = DateTime.Now,
|
|
Remark = "激活码兑换"
|
|
};
|
|
await _activationCodeRecordRepository.InsertAsync(record);
|
|
|
|
_logger.LogInformation("用户 {UserId} 兑换激活码 {Code} 成功", userId, activationCode.Code);
|
|
|
|
return new ActivationCodeRedeemContext
|
|
{
|
|
ActivationCode = activationCode,
|
|
PackageName = packageName,
|
|
Goods = goods
|
|
};
|
|
}
|
|
|
|
private async Task<string> GenerateUniqueActivationCodeAsync()
|
|
{
|
|
string code;
|
|
do
|
|
{
|
|
code = GenerateActivationCode();
|
|
} while (await _activationCodeRepository._DbQueryable.AnyAsync(x => x.Code == code));
|
|
|
|
return code;
|
|
}
|
|
|
|
private string GenerateActivationCode()
|
|
{
|
|
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
|
var random = new Random();
|
|
var builder = new StringBuilder(16);
|
|
for (var i = 0; i < 16; i++)
|
|
{
|
|
builder.Append(chars[random.Next(chars.Length)]);
|
|
}
|
|
|
|
return builder.ToString();
|
|
}
|
|
}
|