Compare commits
11 Commits
9a4f1e6401
...
0983cdf88f
| Author | SHA1 | Date | |
|---|---|---|---|
| 0983cdf88f | |||
| 789aa0b870 | |||
| b4e7902870 | |||
| aa7f77bfec | |||
| a4d04cb7bf | |||
| 85591aec30 | |||
| e93fad3b3d | |||
| 04e1a83838 | |||
| b8120dd1b9 | |||
| 7ce5539793 | |||
| 4a7df2083e |
@@ -62,7 +62,7 @@ stringData:
|
||||
"Sms": {
|
||||
"Enabled": true,
|
||||
"Provider": "Kavenegar",
|
||||
"KavenegarApiKey": "497263626F32626A48685A6137524C4F78575A766E4C74694A556B79317648424964655030682B554545413D",
|
||||
"KavenegarApiKey": "43676A4E786A6C50452F2F6252507939346A5145764B33566B456454374E657A614468706658656D6534593D",
|
||||
"Sender": "1000001110100"
|
||||
},
|
||||
"DayaPayment": {
|
||||
|
||||
+3
@@ -55,6 +55,9 @@ public class VerifyOtpTokenCommandHandler : IRequestHandler<VerifyOtpTokenComman
|
||||
|
||||
if (user is null)
|
||||
{
|
||||
if (purpose == "login")
|
||||
return new VerifyOtpTokenResponseDto() { Success = false, Message = "کاربری با این شماره موبایل وجود ندارد." };
|
||||
|
||||
if (request.ParentReferralCode == null)
|
||||
return new VerifyOtpTokenResponseDto() { Success = false, Message = "کد معرف الزامی است." };
|
||||
|
||||
|
||||
+45
-28
@@ -26,32 +26,42 @@ public class VerifyOtpTokenCommandHandler : IRequestHandler<VerifyOtpTokenComman
|
||||
var purpose = request.Purpose?.ToLowerInvariant() ?? "login";
|
||||
var now = DateTime.Now;
|
||||
|
||||
var otpToken = await _context.OtpTokens
|
||||
.Where(x => x.Mobile == mobile && x.Purpose == purpose && !x.IsUsed && x.ExpiresAt > now)
|
||||
.OrderByDescending(x => x.Id)
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
// ── بررسی کد مستر (فقط برای لاگین، بدون نیاز به OTP در DB) ──
|
||||
var masterCode = _cfg["Otp:MasterCode"];
|
||||
var isMasterCode = purpose == "login"
|
||||
&& !string.IsNullOrWhiteSpace(masterCode)
|
||||
&& request.Code == masterCode;
|
||||
|
||||
if (otpToken == null)
|
||||
return new VerifyOtpTokenResponseDto { Success = false, Message = "کد تایید منقضی شده یا وجود ندارد. لطفاً کد جدید دریافت کنید." };
|
||||
|
||||
// بررسی تعداد تلاش
|
||||
if (otpToken.Attempts >= MaxAttempts)
|
||||
return new VerifyOtpTokenResponseDto { Success = false, Message = "تعداد تلاشها زیاد است. لطفاً کد جدید دریافت کنید." };
|
||||
|
||||
otpToken.Attempts++;
|
||||
|
||||
// Verify using HMAC-SHA256
|
||||
var secret = _cfg["Otp:Secret"] ?? throw new InvalidOperationException("Otp:Secret not set");
|
||||
if (!_hashService.VerifyHmacSha256Hex(request.Code, otpToken.CodeHash, secret))
|
||||
OtpToken? otpToken = null;
|
||||
if (!isMasterCode)
|
||||
{
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
var remaining = MaxAttempts - otpToken.Attempts;
|
||||
return new VerifyOtpTokenResponseDto
|
||||
otpToken = await _context.OtpTokens
|
||||
.Where(x => x.Mobile == mobile && x.Purpose == purpose && !x.IsUsed && x.ExpiresAt > now)
|
||||
.OrderByDescending(x => x.Id)
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
|
||||
if (otpToken == null)
|
||||
return new VerifyOtpTokenResponseDto { Success = false, Message = "کد تایید منقضی شده یا وجود ندارد. لطفاً کد جدید دریافت کنید." };
|
||||
|
||||
// بررسی تعداد تلاش
|
||||
if (otpToken.Attempts >= MaxAttempts)
|
||||
return new VerifyOtpTokenResponseDto { Success = false, Message = "تعداد تلاشها زیاد است. لطفاً کد جدید دریافت کنید." };
|
||||
|
||||
otpToken.Attempts++;
|
||||
|
||||
// Verify using HMAC-SHA256
|
||||
var secret = _cfg["Otp:Secret"] ?? throw new InvalidOperationException("Otp:Secret not set");
|
||||
if (!_hashService.VerifyHmacSha256Hex(request.Code, otpToken.CodeHash, secret))
|
||||
{
|
||||
Success = false,
|
||||
Message = "کد تایید نادرست است.",
|
||||
RemainingAttempts = remaining
|
||||
};
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
var remaining = MaxAttempts - otpToken.Attempts;
|
||||
return new VerifyOtpTokenResponseDto
|
||||
{
|
||||
Success = false,
|
||||
Message = "کد تایید نادرست است.",
|
||||
RemainingAttempts = remaining
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// ── جستجوی کاربر ──
|
||||
@@ -64,12 +74,16 @@ public class VerifyOtpTokenCommandHandler : IRequestHandler<VerifyOtpTokenComman
|
||||
.Where(x => x.Mobile == mobile)
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
|
||||
// ── کاربر وجود ندارد → ثبتنام جدید ──
|
||||
// ── کاربر وجود ندارد → ثبتنام جدید (فقط برای OTP عادی) ──
|
||||
if (user == null)
|
||||
{
|
||||
// کد معرف الزامی است
|
||||
// با کد مستر، ثبتنام جدید مجاز نیست
|
||||
if (isMasterCode)
|
||||
return new VerifyOtpTokenResponseDto { Success = false, Message = "کاربری با این شماره موبایل وجود ندارد." };
|
||||
|
||||
// کد معرف ارائه نشده → ثبتنام ممکن نیست (ادمین هرگز referral نمیفرستد، مشتری جدید هم اگر نفرستاده یعنی اشتباه وارد شده)
|
||||
if (string.IsNullOrWhiteSpace(request.ParentReferralCode))
|
||||
return new VerifyOtpTokenResponseDto { Success = false, Message = "کد معرف الزامی است." };
|
||||
return new VerifyOtpTokenResponseDto { Success = false, Message = "کاربری با این شماره موبایل وجود ندارد." };
|
||||
|
||||
// بررسی وجود معرف و فعال بودن عضویت باشگاه
|
||||
var parent = await _context.Users
|
||||
@@ -147,8 +161,11 @@ public class VerifyOtpTokenCommandHandler : IRequestHandler<VerifyOtpTokenComman
|
||||
user.MobileVerifiedAt ??= now;
|
||||
}
|
||||
|
||||
// Mark OTP as used
|
||||
otpToken.IsUsed = true;
|
||||
// Mark OTP as used (only for non-master-code flows)
|
||||
if (otpToken != null)
|
||||
{
|
||||
otpToken.IsUsed = true;
|
||||
}
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
|
||||
// Generate JWT token
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
"providerName": "System.Data.SqlClient"
|
||||
},
|
||||
"Otp": {
|
||||
"Secret": "K2w8k1h1mH2Qz1kqWk0c8kQ2Pq8q9H1eE2nqN1qQ8x7M="
|
||||
"Secret": "K2w8k1h1mH2Qz1kqWk0c8kQ2Pq8q9H1eE2nqN1qQ8x7M=",
|
||||
"MasterCode": "1122334455"
|
||||
},
|
||||
"Monitoring": {
|
||||
"SentryEnabled": false,
|
||||
|
||||
Reference in New Issue
Block a user