fix: pass amount to ZarinPal VerifyPaymentAsync — fix verify failure (amount=0 bug)
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 9m38s
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 9m38s
- PackageService.CustomerVerifyPackagePurchase: look up PaymentTransaction.Amount and pass to 3-arg overload - TransactionsService.CustomerPaymentVerification: same fix - VerifyDiscountWalletChargeCommandHandler: look up amount from PaymentTransaction - VerifyPackagePurchaseCommandHandler: fix copy-paste bug (Authority as verificationToken) + add amount - IPaymentGatewayService: throw NotImplementedException in default 3-arg impl to prevent silent amount=0 - MockPaymentGatewayService & DayaPaymentService: add 3-arg overload for compatibility Root cause: ZarinPal requires the exact amount in verify request. The 2-arg overload was sending amount=0 which caused Code=-1 (تأیید تراکنش ناموفق).
This commit is contained in:
@@ -41,8 +41,10 @@ public interface IPaymentGatewayService
|
|||||||
decimal amountInToman,
|
decimal amountInToman,
|
||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
// پیشفرض: درگاههایی که Amount نمیخواهند، از overload بدون amount استفاده کنند
|
// ⚠️ هشدار: این پیادهسازی پیشفرض مبلغ را نادیده میگیرد.
|
||||||
return VerifyPaymentAsync(refId, verificationToken, cancellationToken);
|
// درگاههایی مثل زرینپال باید حتماً این متد را override کنند.
|
||||||
|
throw new NotImplementedException(
|
||||||
|
"درگاه پرداخت باید متد VerifyPaymentAsync با مبلغ را پیادهسازی کند");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+10
-2
@@ -58,10 +58,18 @@ public class VerifyPackagePurchaseCommandHandler
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Verify با درگاه بانکی
|
// واکشی PaymentTransaction برای گرفتن مبلغ (تومان) جهت verify
|
||||||
|
var paymentTx = await _context.PaymentTransactions
|
||||||
|
.FirstOrDefaultAsync(pt => pt.Authority == request.Authority, cancellationToken);
|
||||||
|
|
||||||
|
var amountInToman = (decimal)(paymentTx?.Amount ?? order.Amount);
|
||||||
|
|
||||||
|
// 3. Verify با درگاه بانکی (مبلغ به تومان — تبدیل به ریال در ZarinPalService)
|
||||||
var verifyResult = await _paymentGateway.VerifyPaymentAsync(
|
var verifyResult = await _paymentGateway.VerifyPaymentAsync(
|
||||||
request.Authority,
|
request.Authority,
|
||||||
request.Authority // verificationToken - در بعضی درگاهها همان Authority است
|
"OK", // verificationToken — Status از درگاه
|
||||||
|
amountInToman,
|
||||||
|
cancellationToken
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!verifyResult.IsSuccess)
|
if (!verifyResult.IsSuccess)
|
||||||
|
|||||||
+11
-8
@@ -49,16 +49,19 @@ public class VerifyDiscountWalletChargeCommandHandler
|
|||||||
throw new NotFoundException(nameof(User), request.UserId);
|
throw new NotFoundException(nameof(User), request.UserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Verify با درگاه
|
// واکشی PaymentTransaction برای گرفتن مبلغ (تومان) جهت verify
|
||||||
// Authority = کد مرجع تراکنش، Status = "OK" (تأیید کاربر از درگاه)
|
|
||||||
var verifyResult = await _paymentGateway.VerifyPaymentAsync(
|
|
||||||
request.Authority,
|
|
||||||
"OK" // وقتی این handler فراخوانی میشه یعنی کاربر از درگاه برگشته — Status باید OK باشه
|
|
||||||
);
|
|
||||||
|
|
||||||
// آپدیت PaymentTransaction با نتیجه verify
|
|
||||||
var paymentTx = await _context.PaymentTransactions
|
var paymentTx = await _context.PaymentTransactions
|
||||||
.FirstOrDefaultAsync(pt => pt.Authority == request.Authority, cancellationToken);
|
.FirstOrDefaultAsync(pt => pt.Authority == request.Authority, cancellationToken);
|
||||||
|
|
||||||
|
var amountInToman = (decimal)(paymentTx?.Amount ?? 0);
|
||||||
|
|
||||||
|
// 2. Verify با درگاه (مبلغ به تومان — تبدیل به ریال در ZarinPalService)
|
||||||
|
var verifyResult = await _paymentGateway.VerifyPaymentAsync(
|
||||||
|
request.Authority,
|
||||||
|
"OK", // وقتی این handler فراخوانی میشه یعنی کاربر از درگاه برگشته — Status باید OK باشه
|
||||||
|
amountInToman,
|
||||||
|
cancellationToken
|
||||||
|
);
|
||||||
if (paymentTx != null)
|
if (paymentTx != null)
|
||||||
{
|
{
|
||||||
paymentTx.PaymentStatus = verifyResult.IsSuccess;
|
paymentTx.PaymentStatus = verifyResult.IsSuccess;
|
||||||
|
|||||||
@@ -193,6 +193,16 @@ public class DayaPaymentService : IPaymentGatewayService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task<PaymentVerificationResult> VerifyPaymentAsync(
|
||||||
|
string refId,
|
||||||
|
string verificationToken,
|
||||||
|
decimal amountInToman,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
// دایا: درگاه دایا مبلغ را در verify نیاز ندارد — از overload بدون مبلغ استفاده میشود
|
||||||
|
return VerifyPaymentAsync(refId, verificationToken, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<PayoutResult> ProcessPayoutAsync(
|
public async Task<PayoutResult> ProcessPayoutAsync(
|
||||||
PayoutRequest request,
|
PayoutRequest request,
|
||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
|
|||||||
@@ -74,6 +74,16 @@ public class MockPaymentGatewayService : IPaymentGatewayService
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task<PaymentVerificationResult> VerifyPaymentAsync(
|
||||||
|
string refId,
|
||||||
|
string verificationToken,
|
||||||
|
decimal amountInToman,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
// Mock: مبلغ تفاوتی نمیکند، از همان overload بدون مبلغ استفاده میشود
|
||||||
|
return VerifyPaymentAsync(refId, verificationToken, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<PayoutResult> ProcessPayoutAsync(
|
public async Task<PayoutResult> ProcessPayoutAsync(
|
||||||
PayoutRequest request,
|
PayoutRequest request,
|
||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
|
|||||||
@@ -274,13 +274,15 @@ public class PackageService : PackageContract.PackageContractBase
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify with payment gateway
|
// واکشی PaymentTransaction برای گرفتن مبلغ (تومان) جهت verify
|
||||||
var verifyResult = await _paymentGateway.VerifyPaymentAsync(
|
|
||||||
request.Authority, request.Status, context.CancellationToken);
|
|
||||||
|
|
||||||
// آپدیت PaymentTransaction
|
|
||||||
var paymentTx = await _context.PaymentTransactions
|
var paymentTx = await _context.PaymentTransactions
|
||||||
.FirstOrDefaultAsync(pt => pt.Authority == request.Authority, context.CancellationToken);
|
.FirstOrDefaultAsync(pt => pt.Authority == request.Authority, context.CancellationToken);
|
||||||
|
|
||||||
|
var amountInToman = paymentTx?.Amount ?? purchase.Amount;
|
||||||
|
|
||||||
|
// Verify with payment gateway (مبلغ به تومان — سرویس زرینپال خودش ×۱۰ میکنه)
|
||||||
|
var verifyResult = await _paymentGateway.VerifyPaymentAsync(
|
||||||
|
request.Authority, request.Status, (decimal)amountInToman, context.CancellationToken);
|
||||||
if (paymentTx != null)
|
if (paymentTx != null)
|
||||||
{
|
{
|
||||||
paymentTx.PaymentStatus = verifyResult.IsSuccess;
|
paymentTx.PaymentStatus = verifyResult.IsSuccess;
|
||||||
|
|||||||
@@ -235,13 +235,15 @@ public class TransactionsService : TransactionsContract.TransactionsContractBase
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify with gateway
|
// واکشی PaymentTransaction برای گرفتن مبلغ (تومان) جهت verify
|
||||||
var verifyResult = await _paymentGateway.VerifyPaymentAsync(
|
|
||||||
request.Authority, request.Status, context.CancellationToken);
|
|
||||||
|
|
||||||
// آپدیت PaymentTransaction
|
|
||||||
var paymentTx = await _context.PaymentTransactions
|
var paymentTx = await _context.PaymentTransactions
|
||||||
.FirstOrDefaultAsync(pt => pt.Authority == request.Authority, context.CancellationToken);
|
.FirstOrDefaultAsync(pt => pt.Authority == request.Authority, context.CancellationToken);
|
||||||
|
|
||||||
|
var amountInToman = paymentTx?.Amount ?? transaction.Amount;
|
||||||
|
|
||||||
|
// Verify with gateway (مبلغ به تومان — سرویس زرینپال خودش ×۱۰ میکنه)
|
||||||
|
var verifyResult = await _paymentGateway.VerifyPaymentAsync(
|
||||||
|
request.Authority, request.Status, (decimal)amountInToman, context.CancellationToken);
|
||||||
if (paymentTx != null)
|
if (paymentTx != null)
|
||||||
{
|
{
|
||||||
paymentTx.PaymentStatus = verifyResult.IsSuccess;
|
paymentTx.PaymentStatus = verifyResult.IsSuccess;
|
||||||
|
|||||||
Reference in New Issue
Block a user