Skip to content

Commit

Permalink
Version 1.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
ben-foster-cko authored Feb 12, 2019
2 parents 24564d9 + 63c0192 commit f2c653e
Show file tree
Hide file tree
Showing 20 changed files with 369 additions and 26 deletions.
7 changes: 7 additions & 0 deletions src/CheckoutSdk/CheckoutApi.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Checkout.Payments;
using Checkout.Sources;
using Checkout.Tokens;

namespace Checkout
Expand All @@ -16,6 +17,7 @@ public class CheckoutApi : ICheckoutApi
public CheckoutApi(IApiClient apiClient, CheckoutConfiguration configuration)
{
Payments = new PaymentsClient(apiClient, configuration);
Sources = new SourcesClient(apiClient, configuration);
Tokens = new TokensClient(apiClient, configuration);
}

Expand All @@ -24,6 +26,11 @@ public CheckoutApi(IApiClient apiClient, CheckoutConfiguration configuration)
/// </summary>
public IPaymentsClient Payments { get; }

/// <summary>
/// Gets the Sources API.
/// </summary>
public ISourcesClient Sources { get; }

/// <summary>
/// Gets the Tokenization API.
/// </summary>
Expand Down
6 changes: 6 additions & 0 deletions src/CheckoutSdk/ICheckoutApi.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Checkout.Payments;
using Checkout.Sources;
using Checkout.Tokens;

namespace Checkout
Expand All @@ -13,6 +14,11 @@ public interface ICheckoutApi
/// </summary>
IPaymentsClient Payments { get; }

/// <summary>
/// Gets the Sources API.
/// </summary>
ISourcesClient Sources { get; }

/// <summary>
/// Gets the Tokenization API.
/// </summary>
Expand Down
13 changes: 10 additions & 3 deletions src/CheckoutSdk/Payments/AlternativePaymentSource.cs
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
using System;
using System.Collections.Generic;

