- Implemented Create, Delete, Get, and Update validators for Product Galleries. - Added Create, Delete, Get, and Update validators for Product Tags. - Created service classes for handling Discount Categories, Discount Orders, Discount Products, Discount Shopping Cart, Product Categories, Product Galleries, and Product Tags. - Each service class integrates with CQRS for command and query handling. - Established mapping profiles for Product Galleries.
120 lines
4.8 KiB
C#
120 lines
4.8 KiB
C#
using CMSMicroservice.Domain.Events;
|
|
using Microsoft.Extensions.Configuration;
|
|
|
|
namespace CMSMicroservice.Application.OtpTokenCQ.Commands.VerifyOtpToken;
|
|
|
|
public class VerifyOtpTokenCommandHandler : IRequestHandler<VerifyOtpTokenCommand, VerifyOtpTokenResponseDto>
|
|
{
|
|
private readonly IApplicationDbContext _context;
|
|
private readonly IConfiguration _cfg;
|
|
private readonly IHashService _hashService;
|
|
|
|
public VerifyOtpTokenCommandHandler(IApplicationDbContext context, IConfiguration cfg, IHashService hashService)
|
|
{
|
|
_context = context;
|
|
_cfg = cfg;
|
|
_hashService = hashService;
|
|
}
|
|
|
|
const int MaxAttempts = 5; // محدودیت تلاش
|
|
|
|
public async Task<VerifyOtpTokenResponseDto> Handle(VerifyOtpTokenCommand request,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
var mobile = request.Mobile.NormalizeIranMobile();
|
|
var purpose = request.Purpose?.ToLowerInvariant() ?? "signup";
|
|
var now = DateTime.Now;
|
|
|
|
var otp = await _context.OtpTokens
|
|
.Where(o => o.Mobile == mobile && o.Purpose == purpose && !o.IsUsed && o.ExpiresAt > now)
|
|
.OrderByDescending(o => o.Created)
|
|
.FirstOrDefaultAsync(cancellationToken);
|
|
|
|
if (otp is null)
|
|
return new VerifyOtpTokenResponseDto() { Success = false, Message = "کد پیدا نشد یا منقضی شده است." };
|
|
|
|
if (otp.Attempts >= MaxAttempts)
|
|
return new VerifyOtpTokenResponseDto()
|
|
{ Success = false, Message = "تعداد تلاشها زیاد است. دوباره کد بگیرید." };
|
|
|
|
otp.Attempts++;
|
|
|
|
var secret = _cfg["Otp:Secret"] ?? throw new InvalidOperationException("Otp:Secret not set");
|
|
if (!_hashService.VerifyHmacSha256Hex(request.Code, otp.CodeHash, secret))
|
|
{
|
|
await _context.SaveChangesAsync(cancellationToken);
|
|
return new VerifyOtpTokenResponseDto() { Success = false, Message = "کد نادرست است." };
|
|
}
|
|
|
|
// موفق
|
|
otp.IsUsed = true;
|
|
|
|
// کاربر را بساز/بهروزرسانی کن
|
|
var user = await _context.Users.FirstOrDefaultAsync(u => u.Mobile == mobile, cancellationToken);
|
|
|
|
if (user is null)
|
|
{
|
|
if (request.ParentReferralCode == null)
|
|
return new VerifyOtpTokenResponseDto() { Success = false, Message = "کد معرف الزامی است." };
|
|
|
|
var parent = await _context.Users.FirstOrDefaultAsync(u => u.ReferralCode == request.ParentReferralCode,
|
|
cancellationToken: cancellationToken);
|
|
if (parent == null)
|
|
return new VerifyOtpTokenResponseDto() { Success = false, Message = "معرف وجود ندارد." };
|
|
|
|
if (await _context.Users.CountAsync(x => x.NetworkParentId == parent.Id, cancellationToken: cancellationToken) > 1)
|
|
return new VerifyOtpTokenResponseDto() { Success = false, Message = "ظرفیت معرف تکمیل است!!" };
|
|
|
|
user = new User
|
|
{
|
|
Mobile = mobile,
|
|
ReferralCode = UtilExtensions.Generate(digits: 10, firstDigitNonZero: true),
|
|
IsMobileVerified = true,
|
|
MobileVerifiedAt = now,
|
|
IsRulesAccepted = true,
|
|
RulesAcceptedAt = now,
|
|
NetworkParentId = parent.Id
|
|
};
|
|
await _context.Users.AddAsync(user, cancellationToken);
|
|
user.AddDomainEvent(new CreateNewUserEvent(user));
|
|
await _context.SaveChangesAsync(cancellationToken);
|
|
|
|
var userRole = new UserRole
|
|
{
|
|
UserId = user.Id,
|
|
RoleId = 1, //UserRoleEnum.User
|
|
};
|
|
|
|
await _context.UserRoles.AddAsync(userRole, cancellationToken);
|
|
user.AddDomainEvent(new CreateNewUserRoleEvent(userRole));
|
|
|
|
var userWallet = new UserWallet
|
|
{
|
|
UserId = user.Id,
|
|
Balance = 0,
|
|
NetworkBalance = 0
|
|
};
|
|
await _context.UserWallets.AddAsync(userWallet, cancellationToken);
|
|
user.AddDomainEvent(new CreateNewUserWalletEvent(userWallet));
|
|
await _context.SaveChangesAsync(cancellationToken);
|
|
}
|
|
else
|
|
{
|
|
user.IsMobileVerified = true;
|
|
user.MobileVerifiedAt ??= now;
|
|
|
|
_context.Users.Update(user);
|
|
user.AddDomainEvent(new UpdateUserEvent(user));
|
|
await _context.SaveChangesAsync(cancellationToken);
|
|
}
|
|
|
|
return new VerifyOtpTokenResponseDto()
|
|
{
|
|
Success = true,
|
|
Message = "اعتبارسنجی موفق.",
|
|
UserId = user.Id,
|
|
RemainingAttempts = MaxAttempts,
|
|
RemainingSeconds = (otp.ExpiresAt - now).Seconds
|
|
};
|
|
}
|
|
} |