diff --git a/src/FrontOffice.Main/Pages/Checkout.razor.cs b/src/FrontOffice.Main/Pages/Checkout.razor.cs index 253feef..24e2a78 100644 --- a/src/FrontOffice.Main/Pages/Checkout.razor.cs +++ b/src/FrontOffice.Main/Pages/Checkout.razor.cs @@ -173,6 +173,8 @@ public partial class Checkout private async Task ProcessPayment() { + if (_isProcessingPayment) return; + if (!CanProceedToPayment || _selectedPackage == null || _selectedAddress == null) { Snackbar.Add("لطفاً پکیج و آدرس را انتخاب کنید.", Severity.Warning); diff --git a/src/FrontOffice.Main/Pages/Profile/PaymentCallback.razor b/src/FrontOffice.Main/Pages/Profile/PaymentCallback.razor index d26bd56..25cf450 100644 --- a/src/FrontOffice.Main/Pages/Profile/PaymentCallback.razor +++ b/src/FrontOffice.Main/Pages/Profile/PaymentCallback.razor @@ -91,6 +91,8 @@ 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"; @@ -100,9 +102,29 @@ protected override async Task OnAfterRenderAsync(bool firstRender) { - if (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(); } }