Ejemplo n.º 1
0
        public void GivenAPaymentProcessingRequestIsProvided_WhenPostingToAcquirerBank_ThenItReturnsABankingResponse()
        {
            // Given

            var mockedAcquirerBankingService = Substitute.For <IAcquirerBankingService>();
            var mockedLogger = Substitute.For <ILogger <BankingHandler> >();

            var realBankingHandler = new BankingHandler(mockedLogger, mockedAcquirerBankingService);
            var request            = new PaymentProcessingRequest();

            mockedAcquirerBankingService
            .Post(request)
            .Returns(new BankingResponse {
                Success = true, TransactionId = Guid.NewGuid()
            });

            // When

            var response = realBankingHandler.Handle(request).GetAwaiter().GetResult();

            // Then

            response.Should().NotBeNull();
            response.Should().BeOfType <BankingResponse>();
            response.Success.Should().BeTrue();
        }
Ejemplo n.º 2
0
        public void GivenAcquirerBankingServiceThrowsAnException_WhenPostingToAcquirerBank_ThenItReturnsABankingException()
        {
            // Given

            var mockedAcquirerBankingService = Substitute.For <IAcquirerBankingService>();
            var mockedLogger = Substitute.For <ILogger <BankingHandler> >();

            var realBankingHandler = new BankingHandler(mockedLogger, mockedAcquirerBankingService);
            var request            = new PaymentProcessingRequest();

            var exception = new Exception("Exception thrown");

            mockedAcquirerBankingService
            .Post(request)
            .Throws(exception);

            // When

            var response = Assert.Throws <BankingException>(() => realBankingHandler.Handle(request).GetAwaiter().GetResult());

            // Then

            response.Should().NotBeNull();
            response.Should().BeOfType <BankingException>();
            response.Message.Should().Be(exception.Message);
        }
Ejemplo n.º 3
0
        public void GivenAPaymentProcessingRequestIsProvided_WhenHandlingItAndTheBankingReturnsAFailedTransactionResponse_ThenItReturnsAFailedPaymentProcessingResponse()
        {
            // Given

            var mockedLogger            = Substitute.For <ILogger <PaymentHandler> >();
            var mockedBankingHandler    = Substitute.For <IBankingHandler>();
            var mockedPaymentRepository = Substitute.For <IPaymentRepository>();

            var realPaymentHandler = new PaymentHandler(mockedLogger, mockedBankingHandler, mockedPaymentRepository);

            var request = new PaymentProcessingRequest();

            mockedBankingHandler
            .Handle(request)
            .Returns(new BankingResponse {
                Success = false, TransactionId = Guid.NewGuid()
            });

            // When

            var response = realPaymentHandler.Handle(request).GetAwaiter().GetResult();

            // Then

            response.Should().NotBeNull();
            response.Should().BeOfType <PaymentProcessingResponse>();
            response.Success.Should().BeFalse();

            mockedPaymentRepository.Received(2).Upsert(Arg.Any <PaymentRecord>());
            mockedBankingHandler.Received(1).Handle(request);
        }
        public async Task <IActionResult> Post([FromBody] PaymentProcessingRequest request)
        {
            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            try
            {
                var result = await _paymentHandler.Handle(request);

                return(Ok(result));
            }
            catch (PaymentProcessingException exception)
            {
                _logger.LogError(exception.ToString());

                return(BadRequest(new PaymentProcessingFailedResponse
                {
                    Success = false,
                    Message = $"An error has occurred. Details: {exception.Message}"
                }));
            }
            catch (Exception exception)
            {
                _logger.LogError(exception.ToString());

                return(BadRequest(new PaymentProcessingFailedResponse
                {
                    Success = false,
                    Message = $"An unhandled error has occurred. Details: {exception.Message}"
                }));
            }
        }
