From 491b8a0d0f5acd5bb5d70cf0a6482ef0fdcc7d08 Mon Sep 17 00:00:00 2001 From: masoodafar-web Date: Tue, 24 Feb 2026 00:49:16 +0330 Subject: [PATCH] =?UTF-8?q?fix:=20remove=20double=20=C3=9710=20Rial=20conv?= =?UTF-8?q?ersion=20in=20ZarinPalPaymentService?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause: FrontOffice already converts Toman→Rial (×10) before sending to CMS. ZarinPalPaymentService was multiplying by 10 AGAIN, causing amounts to be 10x too large. Example: user enters 500K Toman → FO sends 5M Rial → CMS did ×10 → 50M Rial sent to ZarinPal → showed 5M Toman instead of 500K. Changes: - ZarinPalPaymentService.InitiatePaymentAsync: remove ×10 (amount already Rial) - ZarinPalPaymentService.VerifyPaymentWithAmountAsync: remove ×10 + accept Rial - ZarinPalPaymentService.VerifyResult.Amount: return Rial (no /10 conversion) - VerifyMagicWalletChargeCommandHandler: remove /10 before calling Verify - PaymentCallbackController: update comments (amount is Rial) - Also includes: improved HTTP error logging for non-200 responses - Also includes: production URL fix (kbs1→kbs2) --- .../VerifyMagicWalletChargeCommandHandler.cs | 5 +-- .../Payment/ZarinPalPaymentService.cs | 41 ++++++++++++------- .../Controllers/PaymentCallbackController.cs | 4 +- 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/CMSMicroservice.Application/WalletCQ/Commands/VerifyMagicWalletCharge/VerifyMagicWalletChargeCommandHandler.cs b/src/CMSMicroservice.Application/WalletCQ/Commands/VerifyMagicWalletCharge/VerifyMagicWalletChargeCommandHandler.cs index 855c657..9bf541c 100644 --- a/src/CMSMicroservice.Application/WalletCQ/Commands/VerifyMagicWalletCharge/VerifyMagicWalletChargeCommandHandler.cs +++ b/src/CMSMicroservice.Application/WalletCQ/Commands/VerifyMagicWalletCharge/VerifyMagicWalletChargeCommandHandler.cs @@ -74,12 +74,11 @@ public class VerifyMagicWalletChargeCommandHandler throw new BadRequestException("پرداخت توسط کاربر لغو شد"); } - // 3. Verify با درگاه (زرین‌پال نیاز به مبلغ دارد) - var amountInToman = depositAmount / 10m; + // 3. Verify با درگاه (مبلغ به ریال) var verifyResult = await _paymentGateway.VerifyPaymentAsync( request.Authority, request.Status, - amountInToman, + depositAmount, cancellationToken ); diff --git a/src/CMSMicroservice.Infrastructure/Services/Payment/ZarinPalPaymentService.cs b/src/CMSMicroservice.Infrastructure/Services/Payment/ZarinPalPaymentService.cs index 46dab44..9b790ee 100644 --- a/src/CMSMicroservice.Infrastructure/Services/Payment/ZarinPalPaymentService.cs +++ b/src/CMSMicroservice.Infrastructure/Services/Payment/ZarinPalPaymentService.cs @@ -66,8 +66,8 @@ public class ZarinPalPaymentService : IPaymentGatewayService { try { - // زرین‌پال مبلغ را به ریال می‌خواهد — تبدیل تومان به ریال - var amountInRials = (long)(request.Amount * 10); + // مبلغ از caller به ریال می‌رسد — مستقیم ارسال به زرین‌پال + var amountInRials = (long)request.Amount; var zarinPalRequest = new ZarinPalPaymentRequest { @@ -85,12 +85,26 @@ public class ZarinPalPaymentService : IPaymentGatewayService var content = new StringContent(jsonContent, Encoding.UTF8, "application/json"); _logger.LogInformation( - "ZarinPal payment request: Amount={AmountToman} Toman ({AmountRial} Rial), User={UserId}, Sandbox={Sandbox}", - request.Amount, amountInRials, request.UserId, _useSandbox); + "ZarinPal payment request: Amount={AmountRial} Rial ({AmountToman} Toman), User={UserId}, Sandbox={Sandbox}", + amountInRials, amountInRials / 10m, request.UserId, _useSandbox); var response = await _httpClient.PostAsync(RequestEndpoint, content, cancellationToken); var responseBody = await response.Content.ReadAsStringAsync(cancellationToken); + // لاگ HTTP status — مهم برای دیباگ + if (!response.IsSuccessStatusCode) + { + _logger.LogError( + "ZarinPal HTTP error: StatusCode={StatusCode}, Body={Body}", + (int)response.StatusCode, responseBody); + + return new PaymentInitiateResult + { + IsSuccess = false, + ErrorMessage = $"خطای ارتباط با زرین‌پال (HTTP {(int)response.StatusCode}). لطفاً MerchantId و IP سرور در پنل زرین‌پال بررسی شود." + }; + } + _logger.LogDebug("ZarinPal request response: {StatusCode} - {Body}", response.StatusCode, responseBody); @@ -153,21 +167,21 @@ public class ZarinPalPaymentService : IPaymentGatewayService /// /// تأیید پرداخت با مبلغ — نسخه اصلی برای زرین‌پال - /// refId = Authority، verificationToken = Status (OK/NOK)، amountInToman = مبلغ به تومان + /// refId = Authority، verificationToken = Status (OK/NOK)، amount = مبلغ به ریال /// public Task VerifyPaymentAsync( string refId, string verificationToken, - decimal amountInToman, + decimal amount, CancellationToken cancellationToken = default) { - return VerifyPaymentWithAmountAsync(refId, verificationToken, amountInToman, cancellationToken); + return VerifyPaymentWithAmountAsync(refId, verificationToken, amount, cancellationToken); } private async Task VerifyPaymentWithAmountAsync( string refId, string verificationToken, - decimal amountInToman, + decimal amountInRials, CancellationToken cancellationToken) { try @@ -184,21 +198,18 @@ public class ZarinPalPaymentService : IPaymentGatewayService }; } - // تبدیل تومان → ریال (×۱۰) - var amountInRials = (long)(amountInToman * 10); - var verifyRequest = new ZarinPalVerifyRequest { MerchantId = _merchantId, Authority = refId, - Amount = amountInRials + Amount = (long)amountInRials }; var jsonContent = JsonSerializer.Serialize(verifyRequest, JsonOptions); var content = new StringContent(jsonContent, Encoding.UTF8, "application/json"); - _logger.LogInformation("ZarinPal verify request: Authority={Authority}, Amount={Amount} Rial", - refId, amountInRials); + _logger.LogInformation("ZarinPal verify request: Authority={Authority}, Amount={Amount} Rial ({AmountToman} Toman)", + refId, (long)amountInRials, amountInRials / 10m); var response = await _httpClient.PostAsync(VerifyEndpoint, content, cancellationToken); var responseBody = await response.Content.ReadAsStringAsync(cancellationToken); @@ -220,7 +231,7 @@ public class ZarinPalPaymentService : IPaymentGatewayService IsSuccess = true, RefId = refId, TrackingCode = result.Data.RefId?.ToString(), - Amount = (result.Data.Amount ?? 0) / 10m, // ریال → تومان + Amount = result.Data.Amount ?? 0, // ریال — بدون تبدیل CardPan = result.Data.CardPan, CardHash = result.Data.CardHash, VerificationCode = result.Data.Code, diff --git a/src/CMSMicroservice.WebApi/Controllers/PaymentCallbackController.cs b/src/CMSMicroservice.WebApi/Controllers/PaymentCallbackController.cs index 404ce91..d553488 100644 --- a/src/CMSMicroservice.WebApi/Controllers/PaymentCallbackController.cs +++ b/src/CMSMicroservice.WebApi/Controllers/PaymentCallbackController.cs @@ -82,11 +82,11 @@ public class PaymentCallbackController : ControllerBase if (string.Equals(status, "OK", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(authority)) { - // Verify با مبلغ از دیتابیس (تومان) + // Verify با مبلغ از دیتابیس (ریال) var verifyResult = await _paymentGateway.VerifyPaymentAsync( authority, status!, - order.GatewayAmountPaid, // مبلغ به تومان + order.GatewayAmountPaid, // مبلغ به ریال cancellationToken); paymentSuccess = verifyResult.IsSuccess;