Try your search with a different keyword or use * as a wildcard.
using System.Text;
using Microsoft.Net.Http.Headers;
using Newtonsoft.Json;
using Nop.Core;
using Nop.Plugin.Payments.PayPalCommerce.Services.Api;
using Nop.Plugin.Payments.PayPalCommerce.Services.Api.Authentication;
using Nop.Plugin.Payments.PayPalCommerce.Services.Api.Models;
using Nop.Plugin.Payments.PayPalCommerce.Services.Api.Onboarding;
namespace Nop.Plugin.Payments.PayPalCommerce.Services;
///
/// Represents the HTTP client to request PayPal API
///
public class PayPalCommerceHttpClient
{
#region Fields
private readonly HttpClient _httpClient;
private static Dictionary _accessTokens = new();
#endregion
#region Ctor
public PayPalCommerceHttpClient(HttpClient httpClient)
{
_httpClient = httpClient;
}
#endregion
#region Utilities
///
/// Get access token
///
/// Plugin settings
///
/// A task that represents the asynchronous operation
/// The task result contains the access token
///
private async Task GetAccessTokenAsync(PayPalCommerceSettings settings)
{
if (!PayPalCommerceServiceManager.IsConfigured(settings))
throw new NopException("Plugin is not configured");
//no need to request a token if there is already a cached one and it has not expired (lifetime is about 9 hours)
if (!_accessTokens.TryGetValue(settings.ClientId, out var accessToken) ||
string.IsNullOrEmpty(accessToken?.Token) ||
accessToken.IsExpired)
{
//get new access token
accessToken = await RequestAsync(new()
{
ClientId = settings.ClientId,
Secret = settings.SecretKey,
GrantType = "client_credentials"
}, settings);
_accessTokens[settings.ClientId] = accessToken;
}
return accessToken.Token;
}
#endregion
#region Methods
///
/// Request remote service
///
/// Request type
/// Response type
/// Request
/// Plugin settings
///
/// A task that represents the asynchronous operation
/// The task result contains the response details
///
public async Task RequestAsync(TRequest request, PayPalCommerceSettings settings)
where TRequest : IApiRequest where TResponse : IApiResponse
{
//prepare request body, content is always JSON except for access token requests
var requestString = JsonConvert.SerializeObject(request, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
var requestContent = request is GetAccessTokenRequest accessTokenRequest
? new FormUrlEncodedContent(PayPalCommerceServiceManager.ObjectToDictionary(accessTokenRequest))
: (ByteArrayContent)new StringContent(requestString, Encoding.Default, MimeTypes.ApplicationJson);
//URL depends on environment
var baseUrl = settings.UseSandbox
? PayPalCommerceDefaults.ServiceUrl.Sandbox
: PayPalCommerceDefaults.ServiceUrl.Live;
var requestMessage = new HttpRequestMessage(new HttpMethod(request.Method), new Uri(new Uri(baseUrl), request.Path))
{
Content = requestContent
};
//set timeout
try
{
var timeout = TimeSpan.FromSeconds(settings.RequestTimeout ?? PayPalCommerceDefaults.RequestTimeout);
if (_httpClient.Timeout != timeout)
_httpClient.Timeout = timeout;
}
catch { }
//add authorization and some custom headers
var authorization = request switch
{
IAuthorizedRequest => $"Bearer {await GetAccessTokenAsync(settings)}",
GetCredentialsRequest credentialsRequest => $"Bearer {credentialsRequest.AccessToken}",
GetAccessTokenRequest tokenRequest =>
$"Basic {Convert.ToBase64String(Encoding.Default.GetBytes($"{tokenRequest.ClientId}:{tokenRequest.Secret}"))}",
_ => null
};
if (!string.IsNullOrEmpty(authorization))
requestMessage.Headers.Add(HeaderNames.Authorization, authorization);
requestMessage.Headers.Add(HeaderNames.UserAgent, PayPalCommerceDefaults.UserAgent);
requestMessage.Headers.Add(HeaderNames.Accept, MimeTypes.ApplicationJson);
requestMessage.Headers.Add(PayPalCommerceDefaults.PartnerHeader.Name, PayPalCommerceDefaults.PartnerHeader.Value);
requestMessage.Headers.Add("PayPal-Request-Id", Guid.NewGuid().ToString());
requestMessage.Headers.Add("Prefer", "return=representation");
//execute the request and get a result
var httpResponse = await _httpClient.SendAsync(requestMessage);
var responseString = await httpResponse.Content.ReadAsStringAsync();
//successful request processing
if (httpResponse.IsSuccessStatusCode)
{
if (typeof(TResponse) == typeof(EmptyResponse))
return default;
return JsonConvert.DeserializeObject(responseString ?? string.Empty) ?? default;
}
//failed request processing
var error = $"Failed request ({httpResponse.StatusCode})";
var identityErrorResponse = JsonConvert.DeserializeObject(responseString ?? string.Empty);
if (!string.IsNullOrEmpty(identityErrorResponse?.Error))
{
var description = !string.IsNullOrEmpty(identityErrorResponse.ErrorDescription)
? identityErrorResponse.ErrorDescription
: identityErrorResponse.Error;
error += $": {description}";
}
var errorResponse = JsonConvert.DeserializeObject(responseString ?? string.Empty);
if (!string.IsNullOrEmpty(errorResponse?.Name))
{
error += $": {(!string.IsNullOrEmpty(errorResponse.Message) ? errorResponse.Message : errorResponse.Name)}";
error += $"{Environment.NewLine}{JsonConvert.SerializeObject(errorResponse, Formatting.Indented)}";
}
throw new NopException("Failed request", new NopException(error));
}
#endregion
}