Ejemplo n.º 5
0
        public void GivenABankingExceptionIsThrown_WhenHandlingIt_ThenItReturnsAPaymentProcessingException()
        {
            // Given

            var mockedLogger            = Substitute.For <ILogger <PaymentHandler> >();
            var mockedBankingHandler    = Substitute.For <IBankingHandler>();
            var mockedPaymentRepository = Substitute.For <IPaymentRepository>();

            var realPaymentHandler = new PaymentHandler(mockedLogger, mockedBankingHandler, mockedPaymentRepository);

            var request = new PaymentProcessingRequest();

            var exception = new BankingException("test");

            mockedBankingHandler
            .Handle(request)
            .Throws(exception);

            // When

            var response = Assert.Throws <PaymentProcessingException>(() => realPaymentHandler.Handle(request).GetAwaiter().GetResult());


            // Then

            response.Should().NotBeNull();
            response.Should().BeOfType <PaymentProcessingException>();
            response.Message.Should().Be($"There was an issue when processing the transaction with the bank. Details: {exception.Message}");

            mockedPaymentRepository.Received(1).Upsert(Arg.Any <PaymentRecord>());
            mockedBankingHandler.Received(1).Handle(request);
        }
        public void GivenPaymentHandlerThrowsAnUnhandledException_WhenTryingToPostIt_ThenItReturnsABadRequestResponse()
        {
            // Given

            var mockedLogger         = Substitute.For <ILogger <PaymentProcessingController> >();
            var mockedPaymentHandler = Substitute.For <IPaymentHandler>();

            var realPaymentProcessingController = new PaymentProcessingController(mockedLogger, mockedPaymentHandler);

            var request = new PaymentProcessingRequest();

            var exception = new Exception("Test");

            mockedPaymentHandler
            .Handle(request)
            .Throws(exception);

            // When

            var response = realPaymentProcessingController.Post(request).GetAwaiter().GetResult();

            // Then

            response.Should().NotBeNull();
            response.Should().BeOfType <BadRequestObjectResult>();
            response.As <BadRequestObjectResult>().Value.As <PaymentProcessingFailedResponse>().Success.Should().BeFalse();
            response.As <BadRequestObjectResult>().Value.As <PaymentProcessingFailedResponse>().Message.Should().Be($"An unhandled error has occurred. Details: {exception.Message}");

            mockedPaymentHandler.Received(1).Handle(request);
        }
Ejemplo n.º 7
0
 private static bool AreFieldsEqual(PaymentRequest paymentRequest, PaymentProcessingRequest servicePaymentRequest)
 {
     return(paymentRequest.Number == servicePaymentRequest.Number &&
            paymentRequest.Amount == servicePaymentRequest.Amount &&
            paymentRequest.CVV == servicePaymentRequest.CVV &&
            paymentRequest.Currency == servicePaymentRequest.Currency &&
            paymentRequest.ExpiryMonth == servicePaymentRequest.ExpiryMonth &&
            paymentRequest.ExpiryYear == servicePaymentRequest.ExpiryYear &&
            paymentRequest.Name == servicePaymentRequest.Name);
 }
        public async Task Process_AnyPaymentRequest_ReturnsSomeStatus()
        {
            // Arrange
            var paymentRequest = new PaymentProcessingRequest("Test", "1111111111111111", 12, 2025, 20, "EUR", 132);

            // Act
            var result = await _target.Process(paymentRequest);

            // Assert
            Assert.IsNotNull(result);
            Assert.IsFalse(string.IsNullOrEmpty(result.Status));
        }
