125 lines
4.4 KiB
C#
125 lines
4.4 KiB
C#
using System.Text;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.Net.Http.Headers;
|
|
using Newtonsoft.Json;
|
|
using Nop.Core;
|
|
using Nop.Plugin.Misc.Zettle.Domain.Api;
|
|
using Nop.Plugin.Misc.Zettle.Domain.Api.OAuth;
|
|
|
|
namespace Nop.Plugin.Misc.Zettle.Services;
|
|
|
|
/// <summary>
|
|
/// Represents HTTP client to request third-party services
|
|
/// </summary>
|
|
public class ZettleHttpClient
|
|
{
|
|
#region Fields
|
|
|
|
protected readonly HttpClient _httpClient;
|
|
protected readonly ZettleSettings _zettleSettings;
|
|
|
|
protected string _accessToken;
|
|
|
|
#endregion
|
|
|
|
#region Ctor
|
|
|
|
public ZettleHttpClient(HttpClient httpClient, ZettleSettings zettleSettings)
|
|
{
|
|
httpClient.Timeout = TimeSpan.FromSeconds(zettleSettings.RequestTimeout ?? ZettleDefaults.RequestTimeout);
|
|
httpClient.DefaultRequestHeaders.Add(HeaderNames.UserAgent, ZettleDefaults.UserAgent);
|
|
httpClient.DefaultRequestHeaders.Add(HeaderNames.Accept, MimeTypes.ApplicationJson);
|
|
httpClient.DefaultRequestHeaders.Add(ZettleDefaults.PartnerHeader.Name, ZettleDefaults.PartnerHeader.Value);
|
|
|
|
_httpClient = httpClient;
|
|
_zettleSettings = zettleSettings;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Utilities
|
|
|
|
/// <summary>
|
|
/// Get access token
|
|
/// </summary>
|
|
/// <returns>The asynchronous task whose result contains access token</returns>
|
|
protected async Task<string> GetAccessTokenAsync()
|
|
{
|
|
if (!string.IsNullOrEmpty(_accessToken))
|
|
return _accessToken;
|
|
|
|
if (string.IsNullOrEmpty(_zettleSettings.ApiKey))
|
|
throw new NopException("API key is not set");
|
|
|
|
_accessToken = (await RequestAsync<GetAuthenticationRequest, Authentication>(new()
|
|
{
|
|
Assertion = _zettleSettings.ApiKey,
|
|
ClientId = ZettleDefaults.PartnerHeader.Value,
|
|
GrantType = "urn:ietf:params:oauth:grant-type:jwt-bearer"
|
|
}))?.AccessToken;
|
|
|
|
return _accessToken;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Methods
|
|
|
|
/// <summary>
|
|
/// Request services
|
|
/// </summary>
|
|
/// <typeparam name="TRequest">Request type</typeparam>
|
|
/// <typeparam name="TResponse">Response type</typeparam>
|
|
/// <param name="request">Request</param>
|
|
/// <returns>The asynchronous task whose result contains response details</returns>
|
|
public async Task<TResponse> RequestAsync<TRequest, TResponse>(TRequest request) where TRequest : IApiRequest where TResponse : IApiResponse
|
|
{
|
|
//prepare request parameters
|
|
var requestString = JsonConvert.SerializeObject(request);
|
|
var requestContent = request is not GetAuthenticationRequest authentication
|
|
? (ByteArrayContent)new StringContent(requestString, Encoding.UTF8, MimeTypes.ApplicationJson)
|
|
: new FormUrlEncodedContent(new Dictionary<string, string>
|
|
{
|
|
["assertion"] = authentication.Assertion,
|
|
["client_id"] = authentication.ClientId,
|
|
["grant_type"] = authentication.GrantType
|
|
});
|
|
|
|
var requestMessage = new HttpRequestMessage(new HttpMethod(request.Method), new Uri(new Uri(request.BaseUrl), request.Path))
|
|
{
|
|
Content = requestContent
|
|
};
|
|
|
|
//add authorization
|
|
if (request is IAuthorizedRequest)
|
|
{
|
|
var accessToken = await GetAccessTokenAsync();
|
|
requestMessage.Headers.Add(HeaderNames.Authorization, $"Bearer {accessToken}");
|
|
}
|
|
|
|
//add ETag
|
|
if (request is IConditionalRequest conditionalRequest)
|
|
{
|
|
var header = request.Method == HttpMethods.Get
|
|
? HeaderNames.IfNoneMatch
|
|
: HeaderNames.IfMatch;
|
|
requestMessage.Headers.Add(header, conditionalRequest.ETag);
|
|
}
|
|
|
|
//execute request and get result
|
|
var httpResponse = await _httpClient.SendAsync(requestMessage);
|
|
var responseString = await httpResponse.Content.ReadAsStringAsync();
|
|
var result = JsonConvert.DeserializeObject<TResponse>(responseString ?? string.Empty);
|
|
if (!string.IsNullOrEmpty(result?.Error))
|
|
{
|
|
var error = !string.IsNullOrEmpty(result.ErrorDescription) ? result.ErrorDescription : result.Error;
|
|
throw new NopException($"Request error: {error}");
|
|
}
|
|
if (!string.IsNullOrEmpty(result?.DeveloperMessage))
|
|
throw new NopException($"Request error: {result.DeveloperMessage}{Environment.NewLine}Details: {responseString}");
|
|
|
|
return result;
|
|
}
|
|
|
|
#endregion
|
|
} |