feat: add PaymentTransaction table for gateway-level tracking
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 9m6s
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:
@@ -94,6 +94,7 @@ public class ApplicationDbContext : DbContext, IApplicationDbContext
|
||||
|
||||
// Payment
|
||||
public DbSet<ManualPayment> ManualPayments => Set<ManualPayment>();
|
||||
public DbSet<PaymentTransaction> PaymentTransactions => Set<PaymentTransaction>();
|
||||
|
||||
// Message
|
||||
public DbSet<PublicMessage> PublicMessages => Set<PublicMessage>();
|
||||
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
using CMSMicroservice.Domain.Entities.Payment;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Configurations;
|
||||
|
||||
public class PaymentTransactionConfiguration : IEntityTypeConfiguration<PaymentTransaction>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<PaymentTransaction> builder)
|
||||
{
|
||||
builder.HasQueryFilter(p => !p.IsDeleted);
|
||||
builder.Ignore(entity => entity.DomainEvents);
|
||||
builder.HasKey(entity => entity.Id);
|
||||
builder.Property(entity => entity.Id).UseIdentityColumn();
|
||||
|
||||
// اطلاعات درخواست
|
||||
builder.Property(e => e.GatewayProvider).IsRequired().HasMaxLength(50);
|
||||
builder.Property(e => e.MerchantId).IsRequired().HasMaxLength(200);
|
||||
builder.Property(e => e.Amount).IsRequired();
|
||||
builder.Property(e => e.CallbackUrl).IsRequired().HasMaxLength(500);
|
||||
builder.Property(e => e.Description).IsRequired().HasMaxLength(500);
|
||||
builder.Property(e => e.Mobile).HasMaxLength(20);
|
||||
builder.Property(e => e.UserId);
|
||||
|
||||
// پاسخ درخواست
|
||||
builder.Property(e => e.RequestStatusCode);
|
||||
builder.Property(e => e.RequestStatusMessage).HasMaxLength(500);
|
||||
builder.Property(e => e.Authority).HasMaxLength(200);
|
||||
|
||||
// وضعیت پرداخت
|
||||
builder.Property(e => e.PaymentStatus).IsRequired();
|
||||
|
||||
// نتیجه verify
|
||||
builder.Property(e => e.VerificationStatusCode);
|
||||
builder.Property(e => e.VerificationStatusMessage).HasMaxLength(500);
|
||||
builder.Property(e => e.CardHash).HasMaxLength(200);
|
||||
builder.Property(e => e.CardPan).HasMaxLength(30);
|
||||
builder.Property(e => e.RefId).HasMaxLength(200);
|
||||
|
||||
// ارتباط داخلی
|
||||
builder.Property(e => e.TransactionId);
|
||||
builder.Property(e => e.OrderId).HasMaxLength(100);
|
||||
|
||||
// ایندکسها
|
||||
builder.HasIndex(e => e.Authority);
|
||||
builder.HasIndex(e => e.GatewayProvider);
|
||||
builder.HasIndex(e => e.UserId);
|
||||
builder.HasIndex(e => e.TransactionId);
|
||||
builder.HasIndex(e => e.RefId);
|
||||
}
|
||||
}
|
||||
+4518
File diff suppressed because it is too large
Load Diff
+89
@@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddPaymentTransactionTable : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "PaymentTransactions",
|
||||
schema: "CMS",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("SqlServer:Identity", "1, 1"),
|
||||
GatewayProvider = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
|
||||
MerchantId = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
|
||||
Amount = table.Column<long>(type: "bigint", nullable: false),
|
||||
CallbackUrl = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: false),
|
||||
Description = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: false),
|
||||
Mobile = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
|
||||
UserId = table.Column<long>(type: "bigint", nullable: true),
|
||||
RequestStatusCode = table.Column<int>(type: "int", nullable: true),
|
||||
RequestStatusMessage = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true),
|
||||
Authority = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true),
|
||||
PaymentStatus = table.Column<bool>(type: "bit", nullable: false),
|
||||
VerificationStatusCode = table.Column<int>(type: "int", nullable: true),
|
||||
VerificationStatusMessage = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true),
|
||||
CardHash = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true),
|
||||
CardPan = table.Column<string>(type: "nvarchar(30)", maxLength: 30, nullable: true),
|
||||
RefId = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true),
|
||||
TransactionId = table.Column<long>(type: "bigint", nullable: true),
|
||||
OrderId = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
|
||||
Created = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||
CreatedBy = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
LastModified = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
LastModifiedBy = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
IsDeleted = table.Column<bool>(type: "bit", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_PaymentTransactions", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PaymentTransactions_Authority",
|
||||
schema: "CMS",
|
||||
table: "PaymentTransactions",
|
||||
column: "Authority");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PaymentTransactions_GatewayProvider",
|
||||
schema: "CMS",
|
||||
table: "PaymentTransactions",
|
||||
column: "GatewayProvider");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PaymentTransactions_RefId",
|
||||
schema: "CMS",
|
||||
table: "PaymentTransactions",
|
||||
column: "RefId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PaymentTransactions_TransactionId",
|
||||
schema: "CMS",
|
||||
table: "PaymentTransactions",
|
||||
column: "TransactionId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PaymentTransactions_UserId",
|
||||
schema: "CMS",
|
||||
table: "PaymentTransactions",
|
||||
column: "UserId");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "PaymentTransactions",
|
||||
schema: "CMS");
|
||||
}
|
||||
}
|
||||
}
|
||||
+108
@@ -2328,6 +2328,114 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("ManualPayments", "CMS");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.Payment.PaymentTransaction", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<long>("Amount")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("Authority")
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("nvarchar(200)");
|
||||
|
||||
b.Property<string>("CallbackUrl")
|
||||
.IsRequired()
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("nvarchar(500)");
|
||||
|
||||
b.Property<string>("CardHash")
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("nvarchar(200)");
|
||||
|
||||
b.Property<string>("CardPan")
|
||||
.HasMaxLength(30)
|
||||
.HasColumnType("nvarchar(30)");
|
||||
|
||||
b.Property<DateTime>("Created")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<string>("CreatedBy")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("nvarchar(500)");
|
||||
|
||||
b.Property<string>("GatewayProvider")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("nvarchar(50)");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<DateTime?>("LastModified")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<string>("LastModifiedBy")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("MerchantId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("nvarchar(200)");
|
||||
|
||||
b.Property<string>("Mobile")
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("nvarchar(20)");
|
||||
|
||||
b.Property<string>("OrderId")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("nvarchar(100)");
|
||||
|
||||
b.Property<bool>("PaymentStatus")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<string>("RefId")
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("nvarchar(200)");
|
||||
|
||||
b.Property<int?>("RequestStatusCode")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("RequestStatusMessage")
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("nvarchar(500)");
|
||||
|
||||
b.Property<long?>("TransactionId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<long?>("UserId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<int?>("VerificationStatusCode")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("VerificationStatusMessage")
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("nvarchar(500)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Authority");
|
||||
|
||||
b.HasIndex("GatewayProvider");
|
||||
|
||||
b.HasIndex("RefId");
|
||||
|
||||
b.HasIndex("TransactionId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("PaymentTransactions", "CMS");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.Product", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
|
||||
Reference in New Issue
Block a user