From 732ca424c21088d3fbbab044dc24990e1af8ca94 Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Sat, 8 Jan 2022 19:54:03 +0300 Subject: [PATCH 1/8] updated payment ui --- .../Components/Payment/Default.cshtml | 65 ++++++++++--------- .../Payment/PaymentWidgetViewComponent.cs | 13 +++- .../EShopOnAbp.PublicWeb/Pages/Payment.cshtml | 1 - .../Pages/Payment.cshtml.cs | 2 +- .../ServiceProviders/PaymentTypeProvider.cs | 24 +++++++ .../ServiceProviders/UserAddressProvider.cs | 4 +- .../components/payment/payment-widget.css | 12 ++++ .../components/payment/payment-widget.js | 14 +++- 8 files changed, 95 insertions(+), 40 deletions(-) create mode 100644 apps/public-web/src/EShopOnAbp.PublicWeb/ServiceProviders/PaymentTypeProvider.cs diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/Components/Payment/Default.cshtml b/apps/public-web/src/EShopOnAbp.PublicWeb/Components/Payment/Default.cshtml index 96f2a3b5..08495130 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/Components/Payment/Default.cshtml +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/Components/Payment/Default.cshtml @@ -12,40 +12,47 @@
-

Select Address

- @for (int i = 0; i < Math.Ceiling(Model.Address.Count / (double) defaultColumnSize); i++) - { - - @for (int j = 0; j < defaultColumnSize; j++) - { - - @if (i * defaultColumnSize + j < Model.Address.Count) - { - var address = Model.Address[(i * defaultColumnSize) + j]; - string isSelected = address.IsDefault ? "is-selected" : string.Empty; -
-

@address.Type

-
-

@address.ToString()

-
- -
- } -
- } -
- } +
Select Address
+ + @foreach (var address in Model.Address) + { + string isSelectedAddressClass = address.IsDefault ? "is-selected" : string.Empty; + +
+
+

@address.Type

+
+
+

@address.ToString()

+
+ +
+
+ } +
-

Select Payment Method

+
Select Payment Method
- - - paypal logo - - + @foreach (var paymentType in Model.PaymentTypes) + { + string isSelectedClass = paymentType.IsDefault ? "is-selected" : ""; + + + +

+ @paymentType.Name +

+

+ +

+
+
+
+ }
+
diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/Components/Payment/PaymentWidgetViewComponent.cs b/apps/public-web/src/EShopOnAbp.PublicWeb/Components/Payment/PaymentWidgetViewComponent.cs index e0335a7a..0e458afa 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/Components/Payment/PaymentWidgetViewComponent.cs +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/Components/Payment/PaymentWidgetViewComponent.cs @@ -18,19 +18,25 @@ public class PaymentWidgetViewComponent : AbpViewComponent { private readonly UserBasketProvider _userBasketProvider; private readonly UserAddressProvider _userAddressProvider; + private readonly PaymentTypeProvider _paymentTypeProvider; - public PaymentWidgetViewComponent(UserBasketProvider userBasketProvider, UserAddressProvider userAddressProvider) + public PaymentWidgetViewComponent( + UserBasketProvider userBasketProvider, + UserAddressProvider userAddressProvider, + PaymentTypeProvider paymentTypeProvider) { _userBasketProvider = userBasketProvider; _userAddressProvider = userAddressProvider; + _paymentTypeProvider = paymentTypeProvider; } public async Task InvokeAsync() { - var viewModel = new PaymentViewModel() + var viewModel = new PaymentViewModel { Basket = await _userBasketProvider.GetBasketAsync(), - Address = _userAddressProvider.GetDemoAddresses() + Address = _userAddressProvider.GetDemoAddresses(), + PaymentTypes = _paymentTypeProvider.GetPaymentTypes() }; return View("~/Components/Payment/Default.cshtml", viewModel); } @@ -40,4 +46,5 @@ public class PaymentViewModel { public BasketDto Basket { get; set; } public List Address { get; set; } + public List PaymentTypes { get; set; } } \ No newline at end of file diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/Payment.cshtml b/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/Payment.cshtml index 96ece09b..bdfd8c57 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/Payment.cshtml +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/Payment.cshtml @@ -11,7 +11,6 @@ }
- @*

@L["Payment"]

