264 lines
11 KiB
C#
264 lines
11 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Net;
|
|
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using gehGassi.Core.Interfaces;
|
|
using gehGassi.Domain.Common;
|
|
using Microsoft.Extensions.Options;
|
|
using PayPalCheckoutSdk.Core;
|
|
using PayPalCheckoutSdk.Orders;
|
|
using PayPalHttp;
|
|
|
|
|
|
namespace gehGassi.External.Services
|
|
{
|
|
/// <summary>
|
|
/// Service der alle PayPal-Funktionen zur Verfügung stellt
|
|
/// </summary>
|
|
public class PayPalService : IPayPalService
|
|
{
|
|
private HttpClient _httpClient;
|
|
private readonly IOptions<ShopOptions> _shopOptions;
|
|
private readonly IOrderService _orderService;
|
|
private readonly ICustomerService _customerService;
|
|
|
|
/// <summary>
|
|
/// Erstellt eine Instanz
|
|
/// </summary>
|
|
/// <param name="shopOptions">Instanz von PaymentOptions</param>
|
|
/// <param name="orderService">Instanz eines IOrderService</param>
|
|
/// <param name="customerService">Instanz eines ICustomerService</param>
|
|
public PayPalService(IOptions<ShopOptions> shopOptions, IOrderService orderService, ICustomerService customerService)
|
|
{
|
|
_shopOptions = shopOptions;
|
|
_orderService = orderService;
|
|
_customerService = customerService;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt einen HTTP-Client für die Kommunikation mit PayPal zurück
|
|
/// </summary>
|
|
/// <param name="environment">PayPalEnvironment</param>
|
|
/// <returns>HttpClient</returns>
|
|
internal HttpClient GetHttpClient(PayPalEnvironment environment)
|
|
{
|
|
return _httpClient ??= new PayPalHttpClient(environment);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt das PayPal Environment basierend auf den Einstellungen zurück
|
|
/// </summary>
|
|
/// <param name="clientId">PayPal ClientId</param>
|
|
/// <param name="secret">PayPal Secret</param>
|
|
/// <returns>PayPal Environment</returns>
|
|
internal PayPalEnvironment GetEnvironment(string clientId, string secret)
|
|
{
|
|
PayPalEnvironment environment;
|
|
if (_shopOptions.Value.PayPalUseSandbox)
|
|
environment = new SandboxEnvironment(clientId, secret);
|
|
else
|
|
environment = new LiveEnvironment(clientId, secret);
|
|
return environment;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Prüft ob die PayPal Credentials korrekt sind und eine Verbindung zur Api aufgenommen werden kann
|
|
/// </summary>
|
|
/// <param name="clientId">PayPal ClientId</param>
|
|
/// <param name="secret">PayPal Secret</param>
|
|
/// <returns>true wenn erfolgreich, false sonst</returns>
|
|
public async Task<bool> TestCredentialsAsync(string clientId, string secret)
|
|
{
|
|
var environment = GetEnvironment(clientId, secret);
|
|
var client = GetHttpClient(environment);
|
|
var request = new AccessTokenRequest(GetEnvironment(clientId, secret));
|
|
try
|
|
{
|
|
var result = await client.Execute(request);
|
|
return result.StatusCode == HttpStatusCode.OK;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Erstellen einer PayPal-Order
|
|
/// </summary>
|
|
/// <param name="orderId">Id der Bestellung</param>
|
|
/// <param name="clientId">PayPal ClientId</param>
|
|
/// <param name="secret">PayPal Secret</param>
|
|
/// <param name="successUrl">Redirect-Url für ERFOLG</param>
|
|
/// <param name="cancelUrl">Redirect-URL für Fehler oder Abbrechen</param>
|
|
/// <returns>REdirect-Url zu PayPal oder leer wenn Fehler</returns>
|
|
public async Task<string> CreateOrderAsync(long orderId, string clientId, string secret, string successUrl, string cancelUrl)
|
|
{
|
|
var environment = GetEnvironment(clientId, secret);
|
|
var client = GetHttpClient(environment);
|
|
|
|
var order = await _orderService.GetAsync(orderId);
|
|
if (order == null)
|
|
return string.Empty;
|
|
|
|
var orderItems = await _orderService.GetItemsAsync(orderId);
|
|
if (!orderItems.Any())
|
|
return string.Empty;
|
|
|
|
var customer = await _customerService.GetAsync(order.CustomerId.Value);
|
|
if (customer == null)
|
|
return string.Empty;
|
|
|
|
var payPalOrder = new OrderRequest
|
|
{
|
|
CheckoutPaymentIntent = "CAPTURE",
|
|
ApplicationContext = new ApplicationContext()
|
|
{
|
|
BrandName = $"gehGassi GmbH",
|
|
LandingPage = "NO_PREFERENCE",
|
|
UserAction = "CONTINUE",
|
|
ShippingPreference = "SET_PROVIDED_ADDRESS",
|
|
ReturnUrl = successUrl,
|
|
CancelUrl = cancelUrl
|
|
},
|
|
PurchaseUnits = new List<PurchaseUnitRequest>()
|
|
{
|
|
new PurchaseUnitRequest()
|
|
{
|
|
CustomId = order.UniqueId.ToString(),
|
|
InvoiceId = order.Number,
|
|
SoftDescriptor = $"gehGassi GmbH",
|
|
AmountWithBreakdown = new AmountWithBreakdown()
|
|
{
|
|
AmountBreakdown = new AmountBreakdown()
|
|
{
|
|
ItemTotal = new Money(){CurrencyCode = "EUR", Value = order.Subtotal.ToString(CultureInfo.InvariantCulture)},
|
|
Shipping = new Money(){CurrencyCode = "EUR", Value = order.Shipment.ToString(CultureInfo.InvariantCulture)},
|
|
TaxTotal = new Money(){CurrencyCode = "EUR", Value = (order.TotalGross - order.Total).ToString(CultureInfo.InvariantCulture)},
|
|
},
|
|
CurrencyCode = "EUR",
|
|
Value = order.TotalGross.ToString(CultureInfo.InvariantCulture)
|
|
},
|
|
ShippingDetail = new ShippingDetail()
|
|
{
|
|
Name = new Name()
|
|
{
|
|
FullName = $"{order.DeliveryAddress.GetNameForPayPal()}"
|
|
},
|
|
AddressPortable = new AddressPortable()
|
|
{
|
|
AddressLine1 = order.DeliveryAddress.AddressLine1,
|
|
AddressLine2 = order.DeliveryAddress.AddressLine2,
|
|
AdminArea2 = order.DeliveryAddress.City,
|
|
AdminArea1 = order.DeliveryAddress.State,
|
|
PostalCode = order.DeliveryAddress.Zip,
|
|
CountryCode = order.DeliveryAddress.CountryCode
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
var items = new List<Item>();
|
|
foreach (var orderItem in orderItems)
|
|
{
|
|
var price = orderItem.Price + orderItem.Price2;
|
|
price = decimal.Round(price, 2, MidpointRounding.AwayFromZero);
|
|
var item = new Item()
|
|
{
|
|
Name = orderItem.Name,
|
|
Quantity = orderItem.Quantity.ToString(CultureInfo.InvariantCulture),
|
|
UnitAmount = new Money() { CurrencyCode = "EUR", Value = price.ToString(CultureInfo.InvariantCulture) },
|
|
//Tax = new Money() { CurrencyCode = "EUR", Value = (orderItem.PriceGross - orderItem.Price).ToString(CultureInfo.InvariantCulture) },
|
|
//Category = "PHYSICAL_GOODS"
|
|
};
|
|
switch (orderItem.ProductType)
|
|
{
|
|
case ProductType.Physical:
|
|
item.Category = "PHYSICAL_GOODS";
|
|
break;
|
|
case ProductType.Download:
|
|
item.Category = "DIGITAL_GOODS";
|
|
break;
|
|
case ProductType.Listing:
|
|
item.Category = "DIGITAL_GOODS";
|
|
break;
|
|
case ProductType.Advertisement:
|
|
item.Category = "DIGITAL_GOODS";
|
|
break;
|
|
case ProductType.Pin:
|
|
item.Category = "DIGITAL_GOODS";
|
|
break;
|
|
case ProductType.Banner:
|
|
item.Category = "DIGITAL_GOODS";
|
|
break;
|
|
default:
|
|
item.Category = "PHYSICAL_GOODS";
|
|
break;
|
|
}
|
|
|
|
items.Add(item);
|
|
}
|
|
payPalOrder.PurchaseUnits.First().Items = items;
|
|
|
|
try
|
|
{
|
|
|
|
var payPalOrderCreateRequest = new OrdersCreateRequest();
|
|
payPalOrderCreateRequest.Prefer("return=representation");
|
|
payPalOrderCreateRequest.RequestBody(payPalOrder);
|
|
var orderResponse = await _httpClient.Execute(payPalOrderCreateRequest);
|
|
var statusCode = orderResponse.StatusCode;
|
|
if (statusCode == HttpStatusCode.Created)
|
|
{
|
|
var result = orderResponse.Result<Order>();
|
|
|
|
var approveLink = string.Empty;
|
|
if (result.Links.Any())
|
|
{
|
|
var link = result.Links.FirstOrDefault(c => c.Rel == "approve");
|
|
if (link != null)
|
|
approveLink = link.Href;
|
|
}
|
|
|
|
order.PayPalOrderId = result.Id;
|
|
order.PaymentStatus = PaymentStatus.Pending;
|
|
order.PaymentInfo = $"{DateTime.UtcNow}: PayPal order created. OrderId: {result.Id}" + System.Environment.NewLine + order.PaymentInfo;
|
|
await _orderService.CommitAsync("paypal");
|
|
|
|
return approveLink;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
var msg = ex.Message;
|
|
}
|
|
return string.Empty;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Authorisieren der PayPal Order - Bezahlung durchführen
|
|
/// </summary>
|
|
/// <param name="payPalOrder">PayPal-Order-Id</param>
|
|
/// <param name="clientId">PayPal ClientId</param>
|
|
/// <param name="secret">PayPal Secret</param>
|
|
/// <returns>true wenn erfolgreich, false sonst</returns>
|
|
public async Task<bool> AuthorizeOrderAsync(string payPalOrder, string clientId, string secret)
|
|
{
|
|
var environment = GetEnvironment(clientId, secret);
|
|
var client = GetHttpClient(environment);
|
|
|
|
var request = new OrdersCaptureRequest(payPalOrder);
|
|
request.Prefer("return=representation");
|
|
request.RequestBody(new OrderActionRequest());
|
|
var response = await client.Execute(request);
|
|
var result = response.Result<Order>();
|
|
return result.Status.ToUpper() == "COMPLETED";
|
|
}
|
|
}
|
|
}
|