2020-03-02 16:50:28 +01:00
|
|
|
using System;
|
|
|
|
using System.Collections;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Linq;
|
|
|
|
using System.Net.Http;
|
|
|
|
using System.Net.Http.Headers;
|
2020-03-13 11:47:22 +01:00
|
|
|
using System.Text;
|
2021-04-26 05:37:56 +02:00
|
|
|
using System.Threading;
|
2020-03-02 16:50:28 +01:00
|
|
|
using System.Threading.Tasks;
|
2020-03-20 06:01:51 +01:00
|
|
|
using Newtonsoft.Json;
|
2020-03-02 16:50:28 +01:00
|
|
|
|
|
|
|
namespace BTCPayServer.Client
|
|
|
|
{
|
|
|
|
public partial class BTCPayServerClient
|
|
|
|
{
|
|
|
|
private readonly string _apiKey;
|
|
|
|
private readonly Uri _btcpayHost;
|
2020-03-20 17:14:47 +01:00
|
|
|
private readonly string _username;
|
|
|
|
private readonly string _password;
|
2020-03-02 16:50:28 +01:00
|
|
|
private readonly HttpClient _httpClient;
|
2020-06-27 08:34:03 +02:00
|
|
|
public Uri Host => _btcpayHost;
|
|
|
|
|
2020-03-16 08:36:55 +01:00
|
|
|
public string APIKey => _apiKey;
|
|
|
|
|
2020-03-18 15:10:15 +01:00
|
|
|
public BTCPayServerClient(Uri btcpayHost, HttpClient httpClient = null)
|
|
|
|
{
|
|
|
|
if (btcpayHost == null)
|
|
|
|
throw new ArgumentNullException(nameof(btcpayHost));
|
|
|
|
_btcpayHost = btcpayHost;
|
|
|
|
_httpClient = httpClient ?? new HttpClient();
|
|
|
|
}
|
2020-03-02 16:50:28 +01:00
|
|
|
public BTCPayServerClient(Uri btcpayHost, string APIKey, HttpClient httpClient = null)
|
|
|
|
{
|
|
|
|
_apiKey = APIKey;
|
|
|
|
_btcpayHost = btcpayHost;
|
|
|
|
_httpClient = httpClient ?? new HttpClient();
|
|
|
|
}
|
2020-06-28 10:55:27 +02:00
|
|
|
|
2020-03-20 17:14:47 +01:00
|
|
|
public BTCPayServerClient(Uri btcpayHost, string username, string password, HttpClient httpClient = null)
|
|
|
|
{
|
|
|
|
_apiKey = APIKey;
|
|
|
|
_btcpayHost = btcpayHost;
|
|
|
|
_username = username;
|
|
|
|
_password = password;
|
|
|
|
_httpClient = httpClient ?? new HttpClient();
|
|
|
|
}
|
2020-03-02 16:50:28 +01:00
|
|
|
|
2020-06-08 16:40:58 +02:00
|
|
|
protected async Task HandleResponse(HttpResponseMessage message)
|
2020-03-02 16:50:28 +01:00
|
|
|
{
|
2021-12-16 15:04:06 +01:00
|
|
|
if (!message.IsSuccessStatusCode && message.Content?.Headers?.ContentType?.MediaType?.StartsWith("application/json", StringComparison.OrdinalIgnoreCase) is true)
|
2020-06-08 16:40:58 +02:00
|
|
|
{
|
2021-12-16 15:04:06 +01:00
|
|
|
if (message.StatusCode == System.Net.HttpStatusCode.UnprocessableEntity)
|
|
|
|
{
|
|
|
|
var err = JsonConvert.DeserializeObject<Models.GreenfieldValidationError[]>(await message.Content.ReadAsStringAsync());
|
2022-01-14 05:05:23 +01:00
|
|
|
throw new GreenfieldValidationException(err);
|
2021-12-16 15:04:06 +01:00
|
|
|
}
|
|
|
|
if (message.StatusCode == System.Net.HttpStatusCode.Forbidden)
|
|
|
|
{
|
|
|
|
var err = JsonConvert.DeserializeObject<Models.GreenfieldPermissionAPIError>(await message.Content.ReadAsStringAsync());
|
2022-01-14 05:05:23 +01:00
|
|
|
throw new GreenfieldAPIException((int)message.StatusCode, err);
|
2021-12-16 15:04:06 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
var err = JsonConvert.DeserializeObject<Models.GreenfieldAPIError>(await message.Content.ReadAsStringAsync());
|
|
|
|
if (err.Code != null)
|
2022-01-14 05:05:23 +01:00
|
|
|
throw new GreenfieldAPIException((int)message.StatusCode, err);
|
2021-12-16 15:04:06 +01:00
|
|
|
}
|
2020-06-08 16:40:58 +02:00
|
|
|
}
|
2020-03-02 16:50:28 +01:00
|
|
|
message.EnsureSuccessStatusCode();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected async Task<T> HandleResponse<T>(HttpResponseMessage message)
|
|
|
|
{
|
2020-06-08 16:40:58 +02:00
|
|
|
await HandleResponse(message);
|
2020-11-13 06:01:51 +01:00
|
|
|
var str = await message.Content.ReadAsStringAsync();
|
|
|
|
return JsonConvert.DeserializeObject<T>(str);
|
2020-03-02 16:50:28 +01:00
|
|
|
}
|
|
|
|
|
2021-04-26 05:37:56 +02:00
|
|
|
public async Task<T> SendHttpRequest<T>(string path,
|
|
|
|
Dictionary<string, object> queryPayload = null,
|
|
|
|
HttpMethod method = null, CancellationToken cancellationToken = default)
|
|
|
|
{
|
|
|
|
using var resp = await _httpClient.SendAsync(CreateHttpRequest(path, queryPayload, method), cancellationToken);
|
|
|
|
return await HandleResponse<T>(resp);
|
|
|
|
}
|
2022-01-10 14:10:04 +01:00
|
|
|
public async Task<T> SendHttpRequest<T>(string path,
|
|
|
|
object bodyPayload = null,
|
|
|
|
HttpMethod method = null, CancellationToken cancellationToken = default)
|
|
|
|
{
|
|
|
|
using var resp = await _httpClient.SendAsync(CreateHttpRequest(path: path, bodyPayload: bodyPayload, method: method), cancellationToken);
|
|
|
|
return await HandleResponse<T>(resp);
|
|
|
|
}
|
2020-03-02 16:50:28 +01:00
|
|
|
protected virtual HttpRequestMessage CreateHttpRequest(string path,
|
|
|
|
Dictionary<string, object> queryPayload = null,
|
|
|
|
HttpMethod method = null)
|
|
|
|
{
|
2020-06-28 10:55:27 +02:00
|
|
|
UriBuilder uriBuilder = new UriBuilder(_btcpayHost) { Path = path };
|
2020-03-02 16:50:28 +01:00
|
|
|
if (queryPayload != null && queryPayload.Any())
|
|
|
|
{
|
|
|
|
AppendPayloadToQuery(uriBuilder, queryPayload);
|
|
|
|
}
|
|
|
|
|
|
|
|
var httpRequest = new HttpRequestMessage(method ?? HttpMethod.Get, uriBuilder.Uri);
|
2020-03-18 15:10:15 +01:00
|
|
|
if (_apiKey != null)
|
|
|
|
httpRequest.Headers.Authorization = new AuthenticationHeaderValue("token", _apiKey);
|
2020-03-20 17:14:47 +01:00
|
|
|
else if (!string.IsNullOrEmpty(_username))
|
|
|
|
{
|
|
|
|
httpRequest.Headers.Authorization = new AuthenticationHeaderValue("Basic", System.Convert.ToBase64String(Encoding.ASCII.GetBytes(_username + ":" + _password)));
|
|
|
|
}
|
2020-03-02 16:50:28 +01:00
|
|
|
|
|
|
|
|
|
|
|
return httpRequest;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected virtual HttpRequestMessage CreateHttpRequest<T>(string path,
|
|
|
|
Dictionary<string, object> queryPayload = null,
|
|
|
|
T bodyPayload = default, HttpMethod method = null)
|
|
|
|
{
|
|
|
|
var request = CreateHttpRequest(path, queryPayload, method);
|
|
|
|
if (typeof(T).IsPrimitive || !EqualityComparer<T>.Default.Equals(bodyPayload, default(T)))
|
|
|
|
{
|
2020-03-20 10:56:30 +01:00
|
|
|
request.Content = new StringContent(JsonConvert.SerializeObject(bodyPayload), Encoding.UTF8, "application/json");
|
2020-03-02 16:50:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return request;
|
|
|
|
}
|
|
|
|
|
2020-08-28 09:15:08 +02:00
|
|
|
public static void AppendPayloadToQuery(UriBuilder uri, KeyValuePair<string, object> keyValuePair)
|
2020-03-02 16:50:28 +01:00
|
|
|
{
|
|
|
|
if (uri.Query.Length > 1)
|
|
|
|
uri.Query += "&";
|
2020-08-04 13:10:48 +02:00
|
|
|
|
|
|
|
UriBuilder uriBuilder = uri;
|
|
|
|
if (!(keyValuePair.Value is string) &&
|
|
|
|
keyValuePair.Value.GetType().GetInterfaces().Contains((typeof(IEnumerable))))
|
2020-03-02 16:50:28 +01:00
|
|
|
{
|
2020-08-04 13:10:48 +02:00
|
|
|
foreach (var item in (IEnumerable)keyValuePair.Value)
|
2020-03-02 16:50:28 +01:00
|
|
|
{
|
|
|
|
uriBuilder.Query = uriBuilder.Query + Uri.EscapeDataString(keyValuePair.Key) + "=" +
|
2020-08-04 13:10:48 +02:00
|
|
|
Uri.EscapeDataString(item.ToString()) + "&";
|
2020-03-02 16:50:28 +01:00
|
|
|
}
|
|
|
|
}
|
2020-08-04 13:10:48 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
uriBuilder.Query = uriBuilder.Query + Uri.EscapeDataString(keyValuePair.Key) + "=" +
|
|
|
|
Uri.EscapeDataString(keyValuePair.Value.ToString()) + "&";
|
|
|
|
}
|
2020-03-02 16:50:28 +01:00
|
|
|
uri.Query = uri.Query.Trim('&');
|
|
|
|
}
|
2020-08-04 13:10:48 +02:00
|
|
|
|
2020-08-28 09:15:08 +02:00
|
|
|
public static void AppendPayloadToQuery(UriBuilder uri, Dictionary<string, object> payload)
|
2020-08-04 13:10:48 +02:00
|
|
|
{
|
|
|
|
if (uri.Query.Length > 1)
|
|
|
|
uri.Query += "&";
|
|
|
|
foreach (KeyValuePair<string, object> keyValuePair in payload)
|
|
|
|
{
|
|
|
|
AppendPayloadToQuery(uri, keyValuePair);
|
|
|
|
}
|
|
|
|
}
|
2020-03-02 16:50:28 +01:00
|
|
|
}
|
|
|
|
}
|