Skip to content

Commit 5facdf7

Browse files
Merge pull request #41 from StuartFerguson/task/#39_adddeviceoninitiallogon
Add Device on Inital Logon Txn
2 parents 4939929 + b5f5845 commit 5facdf7

File tree

25 files changed

+608
-111
lines changed

25 files changed

+608
-111
lines changed

.github/workflows/createrelease.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ jobs:
1919
id: get_version
2020
run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}
2121

22-
- name: Setup .NET Core 3.0
22+
- name: Setup .NET Core
2323
uses: actions/setup-dotnet@v1
2424
with:
25-
dotnet-version: 3.0.100
25+
dotnet-version: 3.1.100
2626

2727
- name: Restore Nuget Packages
2828
run: dotnet restore TransactionProcessor.sln --source https://api.nuget.org/v3/index.json --source https://www.myget.org/F/transactionprocessing/api/v3/index.json

.github/workflows/nightlybuild.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
- name: Setup .NET Core
1919
uses: actions/setup-dotnet@v1
2020
with:
21-
dotnet-version: 3.0.100
21+
dotnet-version: 3.1.100
2222

2323
- name: Restore Nuget Packages
2424
run: dotnet restore TransactionProcessor.sln --source https://api.nuget.org/v3/index.json --source https://www.myget.org/F/transactionprocessing/api/v3/index.json

.github/workflows/pullrequest.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
- name: Setup .NET Core
2020
uses: actions/setup-dotnet@v1
2121
with:
22-
dotnet-version: 3.0.100
22+
dotnet-version: 3.1.100
2323

2424
- name: Restore Nuget Packages
2525
run: dotnet restore TransactionProcessor.sln --source https://api.nuget.org/v3/index.json --source https://www.myget.org/F/transactionprocessing/api/v3/index.json

