Skip to content

Commit

Permalink
Request builder added. StarlingClient wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
rowellheria-ad committed Sep 24, 2018
1 parent b3d98ca commit d31886e
Show file tree
Hide file tree
Showing 12 changed files with 270 additions and 127 deletions.
21 changes: 21 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2018 Rowell Heria

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Starling Bank
12 changes: 3 additions & 9 deletions StarlingBank.sln
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StarlingBank", "StarlingBank\StarlingBank.csproj", "{9044593E-C19A-479A-A011-603E6D6D44CF}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{D7396B59-0C59-4FF4-8002-9B1F44C243AC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StarlingBank.UnitTests", "tests\StarlingBank.UnitTests\StarlingBank.UnitTests.csproj", "{38A5B107-0E2F-4F73-A90A-EB8BBDF50294}"
ProjectSection(SolutionItems) = preProject
tests\StarlingBank.UnitTests\StarlingBank.UnitTests.csproj = tests\StarlingBank.UnitTests\StarlingBank.UnitTests.csproj
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -19,17 +20,10 @@ Global
{9044593E-C19A-479A-A011-603E6D6D44CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9044593E-C19A-479A-A011-603E6D6D44CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9044593E-C19A-479A-A011-603E6D6D44CF}.Release|Any CPU.Build.0 = Release|Any CPU
{38A5B107-0E2F-4F73-A90A-EB8BBDF50294}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{38A5B107-0E2F-4F73-A90A-EB8BBDF50294}.Debug|Any CPU.Build.0 = Debug|Any CPU
{38A5B107-0E2F-4F73-A90A-EB8BBDF50294}.Release|Any CPU.ActiveCfg = Release|Any CPU
{38A5B107-0E2F-4F73-A90A-EB8BBDF50294}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{38A5B107-0E2F-4F73-A90A-EB8BBDF50294} = {D7396B59-0C59-4FF4-8002-9B1F44C243AC}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {552B3E62-DA4C-4A2E-B6DA-960C87E48DE4}
EndGlobalSection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,20 @@
using System.Threading.Tasks;
using StarlingBank.Entities.SavingsGoals;

namespace StarlingBank
namespace StarlingBank.Api
{
public interface IStarlingBankClient
public interface IStarlingClient
{
string BaseUrl { get; set; }

#region SavingsGoal
string AccessToken { get; set; }

// SavingsGoal

Task<(HttpStatusCode status, CreateOrUpdateSavingsGoalResponse response)> CreateGoal(SavingsGoalRequest goal);

Task<(HttpStatusCode status, SavingsGoal goal)> GetGoal(Guid goalId);

Task<(HttpStatusCode status, CreateOrUpdateSavingsGoalResponse response)> AddMoney(Guid goalId, TopUpRequest topup);

#endregion
}
}
60 changes: 60 additions & 0 deletions StarlingBank/Api/StarlingClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using StarlingBank.Entities.SavingsGoals;

namespace StarlingBank.Api
{
public class StarlingClient : IStarlingClient, IDisposable
{
public StarlingClient()
{
this.RequestBuilder = new StarlingRequestBuilder();
}

private StarlingRequestBuilder RequestBuilder { get; }

public string BaseUrl { get; set; }

public string AccessToken { get; set; }

public void Dispose()
{
this.RequestBuilder.Dispose();
}

public Task<(HttpStatusCode status, CreateOrUpdateSavingsGoalResponse response)> CreateGoal(SavingsGoalRequest goal)
{
var goalId = Guid.NewGuid();

return this.RequestBuilder
.WithUrl($"{this.BaseUrl}v1/savings-goals/{goalId}")
.WithMethod(HttpMethod.Put)
.WithHeader("Authorization", $"Bearer {this.AccessToken}")
.WithBody(goal)
.SendAsync<CreateOrUpdateSavingsGoalResponse>();
}

public Task<(HttpStatusCode status, SavingsGoal goal)> GetGoal(Guid goalId)
{
return this.RequestBuilder
.WithUrl($"{this.BaseUrl}v1/savings-goals/{goalId}")
.WithMethod(HttpMethod.Get)
.WithHeader("Authorization", $"Bearer {this.AccessToken}")
.SendAsync<SavingsGoal>();
}

public Task<(HttpStatusCode status, CreateOrUpdateSavingsGoalResponse response)> AddMoney(Guid goalId, TopUpRequest topup)
{
var transferId = Guid.NewGuid();

return this.RequestBuilder
.WithUrl($"{this.BaseUrl}v1/savings-goals/{goalId}/add-money/{transferId}")
.WithMethod(HttpMethod.Put)
.WithHeader("Authorization", $"Bearer {this.AccessToken}")
.WithBody(topup)
.SendAsync<CreateOrUpdateSavingsGoalResponse>();
}
}
}
119 changes: 119 additions & 0 deletions StarlingBank/Api/StarlingRequestBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace StarlingBank.Api
{
public class StarlingRequestBuilder : IDisposable, IStarlingRequestBuilder, IStarlingRequestBuilderMethod, IStarlingRequestBuilderHeadersBodySend
{
public StarlingRequestBuilder()
{
this.Client = new HttpClient();
}

private StarlingRequestBuilder(HttpClient client, HttpRequestMessage request)
{
this.Client = client;
this.Request = request;
}

protected HttpClient Client { get; }

protected HttpRequestMessage Request { get; }

private JsonSerializerSettings SerializerSettings { get; } = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
};


public IStarlingRequestBuilderMethod WithUrl(string url)
{
var request = new HttpRequestMessage
{
RequestUri = new Uri(url)
};

return new StarlingRequestBuilder(this.Client, request);
}

public IStarlingRequestBuilderHeadersBodySend WithMethod(HttpMethod method)
{
this.Request.Method = method;

return this;
}

public IStarlingRequestBuilderHeadersBodySend WithHeader(string header, string value)
{
this.Request.Headers.Add(header, value);

return this;
}

public IStarlingRequestBuilderHeadersBodySend WithHeaders(params KeyValuePair<string, string>[] headers)
{
foreach (var kvp in headers)
{
this.Request.Headers.Add(kvp.Key, kvp.Value);
}

return this;
}

public IStarlingRequestBuilderHeadersBodySend WithBody<T>(T body) where T : class
{
var json = JsonConvert.SerializeObject(body, this.SerializerSettings);
var content = new StringContent(json, Encoding.UTF8, "application/json");
this.Request.Content = content;

return this;
}

public async Task<(HttpStatusCode code, TResult result)> SendAsync<TResult>()
{
var response = await this.Client.SendAsync(this.Request);
var result = await response.Content.ReadAsAsync<TResult>();

return (response.StatusCode, result);
}

public Task<HttpResponseMessage> SendAsync()
{
return this.Client.SendAsync(this.Request);
}

public void Dispose()
{
this.Client?.Dispose();
}
}

public interface IStarlingRequestBuilder
{
IStarlingRequestBuilderMethod WithUrl(string url);
}

public interface IStarlingRequestBuilderMethod
{
IStarlingRequestBuilderHeadersBodySend WithMethod(HttpMethod method);
}

public interface IStarlingRequestBuilderHeadersBodySend
{
IStarlingRequestBuilderHeadersBodySend WithHeader(string header, string value);

IStarlingRequestBuilderHeadersBodySend WithHeaders(params KeyValuePair<string, string>[] headers);

IStarlingRequestBuilderHeadersBodySend WithBody<T>(T body) where T : class;

Task<(HttpStatusCode code, TResult result)> SendAsync<TResult>();

Task<HttpResponseMessage> SendAsync();
}
}
2 changes: 1 addition & 1 deletion StarlingBank/Entities/Webhook/TransactionContent.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System;

namespace StarlingBank.Webhook
namespace StarlingBank.Entities.Webhook
{
/// <summary>
/// Starling Bank: payload content.
Expand Down
5 changes: 3 additions & 2 deletions StarlingBank/Entities/Webhook/TransactionPayload.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using StarlingBank.Constants;

namespace StarlingBank.Webhook
namespace StarlingBank.Entities.Webhook
{
public class TransactionPayload
{
Expand All @@ -13,7 +14,7 @@ public class TransactionPayload
public Guid AccountHolderUid { get; set; }

/// <summary>
/// String representation of the webhook event type. <see cref="WebhookTypes"/>
/// String representation of the webhook event type. See <see cref="WebhookTypes"/> for a complete list.
/// </summary>
public string WebhookType { get; set; }

Expand Down
15 changes: 0 additions & 15 deletions StarlingBank/Extensions/HttpResponseMessageExtensions.cs

This file was deleted.

Loading

0 comments on commit d31886e

Please sign in to comment.