forked from tsai/eShopOnAbp
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 |
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