-
Notifications
You must be signed in to change notification settings - Fork 572
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
626 additions
and
246 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
namespace Stripe | ||
{ | ||
using System; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
/// <summary> | ||
/// Abstract base class for HTTP clients used to make requests to Stripe's API. | ||
/// </summary> | ||
public abstract class HttpClient | ||
{ | ||
/// <summary>Gets or sets the last request made by this client.</summary> | ||
/// <value>The last request made by this client.</value> | ||
public StripeRequest LastRequest { get; protected set; } | ||
|
||
/// <summary>Gets or sets the duration of the last request.</summary> | ||
/// <value>The duration of the last request.</value> | ||
public TimeSpan? LastRequestDuration { get; protected set; } | ||
|
||
/// <summary>Gets or sets the last response received by this client.</summary> | ||
/// <value>The last response received by this client.</value> | ||
public StripeResponse LastResponse { get; protected set; } | ||
|
||
/// <summary>Sends a request to Stripe's API as an asynchronous operation.</summary> | ||
/// <param name="request">The parameters of the request to send.</param> | ||
/// <param name="cancellationToken">The cancellation token to cancel operation.</param> | ||
/// <returns>The task object representing the asynchronous operation.</returns> | ||
public abstract Task<StripeResponse> MakeRequestAsync( | ||
StripeRequest request, | ||
CancellationToken cancellationToken = default(CancellationToken)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
namespace Stripe | ||
{ | ||
using System.Net.Http; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
/// <summary> | ||
/// Interface for a Stripe client. | ||
/// </summary> | ||
public interface IStripeClient | ||
{ | ||
/// <summary>Sends a request to Stripe's API as an asynchronous operation.</summary> | ||
/// <typeparam name="T">Type of the Stripe entity returned by the API.</typeparam> | ||
/// <param name="method">The HTTP method.</param> | ||
/// <param name="path">The path of the request.</param> | ||
/// <param name="options">The parameters of the request.</param> | ||
/// <param name="requestOptions">The special modifiers of the request.</param> | ||
/// <param name="cancellationToken">The cancellation token to cancel operation.</param> | ||
/// <returns>The task object representing the asynchronous operation.</returns> | ||
Task<T> RequestAsync<T>( | ||
HttpMethod method, | ||
string path, | ||
BaseOptions options, | ||
RequestOptions requestOptions, | ||
CancellationToken cancellationToken = default(CancellationToken)) | ||
where T : IStripeEntity; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
namespace Stripe | ||
{ | ||
using System.Net; | ||
using System.Net.Http; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Newtonsoft.Json.Linq; | ||
|
||
/// <summary> | ||
/// A Stripe client, used to issue requests to Stripe's API and deserialize responses. | ||
/// </summary> | ||
public class StripeClient : IStripeClient | ||
{ | ||
/// <summary>Initializes a new instance of the <see cref="StripeClient"/> class.</summary> | ||
/// <param name="httpClient"> | ||
/// The <see cref="Stripe.HttpClient"/> client to use. If <c>null</c>, | ||
/// an HTTP client will be created with default parameters. | ||
/// </param> | ||
public StripeClient(Stripe.HttpClient httpClient = null) | ||
{ | ||
this.HttpClient = httpClient ?? BuildDefaultHttpClient(); | ||
} | ||
|
||
/// <summary>Gets the <see cref="Stripe.HttpClient"/> used to send HTTP requests.</summary> | ||
/// <value>The <see cref="Stripe.HttpClient"/> used to send HTTP requests.</value> | ||
public Stripe.HttpClient HttpClient { get; } | ||
|
||
/// <summary>Sends a request to Stripe's API as an asynchronous operation.</summary> | ||
/// <typeparam name="T">Type of the Stripe entity returned by the API.</typeparam> | ||
/// <param name="method">The HTTP method.</param> | ||
/// <param name="path">The path of the request.</param> | ||
/// <param name="options">The parameters of the request.</param> | ||
/// <param name="requestOptions">The special modifiers of the request.</param> | ||
/// <param name="cancellationToken">The cancellation token to cancel operation.</param> | ||
/// <returns>The task object representing the asynchronous operation.</returns> | ||
public async Task<T> RequestAsync<T>( | ||
HttpMethod method, | ||
string path, | ||
BaseOptions options, | ||
RequestOptions requestOptions, | ||
CancellationToken cancellationToken = default(CancellationToken)) | ||
where T : IStripeEntity | ||
{ | ||
var request = new StripeRequest(method, path, options, requestOptions); | ||
|
||
var response = await this.HttpClient.MakeRequestAsync(request); | ||
|
||
return ProcessResponse<T>(response); | ||
} | ||
|
||
private static Stripe.HttpClient BuildDefaultHttpClient() | ||
{ | ||
return new SystemNetHttpClient(); | ||
} | ||
|
||
private static T ProcessResponse<T>(StripeResponse response) | ||
where T : IStripeEntity | ||
{ | ||
if (response.StatusCode != HttpStatusCode.OK) | ||
{ | ||
throw BuildStripeException(response); | ||
} | ||
|
||
var obj = StripeEntity.FromJson<T>(response.Content); | ||
obj.StripeResponse = response; | ||
|
||
return obj; | ||
} | ||
|
||
private static StripeException BuildStripeException(StripeResponse response) | ||
{ | ||
// If the value of the `error` key is a string, then the error is an OAuth error | ||
// and we instantiate the StripeError object with the entire JSON. | ||
// Otherwise, it's a regular API error and we instantiate the StripeError object | ||
// with just the nested hash contained in the `error` key. | ||
var errorToken = JObject.Parse(response.Content)["error"]; | ||
var stripeError = errorToken.Type == JTokenType.String | ||
? StripeError.FromJson(response.Content) | ||
: StripeError.FromJson(errorToken.ToString()); | ||
|
||
stripeError.StripeResponse = response; | ||
|
||
return new StripeException( | ||
response.StatusCode, | ||
stripeError, | ||
stripeError.Message) | ||
{ | ||
StripeResponse = response, | ||
}; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,90 @@ | ||
namespace Stripe | ||
{ | ||
using System; | ||
using System.Linq; | ||
using System.Net; | ||
using System.Net.Http.Headers; | ||
|
||
/// <summary> | ||
/// Represents a response from Stripe's API. | ||
/// </summary> | ||
public class StripeResponse | ||
{ | ||
public string ResponseJson { get; set; } | ||
/// <summary>Initializes a new instance of the <see cref="StripeResponse"/> class.</summary> | ||
/// <param name="statusCode">The HTTP status code.</param> | ||
/// <param name="headers">The HTTP headers of the response.</param> | ||
/// <param name="content">The body of the response.</param> | ||
public StripeResponse(HttpStatusCode statusCode, HttpResponseHeaders headers, string content) | ||
{ | ||
this.StatusCode = statusCode; | ||
this.Headers = headers; | ||
this.Content = content; | ||
} | ||
|
||
public string RequestId { get; set; } | ||
/// <summary>Gets the HTTP status code of the response.</summary> | ||
/// <value>The HTTP status code of the response.</value> | ||
public HttpStatusCode StatusCode { get; } | ||
|
||
public DateTime RequestDate { get; set; } | ||
/// <summary>Gets the HTTP headers of the response.</summary> | ||
/// <value>The HTTP headers of the response.</value> | ||
public HttpResponseHeaders Headers { get; } | ||
|
||
/// <summary>Gets the body of the response.</summary> | ||
/// <value>The body of the response.</value> | ||
public string Content { get; } | ||
|
||
/// <summary>Gets the date of the request, as returned by Stripe.</summary> | ||
/// <value>The date of the request, as returned by Stripe.</value> | ||
public DateTimeOffset? Date => this.Headers?.Date; | ||
|
||
/// <summary>Gets the idempotency key of the request, as returned by Stripe.</summary> | ||
/// <value>The idempotency key of the request, as returned by Stripe.</value> | ||
public string IdempotencyKey => MaybeGetHeader(this.Headers, "Idempotency-Key"); | ||
|
||
/// <summary>Gets the ID of the request, as returned by Stripe.</summary> | ||
/// <value>The ID of the request, as returned by Stripe.</value> | ||
public string RequestId => MaybeGetHeader(this.Headers, "Request-Id"); | ||
|
||
/// <summary> | ||
/// Gets the body of the response. | ||
/// This method is deprecated and will be removed in a future version, please use the | ||
/// <see cref="Content"/> property getter instead. | ||
/// </summary> | ||
/// <value>The body of the response.</value> | ||
// TODO: remove this in a future a major version | ||
[Obsolete("Use Content instead")] | ||
public string ResponseJson => this.Content; | ||
|
||
/// <summary> | ||
/// Gets the date of the request, as returned by Stripe. | ||
/// This method is deprecated and will be removed in a future version, please use the | ||
/// <see cref="Date"/> property getter instead. | ||
/// </summary> | ||
/// <value>The date of the request, as returned by Stripe.</value> | ||
// TODO: remove this in a future a major version | ||
[Obsolete("Use Date instead")] | ||
public DateTime RequestDate => this.Date?.DateTime ?? default(DateTime); | ||
|
||
/// <summary>Returns a string that represents the <see cref="StripeResponse"/>.</summary> | ||
/// <returns>A string that represents the <see cref="StripeResponse"/>.</returns> | ||
public override string ToString() | ||
{ | ||
return string.Format( | ||
"<{0} status={1} Request-Id={2} Date={3}>", | ||
this.GetType().FullName, | ||
(int)this.StatusCode, | ||
this.RequestId, | ||
this.Date?.ToString("s")); | ||
} | ||
|
||
private static string MaybeGetHeader(HttpHeaders headers, string name) | ||
{ | ||
if ((headers == null) || (!headers.Contains(name))) | ||
{ | ||
return null; | ||
} | ||
|
||
return headers.GetValues(name).First(); | ||
} | ||
} | ||
} |
Oops, something went wrong.