Ejemplo n.º 9
0
        public async Task <BankingResponse> Handle(PaymentProcessingRequest paymentProcessingRequest)
        {
            try
            {
                var response = await _acquirerBankingService.Post(paymentProcessingRequest);

                return(response);
            }
            catch (Exception exception)
            {
                throw new BankingException(exception.Message);
            }
        }
        public void GivenAPaymentProcessingRequestIsProvidedAndPaymentHandlerReturnsAFailedTransaction_WhenHandlingIt_ThenItReturnsAFailedResponse()
        {
            // Given

            var mockedLogger         = Substitute.For <ILogger <PaymentProcessingController> >();
            var mockedPaymentHandler = Substitute.For <IPaymentHandler>();

            var realPaymentProcessingController = new PaymentProcessingController(mockedLogger, mockedPaymentHandler);

            const string cardNumber      = "1234567812345678";
            const int    expiryMonth     = 12;
            const int    expiryYear      = 2025;
            const int    cvv             = 123;
            const double amount          = 123.45;
            const string currencyIsoCode = "GBP";

            var request = new PaymentProcessingRequest
            {
                CardNumber      = cardNumber,
                ExpiryMonth     = expiryMonth,
                ExpiryYear      = expiryYear,
                Cvv             = cvv,
                Amount          = amount,
                CurrencyIsoCode = currencyIsoCode
            };

            var expectedId = Guid.NewGuid();

            mockedPaymentHandler
            .Handle(request)
            .Returns(new PaymentProcessingResponse()
            {
                Success = false, PaymentGatewayId = expectedId
            });

            // When

            var response = realPaymentProcessingController.Post(request).GetAwaiter().GetResult();

            // Then

            response.Should().NotBeNull();
            response.Should().BeOfType <OkObjectResult>();
            response.As <OkObjectResult>().Value.Should().BeOfType <PaymentProcessingResponse>();
            response.As <OkObjectResult>().Value.As <PaymentProcessingResponse>().Success.Should().BeFalse();
            response.As <OkObjectResult>().Value.As <PaymentProcessingResponse>().PaymentGatewayId.Should().Be(expectedId);

            mockedPaymentHandler.Received(1).Handle(request);
        }
Ejemplo n.º 11
0
        public static PaymentRecord Convert(PaymentProcessingRequest paymentProcessingRequest)
        {
            if (paymentProcessingRequest == null)
            {
                throw new ArgumentException("PaymentProcessingRequest cannot be null.");
            }

            return(new PaymentRecord
            {
                CardNumber = paymentProcessingRequest.CardNumber,
                ExpiryMonth = paymentProcessingRequest.ExpiryMonth,
                ExpiryYear = paymentProcessingRequest.ExpiryYear,
                Cvv = paymentProcessingRequest.Cvv,
                Amount = paymentProcessingRequest.Amount,
                CurrencyIsoCode = paymentProcessingRequest.CurrencyIsoCode,
                PaymentStatus = PaymentStatus.Pending,
                PaymentGatewayId = Guid.NewGuid()
            });
        }
Ejemplo n.º 12
0
        public async Task <PaymentProcessingResponse> Handle(PaymentProcessingRequest paymentProcessingRequest)
        {
            var paymentRecord = PaymentRecord.Convert(paymentProcessingRequest);

            try
            {
                await _paymentRepository.Upsert(paymentRecord);

                var bankResponse = await _bankHandler.Handle(paymentProcessingRequest);

                paymentRecord.BankTransactionId = bankResponse.TransactionId;
                paymentRecord.PaymentStatus     = bankResponse.Success ? PaymentStatus.Success : PaymentStatus.Failed;

                await _paymentRepository.Upsert(paymentRecord);
            }
            catch (BankingException bankingException)
            {
                _logger.LogError(bankingException.ToString());

                throw new PaymentProcessingException($"There was an issue when processing the transaction with the bank. Details: {bankingException.Message}");
            }
            catch (PaymentRepositoryException paymentRepositoryException)
            {
                _logger.LogError(paymentRepositoryException.ToString());

                throw new PaymentProcessingException($"There was an issue when saving the request. Details: {paymentRepositoryException.Message}");
            }
            catch (Exception exception)
            {
                _logger.LogError(exception.ToString());

                throw new PaymentProcessingException($"An unhandled error has occurred. Details: {exception.Message}");
            }

            var response = new PaymentProcessingResponse
            {
                PaymentGatewayId = paymentRecord.PaymentGatewayId,
                Success          = paymentRecord.PaymentStatus == PaymentStatus.Success
            };

            return(response);
        }
