feat: add PaymentTransaction table for gateway-level tracking
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 9m6s

- New PaymentTransaction entity (Domain/Entities/Payment/) with all gateway fields:
  GatewayProvider, MerchantId, Authority, CardPan, CardHash, RefId, VerificationStatusCode, etc.
- New PaymentTransactionConfiguration with indexes on Authority, GatewayProvider, UserId, TransactionId, RefId
- Added DbSet<PaymentTransaction> to IApplicationDbContext and ApplicationDbContext
- Extended PaymentVerificationResult DTO with CardPan, CardHash, VerificationCode
- Updated ZarinPalPaymentService.VerifyPayment to return CardPan/CardHash/VerificationCode
- Updated all 5 payment consumers to create/update PaymentTransaction:
  * PlaceOrderCommandHandler — creates PaymentTransaction after InitiatePayment
  * PaymentCallbackController — updates PaymentTransaction after VerifyPayment
  * ChargeDiscountWalletCommandHandler — creates PaymentTransaction + fixed callback URL
  * VerifyDiscountWalletChargeCommandHandler — updates PaymentTransaction after verify
  * TransactionsService.CustomerPaymentRequest/Verification — create/update PaymentTransaction
  * PackageService.CustomerPurchasePackage/Verify — create/update PaymentTransaction
- Transaction table untouched — PaymentTransaction is a separate table
- Pattern inspired by PYMS: create row before gateway → update after verify
- EF migration: AddPaymentTransactionTable
This commit is contained in:
masoodafar-web
2026-02-15 23:53:28 +03:30
parent 207f53ef80
commit a39a36e66d
15 changed files with 5017 additions and 5 deletions
@@ -0,0 +1,73 @@
namespace CMSMicroservice.Domain.Entities.Payment;
/// <summary>
/// جدول ثبت تراکنش‌های درگاه پرداخت آنلاین
/// الگو از PYMS — همه فیلدهای gateway-level اینجا ذخیره می‌شوند
/// جدول Transaction فعلی دست‌نخورده باقی می‌ماند
/// </summary>
public class PaymentTransaction : BaseAuditableEntity
{
// ── اطلاعات درخواست (مرحله Request) ──
/// <summary>نام درگاه (zarinpal, daya, mock, ...)</summary>
public string GatewayProvider { get; set; } = string.Empty;
/// <summary>شناسه مرچنت مورد استفاده</summary>
public string MerchantId { get; set; } = string.Empty;
/// <summary>مبلغ به تومان</summary>
public long Amount { get; set; }
/// <summary>آدرس بازگشت بعد از پرداخت</summary>
public string CallbackUrl { get; set; } = string.Empty;
/// <summary>شرح تراکنش</summary>
public string Description { get; set; } = string.Empty;
/// <summary>شماره موبایل پرداخت‌کننده</summary>
public string? Mobile { get; set; }
/// <summary>شناسه کاربر</summary>
public long? UserId { get; set; }
// ── پاسخ درخواست (بعد از فراخوانی Request API) ──
/// <summary>کد وضعیت درخواست (100=موفق در زرین‌پال)</summary>
public int? RequestStatusCode { get; set; }
/// <summary>پیام درخواست</summary>
public string? RequestStatusMessage { get; set; }
/// <summary>Authority — کلید یکتای تراکنش در درگاه</summary>
public string? Authority { get; set; }
// ── وضعیت پرداخت ──
/// <summary>آیا پرداخت موفق بوده؟</summary>
public bool PaymentStatus { get; set; }
// ── نتیجه تأیید (بعد از Verify API) ──
/// <summary>کد وضعیت verify (100=موفق، 101=قبلاً تأیید شده)</summary>
public int? VerificationStatusCode { get; set; }
/// <summary>پیام verify</summary>
public string? VerificationStatusMessage { get; set; }
/// <summary>هش کارت بانکی</summary>
public string? CardHash { get; set; }
/// <summary>شماره کارت ماسک‌شده (مثلاً 6037-****-****-1234)</summary>
public string? CardPan { get; set; }
/// <summary>شماره مرجع بانکی (RefId عددی زرین‌پال — کد پیگیری)</summary>
public string? RefId { get; set; }
// ── ارتباط با سیستم داخلی ──
/// <summary>شناسه Transaction داخلی (جدول Transactions فعلی)</summary>
public long? TransactionId { get; set; }
/// <summary>شناسه سفارش (اگر مرتبط با سفارش باشد)</summary>
public string? OrderId { get; set; }
}