namespace Checkout.Payments
{
/// <summary>
/// Represents an Alternative Payment source for a payment request.
/// </summary>
public class AlternativePaymentSource : Dictionary<string, string>, IRequestSource
public class AlternativePaymentSource : Dictionary<string, object>, IRequestSource
{
private const string TypeField = "type";

/// <summary>
/// Creates a new <see cref="AlternativePaymentSource"/> instance.
/// </summary>
public AlternativePaymentSource(string type) {
/// <param name="type">The type of the Alternative Payment source.</param>
public AlternativePaymentSource(string type)
{
if (string.IsNullOrWhiteSpace(type))
throw new ArgumentException("The alternative payment source type is required.", nameof(type));

Type = type;
}

/// <summary>
/// Gets or sets the type of source.
/// </summary>
public string Type {
public string Type
{
get { return this[TypeField].ToString(); }
set { this[TypeField] = value; }
}
Expand Down
4 changes: 2 additions & 2 deletions src/CheckoutSdk/Payments/AlternativePaymentSourceResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ namespace Checkout.Payments
/// <summary>
/// The alternative payment used to complete a payment request.
/// </summary>
public class AlternativePaymentSourceResponse : Dictionary<string, string>, IResponseSource
{
public class AlternativePaymentSourceResponse : Dictionary<string, object>, IResponseSource
{
/// <summary>
/// Gets or sets the type of source.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/CheckoutSdk/Payments/CardSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public CardSource(string number, int expiryMonth, int expiryYear)
throw new ArgumentException("The card number is required.", nameof(number));

if (expiryMonth < 1 || expiryMonth > 12)
throw new ArgumentOutOfRangeException("The exiry month must be between 1 and 12", nameof(expiryMonth));
throw new ArgumentOutOfRangeException("The expiry month must be between 1 and 12", nameof(expiryMonth));

Number = number;
ExpiryMonth = expiryMonth;
Expand Down
1 change: 1 addition & 0 deletions src/CheckoutSdk/Payments/PaymentRequest.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Checkout.Common;
using Newtonsoft.Json;

namespace Checkout.Payments
Expand Down
30 changes: 17 additions & 13 deletions src/CheckoutSdk/Payments/PaymentsClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Checkout.Payments
/// </summary>
public class PaymentsClient : IPaymentsClient
{
private static readonly Dictionary<HttpStatusCode, Type> CardPaymentMappings = new Dictionary<HttpStatusCode, Type>
private static readonly Dictionary<HttpStatusCode, Type> PaymentResponseMappings = new Dictionary<HttpStatusCode, Type>
{
{ HttpStatusCode.Accepted, typeof(PaymentPending)},
{ HttpStatusCode.Created, typeof(PaymentProcessed)}
Expand All @@ -22,7 +22,7 @@ public class PaymentsClient : IPaymentsClient

public PaymentsClient(IApiClient apiClient, CheckoutConfiguration configuration)
{
this._apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
_apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
if (configuration == null) throw new ArgumentNullException(nameof(configuration));

_credentials = new SecretKeyCredentials(configuration);
Expand All @@ -31,7 +31,7 @@ public PaymentsClient(IApiClient apiClient, CheckoutConfiguration configuration)
public Task<PaymentResponse> RequestAsync<TRequestSource>(PaymentRequest<TRequestSource> paymentRequest, CancellationToken cancellationToken = default(CancellationToken))
where TRequestSource : IRequestSource
{
return RequestPaymentAsync(paymentRequest, CardPaymentMappings, cancellationToken);
return RequestPaymentAsync(paymentRequest, PaymentResponseMappings, cancellationToken);
}

public Task<GetPaymentResponse> GetAsync(string paymentId, CancellationToken cancellationToken = default(CancellationToken))
Expand All @@ -41,35 +41,39 @@ public PaymentsClient(IApiClient apiClient, CheckoutConfiguration configuration)

public Task<IEnumerable<PaymentAction>> GetActionsAsync(string paymentId, CancellationToken cancellationToken = default(CancellationToken))
{
return _apiClient.GetAsync<IEnumerable<PaymentAction>>(GetPaymentUrl(paymentId) + "/actions", _credentials, cancellationToken);
const string path = "/actions";
return _apiClient.GetAsync<IEnumerable<PaymentAction>>(GetPaymentUrl(paymentId) + path, _credentials, cancellationToken);
}

public Task<CaptureResponse> CaptureAsync(string paymentId, CaptureRequest captureRequest = null, CancellationToken cancellationToken = default(CancellationToken))
{
return _apiClient.PostAsync<CaptureResponse>(GetPaymentUrl(paymentId) + "/captures", _credentials, cancellationToken, captureRequest);
const string path = "/captures";
return _apiClient.PostAsync<CaptureResponse>(GetPaymentUrl(paymentId) + path, _credentials, cancellationToken, captureRequest);
}

public Task<RefundResponse> RefundAsync(string paymentId, RefundRequest refundRequest = null, CancellationToken cancellationToken = default(CancellationToken))
{
return _apiClient.PostAsync<RefundResponse>(GetPaymentUrl(paymentId) + "/refunds", _credentials, cancellationToken, refundRequest);
const string path = "/refunds";
return _apiClient.PostAsync<RefundResponse>(GetPaymentUrl(paymentId) + path, _credentials, cancellationToken, refundRequest);
}

public Task<VoidResponse> VoidAsync(string paymentId, VoidRequest voidRequest = null, CancellationToken cancellationToken = default(CancellationToken))
{
return _apiClient.PostAsync<VoidResponse>(GetPaymentUrl(paymentId) + "/voids", _credentials, cancellationToken, voidRequest);
const string path = "/voids";
return _apiClient.PostAsync<VoidResponse>(GetPaymentUrl(paymentId) + path, _credentials, cancellationToken, voidRequest);
}

private async Task<PaymentResponse> RequestPaymentAsync<TRequestSource>(
PaymentRequest<TRequestSource> paymentRequest,
Dictionary<HttpStatusCode, Type> resultTypeMappings, CancellationToken cancellationToken) where TRequestSource : IRequestSource
private async Task<PaymentResponse> RequestPaymentAsync<TRequestSource>(PaymentRequest<TRequestSource> paymentRequest, Dictionary<HttpStatusCode, Type> resultTypeMappings, CancellationToken cancellationToken) where TRequestSource : IRequestSource
{
var apiResponse = await _apiClient.PostAsync("payments", _credentials, resultTypeMappings, cancellationToken, paymentRequest);
const string path = "payments";
var apiResponse = await _apiClient.PostAsync(path, _credentials, resultTypeMappings, cancellationToken, paymentRequest);
return apiResponse;
}

private static string GetPaymentUrl(string paymentId)
{
return "payments/" + paymentId;
const string path = "payments/";
return path + paymentId;
}
}
}
}
24 changes: 24 additions & 0 deletions src/CheckoutSdk/Sources/CustomerRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
namespace Checkout.Sources
{
/// <summary>
/// Represents a customer in a payment request.
/// </summary>
public class CustomerRequest
{
/// <summary>
/// Gets or sets the unique identifier of the customer. This can be specified in a <see cref="Payments.CustomerSource"/>
/// in subsequent payment requests to use the customer's default payment method.
/// </summary>
public string Id { get; set; }

/// <summary>
/// Gets or sets the customer email address.
/// </summary>
public string Email { get; set; }

/// <summary>
/// Gets or sets the customer full name.
/// </summary>
public string Name { get; set; }
}
}
24 changes: 24 additions & 0 deletions src/CheckoutSdk/Sources/CustomerResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
namespace Checkout.Sources
{
/// <summary>
/// Represents a customer in a payment response.
/// </summary>
public class CustomerResponse
{
/// <summary>
/// Gets or sets the unique identifier of the customer. This can be specified in a <see cref="Payments.CustomerSource"/>
/// in subsequent payment requests to use the customer's default payment method.
/// </summary>
public string Id { get; set; }

/// <summary>
/// Gets or sets the customer email address.
/// </summary>
public string Email { get; set; }

/// <summary>
/// Gets or sets the customer full name.
/// </summary>
public string Name { get; set; }
}
}
18 changes: 18 additions & 0 deletions src/CheckoutSdk/Sources/ISourcesClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System.Threading.Tasks;

namespace Checkout.Sources
{
/// <summary>
/// Defines the operations available on the Checkout.com Sources API.
/// </summary>
public interface ISourcesClient
{
/// <summary>
/// Add a reusable payment source that can be used later to make one or more payments.
/// Payment sources are linked to a specific customer and cannot be shared between customers.
/// </summary>
/// <param name="sourceRequest">The source details such as type and billing address.</param>
/// <returns>A task that upon completion contains the source response.</returns>
Task<SourceResponse> RequestAsync(SourceRequest sourceRequest);
}
}
9 changes: 9 additions & 0 deletions src/CheckoutSdk/Sources/ResponseData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Collections.Generic;

namespace Checkout.Sources
{
/// <summary>
/// Defines the response data of a <see cref="SourceResponse"/>.
/// </summary>
public class ResponseData : Dictionary<string, object> { }
}
9 changes: 9 additions & 0 deletions src/CheckoutSdk/Sources/SourceData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Collections.Generic;

namespace Checkout.Sources
{
/// <summary>
/// Defines the source data of a <see cref="SourceRequest"/>.
/// </summary>
public class SourceData : Dictionary<string, object> { }
}
35 changes: 35 additions & 0 deletions src/CheckoutSdk/Sources/SourceProcessed.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using Checkout.Common;

namespace Checkout.Sources
{
/// <summary>
/// Indicates the source has been successfully processed.
/// </summary>
public class SourceProcessed : Resource
{
/// <summary>
/// Gets or sets the id of the source.
/// </summary>
public string Id { get; set; }

/// <summary>
/// Gets or sets the type of the source.
/// </summary>
public string Type { get; set; }

/// <summary>
/// Gets or sets the response code of the source.
/// </summary>
public string ResponseCode { get; set; }

/// <summary>
/// Gets or sets the customer of the source.
/// </summary>
public CustomerResponse Customer { get; set; }

/// <summary>
/// Gets or sets the <see cref="ResponseData"/> of the source.
/// </summary>
public ResponseData ResponseData { get; set; }
}
}
55 changes: 55 additions & 0 deletions src/CheckoutSdk/Sources/SourceRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using Checkout.Common;
using System;

namespace Checkout.Sources
{
/// <summary>
/// Defines a request for a source.
/// </summary>
public class SourceRequest
{
/// <summary>
/// Creates a new <see cref="SourceRequest"/> instance.
/// </summary>
/// <param name="type">The payment source type.</param>
/// <param name="billingAddress">The payment source owner's billing address.</param>
public SourceRequest(string type, Address billingAddress)
{
if (string.IsNullOrWhiteSpace(type))
throw new ArgumentException("The payment source type is required.", nameof(type));

Type = type;
BillingAddress = billingAddress ?? throw new ArgumentNullException("The payment source owner's billing address is required.", nameof(billingAddress));
}

/// <summary>
/// Gets or sets the type of the source.
/// </summary>
public string Type { get; }

/// <summary>
/// Gets or sets the billing address of the source.
/// </summary>
public Address BillingAddress { get; }

/// <summary>
/// Gets or sets the reference of the source.
/// </summary>
public string Reference { get; set; }

/// <summary>
/// Gets or sets the phone number of the source.
/// </summary>
public Phone Phone { get; set; }

/// <summary>
/// Gets or sets the customer of the source.
/// </summary>
public CustomerRequest Customer { get; set; }

/// <summary>
/// Gets or sets the specific source data of the source.
/// </summary>
public SourceData SourceData { get; set; }
}
}
30 changes: 30 additions & 0 deletions src/CheckoutSdk/Sources/SourceResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using Checkout.Common;

namespace Checkout.Sources
{
/// <summary>
/// Defines a source response.
/// </summary>
public class SourceResponse : Resource
{
/// <summary>
/// Gets or sets the processed response returned following a successfully processed source (HTTP Status Code 201).
/// </summary>
public SourceProcessed Source { get; set; }

/// <summary>
/// Gets a value that indicates whether the source is in a pending state.
/// </summary>
public bool IsPending => Source == null;

/// <summary>
/// Enables the implicit conversion of <see cref="SourceProcessed"/> to <see cref="SourceResponse"/>.
/// This is required for dynamic dispatch during the deserialization of source responses.
/// </summary>
/// <param name="processedResponse">The processed response.</param>
public static implicit operator SourceResponse(SourceProcessed processedResponse)
{
return new SourceResponse { Source = processedResponse };
}
}
}
Loading

0 comments on commit f2c653e

Please sign in to comment.