@page "/profile/payment-callback" @attribute [Authorize] @using Blazored.LocalStorage @using CMSMicroservice.Protobuf.Protos.Package @using CMSMicroservice.Protobuf.Protos.User @using FrontOffice.Main.Utilities نتیجه پرداخت | کارا بازار سلامت @if (_isLoading) { در حال بررسی وضعیت پرداخت... } else if (_isSuccess) { پرداخت موفق @_message @if (_transactionId > 0) { کد ارجاعی: @_transactionId } موجودی کیف پول اصلی: @FormatPrice(_walletBalance) @_successReturnText } else { پرداخت ناموفق @_message @_failReturnText تلاش مجدد } @code { [Inject] private PackageContract.PackageContractClient PackageContractClient { get; set; } = default!; [Inject] private UserContract.UserContractClient UserContractClient { get; set; } = default!; [Inject] private DiscountOrderService DiscountOrderService { get; set; } = default!; [Inject] private ILocalStorageService LocalStorage { get; set; } = default!; [Inject] private AuthService AuthService { get; set; } = default!; [Inject] private NavigationManager NavManager { get; set; } = default!; private const string TokenStorageKey = "auth:token"; /// /// نوع پرداخت: package (پیش‌فرض) | magic-wallet | discount-wallet | discount-order /// [SupplyParameterFromQuery(Name = "type")] private string? PaymentType { get; set; } [SupplyParameterFromQuery(Name = "orderId")] private long OrderId { get; set; } [SupplyParameterFromQuery(Name = "transactionId")] private long TransactionId { get; set; } [SupplyParameterFromQuery(Name = "Authority")] private string? Authority { get; set; } [SupplyParameterFromQuery(Name = "Status")] private string? Status { get; set; } private bool _isLoading = true; private bool _isSuccess; private string _message = string.Empty; private long _transactionId; private long _walletBalance; private bool _verifyCompleted; private readonly SemaphoreSlim _verifyGate = new(1, 1); // دکمه‌های بازگشت بسته به نوع پرداخت private string _successReturnUrl = "/profile"; private string _successReturnText = "بازگشت به پروفایل"; private string _failReturnUrl = "/profile"; private string _failReturnText = "بازگشت به پروفایل"; protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender && !_verifyCompleted) { await VerifyPaymentOnceAsync(); } } /// /// Blazor Server may invoke render/verify twice in quick succession — gate with semaphore. /// private async Task VerifyPaymentOnceAsync() { if (_verifyCompleted) return; await _verifyGate.WaitAsync(); try { if (_verifyCompleted) return; await VerifyPayment(); _verifyCompleted = true; } finally { _verifyGate.Release(); } } private async Task VerifyPayment() { try { // تعیین نوع پرداخت — اگر type نباشد، پیش‌فرض خرید پکیج var type = PaymentType?.ToLowerInvariant() ?? "package"; switch (type) { case "magic-wallet": await VerifyMagicWalletCharge(); break; case "discount-wallet": await VerifyDiscountWalletCharge(); break; case "credit-wallet": await VerifyCreditWalletCharge(); break; case "discount-order": await VerifyDiscountOrderPayment(); break; default: // "package" or missing await VerifyPackagePurchase(); break; } } catch (Exception ex) { _isSuccess = false; _message = $"خطا در بررسی وضعیت پرداخت: {ex.Message}"; } finally { _isLoading = false; StateHasChanged(); } } /// /// تأیید خرید پکیج — رفتار فعلی /// private async Task VerifyPackagePurchase() { _successReturnUrl = "/profile"; _successReturnText = "بازگشت به پروفایل"; _failReturnUrl = "/profile"; _failReturnText = "بازگشت به پروفایل"; if (OrderId <= 0 || string.IsNullOrEmpty(Authority)) { _isSuccess = false; _message = "پارامترهای پرداخت نامعتبر است"; return; } var response = await PackageContractClient.CustomerVerifyPackagePurchaseAsync(new CustomerVerifyPackagePurchaseRequest { OrderId = OrderId, Authority = Authority ?? string.Empty, Status = Status ?? string.Empty }); _isSuccess = response.Success; _message = response.Message; _transactionId = response.TransactionId; if (_isSuccess) { await UpdateWalletBalanceAndRefreshToken(); } } /// /// تأیید شارژ کیف‌پول جادویی /// private async Task VerifyMagicWalletCharge() { _successReturnUrl = "/profile/magic-wallet"; _successReturnText = "بازگشت به کیف پول جادویی"; _failReturnUrl = "/profile/magic-wallet"; _failReturnText = "بازگشت به کیف پول جادویی"; if (string.IsNullOrEmpty(Authority)) { _isSuccess = false; _message = "کد Authority نامعتبر است"; return; } var (success, message) = await WalletService.VerifyMagicChargeAsync( Authority, Status ?? "NOK"); _isSuccess = success; _message = message; if (_isSuccess) { await UpdateWalletBalance(); } } /// /// تأیید شارژ کیف پول تخفیفی /// private async Task VerifyDiscountWalletCharge() { _successReturnUrl = "/profile/charge-discount-wallet"; _successReturnText = "بازگشت به کیف پول تخفیفی"; _failReturnUrl = "/profile/charge-discount-wallet"; _failReturnText = "بازگشت به کیف پول تخفیفی"; if (string.IsNullOrEmpty(Authority)) { _isSuccess = false; _message = "کد Authority نامعتبر است"; return; } var (success, message) = await WalletService.VerifyDiscountChargeAsync( Authority, Status ?? "NOK"); _isSuccess = success; _message = message; if (_isSuccess) { await UpdateWalletBalance(); } } /// /// تأیید شارژ کیف پول اصلی /// private async Task VerifyCreditWalletCharge() { _successReturnUrl = "/profile/charge-credit-wallet?payment=success"; _successReturnText = "بازگشت به شارژ کیف پول اصلی"; _failReturnUrl = "/profile/charge-credit-wallet?payment=failed"; _failReturnText = "بازگشت به شارژ کیف پول اصلی"; if (string.IsNullOrEmpty(Authority)) { _isSuccess = false; _message = "کد Authority نامعتبر است"; return; } var (success, message) = await WalletService.VerifyCreditChargeAsync( Authority, Status ?? "NOK"); _isSuccess = success; _message = message; if (_isSuccess) { await UpdateWalletBalance(); } } /// /// تأیید پرداخت سفارش فروشگاه تخفیفی /// private async Task VerifyDiscountOrderPayment() { _successReturnUrl = $"/discount-store/order/{OrderId}"; _successReturnText = "مشاهده سفارش"; _failReturnUrl = $"/discount-store/order/{OrderId}"; _failReturnText = "مشاهده سفارش"; if (OrderId <= 0 || string.IsNullOrEmpty(Authority)) { _isSuccess = false; _message = "پارامترهای پرداخت نامعتبر است"; return; } var (success, message, _) = await DiscountOrderService.VerifyDiscountOrderPaymentAsync( OrderId, Authority, Status ?? "NOK"); _isSuccess = success; _message = message; } /// /// بروزرسانی موجودی کیف پول /// private async Task UpdateWalletBalance() { try { var balances = await WalletService.GetBalancesAsync(); _walletBalance = balances.CreditBalance; } catch { /* اگر خطا شد، صفر نمایش بده */ } } /// /// بروزرسانی موجودی + refresh توکن (فقط برای خرید پکیج) /// private async Task UpdateWalletBalanceAndRefreshToken() { await UpdateWalletBalance(); await RefreshTokenAsync(); } private void RetryPayment() { var type = PaymentType?.ToLowerInvariant() ?? "package"; var url = type switch { "magic-wallet" => "/profile/magic-wallet", "discount-wallet" => "/profile/charge-discount-wallet", "credit-wallet" => "/profile/charge-credit-wallet", "discount-order" => "/discount-store", _ => "/profile" }; NavManager.NavigateTo(url, forceLoad: true); } /// /// Refresh token after successful payment to update PackagePurchaseMethod claim /// private async Task RefreshTokenAsync() { try { var userResponse = await UserContractClient.GetUserForCustomerAsync(new CMSMicroservice.Protobuf.Protos.User.GetUserForCustomerRequest()); if (!string.IsNullOrWhiteSpace(userResponse.Token)) { // ذخیره توکن جدید در localStorage await LocalStorage.SetItemAsync(TokenStorageKey, userResponse.Token); // به‌روزرسانی UserAuthInfo با claims جدید await AuthService.InitUserAuthInfo(); } } catch { // اگر refresh ناموفق بود، پرداخت همچنان موفق است // کاربر می‌تواند با logout/login دوباره token جدید بگیرد } } private static string FormatPrice(long price) => string.Format("{0:N0} تومان", price); }