diff --git a/API/Controllers/PaymentsController.cs b/API/Controllers/PaymentsController.cs new file mode 100644 index 0000000..4cbd71f --- /dev/null +++ b/API/Controllers/PaymentsController.cs @@ -0,0 +1,23 @@ +using Core.Entities; +using Core.Interfaces; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace API.Controllers +{ + public class PaymentsController : BaseApiController + { + private readonly IPaymentService _paymentService; + public PaymentsController(IPaymentService paymentService) + { + _paymentService = paymentService; + } + + [Authorize] + [HttpPost("{basketId}")] + public async Task> CreateOrUpdatePaymentIntent(string basketId) + { + return await _paymentService.CreateOrUpdatePaymentIntent(basketId); + } + } +} \ No newline at end of file diff --git a/API/Dtos/CustomerBasketDto.cs b/API/Dtos/CustomerBasketDto.cs index 9df57c9..355a204 100644 --- a/API/Dtos/CustomerBasketDto.cs +++ b/API/Dtos/CustomerBasketDto.cs @@ -7,5 +7,8 @@ namespace API.Dtos [Required] public string Id { get; set; } public List Items { get; set; } + public int? DeliveryMethodId { get; set; } + public string ClientSecret { get; set; } + public string PaymentItentId { get; set; } } } \ No newline at end of file diff --git a/API/Extensions/ApplicationServicesExtensions.cs b/API/Extensions/ApplicationServicesExtensions.cs index 7cab7d4..c3ea36d 100644 --- a/API/Extensions/ApplicationServicesExtensions.cs +++ b/API/Extensions/ApplicationServicesExtensions.cs @@ -14,6 +14,7 @@ namespace API.Extensions services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); services.AddScoped(); services.AddScoped(typeof(IGenericRepository<>), (typeof(GenericRepository<>))); services.Configure(options => diff --git a/Core/Entities/CustomerBasket.cs b/Core/Entities/CustomerBasket.cs index ef196bd..aad1470 100644 --- a/Core/Entities/CustomerBasket.cs +++ b/Core/Entities/CustomerBasket.cs @@ -18,5 +18,8 @@ namespace Core.Entities public string Id { get; set; } public List Items { get; set; } = new List(); + public int? DeliveryMethodId { get; set; } + public string ClientSecret { get; set; } + public string PaymentItentId { get; set; } } } \ No newline at end of file diff --git a/Core/Interfaces/IPaymentService.cs b/Core/Interfaces/IPaymentService.cs new file mode 100644 index 0000000..4bf7c33 --- /dev/null +++ b/Core/Interfaces/IPaymentService.cs @@ -0,0 +1,9 @@ +using Core.Entities; + +namespace Core.Interfaces +{ + public interface IPaymentService + { + Task CreateOrUpdatePaymentIntent(string basketId); + } +} \ No newline at end of file diff --git a/Infrastructure/Infrastructure.csproj b/Infrastructure/Infrastructure.csproj index 0c2878c..5cc126d 100644 --- a/Infrastructure/Infrastructure.csproj +++ b/Infrastructure/Infrastructure.csproj @@ -9,6 +9,7 @@ + diff --git a/Infrastructure/Services/PaymentService.cs b/Infrastructure/Services/PaymentService.cs new file mode 100644 index 0000000..6df72f0 --- /dev/null +++ b/Infrastructure/Services/PaymentService.cs @@ -0,0 +1,66 @@ +using Core.Entities; +using Core.Entities.OrderAggregate; +using Core.Interfaces; +using Microsoft.Extensions.Configuration; +using Stripe; +using Product = Core.Entities.Product; + +namespace Infrastructure.Services +{ + public class PaymentService : IPaymentService + { + private readonly IBasketRepository _basketRepository; + private readonly IUnitOfWork _unitOfWork; + private readonly IConfiguration _config; + public PaymentService(IBasketRepository basketRepository, IUnitOfWork unitOfWork, IConfiguration config) + { + _config = config; + _unitOfWork = unitOfWork; + _basketRepository = basketRepository; + } + + public async Task CreateOrUpdatePaymentIntent(string basketId) + { + StripeConfiguration.ApiKey = _config["StripeSettings:SecretKey"]; + var basket = await _basketRepository.GetBasketAsync(basketId); + var shippingPrice = 0m; + + if(basket.DeliveryMethodId.HasValue){ + var deliveryMethod = await _unitOfWork.Repository().GetByIdAsync((int)basket.DeliveryMethodId); + shippingPrice = deliveryMethod.Price; + } + + foreach (var item in basket.Items) + { + var productItem = await _unitOfWork.Repository().GetByIdAsync(item.Id); + if(item.Price != productItem.Price){ + item.Price = productItem.Price; + } + } + + var service = new PaymentIntentService(); + PaymentIntent intent; + if(string.IsNullOrEmpty(basket.PaymentItentId)) + { + var options = new PaymentIntentCreateOptions + { + Amount = (long) basket.Items.Sum(i => i.Quantity * (i.Price * 100)) + (long) shippingPrice * 100, + Currency = "usd", + PaymentMethodTypes = new List{"card"} + }; + intent = await service.CreateAsync(options); + basket.PaymentItentId = intent.Id; + basket.ClientSecret = intent.ClientSecret; + } else + { + var options = new PaymentIntentUpdateOptions + { + Amount = (long) basket.Items.Sum(i => i.Quantity * (i.Price * 100)) + (long) shippingPrice * 100, + }; + await service.UpdateAsync(basket.PaymentItentId, options); + } + await _basketRepository.UpdateBasketAsync(basket); + return basket; + } + } +} \ No newline at end of file