public async Task <ServiceObjectResult <PaymentResult> > ExecutePayment(PaymentRequest paymentRequest) { var sendPaymentResponse = await _bankRequestClient.SendPayment(paymentRequest); if (!sendPaymentResponse.Success || sendPaymentResponse.Result?.PaymentIdentifier == null) { return(ServiceObjectResult <PaymentResult> .Failed(null, sendPaymentResponse.Errors ?? new List <string> { ErrorCodeStrings.InternalError })); } if (!Enum.TryParse <PaymentStatus>(sendPaymentResponse.Result.Status, out var paymentStatus)) { return(ServiceObjectResult <PaymentResult> .Failed(null, ErrorMessages.UnableToProcessPayment)); } var paymentResult = new PaymentResult { PaymentIdentifier = sendPaymentResponse.Result.PaymentIdentifier, CardNumber = paymentRequest.CardNumber, Amount = paymentRequest.Amount, Status = paymentStatus, Timestamp = DateTime.UtcNow }; return(ServiceObjectResult <PaymentResult> .Succeeded(paymentResult)); }
public Task <ServiceObjectResult <ResponseEnvelope <PaymentResponse> > > ProcessPaymentRequest(PaymentRequest request) { switch (request.CardNumber) { case TestConstants.ErrorCardNumber: return(Task.FromResult(ServiceObjectResult <ResponseEnvelope <PaymentResponse> > .Failed(null, new List <string> { ErrorCodeStrings.InternalError }))); case TestConstants.BadRequestCardNumber: var validationErrors = new List <ValidationFieldError> { new ValidationFieldError(nameof(request.CardNumber), ErrorMessages.Validation.FieldInvalidContent) }; return(Task.FromResult(ServiceObjectResult <ResponseEnvelope <PaymentResponse> > .Failed( new ResponseEnvelope <PaymentResponse> { ValidationErrors = validationErrors }, new List <string> { ErrorCodeStrings.BadRequestError }))); case TestConstants.SuccessCardNumber: return(Task.FromResult(ServiceObjectResult <ResponseEnvelope <PaymentResponse> > .Succeeded( new ResponseEnvelope <PaymentResponse> { ResponseValue = new PaymentResponse() }))); default: throw new NotImplementedException(); } }
public async Task <ServiceObjectResult <ResponseEnvelope <PaymentResponse> > > ProcessPaymentRequest(PaymentRequest request) { var responseEnvelope = new ResponseEnvelope <PaymentResponse>(); var validationResult = _requestValidator.ValidateRequest(request); if (!validationResult.Success) { responseEnvelope.ValidationErrors = validationResult.Result; return(ServiceObjectResult <ResponseEnvelope <PaymentResponse> > .Failed( responseEnvelope, validationResult.Errors)); } var paymentResult = await _paymentExecutionService.ExecutePayment(request); if (!paymentResult.Success) { return(ServiceObjectResult <ResponseEnvelope <PaymentResponse> > .Failed(null, new List <string> { ErrorCodeStrings.InternalError })); } await _repository.PutItemAsync(paymentResult.Result); responseEnvelope.ResponseValue = new PaymentResponse { PaymentIdentifier = paymentResult.Result.PaymentIdentifier, Status = paymentResult.Result.Status.ToString() }; return(ServiceObjectResult <ResponseEnvelope <PaymentResponse> > .Succeeded(responseEnvelope)); }
public async Task <ServiceObjectResult <ICollection <Transaction> > > GetAllTransactions(string userId) { //Check cache var cachedTransactions = await _userDataCachingService.RetrieveTransactions(userId); if (!cachedTransactions.Success) { return(ServiceObjectResult <ICollection <Transaction> > .Failed(null, cachedTransactions.Errors)); } if (cachedTransactions.Result != null && cachedTransactions.Result.Any()) { return(ServiceObjectResult <ICollection <Transaction> > .Succeeded(cachedTransactions.Result)); } //Obtain all valid access contexts var accessContextResult = await ObtainValidAccountContexts(userId); if (!accessContextResult.Success) { return(ServiceObjectResult <ICollection <Transaction> > .Failed(null, accessContextResult.Errors)); } var transactionsResult = await ObtainTransactionsForAccountContexts(accessContextResult.Result); if (!transactionsResult.Success) { return(ServiceObjectResult <ICollection <Transaction> > .Failed(null, transactionsResult.Errors)); } await _userDataCachingService.CacheTransactions(userId, transactionsResult.Result, TimeSpan.FromMinutes(10)); return(ServiceObjectResult <ICollection <Transaction> > .Succeeded(transactionsResult.Result)); }
GetTransactionCategoryResponses(string userId, bool detailed = false) { //Check cache var cachedTransactions = await _userDataCachingService.RetrieveTransactions(userId); if (!cachedTransactions.Success) { return(ServiceObjectResult <TransactionCategoryResponse> .Failed(null, cachedTransactions.Errors)); } if (cachedTransactions.Result != null && cachedTransactions.Result.Any()) { return(ServiceObjectResult <TransactionCategoryResponse> .Succeeded(CreateCategoryResponse(cachedTransactions.Result, detailed))); } //Obtain all valid access contexts var accessContextResult = await ObtainValidAccountContexts(userId); if (!accessContextResult.Success) { return(ServiceObjectResult <TransactionCategoryResponse> .Failed(null, accessContextResult.Errors)); } var transactionsResult = await ObtainTransactionsForAccountContexts(accessContextResult.Result); if (!transactionsResult.Success) { return(ServiceObjectResult <TransactionCategoryResponse> .Failed(null, transactionsResult.Errors)); } await _userDataCachingService.CacheTransactions(userId, transactionsResult.Result, TimeSpan.FromMinutes(10)); return(ServiceObjectResult <TransactionCategoryResponse> .Succeeded(CreateCategoryResponse(transactionsResult.Result, detailed))); }
private async Task <ServiceObjectResult <ICollection <Transaction> > > ObtainTransactionsForAccountContexts( ICollection <AccountAccessContext> accessContexts) { var transactions = new List <Transaction>(); foreach (var accessContext in accessContexts) { var accountLookupResult = await _accountService.GetAccountsInContext(accessContext); if (!accountLookupResult.Success) { return(ServiceObjectResult <ICollection <Transaction> > .Failed(null, accountLookupResult.Errors)); } foreach (var accountId in accountLookupResult.Result.Select(x => x.AccountId).Distinct()) { var transactionLookupResult = await _requestExecutor.GetTransactions(accessContext.AccessToken, accountId); if (!transactionLookupResult.Success) { return(ServiceObjectResult <ICollection <Transaction> > .Failed(null, transactionLookupResult.Errors)); } transactions.AddRange(transactionLookupResult.Result.Results); } } return(ServiceObjectResult <ICollection <Transaction> > .Succeeded(transactions)); }
private async Task <ServiceObjectResult <ICollection <AccountAccessContext> > > ObtainValidAccountContexts(string userId) { //Refresh access on all users accounts where required var accessRefreshResult = await _authorizationService.AttemptRefreshAccountContexts(userId); if (!accessRefreshResult.Success) { return(ServiceObjectResult <ICollection <AccountAccessContext> > .Failed(null, accessRefreshResult.Errors)); } //ObtainAccessContexts var accessContextResult = await _accessCachingService.RetrieveAccessContexts(userId, new List <Scope> { Scope.transactions, Scope.accounts }); if (!accessContextResult.Success) { return(ServiceObjectResult <ICollection <AccountAccessContext> > .Failed(null, accessContextResult.Errors)); } if (accessContextResult.Result == null) { return(ServiceObjectResult <ICollection <AccountAccessContext> > .Failed(null, new List <string> { ErrorMessages.UserNotFound })); } return(ServiceObjectResult <ICollection <AccountAccessContext> > .Succeeded(accessContextResult.Result)); }
public async void GetAllTransactions_Should_Retrieve_Accounts_For_Each_Context() { var userId = Guid.NewGuid().ToString(); var accessCode1 = Guid.NewGuid().ToString(); var accessCode2 = Guid.NewGuid().ToString(); SetupEmptyCacheCall(userId); _mockAuthorizationService.Setup(x => x.AttemptRefreshAccountContexts(userId)) .ReturnsAsync(ServiceResult.Succeeded); SetupAccessContextRetrieval(userId, new List <AccountAccessContext> { new AccountAccessContext { AccessToken = accessCode1 }, new AccountAccessContext { AccessToken = accessCode2 } }); _mockAccountService.Setup(x => x.GetAccountsInContext(It.IsAny <AccountAccessContext>())) .ReturnsAsync(ServiceObjectResult <ICollection <Account> > .Succeeded(new List <Account>())); var result = await _transactionService.GetTransactionCategoryResponses(userId); _mockAccountService.Verify(x => x.GetAccountsInContext(It.Is <AccountAccessContext>( context => context.AccessToken == accessCode1)), Times.Once); _mockAccountService.Verify(x => x.GetAccountsInContext(It.Is <AccountAccessContext>( context => context.AccessToken == accessCode2)), Times.Once); }
public async void RefreshAccountTokens_Should_Remove_Access_If_RefreshToken_Empty_When_Expired() { _mockAccessContextCachingService.Setup(x => x.RetrieveAccessContexts(It.IsAny <string>(), null)) .ReturnsAsync(ServiceObjectResult <ICollection <AccountAccessContext> > .Succeeded(new List <AccountAccessContext> { new AccountAccessContext { AccessTokenExpiry = DateTime.UtcNow } })); _mockRequestExecutor.Setup(x => x.RefreshAccountAccess(It.IsAny <AccountAccessContext>())) .ReturnsAsync(ServiceObjectResult <AuthResponse> .Succeeded(new AuthResponse { ExpiresIn = 9999, AccessToken = "string", RefreshToken = "string" })); var result = await _authorizationService.AttemptRefreshAccountContexts("myuser"); Assert.True(result.Success); _mockRequestExecutor.Verify(x => x.RefreshAccountAccess(It.IsAny <AccountAccessContext>()), Times.Never()); _mockAccessContextCachingService.Verify(x => x.RemoveAccessContext(It.IsAny <AccountAccessContext>()), Times.Once); }
private ServiceObjectResult <TReturnType> GenerateResponseForType <TReturnType>(string userId) where TReturnType : class { switch (userId) { case TestConstants.ValidUser: return(ServiceObjectResult <TReturnType> .Succeeded(null)); case TestConstants.ErrorUser: return(ServiceObjectResult <TReturnType> .Failed(null, new List <string> { ErrorCodeStrings.InternalError })); case TestConstants.BadRequestUser: return(ServiceObjectResult <TReturnType> .Failed(null, new List <string> { ErrorCodeStrings.BadRequestError })); case TestConstants.NotFoundUser: return(ServiceObjectResult <TReturnType> .Failed(null, new List <string> { ErrorCodeStrings.NotFoundError })); default: throw new NotImplementedException(); } }
public async Task <ServiceObjectResult <DeliveryRecord> > Update(DeliveryRecord delivery) { var result = await _repository.UpdateItem(delivery); return(!result.Success ? ServiceObjectResult <DeliveryRecord> .Failed(null, result.Errors) : ServiceObjectResult <DeliveryRecord> .Succeeded(delivery)); }
public async Task <ServiceObjectResult <DeliveryRecord> > Select(string deliveryId) { var result = await _repository.GetItem(deliveryId); return(!result.Success ? ServiceObjectResult <DeliveryRecord> .Failed(null, result.Errors) : ServiceObjectResult <DeliveryRecord> .Succeeded(result.Result)); }
public async Task <ServiceObjectResult <TDataType> > GetItem(string partitionKey) { var result = await _dynamoDbContext.LoadAsync <TDataType>(partitionKey); return(result != null ? ServiceObjectResult <TDataType> .Succeeded(result) : ServiceObjectResult <TDataType> .Failed(null, ErrorCodes.Status.NotFound)); }
public async void GetTransactionCategoryResponses_Should_Retrieve_Transactions_For_Each_Account() { var userId = Guid.NewGuid().ToString(); var accessCode1 = Guid.NewGuid().ToString(); var accessCode2 = Guid.NewGuid().ToString(); var accountCode1 = Guid.NewGuid().ToString(); var accountCode2 = Guid.NewGuid().ToString(); var accountCode3 = Guid.NewGuid().ToString(); var accountCode4 = Guid.NewGuid().ToString(); SetupEmptyCacheCall(userId); _mockAuthorizationService.Setup(x => x.AttemptRefreshAccountContexts(userId)) .ReturnsAsync(ServiceResult.Succeeded); SetupAccessContextRetrieval(userId, new List <AccountAccessContext> { new AccountAccessContext { AccessToken = accessCode1 }, new AccountAccessContext { AccessToken = accessCode2 } }); _mockAccountService.Setup(x => x.GetAccountsInContext(It.Is <AccountAccessContext>(context => context.AccessToken == accessCode1))) .ReturnsAsync(ServiceObjectResult <ICollection <Account> > .Succeeded(new List <Account> { new Account { AccountId = accountCode1 }, new Account { AccountId = accountCode2 } })); _mockAccountService.Setup(x => x.GetAccountsInContext(It.Is <AccountAccessContext>(context => context.AccessToken == accessCode2))) .ReturnsAsync(ServiceObjectResult <ICollection <Account> > .Succeeded(new List <Account> { new Account { AccountId = accountCode3 }, new Account { AccountId = accountCode4 } })); _mockTrueLayerDataRequestExecutor.Setup(x => x.GetTransactions(It.IsAny <string>(), It.IsAny <string>())) .ReturnsAsync( ServiceObjectResult <TrueLayerListResponse <Transaction> > .Succeeded( new TrueLayerListResponse <Transaction> { Results = new List <Transaction>() })); var result = await _transactionService.GetTransactionCategoryResponses(userId); _mockTrueLayerDataRequestExecutor.Verify(x => x.GetTransactions(accessCode1, accountCode1), Times.Once); _mockTrueLayerDataRequestExecutor.Verify(x => x.GetTransactions(accessCode1, accountCode2), Times.Once); _mockTrueLayerDataRequestExecutor.Verify(x => x.GetTransactions(accessCode2, accountCode3), Times.Once); _mockTrueLayerDataRequestExecutor.Verify(x => x.GetTransactions(accessCode2, accountCode4), Times.Once); }
public async void ExecutePayment_Should_Return_Failed_If_Client_Result_Has_No_Identifier() { _mockBankRequestClient.Setup(x => x.SendPayment(It.IsAny <PaymentRequest>())) .ReturnsAsync(ServiceObjectResult <BankPaymentResponse> .Succeeded(new BankPaymentResponse())); var result = await _paymentExecutionService.ExecutePayment(new PaymentRequest()); Assert.False(result.Success); }
public async Task <ServiceObjectResult <ICollection <AccountAccessContext> > > RetrieveAccessContexts(string userId, ICollection <Scope> requiredScopes = null) { var accessContexts = await _cache.Get <List <AccountAccessContext> >(userId); return(requiredScopes == null ? ServiceObjectResult <ICollection <AccountAccessContext> > .Succeeded(accessContexts) : ServiceObjectResult <ICollection <AccountAccessContext> > .Succeeded( accessContexts.Where(x => x.Scopes.Distinct().Intersect(requiredScopes.Distinct()).Count() == requiredScopes.Distinct().Count()).ToList())); }
private void SetupRefreshCodeCall() { _mockRequestExecutor.Setup(x => x.RefreshAccountAccess(It.IsAny <AccountAccessContext>())) .ReturnsAsync(ServiceObjectResult <AuthResponse> .Succeeded(new AuthResponse { ExpiresIn = 9999, AccessToken = "string", RefreshToken = "string" })); }
public async Task <ServiceObjectResult <DeliveryRecord> > Create(DeliveryRecord delivery) { delivery.DeliveryId = Guid.NewGuid().ToString(); var saveResult = await _repository.PutItem(delivery); return(saveResult.Success ? ServiceObjectResult <DeliveryRecord> .Succeeded(delivery) : ServiceObjectResult <DeliveryRecord> .Failed(null, saveResult.Errors)); }
private void SetupPaymentExecutionService(string cardNumber, bool success, string resultReference = null) { var result = success ? ServiceObjectResult <PaymentResult> .Succeeded(new PaymentResult { PaymentIdentifier = resultReference }) : ServiceObjectResult <PaymentResult> .Failed(null, ""); _paymentExecutionService.Setup(x => x.ExecutePayment(It.Is <PaymentRequest>(request => request.CardNumber == cardNumber))) .ReturnsAsync(result); }
private void SetupRepositorySuccess(DeliveryRecord record) { _mockRepository.Setup(x => x.PutItem(It.IsAny <DeliveryRecord>())) .ReturnsAsync(ServiceResult.Succeeded); _mockRepository.Setup(x => x.GetItems(It.IsAny <ICollection <QueryModel> >())) .ReturnsAsync(ServiceObjectResult <ICollection <DeliveryRecord> > .Succeeded(new List <DeliveryRecord> { record })); _mockRepository.Setup(x => x.GetItems(default))
public async Task <ServiceObjectResult <ICollection <TDataType> > > GetItems(ICollection <QueryModel> queryModels = null) { var scanConditions = queryModels == null ? new List <ScanCondition>() : queryModels.Select(x => new ScanCondition( x.FieldName, x.Operator, x.Values)).ToList(); var results = await _dynamoDbContext.ScanAsync <TDataType>(scanConditions).GetRemainingAsync(); return(ServiceObjectResult <ICollection <TDataType> > .Succeeded(results)); }
public async void ExecutePayment_Should_Return_Failed_If_Client_Result_Status_Unrecognised() { _mockBankRequestClient.Setup(x => x.SendPayment(It.IsAny <PaymentRequest>())) .ReturnsAsync(ServiceObjectResult <BankPaymentResponse> .Succeeded(new BankPaymentResponse { PaymentIdentifier = Guid.NewGuid().ToString(), Status = "Unknown" })); var result = await _paymentExecutionService.ExecutePayment(new PaymentRequest()); Assert.False(result.Success); }
public async void ExecutePayment_Should_Succeed_If_Client_Call_Obtains_Valid_Result() { _mockBankRequestClient.Setup(x => x.SendPayment(It.IsAny <PaymentRequest>())) .ReturnsAsync(ServiceObjectResult <BankPaymentResponse> .Succeeded(new BankPaymentResponse { PaymentIdentifier = Guid.NewGuid().ToString(), Status = PaymentStatus.Complete.ToString() })); var result = await _paymentExecutionService.ExecutePayment(new PaymentRequest()); Assert.True(result.Success); }
private void SetupValidationService(string cardNumber, ICollection <ValidationFieldError> validationErrors) { var result = validationErrors.Any() ? ServiceObjectResult <ICollection <ValidationFieldError> > .Failed(validationErrors, ErrorCodeStrings.BadRequestError) : ServiceObjectResult <ICollection <ValidationFieldError> > .Succeeded(validationErrors); _requestValidator.Setup(x => x.ValidateRequest(It.Is <PaymentRequest>(request => request.CardNumber == cardNumber))) .Returns(result); }
public async Task <ServiceObjectResult <ICollection <DeliveryRecord> > > Select(DeliveryState?state = null) { var result = state.HasValue ? await _repository.GetItems(new List <QueryModel> { new QueryModel(nameof(DeliveryRecord.State), ScanOperator.Equal, state) }) : await _repository.GetItems(); return(result.Success ? ServiceObjectResult <ICollection <DeliveryRecord> > .Succeeded(result.Result) : ServiceObjectResult <ICollection <DeliveryRecord> > .Failed(null, result.Errors)); }
public async Task <ServiceObjectResult <ICollection <TDataModel> > > QueryByPartitionAsync(string partitionKey) { var queryRequest = new QueryRequest(_configuration.TableName) { ExpressionAttributeNames = new Dictionary <string, string> { { "#partition", _configuration.PartitionKey } }, ExpressionAttributeValues = new Dictionary <string, AttributeValue> { { ":partition", new AttributeValue(partitionKey) } }, KeyConditionExpression = $"#partition = :partition" }; bool operationComplete = false; var results = new List <Dictionary <string, AttributeValue> >(); while (!operationComplete) { var queryResponse = await _dynamoDbClient.QueryAsync(queryRequest); if (queryResponse.HttpStatusCode != HttpStatusCode.OK) { return(ServiceObjectResult <ICollection <TDataModel> > .Failed(null, $"An error occurred querying DynamoDb")); } results.AddRange(queryResponse.Items); if (queryResponse.LastEvaluatedKey.Any()) { queryRequest.ExclusiveStartKey = queryResponse.LastEvaluatedKey; } else { operationComplete = true; } } var dataModels = new List <TDataModel>(); foreach (var result in results) { var dataModel = new TDataModel(); dataModel.FromAttributeMap(result); dataModels.Add(dataModel); } return(ServiceObjectResult <ICollection <TDataModel> > .Succeeded(dataModels)); }
public async void Service_Fails_If_AccessTokenMetadata_Cannot_Be_Obtained() { SetupAccountContexts(true, true); SetupExchangeCodeRequest(); _mockRequestExecutor.Setup(x => x.GetAccessTokenMetadata(It.IsAny <string>())) .ReturnsAsync( ServiceObjectResult <TrueLayerListResponse <AccessTokenMetadata> > .Succeeded(null)); var result = await _authorizationService.ExchangeCode(new AccountAccessContext()); Assert.False(result.Success); Assert.Contains(ErrorMessages.FailedToObtainAccessTokenMetadata, result.Errors); }
private void SetupExchangeCodeRequest(bool succeeded = true, string accessToken = null, string refreshToken = null) { var authResponse = new AuthResponse { AccessToken = accessToken ?? Guid.NewGuid().ToString(), ExpiresIn = 10, RefreshToken = refreshToken ?? Guid.NewGuid().ToString() }; _mockRequestExecutor .Setup(x => x.ExchangeCode(It.IsAny <AccountAccessContext>())) .ReturnsAsync(succeeded ? ServiceObjectResult <AuthResponse> .Succeeded(authResponse) : ServiceObjectResult <AuthResponse> .Failed(null, new List <string> { "Value" })); }
public async void GetAllTransactions_Should_Return_Cached_Transaction_If_Exist() { string userId = Guid.NewGuid().ToString(); _mockUserDataCachingService.Setup(x => x.RetrieveTransactions(userId)) .ReturnsAsync(ServiceObjectResult <ICollection <Transaction> > .Succeeded(new List <Transaction>() { new Transaction() })); var result = await _transactionService.GetAllTransactions(userId); Assert.True(result.Success); Assert.Single(result.Result); }
public async Task <ServiceObjectResult <ICollection <Account> > > GetAccountsInContext( AccountAccessContext accessContext) { var accountsInContextResult = await _requestExecutor.GetAccounts(accessContext.AccessToken); if (!accountsInContextResult.Success || accountsInContextResult.Result.Status != "Succeeded") { return(ServiceObjectResult <ICollection <Account> > .Failed(null, accountsInContextResult.Errors ?? new List <string> { "An error occurred fetching account information" })); } return(ServiceObjectResult <ICollection <Account> > .Succeeded(accountsInContextResult.Result.Results)); }