*@
@await Component.InvokeAsync(typeof(PaymentWidgetViewComponent))
diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/Payment.cshtml.cs b/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/Payment.cshtml.cs index d4191c8c..aac4373c 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/Payment.cshtml.cs +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/Payment.cshtml.cs @@ -59,7 +59,7 @@ public class PaymentModel : AbpPageModel var placedOrder = await _orderAppService.CreateAsync(new OrderCreateDto() { - PaymentTypeId = 1, // Paypal + PaymentTypeId = model.SelectedPaymentId, Address = GetUserAddress(model.SelectedAddressId), Products = productItems }); diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/ServiceProviders/PaymentTypeProvider.cs b/apps/public-web/src/EShopOnAbp.PublicWeb/ServiceProviders/PaymentTypeProvider.cs new file mode 100644 index 00000000..a2b9d755 --- /dev/null +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/ServiceProviders/PaymentTypeProvider.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; +using Volo.Abp.DependencyInjection; + +namespace EShopOnAbp.PublicWeb.ServiceProviders; + +public class PaymentTypeProvider : ITransientDependency +{ + public List GetPaymentTypes() + { + return new List + { + new() {Id = 0, Name = "Demo", IconCss = "fa-credit-card demo", IsDefault = true}, + new() {Id = 1, Name = "Paypal", IconCss = "fa-cc-paypal paypal"} + }; + } +} + +public class PaymentType +{ + public int Id { get; set; } + public string Name { get; set; } + public string IconCss { get; set; } + public bool IsDefault { get; set; } = false; +} \ No newline at end of file diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/ServiceProviders/UserAddressProvider.cs b/apps/public-web/src/EShopOnAbp.PublicWeb/ServiceProviders/UserAddressProvider.cs index 6e343752..9c69caa0 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/ServiceProviders/UserAddressProvider.cs +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/ServiceProviders/UserAddressProvider.cs @@ -26,8 +26,7 @@ public class UserAddressProvider : ITransientDependency Street = "Yeşilköy Serbest Bölge Mah. E-Blok Sk. Bakırköy", City = "İstanbul", Country = "Turkey", - ZipCode = "34149", - Description = "Near Ataturk Airport" + ZipCode = "34149" } }; } @@ -38,7 +37,6 @@ public class AddressDto public int Id { get; set; } public string Type { get; set; } public bool IsDefault { get; set; } = false; - public string Description { get; set; } public string Street { get; set; } public string City { get; set; } public string Country { get; set; } diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/wwwroot/components/payment/payment-widget.css b/apps/public-web/src/EShopOnAbp.PublicWeb/wwwroot/components/payment/payment-widget.css index 1b38f784..90e9a095 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/wwwroot/components/payment/payment-widget.css +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/wwwroot/components/payment/payment-widget.css @@ -17,4 +17,16 @@ .is-selected { border: solid #bfbfe3; +} + +.payment-type-header { + font-weight: 500; +} + +.paypal { + color: #6c84fa; +} + +.demo { + color: darkgray; } \ No newline at end of file diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/wwwroot/components/payment/payment-widget.js b/apps/public-web/src/EShopOnAbp.PublicWeb/wwwroot/components/payment/payment-widget.js index b246c5f1..1c541575 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/wwwroot/components/payment/payment-widget.js +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/wwwroot/components/payment/payment-widget.js @@ -6,12 +6,20 @@ $wrapper .find('.address-list .card') .click(function () { - var $this = $(this); - var addressId = $this.attr('data-address-id'); - abp.utils.setCookieValue("selected-address", addressId); + const $this = $(this); + // const addressId = $this.attr('data-address-id'); $this.parents(".address-list").find('.card').removeClass("is-selected"); $this.addClass("is-selected"); }); + + $wrapper + .find('.payment-list .card') + .click(el => { + const $this = $(el.currentTarget); + // const paymentTypeId = $this.attr('data-payment-id'); + $this.parents(".payment-list").find('.card').removeClass("is-selected"); + $this.addClass("is-selected"); + }); }; return { From 4d5bc063c2d38835a458836aa5fb6713ad892f2a Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Sat, 8 Jan 2022 23:11:12 +0300 Subject: [PATCH 2/8] removed payment bypass service Introduced IPaymentStrategy --- .../IPaymentRequestAppService.cs | 9 +- .../PaymentRequestCompleteInputDto.cs | 10 ++ .../PaymentRequests/PaymentRequestStartDto.cs | 1 + .../PaymentServiceConsts.cs | 1 - .../PaymentRequestAppService.cs | 137 +++++------------- .../PaymentRequestByPassAppService.cs | 38 ----- .../PaymentServiceApplicationModule.cs | 12 -- .../PaymentServices/DemoService.cs | 25 ++++ .../PaymentServices/IPaymentStrategy.cs | 10 ++ .../PaymentServices/PaymentServiceFactory.cs | 41 ++++++ .../PaymentServices/PaypalService.cs | 94 ++++++++++++ .../PayPalConsts.cs | 2 +- .../PaymentRequestDomainService.cs | 39 +++++ .../PaymentServiceHttpApiHostModule.cs | 6 +- 14 files changed, 263 insertions(+), 162 deletions(-) create mode 100644 services/payment/src/EShopOnAbp.PaymentService.Application.Contracts/PaymentRequests/PaymentRequestCompleteInputDto.cs delete mode 100644 services/payment/src/EShopOnAbp.PaymentService.Application/PaymentRequests/PaymentRequestByPassAppService.cs create mode 100644 services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/DemoService.cs create mode 100644 services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/IPaymentStrategy.cs create mode 100644 services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaymentServiceFactory.cs create mode 100644 services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaypalService.cs rename services/payment/src/{EShopOnAbp.PaymentService.Application/PayPal => EShopOnAbp.PaymentService.Domain.Shared}/PayPalConsts.cs (97%) create mode 100644 services/payment/src/EShopOnAbp.PaymentService.Domain/PaymentRequests/PaymentRequestDomainService.cs diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application.Contracts/PaymentRequests/IPaymentRequestAppService.cs b/services/payment/src/EShopOnAbp.PaymentService.Application.Contracts/PaymentRequests/IPaymentRequestAppService.cs index cf3e8f40..c41feb31 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.Application.Contracts/PaymentRequests/IPaymentRequestAppService.cs +++ b/services/payment/src/EShopOnAbp.PaymentService.Application.Contracts/PaymentRequests/IPaymentRequestAppService.cs @@ -9,8 +9,15 @@ namespace EShopOnAbp.PaymentService.PaymentRequests Task StartAsync(PaymentRequestStartDto input); - Task CompleteAsync(string token); + Task CompleteAsync(PaymentRequestCompleteInputDto input); Task HandleWebhookAsync(string payload); + // /// + // /// 0 - Demo + // /// 1 - Paypal + // /// + // /// + // /// + // Task SetPaymentServiceAsync(int paymentTypeId); } } diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application.Contracts/PaymentRequests/PaymentRequestCompleteInputDto.cs b/services/payment/src/EShopOnAbp.PaymentService.Application.Contracts/PaymentRequests/PaymentRequestCompleteInputDto.cs new file mode 100644 index 00000000..2c154610 --- /dev/null +++ b/services/payment/src/EShopOnAbp.PaymentService.Application.Contracts/PaymentRequests/PaymentRequestCompleteInputDto.cs @@ -0,0 +1,10 @@ +using System; + +namespace EShopOnAbp.PaymentService.PaymentRequests; + +[Serializable] +public class PaymentRequestCompleteInputDto +{ + public string Token { get; set; } + public int PaymentTypeId { get; set; } +} \ No newline at end of file diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application.Contracts/PaymentRequests/PaymentRequestStartDto.cs b/services/payment/src/EShopOnAbp.PaymentService.Application.Contracts/PaymentRequests/PaymentRequestStartDto.cs index 44b39fdb..d5b06af4 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.Application.Contracts/PaymentRequests/PaymentRequestStartDto.cs +++ b/services/payment/src/EShopOnAbp.PaymentService.Application.Contracts/PaymentRequests/PaymentRequestStartDto.cs @@ -6,6 +6,7 @@ namespace EShopOnAbp.PaymentService.PaymentRequests [Serializable] public class PaymentRequestStartDto { + public int PaymentTypeId { get; set; } public Guid PaymentRequestId { get; set; } [Required] diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application.Contracts/PaymentServiceConsts.cs b/services/payment/src/EShopOnAbp.PaymentService.Application.Contracts/PaymentServiceConsts.cs index 1b805927..6bfa585d 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.Application.Contracts/PaymentServiceConsts.cs +++ b/services/payment/src/EShopOnAbp.PaymentService.Application.Contracts/PaymentServiceConsts.cs @@ -2,6 +2,5 @@ { public static class PaymentServiceConsts { - public static bool ByPassPaymentProvider { get; set; } } } diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentRequests/PaymentRequestAppService.cs b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentRequests/PaymentRequestAppService.cs index 28bac790..82e582f2 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentRequests/PaymentRequestAppService.cs +++ b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentRequests/PaymentRequestAppService.cs @@ -1,44 +1,49 @@ -using EShopOnAbp.PaymentService.PayPal; -using Newtonsoft.Json.Linq; +using Newtonsoft.Json.Linq; using PayPalCheckoutSdk.Core; using PayPalCheckoutSdk.Orders; using System; -using System.Collections.Generic; -using System.Globalization; using System.Linq; using System.Threading.Tasks; -using Volo.Abp.DependencyInjection; +using EShopOnAbp.PaymentService.PaymentServices; +using Microsoft.Extensions.Logging; namespace EShopOnAbp.PaymentService.PaymentRequests { - [ExposeServices(typeof(PaymentRequestAppService))] public class PaymentRequestAppService : PaymentServiceAppService, IPaymentRequestAppService { + private readonly PaymentServiceFactory _paymentServiceFactory; + private readonly PaymentRequestDomainService _paymentRequestDomainService; protected IPaymentRequestRepository PaymentRequestRepository { get; } protected PayPalHttpClient PayPalHttpClient { get; } + public PaymentRequestAppService( IPaymentRequestRepository paymentRequestRepository, - PayPalHttpClient payPalHttpClient) + PayPalHttpClient payPalHttpClient, + PaymentServiceFactory paymentServiceFactory, + PaymentRequestDomainService paymentRequestDomainService) { PaymentRequestRepository = paymentRequestRepository; PayPalHttpClient = payPalHttpClient; + _paymentServiceFactory = paymentServiceFactory; + _paymentRequestDomainService = paymentRequestDomainService; } public virtual async Task CreateAsync(PaymentRequestCreationDto input) { - var paymentRequest = new PaymentRequest(id: GuidGenerator.Create(), orderId: input.OrderId, orderNo:input.OrderNo, currency: input.Currency, buyerId: input.BuyerId); + var paymentRequest = new PaymentRequest(id: GuidGenerator.Create(), orderId: input.OrderId, + orderNo: input.OrderNo, currency: input.Currency, buyerId: input.BuyerId); foreach (var paymentRequestProduct in input.Products - .Select(s => new PaymentRequestProduct( - GuidGenerator.Create(), - paymentRequestId: paymentRequest.Id, - code: s.Code, - name: s.Name, - unitPrice: s.UnitPrice, - quantity: s.Quantity, - totalPrice: s.TotalPrice, - referenceId: s.ReferenceId))) + .Select(s => new PaymentRequestProduct( + GuidGenerator.Create(), + paymentRequestId: paymentRequest.Id, + code: s.Code, + name: s.Name, + unitPrice: s.UnitPrice, + quantity: s.Quantity, + totalPrice: s.TotalPrice, + referenceId: s.ReferenceId))) { paymentRequest.Products.Add(paymentRequestProduct); } @@ -50,71 +55,17 @@ namespace EShopOnAbp.PaymentService.PaymentRequests public virtual async Task StartAsync(PaymentRequestStartDto input) { - var paymentRequest = await PaymentRequestRepository.GetAsync(input.PaymentRequestId, includeDetails: true); - - var totalCheckoutPrice = paymentRequest.Products.Sum(s => s.TotalPrice); - - var order = new OrderRequest - { - CheckoutPaymentIntent = "CAPTURE", - ApplicationContext = new ApplicationContext - { - ReturnUrl = input.ReturnUrl, - CancelUrl = input.CancelUrl, - }, - PurchaseUnits = new List - { - new PurchaseUnitRequest - { - AmountWithBreakdown = new AmountWithBreakdown - { - AmountBreakdown = new AmountBreakdown - { - ItemTotal = new Money - { - CurrencyCode = paymentRequest.Currency, - Value = totalCheckoutPrice.ToString($"{CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator}00") - } - }, - CurrencyCode = paymentRequest.Currency, - Value = totalCheckoutPrice.ToString($"{CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator}00"), - }, - Items = paymentRequest.Products.Select(p => new Item - { - Quantity = p.Quantity.ToString(), - Name = p.Name, - UnitAmount = new Money - { - CurrencyCode = paymentRequest.Currency, - Value = p.UnitPrice.ToString($"{CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator}00") - } - }).ToList(), - ReferenceId = paymentRequest.Id.ToString() - } - } - }; - - var request = new OrdersCreateRequest(); - request.Prefer("return=representation"); - request.RequestBody(order); - - var result = (await PayPalHttpClient.Execute(request)).Result(); - - return new PaymentRequestStartResultDto - { - CheckoutLink = result.Links.First(x => x.Rel == "approve").Href - }; + PaymentRequest paymentRequest = await PaymentRequestRepository.GetAsync(input.PaymentRequestId, includeDetails: true); + + var paymentService = _paymentServiceFactory.Create(input.PaymentTypeId); + return await paymentService.StartAsync(paymentRequest, input); } - public virtual async Task CompleteAsync(string token) + public virtual async Task CompleteAsync(PaymentRequestCompleteInputDto input) { - var request = new OrdersCaptureRequest(token); - request.RequestBody(new OrderActionRequest()); - - var order = (await PayPalHttpClient.Execute(request)).Result(); - - var paymentRequest = await UpdatePaymentRequestStateAsync(order); - + var paymentService = _paymentServiceFactory.Create(input.PaymentTypeId); + + var paymentRequest = await paymentService.CompleteAsync(PaymentRequestRepository, input.Token); return ObjectMapper.Map(paymentRequest); } @@ -130,34 +81,12 @@ namespace EShopOnAbp.PaymentService.PaymentRequests var response = await PayPalHttpClient.Execute(request); order = response.Result(); - await UpdatePaymentRequestStateAsync(order); + var paymentRequestId = Guid.Parse(order.PurchaseUnits.First().ReferenceId); + await _paymentRequestDomainService.UpdatePaymentRequestStateAsync(paymentRequestId, order.Status, order.Id); // PayPal doesn't accept Http 204 (NoContent) result and tries to execute webhook again. // So with following value, API returns Http 200 (OK) result. return true; } - - protected async Task UpdatePaymentRequestStateAsync(Order order) - { - var paymentRequestId = Guid.Parse(order.PurchaseUnits.First().ReferenceId); - - var paymentRequest = await PaymentRequestRepository.GetAsync(paymentRequestId); - - if (order.Status == PayPalConsts.OrderStatus.Completed || order.Status == PayPalConsts.OrderStatus.Approved) - { - paymentRequest.SetAsCompleted(); - } - else - { - paymentRequest.SetAsFailed(order.Status); - } - - paymentRequest.ExtraProperties[PayPalConsts.OrderIdPropertyName] = order.Id; - paymentRequest.ExtraProperties[nameof(order.Status)] = order.Status; - - await PaymentRequestRepository.UpdateAsync(paymentRequest); - - return paymentRequest; - } } -} +} \ No newline at end of file diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentRequests/PaymentRequestByPassAppService.cs b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentRequests/PaymentRequestByPassAppService.cs deleted file mode 100644 index 1c032844..00000000 --- a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentRequests/PaymentRequestByPassAppService.cs +++ /dev/null @@ -1,38 +0,0 @@ -using PayPalCheckoutSdk.Core; -using System; -using System.Threading.Tasks; -using Volo.Abp.DependencyInjection; - -namespace EShopOnAbp.PaymentService.PaymentRequests -{ - [ExposeServices(typeof(PaymentRequestByPassAppService))] - public class PaymentRequestByPassAppService : PaymentRequestAppService - { - public PaymentRequestByPassAppService( - IPaymentRequestRepository paymentRequestRepository, - PayPalHttpClient payPalHttpClient) - : base(paymentRequestRepository, - payPalHttpClient) - { - } - - public override Task StartAsync(PaymentRequestStartDto input) - { - return Task.FromResult(new PaymentRequestStartResultDto - { - CheckoutLink = input.ReturnUrl + "?token=" + input.PaymentRequestId - }); - } - - public override async Task CompleteAsync(string token) - { - var paymentRequest = await PaymentRequestRepository.GetAsync(Guid.Parse(token)); - - paymentRequest.SetAsCompleted(); - - await PaymentRequestRepository.UpdateAsync(paymentRequest); - - return ObjectMapper.Map(paymentRequest); - } - } -} \ No newline at end of file diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServiceApplicationModule.cs b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServiceApplicationModule.cs index 158e6fb1..e57c90b7 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServiceApplicationModule.cs +++ b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServiceApplicationModule.cs @@ -39,18 +39,6 @@ namespace EShopOnAbp.PaymentService return new PayPalHttpClient(new LiveEnvironment(options.ClientId, options.Secret)); }); - - context.Services.AddTransient(provider => - { - if (PaymentServiceConsts.ByPassPaymentProvider) - { - return provider.GetRequiredService(); - } - else - { - return provider.GetRequiredService(); - } - }); } } } diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/DemoService.cs b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/DemoService.cs new file mode 100644 index 00000000..da54bb5d --- /dev/null +++ b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/DemoService.cs @@ -0,0 +1,25 @@ +using System; +using System.Threading.Tasks; +using EShopOnAbp.PaymentService.PaymentRequests; + +namespace EShopOnAbp.PaymentService.PaymentServices; + +public class DemoService : IPaymentStrategy +{ + public Task StartAsync(PaymentRequest paymentRequest, PaymentRequestStartDto input) + { + return Task.FromResult(new PaymentRequestStartResultDto + { + CheckoutLink = input.ReturnUrl + "?token=" + input.PaymentRequestId + }); + } + + public async Task CompleteAsync(IPaymentRequestRepository paymentRequestRepository, string token) + { + var paymentRequest = await paymentRequestRepository.GetAsync(Guid.Parse(token)); + + paymentRequest.SetAsCompleted(); + + return await paymentRequestRepository.UpdateAsync(paymentRequest); + } +} \ No newline at end of file diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/IPaymentStrategy.cs b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/IPaymentStrategy.cs new file mode 100644 index 00000000..aafab8bd --- /dev/null +++ b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/IPaymentStrategy.cs @@ -0,0 +1,10 @@ +using System.Threading.Tasks; +using EShopOnAbp.PaymentService.PaymentRequests; + +namespace EShopOnAbp.PaymentService.PaymentServices; + +public interface IPaymentStrategy +{ + public Task StartAsync(PaymentRequest paymentRequest, PaymentRequestStartDto input); + public Task CompleteAsync(IPaymentRequestRepository paymentRequestRepository, string token); +} \ No newline at end of file diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaymentServiceFactory.cs b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaymentServiceFactory.cs new file mode 100644 index 00000000..719ea7da --- /dev/null +++ b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaymentServiceFactory.cs @@ -0,0 +1,41 @@ +using System; +using EShopOnAbp.PaymentService.PaymentRequests; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using PayPalCheckoutSdk.Core; +using Volo.Abp.DependencyInjection; + +namespace EShopOnAbp.PaymentService.PaymentServices; + +public class PaymentServiceFactory : ITransientDependency +{ + private readonly IServiceProvider _serviceProvider; + private readonly ILogger _logger; + + public PaymentServiceFactory(IServiceProvider serviceProvider, ILogger logger) + { + logger.LogInformation("== Payment SErvice Factory == "); + _serviceProvider = serviceProvider; + _logger = logger; + } + + public IPaymentStrategy Create(int paymentTypeId) + { + if (paymentTypeId == 0) + { + return new DemoService(); + } + + if (paymentTypeId == 1) + { + var paypalService = _serviceProvider.GetRequiredService(); + _logger.LogInformation($"=== Resolved PaypalService {paypalService} ==="); + var requestDomainService = _serviceProvider.GetRequiredService(); + _logger.LogInformation($"=== Resolved PaymentRequestDomainService {requestDomainService} ==="); + + return new PaypalService(paypalService, requestDomainService); + } + + return new DemoService(); + } +} \ No newline at end of file diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaypalService.cs b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaypalService.cs new file mode 100644 index 00000000..d0dce7c8 --- /dev/null +++ b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaypalService.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Threading.Tasks; +using EShopOnAbp.PaymentService.PaymentRequests; +using PayPalCheckoutSdk.Core; +using PayPalCheckoutSdk.Orders; + +namespace EShopOnAbp.PaymentService.PaymentServices; + +public class PaypalService : IPaymentStrategy +{ + private readonly PayPalHttpClient _payPalHttpClient; + private readonly PaymentRequestDomainService _paymentRequestDomainService; + + public PaypalService(PayPalHttpClient payPalHttpClient, PaymentRequestDomainService paymentRequestDomainService) + { + _payPalHttpClient = payPalHttpClient; + _paymentRequestDomainService = paymentRequestDomainService; + } + + public async Task StartAsync(PaymentRequest paymentRequest, + PaymentRequestStartDto input) + { + var totalCheckoutPrice = paymentRequest.Products.Sum(s => s.TotalPrice); + + var order = new OrderRequest + { + CheckoutPaymentIntent = "CAPTURE", + ApplicationContext = new ApplicationContext + { + ReturnUrl = input.ReturnUrl, + CancelUrl = input.CancelUrl, + }, + PurchaseUnits = new List + { + new PurchaseUnitRequest + { + AmountWithBreakdown = new AmountWithBreakdown + { + AmountBreakdown = new AmountBreakdown + { + ItemTotal = new Money + { + CurrencyCode = paymentRequest.Currency, + Value = totalCheckoutPrice.ToString( + $"{CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator}00") + } + }, + CurrencyCode = paymentRequest.Currency, + Value = totalCheckoutPrice.ToString( + $"{CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator}00"), + }, + Items = paymentRequest.Products.Select(p => new Item + { + Quantity = p.Quantity.ToString(), + Name = p.Name, + UnitAmount = new Money + { + CurrencyCode = paymentRequest.Currency, + Value = p.UnitPrice.ToString( + $"{CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator}00") + } + }).ToList(), + ReferenceId = paymentRequest.Id.ToString() + } + } + }; + + var request = new OrdersCreateRequest(); + request.Prefer("return=representation"); + request.RequestBody(order); + + Order result = (await _payPalHttpClient.Execute(request)).Result(); + + return new PaymentRequestStartResultDto + { + CheckoutLink = result.Links.First(x => x.Rel == "approve").Href + }; + } + + public async Task CompleteAsync(IPaymentRequestRepository paymentRequestRepository, string token) + { + var request = new OrdersCaptureRequest(token); + request.RequestBody(new OrderActionRequest()); + + var order = (await _payPalHttpClient.Execute(request)).Result(); + + var paymentRequestId = Guid.Parse(order.PurchaseUnits.First().ReferenceId); + return await _paymentRequestDomainService.UpdatePaymentRequestStateAsync(paymentRequestId, order.Status, + order.Id); + } +} \ No newline at end of file diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application/PayPal/PayPalConsts.cs b/services/payment/src/EShopOnAbp.PaymentService.Domain.Shared/PayPalConsts.cs similarity index 97% rename from services/payment/src/EShopOnAbp.PaymentService.Application/PayPal/PayPalConsts.cs rename to services/payment/src/EShopOnAbp.PaymentService.Domain.Shared/PayPalConsts.cs index 0e83292c..d13ad8c0 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.Application/PayPal/PayPalConsts.cs +++ b/services/payment/src/EShopOnAbp.PaymentService.Domain.Shared/PayPalConsts.cs @@ -1,4 +1,4 @@ -namespace EShopOnAbp.PaymentService.PayPal +namespace EShopOnAbp.PaymentService { public static class PayPalConsts { diff --git a/services/payment/src/EShopOnAbp.PaymentService.Domain/PaymentRequests/PaymentRequestDomainService.cs b/services/payment/src/EShopOnAbp.PaymentService.Domain/PaymentRequests/PaymentRequestDomainService.cs new file mode 100644 index 00000000..6ea3542a --- /dev/null +++ b/services/payment/src/EShopOnAbp.PaymentService.Domain/PaymentRequests/PaymentRequestDomainService.cs @@ -0,0 +1,39 @@ +using System; +using System.Threading.Tasks; +using Volo.Abp.Domain.Services; + +namespace EShopOnAbp.PaymentService.PaymentRequests; + +public class PaymentRequestDomainService : DomainService +{ + private readonly IPaymentRequestRepository _paymentRequestRepository; + + public PaymentRequestDomainService(IPaymentRequestRepository paymentRequestRepository) + { + _paymentRequestRepository = paymentRequestRepository; + } + + public async Task UpdatePaymentRequestStateAsync( + Guid paymentRequestId, + string orderStatus, + string orderId) + { + var paymentRequest = await _paymentRequestRepository.GetAsync(paymentRequestId); + + if (orderStatus == PayPalConsts.OrderStatus.Completed || orderStatus == PayPalConsts.OrderStatus.Approved) + { + paymentRequest.SetAsCompleted(); + } + else + { + paymentRequest.SetAsFailed(orderStatus); + } + + paymentRequest.ExtraProperties[PayPalConsts.OrderIdPropertyName] = orderId; + paymentRequest.ExtraProperties[nameof(orderStatus)] = orderStatus; + + await _paymentRequestRepository.UpdateAsync(paymentRequest); + + return paymentRequest; + } +} \ No newline at end of file diff --git a/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Host/PaymentServiceHttpApiHostModule.cs b/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Host/PaymentServiceHttpApiHostModule.cs index 23af9ecd..9eed0e02 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Host/PaymentServiceHttpApiHostModule.cs +++ b/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Host/PaymentServiceHttpApiHostModule.cs @@ -30,11 +30,7 @@ namespace EShopOnAbp.PaymentService var hostingEnvironment = context.Services.GetHostingEnvironment(); var configuration = context.Services.GetConfiguration(); - - /// Enable bypassing payment provider via uncommenting code line below. - /// If bypassing is enabled, all payments will be completed immediately. - // PaymentServiceConsts.ByPassPaymentProvider = true; - + JwtBearerConfigurationHelper.Configure(context, "PaymentService"); // SwaggerConfigurationHelper.Configure(context, "Payment Service API"); From 3608029d2fbd54d7c6336ccfa11f49b3e01d8ae5 Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Sat, 8 Jan 2022 23:11:45 +0300 Subject: [PATCH 3/8] updated payment request client proxy --- .../PaymentRequestClientProxy.Generated.cs | 4 ++-- .../ClientProxies/payment-generate-proxy.json | 22 +++++++++---------- .../Controllers/PaymentRequestController.cs | 6 ++--- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Client/ClientProxies/PaymentRequestClientProxy.Generated.cs b/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Client/ClientProxies/PaymentRequestClientProxy.Generated.cs index c59692b4..5295d312 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Client/ClientProxies/PaymentRequestClientProxy.Generated.cs +++ b/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Client/ClientProxies/PaymentRequestClientProxy.Generated.cs @@ -15,11 +15,11 @@ namespace EShopOnAbp.PaymentService.Controllers.ClientProxies [ExposeServices(typeof(IPaymentRequestAppService), typeof(PaymentRequestClientProxy))] public partial class PaymentRequestClientProxy : ClientProxyBase, IPaymentRequestAppService { - public virtual async Task CompleteAsync(string token) + public virtual async Task CompleteAsync(PaymentRequestCompleteInputDto input) { return await RequestAsync(nameof(CompleteAsync), new ClientProxyRequestTypeValue { - { typeof(string), token } + { typeof(PaymentRequestCompleteInputDto), input } }); } diff --git a/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Client/ClientProxies/payment-generate-proxy.json b/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Client/ClientProxies/payment-generate-proxy.json index 7f45f280..ad90fbc0 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Client/ClientProxies/payment-generate-proxy.json +++ b/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Client/ClientProxies/payment-generate-proxy.json @@ -14,33 +14,33 @@ } ], "actions": { - "CompleteAsyncByToken": { - "uniqueName": "CompleteAsyncByToken", + "CompleteAsyncByInput": { + "uniqueName": "CompleteAsyncByInput", "name": "CompleteAsync", "httpMethod": "POST", "url": "api/payment/requests/complete", "supportedVersions": [], "parametersOnMethod": [ { - "name": "token", - "typeAsString": "System.String, System.Private.CoreLib", - "type": "System.String", - "typeSimple": "string", + "name": "input", + "typeAsString": "EShopOnAbp.PaymentService.PaymentRequests.PaymentRequestCompleteInputDto, EShopOnAbp.PaymentService.Application.Contracts", + "type": "EShopOnAbp.PaymentService.PaymentRequests.PaymentRequestCompleteInputDto", + "typeSimple": "EShopOnAbp.PaymentService.PaymentRequests.PaymentRequestCompleteInputDto", "isOptional": false, "defaultValue": null } ], "parameters": [ { - "nameOnMethod": "token", - "name": "token", + "nameOnMethod": "input", + "name": "input", "jsonName": null, - "type": "System.String", - "typeSimple": "string", + "type": "EShopOnAbp.PaymentService.PaymentRequests.PaymentRequestCompleteInputDto", + "typeSimple": "EShopOnAbp.PaymentService.PaymentRequests.PaymentRequestCompleteInputDto", "isOptional": false, "defaultValue": null, "constraintTypes": null, - "bindingSourceId": "ModelBinding", + "bindingSourceId": "Body", "descriptorName": "" } ], diff --git a/services/payment/src/EShopOnAbp.PaymentService.HttpApi/Controllers/PaymentRequestController.cs b/services/payment/src/EShopOnAbp.PaymentService.HttpApi/Controllers/PaymentRequestController.cs index 7325ed28..4c73bf1c 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.HttpApi/Controllers/PaymentRequestController.cs +++ b/services/payment/src/EShopOnAbp.PaymentService.HttpApi/Controllers/PaymentRequestController.cs @@ -20,9 +20,9 @@ namespace EShopOnAbp.PaymentService.Controllers } [HttpPost("complete")] - public Task CompleteAsync(string token) + public Task CompleteAsync(PaymentRequestCompleteInputDto input) { - return PaymentRequestAppService.CompleteAsync(token); + return PaymentRequestAppService.CompleteAsync(input); } [HttpPost] @@ -47,4 +47,4 @@ namespace EShopOnAbp.PaymentService.Controllers return PaymentRequestAppService.StartAsync(input); } } -} +} \ No newline at end of file From 1805c2d1142c84ae5e67da0844f2b34d8af3c31e Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Sat, 8 Jan 2022 23:13:47 +0300 Subject: [PATCH 4/8] fixed payment test compile error --- .../PaymentRequests/PaymentRequestRepository_Tests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/payment/test/EShopOnAbp.PaymentService.EntityFrameworkCore.Tests/PaymentRequests/PaymentRequestRepository_Tests.cs b/services/payment/test/EShopOnAbp.PaymentService.EntityFrameworkCore.Tests/PaymentRequests/PaymentRequestRepository_Tests.cs index 406f5e10..f21634a0 100644 --- a/services/payment/test/EShopOnAbp.PaymentService.EntityFrameworkCore.Tests/PaymentRequests/PaymentRequestRepository_Tests.cs +++ b/services/payment/test/EShopOnAbp.PaymentService.EntityFrameworkCore.Tests/PaymentRequests/PaymentRequestRepository_Tests.cs @@ -18,12 +18,12 @@ namespace EShopOnAbp.PaymentService.PaymentRequests public async Task Should_Insert_Payment_Request() { var id = Guid.NewGuid(); - var paymentRequest = new PaymentRequest(id, "USD"); - + var paymentRequest = new PaymentRequest(id, "123",456,"USD"); + await _paymentRequestRepository.InsertAsync(paymentRequest, autoSave: true); - + var inserted = await _paymentRequestRepository.GetAsync(id); - + inserted.Id.ShouldNotBe(Guid.Empty); } } From ca109136a2175d4fcce87871df9d40b5047260db Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Sat, 8 Jan 2022 23:14:01 +0300 Subject: [PATCH 5/8] updated payment pages --- .../EShopOnAbpPaymentConsts.cs | 1 + .../EShopOnAbp.PublicWeb/Pages/Payment.cshtml.cs | 5 +++-- .../Pages/PaymentCompleted.cshtml.cs | 15 +++++++++++++-- .../wwwroot/components/payment/payment-widget.js | 8 ++++++-- .../Orders/PaymentType.cs | 6 +++--- 5 files changed, 26 insertions(+), 9 deletions(-) diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/EShopOnAbpPaymentConsts.cs b/apps/public-web/src/EShopOnAbp.PublicWeb/EShopOnAbpPaymentConsts.cs index c9a75f54..b58e38a9 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/EShopOnAbpPaymentConsts.cs +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/EShopOnAbpPaymentConsts.cs @@ -3,6 +3,7 @@ public static class EShopOnAbpPaymentConsts { public const string Currency = "USD"; + public const string PaymentIdCookie = "selected_payment_id"; // Setted in payment-widget.js public static class DemoAddressTypes { diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/Payment.cshtml.cs b/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/Payment.cshtml.cs index aac4373c..9ad48597 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/Payment.cshtml.cs +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/Payment.cshtml.cs @@ -59,7 +59,7 @@ public class PaymentModel : AbpPageModel var placedOrder = await _orderAppService.CreateAsync(new OrderCreateDto() { - PaymentTypeId = model.SelectedPaymentId, + PaymentTypeId = model.SelectedPaymentId, Address = GetUserAddress(model.SelectedAddressId), Products = productItems }); @@ -75,9 +75,10 @@ public class PaymentModel : AbpPageModel var response = await _paymentRequestAppService.StartAsync(new PaymentRequestStartDto { + PaymentTypeId = model.SelectedPaymentId, PaymentRequestId = paymentRequest.Id, ReturnUrl = _publicWebPaymentOptions.PaymentSuccessfulCallbackUrl, - CancelUrl = _publicWebPaymentOptions.PaymentFailureCallbackUrl, + CancelUrl = _publicWebPaymentOptions.PaymentFailureCallbackUrl }); return Redirect(response.CheckoutLink); diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/PaymentCompleted.cshtml.cs b/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/PaymentCompleted.cshtml.cs index e313939d..ffaa090e 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/PaymentCompleted.cshtml.cs +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/PaymentCompleted.cshtml.cs @@ -24,12 +24,23 @@ public class PaymentCompletedModel : AbpPageModel public async Task OnGetAsync() { - PaymentRequest = await _paymentRequestAppService.CompleteAsync(Token); + int selectedPaymentId = 0; + if (HttpContext.Request.Cookies.TryGetValue(EShopOnAbpPaymentConsts.PaymentIdCookie, + out var selectedPaymentIdString)) + { + selectedPaymentId = string.IsNullOrEmpty(selectedPaymentIdString) ? 0 : int.Parse(selectedPaymentIdString); + } + + PaymentRequest = await _paymentRequestAppService.CompleteAsync( + new PaymentRequestCompleteInputDto() {Token = Token, PaymentTypeId = selectedPaymentId}); IsSuccessful = PaymentRequest.State == PaymentRequestState.Completed; + if (IsSuccessful) { - return RedirectToPage("OrderReceived", new { orderNo = PaymentRequest.OrderNo }); + // Remove cookie so that can be set again when default payment type is set + HttpContext.Response.Cookies.Delete(EShopOnAbpPaymentConsts.PaymentIdCookie); + return RedirectToPage("OrderReceived", new {orderNo = PaymentRequest.OrderNo}); } return Page(); diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/wwwroot/components/payment/payment-widget.js b/apps/public-web/src/EShopOnAbp.PublicWeb/wwwroot/components/payment/payment-widget.js index 1c541575..0632b47c 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/wwwroot/components/payment/payment-widget.js +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/wwwroot/components/payment/payment-widget.js @@ -1,4 +1,8 @@ (function () { + // Write selected payment type to cookie anyways + const paymentTypeId = $(".payment-list").find(".is-selected").attr('data-payment-id'); + abp.utils.setCookieValue("selected_payment_id", paymentTypeId); + abp.widgets.PaymentWidget = function ($wrapper) { var widgetManager = $wrapper.data('abp-widget-manager'); @@ -7,7 +11,6 @@ .find('.address-list .card') .click(function () { const $this = $(this); - // const addressId = $this.attr('data-address-id'); $this.parents(".address-list").find('.card').removeClass("is-selected"); $this.addClass("is-selected"); }); @@ -16,7 +19,8 @@ .find('.payment-list .card') .click(el => { const $this = $(el.currentTarget); - // const paymentTypeId = $this.attr('data-payment-id'); + const paymentTypeId = $this.attr('data-payment-id'); + abp.utils.setCookieValue("selected_payment_id", paymentTypeId); $this.parents(".payment-list").find('.card').removeClass("is-selected"); $this.addClass("is-selected"); }); diff --git a/services/ordering/src/EShopOnAbp.OrderingService.Domain/Orders/PaymentType.cs b/services/ordering/src/EShopOnAbp.OrderingService.Domain/Orders/PaymentType.cs index 2e556acd..ec3a0e35 100644 --- a/services/ordering/src/EShopOnAbp.OrderingService.Domain/Orders/PaymentType.cs +++ b/services/ordering/src/EShopOnAbp.OrderingService.Domain/Orders/PaymentType.cs @@ -7,16 +7,16 @@ namespace EShopOnAbp.OrderingService.Orders; public class PaymentType : Enumeration { + public static PaymentType Demo = new PaymentType(0, nameof(Demo).ToLowerInvariant()); public static PaymentType Paypal = new PaymentType(1, nameof(Paypal).ToLowerInvariant()); - public static PaymentType Demo = new PaymentType(2, nameof(Paypal).ToLowerInvariant()); public PaymentType(int id, string name) : base(id, name) { } public static IEnumerable List() => - new[] {Paypal, Demo}; - + new[] {Demo, Paypal}; + public static PaymentType FromName(string name) { var state = List() From c15f28ed9b29a8795c67fd6714efeff92c248c57 Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Sat, 8 Jan 2022 23:31:30 +0300 Subject: [PATCH 6/8] removed unused comments and usings --- .../PaymentRequests/IPaymentRequestAppService.cs | 7 ------- .../PaymentRequests/PaymentRequestAppService.cs | 2 -- .../PaymentServiceApplicationModule.cs | 1 + .../PaymentServices/PaymentServiceFactory.cs | 8 +------- 4 files changed, 2 insertions(+), 16 deletions(-) diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application.Contracts/PaymentRequests/IPaymentRequestAppService.cs b/services/payment/src/EShopOnAbp.PaymentService.Application.Contracts/PaymentRequests/IPaymentRequestAppService.cs index c41feb31..366c3413 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.Application.Contracts/PaymentRequests/IPaymentRequestAppService.cs +++ b/services/payment/src/EShopOnAbp.PaymentService.Application.Contracts/PaymentRequests/IPaymentRequestAppService.cs @@ -12,12 +12,5 @@ namespace EShopOnAbp.PaymentService.PaymentRequests Task CompleteAsync(PaymentRequestCompleteInputDto input); Task HandleWebhookAsync(string payload); - // /// - // /// 0 - Demo - // /// 1 - Paypal - // /// - // /// - // /// - // Task SetPaymentServiceAsync(int paymentTypeId); } } diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentRequests/PaymentRequestAppService.cs b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentRequests/PaymentRequestAppService.cs index 82e582f2..9b4120df 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentRequests/PaymentRequestAppService.cs +++ b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentRequests/PaymentRequestAppService.cs @@ -5,7 +5,6 @@ using System; using System.Linq; using System.Threading.Tasks; using EShopOnAbp.PaymentService.PaymentServices; -using Microsoft.Extensions.Logging; namespace EShopOnAbp.PaymentService.PaymentRequests { @@ -16,7 +15,6 @@ namespace EShopOnAbp.PaymentService.PaymentRequests protected IPaymentRequestRepository PaymentRequestRepository { get; } protected PayPalHttpClient PayPalHttpClient { get; } - public PaymentRequestAppService( IPaymentRequestRepository paymentRequestRepository, PayPalHttpClient payPalHttpClient, diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServiceApplicationModule.cs b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServiceApplicationModule.cs index e57c90b7..d4a30160 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServiceApplicationModule.cs +++ b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServiceApplicationModule.cs @@ -7,6 +7,7 @@ using EShopOnAbp.PaymentService.PayPal; using PayPalCheckoutSdk.Core; using System; using EShopOnAbp.PaymentService.PaymentRequests; +using EShopOnAbp.PaymentService.PaymentServices; namespace EShopOnAbp.PaymentService { diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaymentServiceFactory.cs b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaymentServiceFactory.cs index 719ea7da..7e2fab1d 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaymentServiceFactory.cs +++ b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaymentServiceFactory.cs @@ -1,7 +1,6 @@ using System; using EShopOnAbp.PaymentService.PaymentRequests; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; using PayPalCheckoutSdk.Core; using Volo.Abp.DependencyInjection; @@ -10,13 +9,10 @@ namespace EShopOnAbp.PaymentService.PaymentServices; public class PaymentServiceFactory : ITransientDependency { private readonly IServiceProvider _serviceProvider; - private readonly ILogger _logger; - public PaymentServiceFactory(IServiceProvider serviceProvider, ILogger logger) + public PaymentServiceFactory(IServiceProvider serviceProvider) { - logger.LogInformation("== Payment SErvice Factory == "); _serviceProvider = serviceProvider; - _logger = logger; } public IPaymentStrategy Create(int paymentTypeId) @@ -29,9 +25,7 @@ public class PaymentServiceFactory : ITransientDependency if (paymentTypeId == 1) { var paypalService = _serviceProvider.GetRequiredService(); - _logger.LogInformation($"=== Resolved PaypalService {paypalService} ==="); var requestDomainService = _serviceProvider.GetRequiredService(); - _logger.LogInformation($"=== Resolved PaymentRequestDomainService {requestDomainService} ==="); return new PaypalService(paypalService, requestDomainService); } From 172fb205c9bdaba302fb41dc89c9194383477a50 Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Sat, 8 Jan 2022 23:53:25 +0300 Subject: [PATCH 7/8] Updated PaymentFactory injections --- .../PaymentRequests/PaymentRequestAppService.cs | 7 ++++--- .../PaymentServices/DemoService.cs | 2 ++ .../PaymentServices/IPaymentStrategy.cs | 3 ++- .../PaymentServices/PaymentServiceFactory.cs | 11 +++-------- .../PaymentServices/PaypalService.cs | 2 ++ 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentRequests/PaymentRequestAppService.cs b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentRequests/PaymentRequestAppService.cs index 9b4120df..da80df90 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentRequests/PaymentRequestAppService.cs +++ b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentRequests/PaymentRequestAppService.cs @@ -53,8 +53,9 @@ namespace EShopOnAbp.PaymentService.PaymentRequests public virtual async Task StartAsync(PaymentRequestStartDto input) { - PaymentRequest paymentRequest = await PaymentRequestRepository.GetAsync(input.PaymentRequestId, includeDetails: true); - + PaymentRequest paymentRequest = + await PaymentRequestRepository.GetAsync(input.PaymentRequestId, includeDetails: true); + var paymentService = _paymentServiceFactory.Create(input.PaymentTypeId); return await paymentService.StartAsync(paymentRequest, input); } @@ -62,7 +63,7 @@ namespace EShopOnAbp.PaymentService.PaymentRequests public virtual async Task CompleteAsync(PaymentRequestCompleteInputDto input) { var paymentService = _paymentServiceFactory.Create(input.PaymentTypeId); - + var paymentRequest = await paymentService.CompleteAsync(PaymentRequestRepository, input.Token); return ObjectMapper.Map(paymentRequest); } diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/DemoService.cs b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/DemoService.cs index da54bb5d..403d0eb5 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/DemoService.cs +++ b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/DemoService.cs @@ -1,9 +1,11 @@ using System; using System.Threading.Tasks; using EShopOnAbp.PaymentService.PaymentRequests; +using Volo.Abp.DependencyInjection; namespace EShopOnAbp.PaymentService.PaymentServices; +[ExposeServices(typeof(IPaymentStrategy), typeof(DemoService))] public class DemoService : IPaymentStrategy { public Task StartAsync(PaymentRequest paymentRequest, PaymentRequestStartDto input) diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/IPaymentStrategy.cs b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/IPaymentStrategy.cs index aafab8bd..4bb0a065 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/IPaymentStrategy.cs +++ b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/IPaymentStrategy.cs @@ -1,9 +1,10 @@ using System.Threading.Tasks; using EShopOnAbp.PaymentService.PaymentRequests; +using Volo.Abp.DependencyInjection; namespace EShopOnAbp.PaymentService.PaymentServices; -public interface IPaymentStrategy +public interface IPaymentStrategy : ITransientDependency { public Task StartAsync(PaymentRequest paymentRequest, PaymentRequestStartDto input); public Task CompleteAsync(IPaymentRequestRepository paymentRequestRepository, string token); diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaymentServiceFactory.cs b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaymentServiceFactory.cs index 7e2fab1d..0a4c15b4 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaymentServiceFactory.cs +++ b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaymentServiceFactory.cs @@ -1,7 +1,5 @@ using System; -using EShopOnAbp.PaymentService.PaymentRequests; using Microsoft.Extensions.DependencyInjection; -using PayPalCheckoutSdk.Core; using Volo.Abp.DependencyInjection; namespace EShopOnAbp.PaymentService.PaymentServices; @@ -19,17 +17,14 @@ public class PaymentServiceFactory : ITransientDependency { if (paymentTypeId == 0) { - return new DemoService(); + return _serviceProvider.GetRequiredService(); } if (paymentTypeId == 1) { - var paypalService = _serviceProvider.GetRequiredService(); - var requestDomainService = _serviceProvider.GetRequiredService(); - - return new PaypalService(paypalService, requestDomainService); + return _serviceProvider.GetRequiredService(); } - return new DemoService(); + return _serviceProvider.GetRequiredService(); } } \ No newline at end of file diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaypalService.cs b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaypalService.cs index d0dce7c8..17cf81ef 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaypalService.cs +++ b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaypalService.cs @@ -6,9 +6,11 @@ using System.Threading.Tasks; using EShopOnAbp.PaymentService.PaymentRequests; using PayPalCheckoutSdk.Core; using PayPalCheckoutSdk.Orders; +using Volo.Abp.DependencyInjection; namespace EShopOnAbp.PaymentService.PaymentServices; +[ExposeServices(typeof(IPaymentStrategy), typeof(PaypalService))] public class PaypalService : IPaymentStrategy { private readonly PayPalHttpClient _payPalHttpClient; From e3acd376b581362c6dfefc92e161e8d76e2efd50 Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Sun, 9 Jan 2022 00:49:34 +0300 Subject: [PATCH 8/8] Updated to resolvers --- .../PaymentRequestAppService.cs | 10 +++--- .../PaymentServiceApplicationModule.cs | 10 ++++-- .../{DemoService.cs => DemoPaymentMethod.cs} | 11 +++++-- ...{IPaymentStrategy.cs => IPaymentMethod.cs} | 3 +- .../PaymentServices/PaymentMethodResolver.cs | 31 +++++++++++++++++++ .../PaymentServices/PaymentServiceFactory.cs | 30 ------------------ .../{PaypalService.cs => PaypalMethod.cs} | 8 +++-- 7 files changed, 60 insertions(+), 43 deletions(-) rename services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/{DemoService.cs => DemoPaymentMethod.cs} (78%) rename services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/{IPaymentStrategy.cs => IPaymentMethod.cs} (81%) create mode 100644 services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaymentMethodResolver.cs delete mode 100644 services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaymentServiceFactory.cs rename services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/{PaypalService.cs => PaypalMethod.cs} (92%) diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentRequests/PaymentRequestAppService.cs b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentRequests/PaymentRequestAppService.cs index da80df90..15b62860 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentRequests/PaymentRequestAppService.cs +++ b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentRequests/PaymentRequestAppService.cs @@ -10,7 +10,7 @@ namespace EShopOnAbp.PaymentService.PaymentRequests { public class PaymentRequestAppService : PaymentServiceAppService, IPaymentRequestAppService { - private readonly PaymentServiceFactory _paymentServiceFactory; + private readonly PaymentMethodResolver _paymentMethodResolver; private readonly PaymentRequestDomainService _paymentRequestDomainService; protected IPaymentRequestRepository PaymentRequestRepository { get; } protected PayPalHttpClient PayPalHttpClient { get; } @@ -18,12 +18,12 @@ namespace EShopOnAbp.PaymentService.PaymentRequests public PaymentRequestAppService( IPaymentRequestRepository paymentRequestRepository, PayPalHttpClient payPalHttpClient, - PaymentServiceFactory paymentServiceFactory, + PaymentMethodResolver paymentMethodResolver, PaymentRequestDomainService paymentRequestDomainService) { PaymentRequestRepository = paymentRequestRepository; PayPalHttpClient = payPalHttpClient; - _paymentServiceFactory = paymentServiceFactory; + _paymentMethodResolver = paymentMethodResolver; _paymentRequestDomainService = paymentRequestDomainService; } @@ -56,13 +56,13 @@ namespace EShopOnAbp.PaymentService.PaymentRequests PaymentRequest paymentRequest = await PaymentRequestRepository.GetAsync(input.PaymentRequestId, includeDetails: true); - var paymentService = _paymentServiceFactory.Create(input.PaymentTypeId); + var paymentService = _paymentMethodResolver.Resolve(input.PaymentTypeId); return await paymentService.StartAsync(paymentRequest, input); } public virtual async Task CompleteAsync(PaymentRequestCompleteInputDto input) { - var paymentService = _paymentServiceFactory.Create(input.PaymentTypeId); + var paymentService = _paymentMethodResolver.Resolve(input.PaymentTypeId); var paymentRequest = await paymentService.CompleteAsync(PaymentRequestRepository, input.Token); return ObjectMapper.Map(paymentRequest); diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServiceApplicationModule.cs b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServiceApplicationModule.cs index d4a30160..f0b21e0f 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServiceApplicationModule.cs +++ b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServiceApplicationModule.cs @@ -8,6 +8,7 @@ using PayPalCheckoutSdk.Core; using System; using EShopOnAbp.PaymentService.PaymentRequests; using EShopOnAbp.PaymentService.PaymentServices; +using Microsoft.Extensions.Logging; namespace EShopOnAbp.PaymentService { @@ -16,7 +17,7 @@ namespace EShopOnAbp.PaymentService typeof(PaymentServiceApplicationContractsModule), typeof(AbpDddApplicationModule), typeof(AbpAutoMapperModule) - )] + )] public class PaymentServiceApplicationModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) @@ -40,6 +41,11 @@ namespace EShopOnAbp.PaymentService return new PayPalHttpClient(new LiveEnvironment(options.ClientId, options.Secret)); }); + + context.Services.AddTransient(provider => new PaymentMethodResolver( + provider.GetServices(), + provider.GetRequiredService>() + )); } } -} +} \ No newline at end of file diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/DemoService.cs b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/DemoPaymentMethod.cs similarity index 78% rename from services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/DemoService.cs rename to services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/DemoPaymentMethod.cs index 403d0eb5..46c8e24d 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/DemoService.cs +++ b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/DemoPaymentMethod.cs @@ -5,9 +5,16 @@ using Volo.Abp.DependencyInjection; namespace EShopOnAbp.PaymentService.PaymentServices; -[ExposeServices(typeof(IPaymentStrategy), typeof(DemoService))] -public class DemoService : IPaymentStrategy +[ExposeServices(typeof(IPaymentMethod), typeof(DemoPaymentMethod))] +public class DemoPaymentMethod : IPaymentMethod { + public int PaymentTypeId { get; } + + public DemoPaymentMethod() + { + PaymentTypeId = 0; + } + public Task StartAsync(PaymentRequest paymentRequest, PaymentRequestStartDto input) { return Task.FromResult(new PaymentRequestStartResultDto diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/IPaymentStrategy.cs b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/IPaymentMethod.cs similarity index 81% rename from services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/IPaymentStrategy.cs rename to services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/IPaymentMethod.cs index 4bb0a065..16d1ed6c 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/IPaymentStrategy.cs +++ b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/IPaymentMethod.cs @@ -4,8 +4,9 @@ using Volo.Abp.DependencyInjection; namespace EShopOnAbp.PaymentService.PaymentServices; -public interface IPaymentStrategy : ITransientDependency +public interface IPaymentMethod : ITransientDependency { + public int PaymentTypeId { get; } public Task StartAsync(PaymentRequest paymentRequest, PaymentRequestStartDto input); public Task CompleteAsync(IPaymentRequestRepository paymentRequestRepository, string token); } \ No newline at end of file diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaymentMethodResolver.cs b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaymentMethodResolver.cs new file mode 100644 index 00000000..7973da79 --- /dev/null +++ b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaymentMethodResolver.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Extensions.Logging; +using Volo.Abp.DependencyInjection; + +namespace EShopOnAbp.PaymentService.PaymentServices; + +public class PaymentMethodResolver : ITransientDependency +{ + private readonly IEnumerable _paymentMethods; + private readonly ILogger _logger; + + public PaymentMethodResolver(IEnumerable paymentMethods, ILogger logger) + { + _paymentMethods = paymentMethods; + _logger = logger; + } + + public IPaymentMethod Resolve(int paymentTypeId) + { + IPaymentMethod paymentMethod = _paymentMethods.FirstOrDefault(q => q.PaymentTypeId == paymentTypeId); + if (paymentMethod == null) + { + _logger.LogError($"Couldn't find Payment method with id:{paymentTypeId}"); + throw new ArgumentException("Payment method not found", paymentTypeId.ToString()); + } + + return paymentMethod; + } +} \ No newline at end of file diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaymentServiceFactory.cs b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaymentServiceFactory.cs deleted file mode 100644 index 0a4c15b4..00000000 --- a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaymentServiceFactory.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.DependencyInjection; - -namespace EShopOnAbp.PaymentService.PaymentServices; - -public class PaymentServiceFactory : ITransientDependency -{ - private readonly IServiceProvider _serviceProvider; - - public PaymentServiceFactory(IServiceProvider serviceProvider) - { - _serviceProvider = serviceProvider; - } - - public IPaymentStrategy Create(int paymentTypeId) - { - if (paymentTypeId == 0) - { - return _serviceProvider.GetRequiredService(); - } - - if (paymentTypeId == 1) - { - return _serviceProvider.GetRequiredService(); - } - - return _serviceProvider.GetRequiredService(); - } -} \ No newline at end of file diff --git a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaypalService.cs b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaypalMethod.cs similarity index 92% rename from services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaypalService.cs rename to services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaypalMethod.cs index 17cf81ef..c660f112 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaypalService.cs +++ b/services/payment/src/EShopOnAbp.PaymentService.Application/PaymentServices/PaypalMethod.cs @@ -10,16 +10,18 @@ using Volo.Abp.DependencyInjection; namespace EShopOnAbp.PaymentService.PaymentServices; -[ExposeServices(typeof(IPaymentStrategy), typeof(PaypalService))] -public class PaypalService : IPaymentStrategy +[ExposeServices(typeof(IPaymentMethod), typeof(PaypalMethod))] +public class PaypalMethod : IPaymentMethod { private readonly PayPalHttpClient _payPalHttpClient; private readonly PaymentRequestDomainService _paymentRequestDomainService; + public int PaymentTypeId { get; } - public PaypalService(PayPalHttpClient payPalHttpClient, PaymentRequestDomainService paymentRequestDomainService) + public PaypalMethod(PayPalHttpClient payPalHttpClient, PaymentRequestDomainService paymentRequestDomainService) { _payPalHttpClient = payPalHttpClient; _paymentRequestDomainService = paymentRequestDomainService; + PaymentTypeId = 1; } public async Task StartAsync(PaymentRequest paymentRequest,