Ejemplo n.º 13
0
        public void GivenAValidPaymentProcessingRequest_WhenTryingToConvertToPaymentRecord_ThenItReturnsAPaymentRecord()
        {
            // Given

            const string cardNumber      = "1234567812345678";
            const int    expiryMonth     = 12;
            const int    expiryYear      = 2025;
            const int    cvv             = 123;
            const double amount          = 123.45;
            const string currencyIsoCode = "GBP";

            var request = new PaymentProcessingRequest
            {
                CardNumber      = cardNumber,
                ExpiryMonth     = expiryMonth,
                ExpiryYear      = expiryYear,
                Cvv             = cvv,
                Amount          = amount,
                CurrencyIsoCode = currencyIsoCode
            };

            // When

            var response = PaymentRecord.Convert(request);


            // Then

            response.Should().NotBeNull();
            response.Should().BeOfType <PaymentRecord>();
            response.CardNumber.Should().Be(cardNumber);
            response.ExpiryMonth.Should().Be(expiryMonth);
            response.ExpiryYear.Should().Be(expiryYear);
            response.Cvv.Should().Be(cvv);
            response.Amount.Should().Be(amount);
            response.CurrencyIsoCode.Should().Be(currencyIsoCode);
            response.PaymentStatus.Should().Be(PaymentStatus.Pending);
            response.PaymentGatewayId.Should().NotBe(Guid.Empty);
        }
Ejemplo n.º 14
0
        public void GivenAValidPaymentRequest_WhenPostingId_ThenItReturnsASuccessfulResponse()
        {
            //Given

            var projectDir = GetProjectPath("", typeof(PaymentGatewayApiIntegrationTests).GetTypeInfo().Assembly);

            _ = new HostBuilder()
                .ConfigureWebHost(webHost =>
                                  webHost
                                  .UseStartup(typeof(AcquiringBank.API.Fake.Startup))
                                  .UseTestServer()
                                  .UseKestrel(options => options.Listen(IPAddress.Any, 51394)))
                .Start();

            const string cardNumber      = "1234567812345678";
            const int    expiryMonth     = 12;
            const int    expiryYear      = 2025;
            const int    cvv             = 123;
            const double amount          = 123.45;
            const string currencyIsoCode = "GBP";

            var request = new PaymentProcessingRequest
            {
                CardNumber      = cardNumber,
                ExpiryMonth     = expiryMonth,
                ExpiryYear      = expiryYear,
                Cvv             = cvv,
                Amount          = amount,
                CurrencyIsoCode = currencyIsoCode
            };

            HttpContent httpRequest = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json");

            ValidateAcquirerBankSuccessfulResponse(projectDir, httpRequest);
            ValidateAcquirerBankFailedResponse(projectDir, httpRequest);
            ValidateIfFailsWhenTryingToReachApiWithoutAuthorizationHeader(projectDir, httpRequest);
        }
        public void GivenAnInvalidPaymentProcessingRequestIsProvided_WhenTryingToPostIt_ThenItReturnsABadRequestResponse()
        {
            // Given

            var mockedLogger         = Substitute.For <ILogger <PaymentProcessingController> >();
            var mockedPaymentHandler = Substitute.For <IPaymentHandler>();

            var realPaymentProcessingController = new PaymentProcessingController(mockedLogger, mockedPaymentHandler);

            var request = new PaymentProcessingRequest();

            realPaymentProcessingController.ModelState.AddModelError("CardNumber", "Error Message");

            // When

            var response = realPaymentProcessingController.Post(request).GetAwaiter().GetResult();

            // Then

            response.Should().NotBeNull();
            response.Should().BeOfType <BadRequestObjectResult>();

            mockedPaymentHandler.Received(0).Handle(request);
        }