diff --git a/0_Framework/Application/PaymentGateway/AqayePardakhtPaymentGateway.cs b/0_Framework/Application/PaymentGateway/AqayePardakhtPaymentGateway.cs index b71f8681..c68790b9 100644 --- a/0_Framework/Application/PaymentGateway/AqayePardakhtPaymentGateway.cs +++ b/0_Framework/Application/PaymentGateway/AqayePardakhtPaymentGateway.cs @@ -39,7 +39,7 @@ public class AqayePardakhtPaymentGateway:IPaymentGateway amount = command.Amount, callback = command.CallBackUrl, card_number = command.CardNumber, - invoice_id = command.InvoiceId, + invoice_id = command.TransactionId, mobile = command.Mobile, email = command.Email??"", description = command.Description, @@ -73,7 +73,7 @@ public class AqayePardakhtPaymentGateway:IPaymentGateway amount = command.Amount, callback = command.CallBackUrl, card_number = command.Amount, - invoice_id = command.InvoiceId, + invoice_id = command.TransactionId, mobile = command.Mobile, email = command.Email, description = command.Email, diff --git a/0_Framework/Application/PaymentGateway/IPaymentGateway.cs b/0_Framework/Application/PaymentGateway/IPaymentGateway.cs index 3565785a..46f43528 100644 --- a/0_Framework/Application/PaymentGateway/IPaymentGateway.cs +++ b/0_Framework/Application/PaymentGateway/IPaymentGateway.cs @@ -49,12 +49,13 @@ public class WalletAmountResponse public class CreatePaymentGatewayRequest { public double Amount { get; set; } + public string TransactionId { get; set; } public string CallBackUrl { get; set; } - public string InvoiceId { get; set; } public string CardNumber { get; set; } public string Mobile { get; set; } public string Email { get; set; } public string Description { get; set; } + public long FinancialInvoiceId { get; set; } public IDictionary ExtraData { get; set; } } diff --git a/0_Framework/Application/PaymentGateway/SepehrPaymentGateway.cs b/0_Framework/Application/PaymentGateway/SepehrPaymentGateway.cs index f11d1b46..03e2f5c8 100644 --- a/0_Framework/Application/PaymentGateway/SepehrPaymentGateway.cs +++ b/0_Framework/Application/PaymentGateway/SepehrPaymentGateway.cs @@ -16,18 +16,17 @@ public class SepehrPaymentGateway:IPaymentGateway { _httpClient = httpClient.CreateClient(); _httpClient.BaseAddress = new Uri("https://sepehr.shaparak.ir/Rest/V1/PeymentApi/"); - - } public async Task Create(CreatePaymentGatewayRequest command, CancellationToken cancellationToken = default) { + command.ExtraData.Add("financialInvoiceId", command.FinancialInvoiceId); var extraData = JsonConvert.SerializeObject(command.ExtraData); var res = await _httpClient.PostAsJsonAsync("GetToken", new { TerminalID = TerminalId, Amount = command.Amount, - InvoiceID = command.InvoiceId, + InvoiceID = command.TransactionId, callbackURL = command.CallBackUrl, payload = extraData }, cancellationToken: cancellationToken); diff --git a/Company.Domain/FinancialInvoiceAgg/FinancialInvoice.cs b/Company.Domain/FinancialInvoiceAgg/FinancialInvoice.cs index 041f8339..33a33149 100644 --- a/Company.Domain/FinancialInvoiceAgg/FinancialInvoice.cs +++ b/Company.Domain/FinancialInvoiceAgg/FinancialInvoice.cs @@ -9,6 +9,7 @@ namespace Company.Domain.FinancialInvoiceAgg; public class FinancialInvoice : EntityBase { + public string InvoiceNumber { get; private set; } public string Description { get; set; } public FinancialInvoiceStatus Status { get; private set; } public DateTime? PaidAt { get; private set; } @@ -23,6 +24,7 @@ public class FinancialInvoice : EntityBase public FinancialInvoice(double amount, long contractingPartyId, string description) { + InvoiceNumber = GenerateInvoiceNumber(); Status = FinancialInvoiceStatus.Unpaid; Amount = amount; PublicId = Guid.NewGuid(); @@ -71,6 +73,18 @@ public class FinancialInvoice : EntityBase IsActive = false; } + public void SetInvoiceNumber(string invoiceNumber) + { + InvoiceNumber = invoiceNumber; + } + + private string GenerateInvoiceNumber() + { + var timestamp = DateTime.Now.ToString("yyyyMMddHHmmss"); + var random = new Random().Next(1000, 9999); + return $"GZ_{timestamp}{random}"; + } + } public class FinancialInvoiceItem : EntityBase diff --git a/Company.Domain/FinancialInvoiceAgg/IFinancialInvoiceRepository.cs b/Company.Domain/FinancialInvoiceAgg/IFinancialInvoiceRepository.cs index fa2ba326..96edcc14 100644 --- a/Company.Domain/FinancialInvoiceAgg/IFinancialInvoiceRepository.cs +++ b/Company.Domain/FinancialInvoiceAgg/IFinancialInvoiceRepository.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Threading.Tasks; using _0_Framework.Domain; using CompanyManagment.App.Contracts.FinancialInvoice; @@ -8,4 +9,5 @@ public interface IFinancialInvoiceRepository : IRepository Search(FinancialInvoiceSearchModel searchModel); + Task GetUnPaidByEntityId(long entityId, FinancialInvoiceItemType financialInvoiceItemType); } \ No newline at end of file diff --git a/CompanyManagment.App.Contracts/FinancialInvoice/EditFinancialInvoice.cs b/CompanyManagment.App.Contracts/FinancialInvoice/EditFinancialInvoice.cs index 7878523e..1975c32a 100644 --- a/CompanyManagment.App.Contracts/FinancialInvoice/EditFinancialInvoice.cs +++ b/CompanyManagment.App.Contracts/FinancialInvoice/EditFinancialInvoice.cs @@ -5,7 +5,11 @@ namespace CompanyManagment.App.Contracts.FinancialInvoice; public class EditFinancialInvoice { public long Id { get; set; } + public string InvoiceNumber { get; set; } public string Description { get; set; } + public double Amount { get; set; } + public FinancialInvoiceStatus Status { get; set; } + public List? Items { get; set; } } diff --git a/CompanyManagment.App.Contracts/FinancialInvoice/FinancialInvoiceViewModel.cs b/CompanyManagment.App.Contracts/FinancialInvoice/FinancialInvoiceViewModel.cs index 9166b8dc..8d2e3416 100644 --- a/CompanyManagment.App.Contracts/FinancialInvoice/FinancialInvoiceViewModel.cs +++ b/CompanyManagment.App.Contracts/FinancialInvoice/FinancialInvoiceViewModel.cs @@ -6,6 +6,7 @@ namespace CompanyManagment.App.Contracts.FinancialInvoice; public class FinancialInvoiceViewModel { public long Id { get; set; } + public string InvoiceNumber { get; set; } public string Description { get; set; } public string Status { get; set; } public string PaidAt { get; set; } diff --git a/CompanyManagment.App.Contracts/InstitutionContract/IInstitutionContractApplication.cs b/CompanyManagment.App.Contracts/InstitutionContract/IInstitutionContractApplication.cs index 92463672..bc697f51 100644 --- a/CompanyManagment.App.Contracts/InstitutionContract/IInstitutionContractApplication.cs +++ b/CompanyManagment.App.Contracts/InstitutionContract/IInstitutionContractApplication.cs @@ -213,7 +213,7 @@ public interface IInstitutionContractApplication Task GetVerificationDetails(Guid id); Task> SendVerifyOtp(Guid id); - Task VerifyOtp(Guid publicId, string code); + Task> VerifyOtpAndMakeGateway(Guid publicId, string code, string callbackUrl); Task GetWorkshopInitialDetails(long workshopDetailsId); #region Extension diff --git a/CompanyManagment.Application/InstitutionContractApplication.cs b/CompanyManagment.Application/InstitutionContractApplication.cs index 12ceb1ae..d0b44a81 100644 --- a/CompanyManagment.Application/InstitutionContractApplication.cs +++ b/CompanyManagment.Application/InstitutionContractApplication.cs @@ -2,10 +2,12 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Net.Http; using System.Threading; using System.Threading.Tasks; using _0_Framework.Application; using _0_Framework.Application.Enums; +using _0_Framework.Application.PaymentGateway; using _0_Framework.Application.Sms; using _0_Framework.Application.UID; using _0_Framework.Exceptions; @@ -18,6 +20,7 @@ using Company.Domain.FinancialStatmentAgg; using Company.Domain.FinancialTransactionAgg; using Company.Domain.InstitutionContractAgg; using Company.Domain.LeftWorkAgg; +using Company.Domain.PaymentTransactionAgg; using Company.Domain.RepresentativeAgg; using Company.Domain.TemporaryClientRegistrationAgg; using Company.Domain.WorkshopAgg; @@ -25,6 +28,7 @@ using CompanyManagment.App.Contracts.FinancialInvoice; using CompanyManagment.App.Contracts.FinancialStatment; using CompanyManagment.App.Contracts.InstitutionContract; using CompanyManagment.App.Contracts.InstitutionContractContactinfo; +using CompanyManagment.App.Contracts.PaymentTransaction; using CompanyManagment.App.Contracts.PersonalContractingParty; using CompanyManagment.App.Contracts.Workshop; using CompanyManagment.EFCore.Migrations; @@ -53,6 +57,8 @@ public class InstitutionContractApplication : IInstitutionContractApplication private readonly ISmsService _smsService; private readonly IUidService _uidService; private readonly IFinancialInvoiceRepository _financialInvoiceRepository; + private readonly IPaymentGateway _paymentGateway; + private readonly IPaymentTransactionRepository _paymentTransactionRepository; public InstitutionContractApplication(IInstitutionContractRepository institutionContractRepository, @@ -62,7 +68,8 @@ public class InstitutionContractApplication : IInstitutionContractApplication IFinancialStatmentApplication financialStatmentApplication, IWorkshopApplication workshopApplication, IContractingPartyTempRepository contractingPartyTempRepository, IFinancialStatmentRepository financialStatmentRepository, IContactInfoApplication contactInfoApplication, - IAccountApplication accountApplication, ISmsService smsService, IUidService uidService, IFinancialInvoiceRepository financialInvoiceRepository) + IAccountApplication accountApplication, ISmsService smsService, IUidService uidService, + IFinancialInvoiceRepository financialInvoiceRepository,IHttpClientFactory httpClientFactory, IPaymentTransactionRepository paymentTransactionRepository) { _institutionContractRepository = institutionContractRepository; _contractingPartyRepository = contractingPartyRepository; @@ -79,6 +86,8 @@ public class InstitutionContractApplication : IInstitutionContractApplication _smsService = smsService; _uidService = uidService; _financialInvoiceRepository = financialInvoiceRepository; + _paymentTransactionRepository = paymentTransactionRepository; + _paymentGateway = new SepehrPaymentGateway(httpClientFactory); } public OperationResult Create(CreateInstitutionContract command) @@ -1109,7 +1118,7 @@ public class InstitutionContractApplication : IInstitutionContractApplication invoiceAmount = command.TotalAmount; invoiceItemDescription = $"پرداخت کل قرارداد شماره {entity.ContractNo}"; invoiceItemType = FinancialInvoiceItemType.BuyInstitutionContract; - invoiceItemEntityId = 0; + invoiceItemEntityId = entity.id; } var financialInvoice = new FinancialInvoice(invoiceAmount, contractingParty.id, $"خرید قرارداد مالی شماره {entity.ContractNo}"); @@ -1257,9 +1266,9 @@ public class InstitutionContractApplication : IInstitutionContractApplication return new OperationResult().Succcedded(result); } - public async Task VerifyOtp(Guid publicId, string code) + public async Task> VerifyOtpAndMakeGateway(Guid publicId, string code,string callbackUrl) { - var op = new OperationResult(); + var op = new OperationResult(); var institutionContract = await _institutionContractRepository.GetByPublicIdAsync(publicId); if (institutionContract == null) { @@ -1280,35 +1289,67 @@ public class InstitutionContractApplication : IInstitutionContractApplication if (institutionContract.VerifyCode != code) return op.Failed("کد وارد شده صحیح نمی باشد"); - var transaction = await _institutionContractRepository.BeginTransactionAsync(); + var dbTransaction = await _institutionContractRepository.BeginTransactionAsync(); - - - institutionContract.SetPendingWorkflow(); - - var phone = institutionContract.ContactInfoList.FirstOrDefault(x => - x.SendSms && x.Position == "طرف قرارداد" && x.PhoneType == "شماره همراه"); - if (phone !=null) + long entityId = 0; + FinancialInvoiceItemType financialInvoiceItemType; + if (institutionContract.IsInstallment) { - var userPass = contractingParty.IsLegal == "حقیقی" - ? contractingParty.Nationalcode - : contractingParty.NationalId; - var createAcc = new RegisterAccount - { - Fullname = contractingParty.LName, - Username = userPass, - Password = userPass, - Mobile = phone.PhoneNumber, - NationalCode = userPass - }; - var res = _accountApplication.RegisterClient(createAcc); - if (res.IsSuccedded) - CreateContractingPartyAccount(contractingParty.id, res.SendId); + entityId = institutionContract.Installments.MinBy(x => x.InstallmentDateGr).Id; + financialInvoiceItemType = FinancialInvoiceItemType.BuyInstitutionContractInstallment; + } + else + { + entityId = institutionContract.id; + financialInvoiceItemType = FinancialInvoiceItemType.BuyInstitutionContract; } - await transaction.CommitAsync(); + var financialInvoice = _financialInvoiceRepository.GetUnPaidByEntityId(entityId, financialInvoiceItemType); + var amount = financialInvoice.Amount; + + var transaction = new PaymentTransaction(institutionContract.ContractingPartyId, amount, + institutionContract.ContractingPartyName, "https://client.gozareshgir.ir", + PaymentTransactionGateWay.SepehrPay); + await _paymentTransactionRepository.CreateAsync(transaction); + await _financialInvoiceRepository.SaveChangesAsync(); + + var createPayment = new CreatePaymentGatewayRequest() + { + Amount = amount, + TransactionId = transaction.id.ToString(), + CallBackUrl = callbackUrl, + FinancialInvoiceId = financialInvoice.id, + }; + var gatewayResponse = await _paymentGateway.Create(createPayment); + if(!gatewayResponse.IsSuccess) + return op.Failed("خطا در ایجاد درگاه پرداخت: " + gatewayResponse.Message + gatewayResponse.ErrorCode); + + + // institutionContract.SetPendingWorkflow(); + // + // var phone = institutionContract.ContactInfoList.FirstOrDefault(x => + // x.SendSms && x.Position == "طرف قرارداد" && x.PhoneType == "شماره همراه"); + // if (phone !=null) + // { + // var userPass = contractingParty.IsLegal == "حقیقی" + // ? contractingParty.Nationalcode + // : contractingParty.NationalId; + // var createAcc = new RegisterAccount + // { + // Fullname = contractingParty.LName, + // Username = userPass, + // Password = userPass, + // Mobile = phone.PhoneNumber, + // NationalCode = userPass + // }; + // var res = _accountApplication.RegisterClient(createAcc); + // if (res.IsSuccedded) + // CreateContractingPartyAccount(contractingParty.id, res.SendId); + // } + + await dbTransaction.CommitAsync(); await _institutionContractRepository.SaveChangesAsync(); - return op.Succcedded(); + return op.Succcedded(gatewayResponse.Token); } public async Task GetWorkshopInitialDetails(long workshopDetailsId) diff --git a/CompanyManagment.EFCore/Repository/FinancialInvoiceRepository.cs b/CompanyManagment.EFCore/Repository/FinancialInvoiceRepository.cs index d7cdb792..66b05f02 100644 --- a/CompanyManagment.EFCore/Repository/FinancialInvoiceRepository.cs +++ b/CompanyManagment.EFCore/Repository/FinancialInvoiceRepository.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using _0_Framework.Application; using _0_Framework.InfraStructure; using Company.Domain.FinancialInvoiceAgg; @@ -30,6 +31,9 @@ public class FinancialInvoiceRepository : RepositoryBase { Id = financialInvoice.id, Description = financialInvoice.Description, + Amount = financialInvoice.Amount, + Status = financialInvoice.Status, + InvoiceNumber = financialInvoice.InvoiceNumber, Items = financialInvoice.Items?.Select(x => new EditFinancialInvoiceItem { Id = x.id, @@ -88,4 +92,12 @@ public class FinancialInvoiceRepository : RepositoryBase ItemsCount = x.Items != null ? x.Items.Count : 0 }).ToList(); } + + public async Task GetUnPaidByEntityId(long entityId, + FinancialInvoiceItemType financialInvoiceItemType) + { + return await _context.FinancialInvoices.Include(x => x.Items) + .Where(x => x.Status == FinancialInvoiceStatus.Unpaid).FirstOrDefaultAsync(x => x.Items + .Any(y => y.Type == financialInvoiceItemType && y.EntityId == entityId)); + } } \ No newline at end of file diff --git a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs index 12ca036f..dfaa451b 100644 --- a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs +++ b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs @@ -1839,7 +1839,9 @@ public class InstitutionContractRepository : RepositoryBase GetByPublicIdAsync(Guid id) { - return await _context.InstitutionContractSet.Include(x=>x.ContactInfoList).FirstOrDefaultAsync(x => x.PublicId == id); + return await _context.InstitutionContractSet.Include(x=>x.ContactInfoList) + .Include(x=>x.Installments) + .FirstOrDefaultAsync(x => x.PublicId == id); } #region Extension diff --git a/ServiceHost/Areas/Admin/Controllers/institutionContractController.cs b/ServiceHost/Areas/Admin/Controllers/institutionContractController.cs index a1087f28..8aea60a9 100644 --- a/ServiceHost/Areas/Admin/Controllers/institutionContractController.cs +++ b/ServiceHost/Areas/Admin/Controllers/institutionContractController.cs @@ -2,6 +2,7 @@ using System.Collections.Concurrent; using System.Transactions; using _0_Framework.Application; using _0_Framework.Application.Enums; +using _0_Framework.Application.PaymentGateway; using _0_Framework.Application.Sms; using _0_Framework.Exceptions; using AccountManagement.Application.Contracts.Account; @@ -37,6 +38,8 @@ public class institutionContractController : AdminBaseController private readonly IWorkshopApplication _workshopApplication; private readonly ITemporaryClientRegistrationApplication _temporaryClientRegistration; private readonly ITemporaryClientRegistrationApplication _clientRegistrationApplication; + private readonly IPaymentGateway _paymentGateway; + private static readonly ConcurrentDictionary _locks = new ConcurrentDictionary(); @@ -45,7 +48,8 @@ public class institutionContractController : AdminBaseController public institutionContractController(IInstitutionContractApplication institutionContractApplication, IPersonalContractingPartyApp contractingPartyApplication, IContactInfoApplication contactInfoApplication, IAccountApplication accountApplication, IEmployerApplication employerApplication, - IWorkshopApplication workshopApplication, ITemporaryClientRegistrationApplication temporaryClientRegistration, ITemporaryClientRegistrationApplication clientRegistrationApplication) + IWorkshopApplication workshopApplication, ITemporaryClientRegistrationApplication temporaryClientRegistration, + ITemporaryClientRegistrationApplication clientRegistrationApplication,IHttpClientFactory httpClientFactory) { _institutionContractApplication = institutionContractApplication; _contractingPartyApplication = contractingPartyApplication; @@ -55,6 +59,7 @@ public class institutionContractController : AdminBaseController _workshopApplication = workshopApplication; _temporaryClientRegistration = temporaryClientRegistration; _clientRegistrationApplication = clientRegistrationApplication; + _paymentGateway = new SepehrPaymentGateway(httpClientFactory); } /// @@ -462,10 +467,12 @@ public class institutionContractController : AdminBaseController [HttpPost("/api/institutionContract/Verify")] [AllowAnonymous] - public async Task> Verify([FromBody] InstitutionVerificationRequest command) + public async Task Verify([FromForm] InstitutionVerificationRequest command) { - var res = await _institutionContractApplication.VerifyOtp(command.Id, command.Code); - return res; + var callBack = Url.Action("Verify", "General", null, Request.Scheme); + var res = await _institutionContractApplication.VerifyOtpAndMakeGateway(command.Id, command.Code, callBack); + var payUrl = _paymentGateway.GetStartPayUrl(res.Data); + return Redirect(payUrl); } [HttpPost("/api/institutionContract/Verification/{id:guid}/send-otp")] diff --git a/ServiceHost/Areas/AdminNew/Pages/Company/AndroidApk/Index.cshtml.cs b/ServiceHost/Areas/AdminNew/Pages/Company/AndroidApk/Index.cshtml.cs index 0bf5ac69..905cb4d8 100644 --- a/ServiceHost/Areas/AdminNew/Pages/Company/AndroidApk/Index.cshtml.cs +++ b/ServiceHost/Areas/AdminNew/Pages/Company/AndroidApk/Index.cshtml.cs @@ -95,7 +95,7 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.AndroidApk var command = new CreatePaymentGatewayRequest() { - InvoiceId = transaction.id.ToString(), + TransactionId = transaction.id.ToString(), Amount = amount, CallBackUrl = callBack }; @@ -240,7 +240,7 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.AndroidApk Amount = 1000, Email = "mahanch83@gmail.com", CallBackUrl = Url.Page("/CallBack/Index", null, null, Request.Scheme, Request.Host.Value), - InvoiceId = "{C771E841-B810-413D-9D4C-9F659575B8CC}", + TransactionId = "{C771E841-B810-413D-9D4C-9F659575B8CC}", }; var createResponse = await _paymentGateway.Create(command, cancellationToken); diff --git a/ServiceHost/Areas/Client/Controllers/FinancialController.cs b/ServiceHost/Areas/Client/Controllers/FinancialController.cs index 6b1d0f11..96b001be 100644 --- a/ServiceHost/Areas/Client/Controllers/FinancialController.cs +++ b/ServiceHost/Areas/Client/Controllers/FinancialController.cs @@ -86,7 +86,7 @@ public class FinancialController : ClientBaseController { CallBackUrl = callbackUrl, Amount = balanceAmount.Amount/10, - InvoiceId = transaction.SendId.ToString(), + TransactionId = transaction.SendId.ToString(), }; var gatewayResponse = await _paymentGateway.Create(command, cancellationToken); diff --git a/ServiceHost/Controllers/GeneralController.cs b/ServiceHost/Controllers/GeneralController.cs index 1209c2c4..01a4f376 100644 --- a/ServiceHost/Controllers/GeneralController.cs +++ b/ServiceHost/Controllers/GeneralController.cs @@ -19,23 +19,25 @@ using System.Globalization; using System.Net.Http; using System.Security.Cryptography; using System.Threading; +using CompanyManagment.App.Contracts.FinancialInvoice; namespace ServiceHost.Controllers; public class GeneralController : GeneralBaseController { - private readonly IPaymentTransactionApplication _paymentTransactionApplication; private readonly IPaymentGateway _paymentGateway; private readonly IFinancialStatmentApplication _financialStatmentApplication; - private readonly IOnlinePayment _onlinePayment; + private readonly IFinancialInvoiceApplication _financialInvoiceApplication; - public GeneralController(IPaymentTransactionApplication paymentTransactionApplication,IHttpClientFactory clientFactory, IFinancialStatmentApplication financialStatmentApplication, IOptions appSetting, IOnlinePayment onlinePayment) + public GeneralController(IPaymentTransactionApplication paymentTransactionApplication, + IHttpClientFactory clientFactory, IFinancialStatmentApplication financialStatmentApplication, + IFinancialInvoiceApplication financialInvoiceApplication) { _paymentTransactionApplication = paymentTransactionApplication; _paymentGateway = new SepehrPaymentGateway(clientFactory); _financialStatmentApplication = financialStatmentApplication; - _onlinePayment = onlinePayment; + _financialInvoiceApplication = financialInvoiceApplication; } /// @@ -63,101 +65,122 @@ public class GeneralController : GeneralBaseController [HttpGet("/api/callback"), HttpPost("/api/callback")] public async Task Verify(SepehrGatewayPayResponse payResponse) { - if (!long.TryParse(payResponse.invoiceid, out var paymentTransactionId)) - { - return BadRequest("Invalid invoice_id"); - } + if (!long.TryParse(payResponse.invoiceid, out var paymentTransactionId)) + { + return BadRequest("Invalid invoice_id"); + } - var transaction = await _paymentTransactionApplication.GetDetails(paymentTransactionId); + var transaction = await _paymentTransactionApplication.GetDetails(paymentTransactionId); - if (transaction == null) - { - return NotFound("Transaction not found"); - } + 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 (transaction.Status != PaymentTransactionStatus.Pending) + { + return BadRequest("این تراکنش قبلا پرداخت شده است"); + } - - 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); - } + if (payResponse.respcode != 0) + { + return await HandleFailedTransaction(transaction); + } - 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 extraData = JsonConvert.DeserializeObject>(payResponse.payload); + extraData.TryGetValue("financialInvoiceId", out var financialInvoiceIdObj); + if (financialInvoiceIdObj == null || + !long.TryParse(financialInvoiceIdObj.ToString(), out var financialInvoiceId)) + { + return BadRequest("فاکتور مالی نامعتبر است"); + } - //var data = JsonConvert.SerializeObject(invoice.AdditionalData); - //var statics = - //JsonConvert.SerializeObject(res); + var financialInvoice = _financialInvoiceApplication.GetDetails(financialInvoiceId); + + if (financialInvoice == null) + { + return BadRequest("فاکتور مالی نامعتبر است"); + } + if (financialInvoice.Status != FinancialInvoiceStatus.Unpaid) + { + return BadRequest("فاکتور مالی نامعتبر است"); + } + if (financialInvoice.Amount != transaction.Amount) + { + 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); + _financialInvoiceApplication.SetPaid(financialInvoiceId, DateTime.Now); + + if (verifyRes.IsSuccess) + { + var command = new CreateFinancialStatment() + { + ContractingPartyId = transaction.ContractingPartyId, + Deptor = 0, + Creditor = transaction.Amount, + DeptorString = "0", + TypeOfTransaction = "credit", + DescriptionOption = financialInvoice.Description +"شماره فاکتور"+financialInvoice.InvoiceNumber, + Description = "درگاه بانکی", + }; + var statementResult = _financialStatmentApplication.CreateFromBankGateway(command); + if (!statementResult.IsSuccedded) + { + return new JsonResult(statementResult); + } - //await _onlinePayment.CancelAsync(invoice); - //return new JsonResult(new - //{ - // data, - // statics - //}); + var setSuccessResult = _paymentTransactionApplication.SetSuccess(paymentTransactionId, + payResponse.cardnumber, payResponse.issuerbank, payResponse.rrn.ToString(), + payResponse.digitalreceipt); - //// 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; + if (!setSuccessResult.IsSuccedded) + { + return await HandleFailedTransaction(transaction); + } - // return Content("The payment was not successful."); - //} + return Redirect(BuildCallbackUrl(transaction.CallBackUrl, true, transaction.Id)); + } - //// Note: Save the verifyResult.TransactionCode in your database. + // در غیر این صورت تراکنش ناموفق است + 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 + //}); - [HttpPost("/api/callback3232")] - public async Task OnGetCallBack(string? transid, string? cardnumber, string? tracking_number, - string bank, string invoice_id, string? status,CancellationToken cancellationToken) + //// 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 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)) { @@ -183,10 +206,10 @@ public class GeneralController : GeneralBaseController var verifyCommand = new VerifyPaymentGateWayRequest() { - Amount = transaction.Amount/10, + Amount = transaction.Amount / 10, TransactionId = transid }; - var verifyRes =await _paymentGateway.Verify(verifyCommand, cancellationToken); + var verifyRes = await _paymentGateway.Verify(verifyCommand, cancellationToken); // اگر استاتوس 1 باشد، تراکنش موفق است if (verifyRes.IsSuccess) @@ -200,7 +223,6 @@ public class GeneralController : GeneralBaseController TypeOfTransaction = "credit", DescriptionOption = "بابت قرارداد مابین (روابط کار)", Description = "درگاه بانکی", - }; var statementResult = _financialStatmentApplication.CreateFromBankGateway(command); if (!statementResult.IsSuccedded) @@ -208,12 +230,14 @@ public class GeneralController : GeneralBaseController return await HandleFailedTransaction(transaction); } - var setSuccessResult = _paymentTransactionApplication.SetSuccess(paymentTransactionId, cardnumber, bank,null,null); + var setSuccessResult = + _paymentTransactionApplication.SetSuccess(paymentTransactionId, cardnumber, bank, null, null); if (!setSuccessResult.IsSuccedded) { return new JsonResult(setSuccessResult); } + return Redirect(BuildCallbackUrl(transaction.CallBackUrl, true, transaction.Id)); } @@ -237,83 +261,83 @@ public class GeneralController : GeneralBaseController var statusCode = isSuccess ? "1" : "0"; return $"{baseUrl}/callback?Status={statusCode}&transactionId={transactionId}"; } - - } public class TokenReq { - - public long Amount { get; set; } + 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 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; } + // 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; } - + [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; } + /* 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; } + [Display(Name = " رسید دیجیتال ")] public string digitalreceipt { get; set; } + public long Tid { get; set; } } \ No newline at end of file