URL generation for ticket payment and processing of its response
This commit is contained in:
parent
d6eded539d
commit
261b928533
@ -1,27 +1,37 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Server.Models;
|
||||||
using Server.Services;
|
using Server.Services;
|
||||||
using SharedModels.DataTransferObjects;
|
using SharedModels.Responses;
|
||||||
|
|
||||||
|
namespace Server.Controllers;
|
||||||
|
|
||||||
[Route("api/payment")]
|
[Route("api/payment")]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
public class PaymentController : ControllerBase
|
public class PaymentController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly IPaymentsService _paymentsService;
|
readonly IPaymentsService _paymentsService;
|
||||||
|
|
||||||
public PaymentController(IPaymentsService paymentsService)
|
public PaymentController(IPaymentsService paymentsService)
|
||||||
{
|
{
|
||||||
_paymentsService = paymentsService;
|
_paymentsService = paymentsService;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpPost("link")]
|
||||||
public async Task<IActionResult> GetPaymentLink([FromQuery] PaymentDto payment)
|
public async Task<IActionResult?> GetPaymentLink([FromBody] IList<StrippedFlattenedEnrollment> input)
|
||||||
{
|
{
|
||||||
var result = await _paymentsService.GetPaymentUrl(payment);
|
var result = await _paymentsService.GetPaymentUrl(input);
|
||||||
|
|
||||||
if (!result.isSucceed)
|
|
||||||
{
|
|
||||||
return result.actionResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(result.url);
|
return Ok(result.url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost("callback")]
|
||||||
|
public async Task<IActionResult> ReceiveCallback()
|
||||||
|
{
|
||||||
|
if (HttpContext.Request.ContentType != "application/x-www-form-urlencoded")
|
||||||
|
return BadRequest();
|
||||||
|
|
||||||
|
var result = await _paymentsService.ReceiveCallback(HttpContext.Request.Form);
|
||||||
|
|
||||||
|
return result.actionResult;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ public class TicketGroup
|
|||||||
[Key]
|
[Key]
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
|
||||||
public DateTime PurchaseDateTimeUtc { get; set; } = DateTime.UtcNow;
|
public DateTime PurchaseDateTimeUtc { get; set; } = DateTime.MinValue;
|
||||||
public bool IsReturned { get; set; } = false;
|
public bool IsReturned { get; set; } = false;
|
||||||
|
|
||||||
public string UserId { get; set; } = null!;
|
public string UserId { get; set; } = null!;
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
using LiqPayIntegration;
|
using LiqPayIntegration;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using SharedModels.DataTransferObjects;
|
using SharedModels.Responses;
|
||||||
using System.Dynamic;
|
|
||||||
|
|
||||||
namespace Server.Services;
|
namespace Server.Services;
|
||||||
|
|
||||||
public interface IPaymentsService
|
public interface IPaymentsService
|
||||||
{
|
{
|
||||||
Task<(bool isSucceed, IActionResult? actionResult, IEnumerable<PaymentResponse> payments)> GetPayments(DateTime from, DateTime to);
|
Task<(bool isSucceed, IActionResult? actionResult, IEnumerable<PaymentResponse> payments)> GetPayments(DateTime from, DateTime to);
|
||||||
Task<(bool isSucceed, IActionResult? actionResult, string url)> GetPaymentUrl(PaymentDto payment);
|
Task<(bool isSucceed, IActionResult? actionResult, string url)> GetPaymentUrl(IList<StrippedFlattenedEnrollment> input);
|
||||||
|
Task<(bool isSucceed, IActionResult? actionResult)> ReceiveCallback(IFormCollection forms);
|
||||||
}
|
}
|
@ -1,23 +1,113 @@
|
|||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
using LiqPayIntegration;
|
using LiqPayIntegration;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using SharedModels.DataTransferObjects;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Server.Constants;
|
||||||
|
using Server.Data;
|
||||||
|
using Server.Models;
|
||||||
|
using SharedModels.Responses;
|
||||||
|
|
||||||
namespace Server.Services;
|
namespace Server.Services;
|
||||||
|
|
||||||
public class PaymentsService : IPaymentsService
|
public class PaymentsService : IPaymentsService
|
||||||
{
|
{
|
||||||
|
readonly ApplicationDbContext _dbContext;
|
||||||
|
|
||||||
// LiqpayIntegration
|
readonly string _userId;
|
||||||
LiqPay liqPay = new LiqPay("sandbox_i23432845039", "sandbox_gymL9PdryqdfAznNQbb7ynLvASDQ5SJCCNJvF2iV");
|
|
||||||
|
// LiqpayIntegration. Change 3-rd argument` address to current machine address in its network. Don't forget about port.
|
||||||
|
LiqPay liqPay = new LiqPay("sandbox_i23432845039", "sandbox_gymL9PdryqdfAznNQbb7ynLvASDQ5SJCCNJvF2iV", "http://localhost:5006/api/payment/callback/");
|
||||||
|
|
||||||
|
public PaymentsService(ApplicationDbContext dbContext, IHttpContextAccessor httpContextAccessor)
|
||||||
|
{
|
||||||
|
_dbContext = dbContext;
|
||||||
|
_userId = httpContextAccessor.HttpContext.User.Claims
|
||||||
|
.FirstOrDefault(c => c.Properties.Values.Any(v => v == JwtStandardClaimNames.Sub))?.Value;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<(bool isSucceed, IActionResult? actionResult, IEnumerable<PaymentResponse> payments)> GetPayments(DateTime from, DateTime to)
|
public async Task<(bool isSucceed, IActionResult? actionResult, IEnumerable<PaymentResponse> payments)> GetPayments(DateTime from, DateTime to)
|
||||||
{
|
{
|
||||||
return(true, null, (await liqPay.PaymentArchive(from, to)).AsEnumerable());
|
return(true, null, (await liqPay.PaymentArchive(from, to)).AsEnumerable());
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(bool isSucceed, IActionResult? actionResult, string url)> GetPaymentUrl(PaymentDto payment)
|
public async Task<(bool isSucceed, IActionResult? actionResult, string url)> GetPaymentUrl(IList<StrippedFlattenedEnrollment> input)
|
||||||
{
|
{
|
||||||
return (true, null, (await liqPay.GetPaymentUrl(payment.Amount, payment.Description, payment.OrderId)));
|
if (input.Count < 1)
|
||||||
|
return (false, new BadRequestResult(), "");
|
||||||
|
|
||||||
|
input.ToList().OrderBy(e => e.Order);
|
||||||
|
|
||||||
|
List<Ticket> tickets = new List<Ticket>();
|
||||||
|
foreach (StrippedFlattenedEnrollment e in input)
|
||||||
|
{
|
||||||
|
tickets.Add(new Ticket
|
||||||
|
{
|
||||||
|
VehicleEnrollmentId = e.Id,
|
||||||
|
FirstRouteAddressId = e.DepartureAddressId,
|
||||||
|
LastRouteAddressId = e.ArrivalAddressId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
TicketGroup ticketGroup = new TicketGroup
|
||||||
|
{
|
||||||
|
Tickets = tickets,
|
||||||
|
UserId = _userId
|
||||||
|
};
|
||||||
|
|
||||||
|
_dbContext.TicketGroups.Add(ticketGroup);
|
||||||
|
await _dbContext.SaveChangesAsync();
|
||||||
|
|
||||||
|
int orderId = ticketGroup.Id;
|
||||||
|
|
||||||
|
var ticketGroups = _dbContext.TicketGroups;
|
||||||
|
var dbTicketGroup = await _dbContext.TicketGroups
|
||||||
|
.Include(tg => tg.Tickets)
|
||||||
|
.ThenInclude(t => t.VehicleEnrollment)
|
||||||
|
.ThenInclude(ve => ve.RouteAddressDetails)
|
||||||
|
.ThenInclude(ve => ve.RouteAddress)
|
||||||
|
.ThenInclude(ra => ra.Route)
|
||||||
|
.ThenInclude(r => r.RouteAddresses)
|
||||||
|
.ThenInclude(ra => ra.Address)
|
||||||
|
.ThenInclude(a => a.City)
|
||||||
|
.ThenInclude(c => c.State)
|
||||||
|
.ThenInclude(s => s.Country)
|
||||||
|
.FirstAsync(tg => tg.Id == orderId);
|
||||||
|
|
||||||
|
double cost = dbTicketGroup.GetCost();
|
||||||
|
string description =
|
||||||
|
$"Ïî¿çäêà ç { dbTicketGroup.GetDepartureAddress().GetFullName()}\n"+
|
||||||
|
$"Äî { dbTicketGroup.GetArrivalAddress().GetFullName()}";
|
||||||
|
string text = await liqPay.GetPaymentUrl(cost, description, orderId.ToString());
|
||||||
|
|
||||||
|
return (true, new OkResult(), text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<(bool isSucceed, IActionResult? actionResult)> ReceiveCallback(IFormCollection forms)
|
||||||
|
{
|
||||||
|
if (!forms.Keys.Contains("data"))
|
||||||
|
return (false, new BadRequestResult());
|
||||||
|
|
||||||
|
var baseData = forms["data"].First();
|
||||||
|
|
||||||
|
var data = Encoding.UTF8.GetString(Convert.FromBase64String(baseData));
|
||||||
|
var jsonData = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(data);
|
||||||
|
|
||||||
|
if (!jsonData.ContainsKey("status") || !jsonData.ContainsKey("order_id"))
|
||||||
|
return (false, new BadRequestResult());
|
||||||
|
|
||||||
|
if (jsonData["status"].GetString() != "success")
|
||||||
|
return (true, new OkResult());
|
||||||
|
|
||||||
|
var orderId = int.Parse(jsonData["order_id"].GetString());
|
||||||
|
var ticket = _dbContext.TicketGroups
|
||||||
|
.Find(orderId);
|
||||||
|
ticket.PurchaseDateTimeUtc = DateTime.UtcNow;
|
||||||
|
|
||||||
|
_dbContext.Update(ticket);
|
||||||
|
await _dbContext.SaveChangesAsync();
|
||||||
|
|
||||||
|
return (true, new OkResult());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
10
SharedModels/Responses/StrippedFlattenedEnrollment.cs
Normal file
10
SharedModels/Responses/StrippedFlattenedEnrollment.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace SharedModels.Responses
|
||||||
|
{
|
||||||
|
public class StrippedFlattenedEnrollment
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int DepartureAddressId { get; set; }
|
||||||
|
public int ArrivalAddressId { get; set; }
|
||||||
|
public int Order { get; set; }
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user