fix(payment): guard against duplicate package payment verify
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 8m36s
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 8m36s
Gate payment callback with a semaphore and block double-clicks on checkout to avoid sending multiple verify requests after gateway redirect. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -173,6 +173,8 @@ public partial class Checkout
|
|||||||
|
|
||||||
private async Task ProcessPayment()
|
private async Task ProcessPayment()
|
||||||
{
|
{
|
||||||
|
if (_isProcessingPayment) return;
|
||||||
|
|
||||||
if (!CanProceedToPayment || _selectedPackage == null || _selectedAddress == null)
|
if (!CanProceedToPayment || _selectedPackage == null || _selectedAddress == null)
|
||||||
{
|
{
|
||||||
Snackbar.Add("لطفاً پکیج و آدرس را انتخاب کنید.", Severity.Warning);
|
Snackbar.Add("لطفاً پکیج و آدرس را انتخاب کنید.", Severity.Warning);
|
||||||
|
|||||||
@@ -91,6 +91,8 @@
|
|||||||
private string _message = string.Empty;
|
private string _message = string.Empty;
|
||||||
private long _transactionId;
|
private long _transactionId;
|
||||||
private long _walletBalance;
|
private long _walletBalance;
|
||||||
|
private bool _verifyCompleted;
|
||||||
|
private readonly SemaphoreSlim _verifyGate = new(1, 1);
|
||||||
|
|
||||||
// دکمههای بازگشت بسته به نوع پرداخت
|
// دکمههای بازگشت بسته به نوع پرداخت
|
||||||
private string _successReturnUrl = "/profile";
|
private string _successReturnUrl = "/profile";
|
||||||
@@ -100,9 +102,29 @@
|
|||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
{
|
{
|
||||||
if (firstRender)
|
if (firstRender && !_verifyCompleted)
|
||||||
{
|
{
|
||||||
|
await VerifyPaymentOnceAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Blazor Server may invoke render/verify twice in quick succession — gate with semaphore.
|
||||||
|
/// </summary>
|
||||||
|
private async Task VerifyPaymentOnceAsync()
|
||||||
|
{
|
||||||
|
if (_verifyCompleted) return;
|
||||||
|
|
||||||
|
await _verifyGate.WaitAsync();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_verifyCompleted) return;
|
||||||
await VerifyPayment();
|
await VerifyPayment();
|
||||||
|
_verifyCompleted = true;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_verifyGate.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user