TransactionProcessor.BusinessLogic.Tests/Services/TransactionDomainServiceTests.cs

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,16 @@ namespace TransactionProcessor.BusinessLogic.Tests.Services
77
using System.Threading;
88
using System.Threading.Tasks;
99
using BusinessLogic.Services;
10+
using EstateManagement.Client;
11+
using Microsoft.Extensions.Configuration;
1012
using Models;
1113
using Moq;
14+
using SecurityService.Client;
15+
using SecurityService.DataTransferObjects.Responses;
1216
using Shared.DomainDrivenDesign.EventStore;
1317
using Shared.EventStore.EventStore;
18+
using Shared.General;
19+
using Shared.Logger;
1420
using Shouldly;
1521
using Testing;
1622
using TransactionAggregate;
@@ -21,6 +27,11 @@ public class TransactionDomainServiceTests
2127
[Fact]
2228
public async Task TransactionDomainService_ProcessLogonTransaction_TransactionIsProcessed()
2329
{
30+
var configurationRoot = new ConfigurationBuilder().AddInMemoryCollection(TestData.DefaultAppSettings).Build();
31+
ConfigurationReader.Initialise(configurationRoot);
32+
33+
Logger.Initialise(NullLogger.Instance);
34+
2435
Mock<IAggregateRepositoryManager> aggregateRepositoryManager = new Mock<IAggregateRepositoryManager>();
2536
Mock<IAggregateRepository<TransactionAggregate>> transactionAggregateRepository = new Mock<IAggregateRepository<TransactionAggregate>>();
2637

@@ -32,15 +43,23 @@ public async Task TransactionDomainService_ProcessLogonTransaction_TransactionIs
3243
.ReturnsAsync(TestData.GetCompletedTransactionAggregate);
3344
transactionAggregateRepository.Setup(t => t.SaveChanges(It.IsAny<TransactionAggregate>(), It.IsAny<CancellationToken>())).Returns(Task.CompletedTask);
3445

35-
TransactionDomainService transactionDomainService = new TransactionDomainService(aggregateRepositoryManager.Object);
46+
Mock<IEstateClient> estateClient = new Mock<IEstateClient>();
47+
Mock<ISecurityServiceClient> securityServiceClient = new Mock<ISecurityServiceClient>();
48+
49+
securityServiceClient.Setup(s => s.GetToken(It.IsAny<String>(), It.IsAny<String>(), It.IsAny<CancellationToken>())).ReturnsAsync(TestData.TokenResponse);
50+
estateClient.Setup(e => e.GetMerchant(It.IsAny<String>(), It.IsAny<Guid>(), It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
51+
.ReturnsAsync(TestData.GetMerchantResponse);
3652

53+
TransactionDomainService transactionDomainService =
54+
new TransactionDomainService(aggregateRepositoryManager.Object, estateClient.Object, securityServiceClient.Object);
55+
3756
ProcessLogonTransactionResponse response = await transactionDomainService.ProcessLogonTransaction(TestData.TransactionId,
38-
TestData.EstateId,
39-
TestData.MerchantId,
40-
TestData.TransactionDateTime,
41-
TestData.TransactionNumber,
42-
TestData.DeviceIdentifier,
43-
CancellationToken.None);
57+
TestData.EstateId,
58+
TestData.MerchantId,
59+
TestData.TransactionDateTime,
60+
TestData.TransactionNumber,
61+
TestData.DeviceIdentifier,
62+
CancellationToken.None);
4463

4564
response.ShouldNotBeNull();
4665
response.ResponseCode.ShouldBe(TestData.ResponseCode);

TransactionProcessor.BusinessLogic.Tests/TransactionProcessor.BusinessLogic.Tests.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>netcoreapp3.0</TargetFramework>
4+
<TargetFramework>netcoreapp3.1</TargetFramework>
55
<DebugType>None</DebugType>
66
<IsPackable>false</IsPackable>
77
</PropertyGroup>
88

99
<ItemGroup>
10-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
10+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
1111
<PackageReference Include="Moq" Version="4.13.1" />
1212
<PackageReference Include="Shouldly" Version="3.0.2" />
1313
<PackageReference Include="xunit" Version="2.4.1" />
1414
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
1515
<PrivateAssets>all</PrivateAssets>
1616
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
1717
</PackageReference>
18-
<PackageReference Include="coverlet.msbuild" Version="2.7.0">
18+
<PackageReference Include="coverlet.msbuild" Version="2.8.0">
1919
<PrivateAssets>all</PrivateAssets>
2020
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
2121
</PackageReference>

TransactionProcessor.BusinessLogic/Services/TransactionDomainService.cs

Lines changed: 162 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
11
namespace TransactionProcessor.BusinessLogic.Services
22
{
33
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
46
using System.Threading;
57
using System.Threading.Tasks;
8+
using EstateManagement.Client;
9+
using EstateManagement.DataTransferObjects.Requests;
10+
using EstateManagement.DataTransferObjects.Responses;
611
using Models;
12+
using SecurityService.Client;
13+
using SecurityService.DataTransferObjects.Responses;
714
using Shared.DomainDrivenDesign.EventStore;
815
using Shared.EventStore.EventStore;
16+
using Shared.General;
17+
using Shared.Logger;
918
using TransactionAggregate;
1019

1120
/// <summary>
@@ -14,13 +23,44 @@
1423
/// <seealso cref="TransactionProcessor.BusinessLogic.Services.ITransactionDomainService" />
1524
public class TransactionDomainService : ITransactionDomainService
1625
{
26+
#region Fields
27+
28+
/// <summary>
29+
/// The aggregate repository manager
30+
/// </summary>
1731
private readonly IAggregateRepositoryManager AggregateRepositoryManager;
1832

19-
public TransactionDomainService(IAggregateRepositoryManager aggregateRepositoryManager)
33+
/// <summary>
34+
/// The estate client
35+
/// </summary>
36+
private readonly IEstateClient EstateClient;
37+
38+
/// <summary>
39+
/// The security service client
40+
/// </summary>
41+
private readonly ISecurityServiceClient SecurityServiceClient;
42+
43+
#endregion
44+
45+
#region Constructors
46+
47+
/// <summary>
48+
/// Initializes a new instance of the <see cref="TransactionDomainService" /> class.
49+
/// </summary>
50+
/// <param name="aggregateRepositoryManager">The aggregate repository manager.</param>
51+
/// <param name="estateClient">The estate client.</param>
52+
/// <param name="securityServiceClient">The security service client.</param>
53+
public TransactionDomainService(IAggregateRepositoryManager aggregateRepositoryManager,
54+
IEstateClient estateClient,
55+
ISecurityServiceClient securityServiceClient)
2056
{
2157
this.AggregateRepositoryManager = aggregateRepositoryManager;
58+
this.EstateClient = estateClient;
59+
this.SecurityServiceClient = securityServiceClient;
2260
}
2361

62+
#endregion
63+
2464
#region Methods
2565

2666
/// <summary>
@@ -34,18 +74,36 @@ public TransactionDomainService(IAggregateRepositoryManager aggregateRepositoryM
3474
/// <param name="deviceIdentifier">The device identifier.</param>
3575
/// <param name="cancellationToken">The cancellation token.</param>
3676
/// <returns></returns>
37-
public async Task<ProcessLogonTransactionResponse> ProcessLogonTransaction(Guid transactionId, Guid estateId, Guid merchantId, DateTime transactionDateTime,
38-
String transactionNumber, String deviceIdentifier, CancellationToken cancellationToken)
77+
public async Task<ProcessLogonTransactionResponse> ProcessLogonTransaction(Guid transactionId,
78+
Guid estateId,
79+
Guid merchantId,
80+
DateTime transactionDateTime,
81+
String transactionNumber,
82+
String deviceIdentifier,
83+
CancellationToken cancellationToken)
3984
{
40-
IAggregateRepository<TransactionAggregate> transactionAggregateRepository = this.AggregateRepositoryManager.GetAggregateRepository<TransactionAggregate>(estateId);
41-
85+
IAggregateRepository<TransactionAggregate> transactionAggregateRepository =
86+
this.AggregateRepositoryManager.GetAggregateRepository<TransactionAggregate>(estateId);
87+
4288
TransactionAggregate transactionAggregate = await transactionAggregateRepository.GetLatestVersion(transactionId, cancellationToken);
4389
transactionAggregate.StartTransaction(transactionDateTime, transactionNumber, "Logon", estateId, merchantId, deviceIdentifier);
4490
await transactionAggregateRepository.SaveChanges(transactionAggregate, cancellationToken);
4591

46-
transactionAggregate = await transactionAggregateRepository.GetLatestVersion(transactionId, cancellationToken);
47-
transactionAggregate.AuthoriseTransactionLocally("ABCD1234", "0000", "SUCCESS");
48-
await transactionAggregateRepository.SaveChanges(transactionAggregate, cancellationToken);
92+
(String responseMessage, TransactionResponseCode responseCode) validationResult = await this.ValidateTransaction(estateId, merchantId, deviceIdentifier, cancellationToken);
93+
94+
if (validationResult.responseCode == TransactionResponseCode.Success)
95+
{
96+
// Record the successful validation
97+
transactionAggregate = await transactionAggregateRepository.GetLatestVersion(transactionId, cancellationToken);
98+
// TODO: Generate local authcode
99+
transactionAggregate.AuthoriseTransactionLocally("ABCD1234", ((Int32)validationResult.responseCode).ToString().PadLeft(4,'0'), validationResult.responseMessage);
100+
await transactionAggregateRepository.SaveChanges(transactionAggregate, cancellationToken);
101+
}
102+
else
103+
{
104+
// Record the failure
105+
throw new NotImplementedException();
106+
}
49107

50108
transactionAggregate = await transactionAggregateRepository.GetLatestVersion(transactionId, cancellationToken);
51109
transactionAggregate.CompleteTransaction();
@@ -60,7 +118,103 @@ public async Task<ProcessLogonTransactionResponse> ProcessLogonTransaction(Guid
60118
};
61119
}
62120

121+
/// <summary>
122+
/// Validates the transaction.
123+
/// </summary>
124+
/// <param name="estateId">The estate identifier.</param>
125+
/// <param name="merchantId">The merchant identifier.</param>
126+
/// <param name="deviceIdentifier">The device identifier.</param>
127+
/// <param name="cancellationToken">The cancellation token.</param>
128+
/// <returns></returns>
129+
/// <exception cref="TransactionProcessor.BusinessLogic.Services.TransactionValidationException">Device Identifier {deviceIdentifier} not valid for Merchant {merchant.MerchantName}</exception>
130+
private async Task<(String responseMessage, TransactionResponseCode responseCode)> ValidateTransaction(Guid estateId,
131+
Guid merchantId,
132+
String deviceIdentifier,
133+
CancellationToken cancellationToken)
134+
{
135+
try
136+
{
137+
138+
// Get a token to talk to the estate service
139+
String clientId = ConfigurationReader.GetValue("AppSettings", "ClientId");
140+
String clientSecret = ConfigurationReader.GetValue("AppSettings", "ClientSecret");
141+
142+
Logger.LogInformation($"Client Id is {clientId}");
143+
Logger.LogInformation($"Client Secret is {clientSecret}");
144+
145+
TokenResponse token = await this.SecurityServiceClient.GetToken(clientId, clientSecret, cancellationToken);
146+
Logger.LogInformation($"Token is {token.AccessToken}");
147+
148+
// get the merchant record and validate the device
149+
// TODO: Token
150+
MerchantResponse merchant = await this.EstateClient.GetMerchant(token.AccessToken, estateId, merchantId, cancellationToken);
151+
152+
if (merchant.Devices == null || merchant.Devices.Any() == false)
153+
{
154+
// Add the device to the merchant
155+
await this.EstateClient.AddDeviceToMerchant(token.AccessToken,
156+
estateId,
157+
merchantId,
158+
new AddMerchantDeviceRequest
159+
{
160+
DeviceIdentifier = deviceIdentifier
161+
},
162+
cancellationToken);
163+
}
164+
else
165+
{
166+
// Validate the device
167+
KeyValuePair<Guid, String> device = merchant.Devices.SingleOrDefault(d => d.Value == deviceIdentifier);
168+
169+
if (device.Key == Guid.Empty)
170+
{
171+
// Device not found,throw error
172+
throw new TransactionValidationException($"Device Identifier {deviceIdentifier} not valid for Merchant {merchant.MerchantName}", TransactionResponseCode.InvalidDeviceIdentifier);
173+
}
174+
}
175+
176+
// If we get here everything is good
177+
return ("SUCCESS", TransactionResponseCode.Success);
178+
}
179+
catch (TransactionValidationException tvex)
180+
{
181+
return (tvex.Message, tvex.ResponseCode);
182+
}
183+
184+
}
63185

64186
#endregion
65187
}
188+
189+
public enum TransactionResponseCode
190+
{
191+
Success = 0,
192+
InvalidDeviceIdentifier = 1000
193+
}
194+
195+
public class TransactionValidationException : Exception
196+
{
197+
public TransactionResponseCode ResponseCode { get; private set; }
198+
199+
/// <summary>
200+
/// Initializes a new instance of the <see cref="TransactionValidationException" /> class.
201+
/// </summary>
202+
/// <param name="message">The message that describes the error.</param>
203+
/// <param name="responseCode">The response code.</param>
204+
public TransactionValidationException(String message, TransactionResponseCode responseCode) : this(message, responseCode, null)
205+
{
206+
207+
}
208+
209+
/// <summary>
210+
/// Initializes a new instance of the <see cref="TransactionValidationException" /> class.
211+
/// </summary>
212+
/// <param name="message">The error message that explains the reason for the exception.</param>
213+
/// <param name="responseCode">The response code.</param>
214+
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
215+
public TransactionValidationException(String message, TransactionResponseCode responseCode, Exception innerException) : base(message, innerException)
216+
{
217+
this.ResponseCode = responseCode;
218+
}
219+
}
66220
}

TransactionProcessor.BusinessLogic/TransactionProcessor.BusinessLogic.csproj

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>netcoreapp3.0</TargetFramework>
4+
<TargetFramework>netcoreapp3.1</TargetFramework>
55
</PropertyGroup>
66

77
<ItemGroup>
8-
<PackageReference Include="Shared" Version="0.0.5.1" />
9-
<PackageReference Include="Shared.DomainDrivenDesign" Version="0.0.5.1" />
10-
<PackageReference Include="Shared.EventStore" Version="0.0.5.1" />
11-
<PackageReference Include="MediatR" Version="7.0.0" />
8+
<PackageReference Include="EstateManagement.Client" Version="0.0.8" />
9+
<PackageReference Include="SecurityService.Client" Version="0.0.6.2" />
10+
<PackageReference Include="Shared" Version="0.0.8.1" />
11+
<PackageReference Include="Shared.DomainDrivenDesign" Version="0.0.8.1" />
12+
<PackageReference Include="Shared.EventStore" Version="0.0.8.1" />
13+
<PackageReference Include="MediatR" Version="8.0.0" />
1214
</ItemGroup>
1315

1416
<ItemGroup>

TransactionProcessor.Client/TransactionProcessor.Client.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
</PropertyGroup>
77

88
<ItemGroup>
9-
<PackageReference Include="ClientProxyBase" Version="0.0.7" />
9+
<PackageReference Include="ClientProxyBase" Version="0.0.8.1" />
1010
</ItemGroup>
1111

1212
<ItemGroup>

0 commit comments

Comments
 (0)