committed by
GitHub
29 changed files with 404 additions and 227 deletions
@ -0,0 +1,24 @@ |
|||
using System.Collections.Generic; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace EShopOnAbp.PublicWeb.ServiceProviders; |
|||
|
|||
public class PaymentTypeProvider : ITransientDependency |
|||
{ |
|||
public List<PaymentType> GetPaymentTypes() |
|||
{ |
|||
return new List<PaymentType> |
|||
{ |
|||
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; |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
using System; |
|||
|
|||
namespace EShopOnAbp.PaymentService.PaymentRequests; |
|||
|
|||
[Serializable] |
|||
public class PaymentRequestCompleteInputDto |
|||
{ |
|||
public string Token { get; set; } |
|||
public int PaymentTypeId { get; set; } |
|||
} |
|||
@ -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<PaymentRequestStartResultDto> StartAsync(PaymentRequestStartDto input) |
|||
{ |
|||
return Task.FromResult(new PaymentRequestStartResultDto |
|||
{ |
|||
CheckoutLink = input.ReturnUrl + "?token=" + input.PaymentRequestId |
|||
}); |
|||
} |
|||
|
|||
public override async Task<PaymentRequestDto> CompleteAsync(string token) |
|||
{ |
|||
var paymentRequest = await PaymentRequestRepository.GetAsync(Guid.Parse(token)); |
|||
|
|||
paymentRequest.SetAsCompleted(); |
|||
|
|||
await PaymentRequestRepository.UpdateAsync(paymentRequest); |
|||
|
|||
return ObjectMapper.Map<PaymentRequest, PaymentRequestDto>(paymentRequest); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using EShopOnAbp.PaymentService.PaymentRequests; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace EShopOnAbp.PaymentService.PaymentServices; |
|||
|
|||
[ExposeServices(typeof(IPaymentMethod), typeof(DemoPaymentMethod))] |
|||
public class DemoPaymentMethod : IPaymentMethod |
|||
{ |
|||
public int PaymentTypeId { get; } |
|||
|
|||
public DemoPaymentMethod() |
|||
{ |
|||
PaymentTypeId = 0; |
|||
} |
|||
|
|||
public Task<PaymentRequestStartResultDto> StartAsync(PaymentRequest paymentRequest, PaymentRequestStartDto input) |
|||
{ |
|||
return Task.FromResult(new PaymentRequestStartResultDto |
|||
{ |
|||
CheckoutLink = input.ReturnUrl + "?token=" + input.PaymentRequestId |
|||
}); |
|||
} |
|||
|
|||
public async Task<PaymentRequest> CompleteAsync(IPaymentRequestRepository paymentRequestRepository, string token) |
|||
{ |
|||
var paymentRequest = await paymentRequestRepository.GetAsync(Guid.Parse(token)); |
|||
|
|||
paymentRequest.SetAsCompleted(); |
|||
|
|||
return await paymentRequestRepository.UpdateAsync(paymentRequest); |
|||
} |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
using System.Threading.Tasks; |
|||
using EShopOnAbp.PaymentService.PaymentRequests; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace EShopOnAbp.PaymentService.PaymentServices; |
|||
|
|||
public interface IPaymentMethod : ITransientDependency |
|||
{ |
|||
public int PaymentTypeId { get; } |
|||
public Task<PaymentRequestStartResultDto> StartAsync(PaymentRequest paymentRequest, PaymentRequestStartDto input); |
|||
public Task<PaymentRequest> CompleteAsync(IPaymentRequestRepository paymentRequestRepository, string token); |
|||
} |
|||
@ -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<IPaymentMethod> _paymentMethods; |
|||
private readonly ILogger<PaymentMethodResolver> _logger; |
|||
|
|||
public PaymentMethodResolver(IEnumerable<IPaymentMethod> paymentMethods, ILogger<PaymentMethodResolver> 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; |
|||
} |
|||
} |
|||
@ -0,0 +1,98 @@ |
|||
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; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace EShopOnAbp.PaymentService.PaymentServices; |
|||
|
|||
[ExposeServices(typeof(IPaymentMethod), typeof(PaypalMethod))] |
|||
public class PaypalMethod : IPaymentMethod |
|||
{ |
|||
private readonly PayPalHttpClient _payPalHttpClient; |
|||
private readonly PaymentRequestDomainService _paymentRequestDomainService; |
|||
public int PaymentTypeId { get; } |
|||
|
|||
public PaypalMethod(PayPalHttpClient payPalHttpClient, PaymentRequestDomainService paymentRequestDomainService) |
|||
{ |
|||
_payPalHttpClient = payPalHttpClient; |
|||
_paymentRequestDomainService = paymentRequestDomainService; |
|||
PaymentTypeId = 1; |
|||
} |
|||
|
|||
public async Task<PaymentRequestStartResultDto> 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<PurchaseUnitRequest> |
|||
{ |
|||
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<Order>(); |
|||
|
|||
return new PaymentRequestStartResultDto |
|||
{ |
|||
CheckoutLink = result.Links.First(x => x.Rel == "approve").Href |
|||
}; |
|||
} |
|||
|
|||
public async Task<PaymentRequest> CompleteAsync(IPaymentRequestRepository paymentRequestRepository, string token) |
|||
{ |
|||
var request = new OrdersCaptureRequest(token); |
|||
request.RequestBody(new OrderActionRequest()); |
|||
|
|||
var order = (await _payPalHttpClient.Execute(request)).Result<Order>(); |
|||
|
|||
var paymentRequestId = Guid.Parse(order.PurchaseUnits.First().ReferenceId); |
|||
return await _paymentRequestDomainService.UpdatePaymentRequestStateAsync(paymentRequestId, order.Status, |
|||
order.Id); |
|||
} |
|||
} |
|||
@ -1,4 +1,4 @@ |
|||
namespace EShopOnAbp.PaymentService.PayPal |
|||
namespace EShopOnAbp.PaymentService |
|||
{ |
|||
public static class PayPalConsts |
|||
{ |
|||
@ -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<PaymentRequest> 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; |
|||
} |
|||
} |
|||
Loading…
Reference in new issue