Introduced the SepehrPaymentGateway to replace the previous payment gateway, AqayePardakht. Added `Rrn` and `DigitalReceipt` columns to the `PaymentTransactions` table for improved payment tracking and verification. Updated the Entity Framework model and mappings to reflect these changes. Refactored payment transaction logic to support the new gateway, including creating, verifying, and handling payments. Added new request/response models for Sepehr gateway integration. Enhanced error handling and financial statement creation upon successful payment verification. Removed legacy code and updated dependency injection for the Parbad library.
319 lines
10 KiB
C#
319 lines
10 KiB
C#
using _0_Framework.Application;
|
||
using _0_Framework.Application.PaymentGateway;
|
||
using Company.Domain.BankAgg;
|
||
using Company.Domain.PaymentTransactionAgg;
|
||
using CompanyManagment.App.Contracts.FinancialStatment;
|
||
using CompanyManagment.App.Contracts.FinancilTransaction;
|
||
using CompanyManagment.App.Contracts.PaymentTransaction;
|
||
using CompanyManagment.App.Contracts.Workshop;
|
||
using CompanyManagment.EFCore.Migrations;
|
||
using Microsoft.AspNetCore.Authorization;
|
||
using Microsoft.AspNetCore.Mvc;
|
||
using Microsoft.Extensions.Options;
|
||
using Newtonsoft.Json;
|
||
using NuGet.Protocol;
|
||
using Parbad;
|
||
using ServiceHost.BaseControllers;
|
||
using System.ComponentModel.DataAnnotations;
|
||
using System.Globalization;
|
||
using System.Net.Http;
|
||
using System.Security.Cryptography;
|
||
using System.Threading;
|
||
|
||
namespace ServiceHost.Controllers;
|
||
|
||
public class GeneralController : GeneralBaseController
|
||
{
|
||
|
||
private readonly IPaymentTransactionApplication _paymentTransactionApplication;
|
||
private readonly IPaymentGateway _paymentGateway;
|
||
private readonly IFinancialStatmentApplication _financialStatmentApplication;
|
||
private readonly IOnlinePayment _onlinePayment;
|
||
|
||
public GeneralController(IPaymentTransactionApplication paymentTransactionApplication,IHttpClientFactory clientFactory, IFinancialStatmentApplication financialStatmentApplication, IOptions<AppSettingConfiguration> appSetting, IOnlinePayment onlinePayment)
|
||
{
|
||
_paymentTransactionApplication = paymentTransactionApplication;
|
||
_paymentGateway = new SepehrPaymentGateway(clientFactory);
|
||
_financialStatmentApplication = financialStatmentApplication;
|
||
_onlinePayment = onlinePayment;
|
||
}
|
||
|
||
/// <summary>
|
||
/// نمایش اطلاعات عمومی مانند تاریخ ها و سال ها
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[HttpGet("Dates")]
|
||
public IActionResult GetDates()
|
||
{
|
||
var pc = new PersianCalendar();
|
||
var now = DateTime.Now;
|
||
var currentYear = pc.GetYear(now);
|
||
var years = Enumerable.Range(1370, currentYear - 1370 + 1).ToList();
|
||
var months = Enumerable.Range(1, 12).ToList();
|
||
var currentDate = new { Year = currentYear, Month = pc.GetMonth(now), Day = pc.GetDayOfMonth(now) };
|
||
return new JsonResult(new
|
||
{
|
||
years,
|
||
months,
|
||
currentDate
|
||
});
|
||
}
|
||
|
||
|
||
[HttpGet("/api/callback"), HttpPost("/api/callback")]
|
||
public async Task<IActionResult> Verify(SepehrGatewayPayResponse payResponse)
|
||
{
|
||
if (!long.TryParse(payResponse.invoiceid, out var paymentTransactionId))
|
||
{
|
||
return BadRequest("Invalid invoice_id");
|
||
}
|
||
|
||
var transaction = await _paymentTransactionApplication.GetDetails(paymentTransactionId);
|
||
|
||
if (transaction == null)
|
||
{
|
||
return NotFound("Transaction not found");
|
||
}
|
||
|
||
if (transaction.Status != PaymentTransactionStatus.Pending)
|
||
{
|
||
return BadRequest("این تراکنش قبلا پرداخت شده است");
|
||
}
|
||
|
||
|
||
if (payResponse.respcode != 0)
|
||
{
|
||
return await HandleFailedTransaction(transaction);
|
||
}
|
||
|
||
var verifyCommand = new VerifyPaymentGateWayRequest()
|
||
{
|
||
Amount = transaction.Amount,
|
||
TransactionId = payResponse.invoiceid,
|
||
DigitalReceipt = payResponse.digitalreceipt
|
||
};
|
||
var verifyRes = await _paymentGateway.Verify(verifyCommand, CancellationToken.None);
|
||
|
||
|
||
|
||
|
||
if (verifyRes.IsSuccess)
|
||
{
|
||
var command = new CreateFinancialStatment()
|
||
{
|
||
ContractingPartyId = transaction.ContractingPartyId,
|
||
Deptor = 0,
|
||
Creditor = transaction.Amount,
|
||
DeptorString = "0",
|
||
TypeOfTransaction = "credit",
|
||
DescriptionOption = "بابت قرارداد مابین (روابط کار)",
|
||
Description = "درگاه بانکی",
|
||
|
||
};
|
||
var statementResult = _financialStatmentApplication.CreateFromBankGateway(command);
|
||
if (!statementResult.IsSuccedded)
|
||
{
|
||
return new JsonResult(statementResult);
|
||
}
|
||
|
||
var setSuccessResult = _paymentTransactionApplication.SetSuccess(paymentTransactionId, payResponse.cardnumber, payResponse.issuerbank, payResponse.rrn.ToString(), payResponse.digitalreceipt);
|
||
|
||
if (!setSuccessResult.IsSuccedded)
|
||
{
|
||
return await HandleFailedTransaction(transaction);
|
||
}
|
||
return Redirect(BuildCallbackUrl(transaction.CallBackUrl, true, transaction.Id));
|
||
}
|
||
|
||
// در غیر این صورت تراکنش ناموفق است
|
||
return await HandleFailedTransaction(transaction);
|
||
|
||
|
||
//var data = JsonConvert.SerializeObject(invoice.AdditionalData);
|
||
//var statics =
|
||
//JsonConvert.SerializeObject(res);
|
||
|
||
//await _onlinePayment.CancelAsync(invoice);
|
||
//return new JsonResult(new
|
||
//{
|
||
// data,
|
||
// statics
|
||
//});
|
||
|
||
//// Check if the invoice is new, or it's already processed before.
|
||
//if (invoice.Status != PaymentFetchResultStatus.ReadyForVerifying)
|
||
//{
|
||
// // You can also see if the invoice is already verified before.
|
||
// var isAlreadyVerified = invoice.IsAlreadyVerified;
|
||
|
||
// return Content("The payment was not successful.");
|
||
//}
|
||
|
||
//// Note: Save the verifyResult.TransactionCode in your database.
|
||
|
||
|
||
|
||
}
|
||
|
||
[HttpPost("/api/callback3232")]
|
||
public async Task<IActionResult> OnGetCallBack(string? transid, string? cardnumber, string? tracking_number,
|
||
string bank, string invoice_id, string? status,CancellationToken cancellationToken)
|
||
{
|
||
if (!long.TryParse(invoice_id, out var paymentTransactionId))
|
||
{
|
||
return BadRequest("Invalid invoice_id");
|
||
}
|
||
|
||
var transaction = await _paymentTransactionApplication.GetDetails(paymentTransactionId);
|
||
if (transaction == null)
|
||
{
|
||
return NotFound("Transaction not found");
|
||
}
|
||
|
||
if (transaction.Status != PaymentTransactionStatus.Pending)
|
||
{
|
||
return BadRequest("این تراکنش قبلا پرداخت شده است");
|
||
}
|
||
|
||
// اگر شماره کارت یا شماره پیگیری خالی باشد، تراکنش ناموفق است
|
||
if (string.IsNullOrWhiteSpace(cardnumber) || string.IsNullOrWhiteSpace(tracking_number))
|
||
{
|
||
return await HandleFailedTransaction(transaction);
|
||
}
|
||
|
||
var verifyCommand = new VerifyPaymentGateWayRequest()
|
||
{
|
||
Amount = transaction.Amount/10,
|
||
TransactionId = transid
|
||
};
|
||
var verifyRes =await _paymentGateway.Verify(verifyCommand, cancellationToken);
|
||
|
||
// اگر استاتوس 1 باشد، تراکنش موفق است
|
||
if (verifyRes.IsSuccess)
|
||
{
|
||
var command = new CreateFinancialStatment()
|
||
{
|
||
ContractingPartyId = transaction.ContractingPartyId,
|
||
Deptor = 0,
|
||
Creditor = transaction.Amount,
|
||
DeptorString = "0",
|
||
TypeOfTransaction = "credit",
|
||
DescriptionOption = "بابت قرارداد مابین (روابط کار)",
|
||
Description = "درگاه بانکی",
|
||
|
||
};
|
||
var statementResult = _financialStatmentApplication.CreateFromBankGateway(command);
|
||
if (!statementResult.IsSuccedded)
|
||
{
|
||
return await HandleFailedTransaction(transaction);
|
||
}
|
||
|
||
var setSuccessResult = _paymentTransactionApplication.SetSuccess(paymentTransactionId, cardnumber, bank,null,null);
|
||
|
||
if (!setSuccessResult.IsSuccedded)
|
||
{
|
||
return new JsonResult(setSuccessResult);
|
||
}
|
||
return Redirect(BuildCallbackUrl(transaction.CallBackUrl, true, transaction.Id));
|
||
}
|
||
|
||
// در غیر این صورت تراکنش ناموفق است
|
||
return await HandleFailedTransaction(transaction);
|
||
}
|
||
|
||
private async Task<IActionResult> HandleFailedTransaction(PaymentTransactionDetailsViewModel transaction)
|
||
{
|
||
var result = _paymentTransactionApplication.SetFailed(transaction.Id);
|
||
if (!result.IsSuccedded)
|
||
{
|
||
return new JsonResult(result);
|
||
}
|
||
|
||
return Redirect(BuildCallbackUrl(transaction.CallBackUrl, false, transaction.Id));
|
||
}
|
||
|
||
private string BuildCallbackUrl(string baseUrl, bool isSuccess, long transactionId)
|
||
{
|
||
var statusCode = isSuccess ? "1" : "0";
|
||
return $"{baseUrl}/callback?Status={statusCode}&transactionId={transactionId}";
|
||
}
|
||
|
||
|
||
}
|
||
|
||
public class TokenReq
|
||
{
|
||
|
||
public long Amount { get; set; }
|
||
|
||
public string CallbackUrl { get; set; }
|
||
[Display(Name = "شماره فاکتور")]
|
||
[MaxLength(100)]
|
||
[Required]
|
||
[Key]
|
||
// be ezaye har pazirande bayad yekta bashad
|
||
public string invoiceID { get; set; }
|
||
[Required]
|
||
public long terminalID { get; set; }
|
||
/*
|
||
* JSON Bashad
|
||
* etelaate takmili site harchi
|
||
* nabayad char khas dashte bashe (*'"xp_%!+- ...)
|
||
*/
|
||
public string Payload { get; set; } = "";
|
||
public string email { get; set; }
|
||
}
|
||
public class TokenResp
|
||
{
|
||
// if 0 = success
|
||
public int Status { get; set; }
|
||
public string AccessToken { get; set; }
|
||
}
|
||
public class PayRequest
|
||
{
|
||
[Required]
|
||
[MaxLength(3000)]
|
||
public string token { get; set; }
|
||
[Required]
|
||
public long terminalID { get; set; }
|
||
public string nationalCode { get; set; }
|
||
|
||
}
|
||
public class SepehrGatewayPayResponse
|
||
{
|
||
/* 0 yni movafaq
|
||
* -1 yni enseraf
|
||
* -2 yni etmam zaman
|
||
*/
|
||
public int respcode { get; set; }
|
||
[Display(Name = "متن نتیجه تراکنش")]
|
||
public string respmsg { get; set; }
|
||
[Display(Name = "مبلغ کسر شده از مشتری")]
|
||
public long amount { get; set; }
|
||
[Display(Name = " شماره فاکتور ")]
|
||
public string invoiceid { get; set; }
|
||
[Display(Name = " اطلاعاتی که پذیرنده ارسال کرد ")]
|
||
public string payload { get; set; }
|
||
[Display(Name = " شماره ترمینال ")]
|
||
public long terminalid { get; set; }
|
||
[Display(Name = " شماره پیگیری ")]
|
||
public long tracenumber { get; set; }
|
||
// bayad negah dari she hatman to db
|
||
[Display(Name = " شماره سند بانکی ")]
|
||
public long rrn { get; set; }
|
||
[Display(Name = " زمان و تاریخ پرداخت ")]
|
||
public string datepaid { get; set; }
|
||
[Display(Name = " رسید دیجیتال ")]
|
||
public string digitalreceipt { get; set; }
|
||
[Display(Name = " نام بانک صادر کننده کارت ")]
|
||
public string issuerbank { get; set; }
|
||
[Display(Name = " شماره کارت ")]
|
||
public string cardnumber { get; set; }
|
||
}
|
||
|
||
public class AdviceReq
|
||
{
|
||
[Display(Name = " رسید دیجیتال ")]
|
||
public string digitalreceipt { get; set; }
|
||
public long Tid { get; set; }
|
||
} |