public void SetUp()
        {
            _request = _fixture.Create <ProcessPaymentCommandRequestModel>();

            _processPaymentCommandRequestValidatorMock.Setup(x => x.Validate(_request))
            .Returns(Enumerable.Empty <ValidationError>());

            _acmeProcessPaymentResult = new AcmeProcessPaymentResult
            {
                Id            = Guid.NewGuid(),
                WasSuccessful = true,
                Error         = null
            };
            _acmeBankApiMock.Setup(x => x.ProcessPayment(_request.CreditCardNumber, _request.CVV, _request.ExpiryMonth, _request.ExpiryYear, _request.Amount, _request.Currency, _request.CustomerName))
            .ReturnsAsync(() => _acmeProcessPaymentResult);

            var options = new DbContextOptionsBuilder <PaymentGatewayDatabaseContext>()
                          .UseInMemoryDatabase(Guid.NewGuid().ToString())
                          .Options;

            _paymentGatewayDatabaseContext = new PaymentGatewayDatabaseContext(options);
            _fixture.Inject(_paymentGatewayDatabaseContext);

            _subject = _fixture.Create <ProcessPaymentCommand>();
        }
        public async Task Proccess_And_Persist_Payment_When_Acquiring_Bank_Fails_To_Process_Payment()
        {
            var someId = Guid.NewGuid().ToString();
            var mockPaymentRepository = new Mock <IAggregateStore <Payment> >();
            var mockCyptoService      = new Mock <ICryptoService>();
            var mockBankClient        = new Mock <IAquiringBankClient>();
            var mockLogger            = new Mock <ILogger>();

            mockBankClient.Setup(x => x.ProcessPayment(It.IsAny <BankPaymentRequest>()))
            .ReturnsAsync(new BankPaymentResponse {
                PaymentIdentifier = someId, PaymentStatus = PaymentStatus.Failed
            });
            mockCyptoService.Setup(x => x.Encrypt(It.IsAny <string>(), It.IsAny <string>()))
            .Returns("__encripted__");
            var sut = new ProcessPaymentCommandHandler(mockPaymentRepository.Object, mockCyptoService.Object, mockBankClient.Object, mockLogger.Object);
            ProcessPaymentCommand command = new ProcessPaymentCommand
            {
                Amount          = 100,
                Currency        = "EUR",
                CardExpiryYear  = "24",
                CardExpiryMonth = "4",
                CardNumber      = "5564876598743467",
                CVV             = "782",
            };

            await sut.Handle(command, new System.Threading.CancellationToken());

            mockCyptoService.Verify(x => x.Encrypt(command.CardNumber, It.IsAny <string>()), Times.Once);
            mockPaymentRepository.Verify(x => x.AppendChanges(It.Is <Payment>(y => y.CardNumber == "__encripted__")), Times.Once);
            mockPaymentRepository.Verify(x => x.AppendChanges(It.Is <Payment>(y => y.BankPaymentIdentifier == someId)), Times.Once);
            mockPaymentRepository.Verify(x => x.AppendChanges(It.Is <Payment>(y => y.PaymentStatus == PaymentStatus.Failed)), Times.Once);
        }
Example #3
0
            public async Task <Result <long> > Handle(ProcessPaymentCommand request, CancellationToken cancellationToken)
            {
                var isPaymentCaptured = await capturePaymentAsync(request);

                var paymentState = isPaymentCaptured ? PaymentState.Processed : PaymentState.Failed;
                var payment      = new PaymentRequest()
                {
                    Amount = request.Amount,
                    Card   = new Domain.ValueObjects.CreditCard()
                    {
                        CardHolderName = request.CardHolderName,
                        ExpirationDate = request.ExpirationDate,
                        Number         = request.CardNumber,
                        SecurityCode   = request.SecurityCode
                    },
                    CurrentState = paymentState,
                    IsDeleted    = false,
                };

                payment.States.Add(new PaymentRequestState()
                {
                    Request = payment,
                    State   = paymentState,
                    At      = DateTimeOffset.Now,
                });

                _dataContext.Payments.Add(payment);
                await _dataContext.SaveChangesAsync(cancellationToken);

                return(Result.Ok(payment.Id));
            }
Example #4
0
        public async Task ProcessPayment_ReturnsPayment()
        {
            //Arrange
            var request = new ProcessPaymentRequest
            {
                Amount     = 100,
                Currency   = "EUR",
                FullName   = "Dmitriy Purtseladze",
                CardNumber = "5555-5555-5555-5555",
                Cvv        = 123,
                Expiry     = "08/22"
            };

            _bankService.ProcessPaymentAsync(request).Returns(new BankServiceResponse
            {
                IsSuccessHttpStatusCode = true,
                HttpMessage             = "success",
                HttpStatusCode          = HttpStatusCode.OK,
                PaymentStatus           = "success",
                PaymentId = Guid.NewGuid().ToString()
            });
            const string encryptedCardNumber = "encrypted-card-number";
            const string decryptedCardNumber = "5555-5555-5555-5555";

            _aesHelper.Encrypt(decryptedCardNumber).Returns(encryptedCardNumber);

            var maskedCardNumber = "xxxx-xxxx-xxxx-5555";

            _creditCardMasker.MaskCreditCardNumber(Arg.Any <string>()).Returns(maskedCardNumber);

            var payment = new Payment
            {
                Id         = Guid.NewGuid(),
                Amount     = request.Amount,
                Currency   = request.Currency,
                FullName   = request.FullName,
                CardNumber = encryptedCardNumber,
                Expiry     = request.Expiry
            };

            _paymentRepository.AddAsync(Arg.Any <Payment>()).Returns(payment);

            var cmd = new ProcessPaymentCommand(request);

            //Act
            var response = await _subject.Handle(cmd);

            //Assert
            Assert.NotNull(response);
            Assert.NotEqual(Guid.Empty, response.Id);
            Assert.Equal(request.FullName, response.FullName);
            Assert.Equal(request.Amount, response.Amount);
            Assert.Equal(request.Currency, response.Currency);
            Assert.Equal(maskedCardNumber, response.CardNumber);
            Assert.Equal(request.Expiry, response.Expiry);

            await _bankService.Received().ProcessPaymentAsync(request);

            await _paymentRepository.Received().AddAsync(Arg.Any <Payment>());
        }
Example #5
0
        public async void Handle_ShouldProcessPayment()
        {
            var accountsRepo = new Mock <IAccountRepository>();

            var account = new Account(Guid.NewGuid(), 100);

            account.AddPaymentRequest(new DateTime(2020, 3, 1), 40);

            accountsRepo.Setup(a => a.GetAsync(account.Id)).ReturnsAsync(account);

            var paymentRepo = new Mock <IPaymentRepository>();

            var payment = account.PaymentRequests.First();

            paymentRepo.Setup(p => p.GetAsync(payment.Id)).ReturnsAsync(payment);
            paymentRepo.Setup(p => p.UnitOfWork.SaveEntitiesAsync(It.IsAny <CancellationToken>())).ReturnsAsync(true);

            var reason  = "Processed";
            var command = new ProcessPaymentCommand(account.Id, payment.Id);

            var handler = new ProcessPaymentHandler(accountsRepo.Object, paymentRepo.Object);
            await handler.Handle(command, new CancellationToken());

            Assert.Equal(PaymentStatus.Processed, payment.Status);
            Assert.Equal(reason, payment.Reason);
        }
Example #6
0
        public void ProcessPayment_Should_ThrowException_When_InvoiceInvalidState()
        {
            var guid = Guid.NewGuid();

            DbContext.Invoices.Add(new Invoice()
            {
                Id       = guid,
                Amount   = Decimal.Zero,
                Payments = new List <Payment>()
                {
                    new Payment()
                    {
                        Amount = 100
                    }
                }
            });

            var command = new ProcessPaymentCommand
            {
                InvoiceId = guid,
                Amount    = 10,
            };
            var handler = new ProcessPaymentCommandHandler(InvoiceRepository);

            Assert.ThrowsAsync <Exceptions.InvalidOperationException>(async() => await handler.Handle(command, CancellationToken.None));
        }
Example #7
0
        public void ProcessPayment_Should_ThrowException_When_PartialAmountPaid_And_NewAmountTooMuch()
        {
            var command = new ProcessPaymentCommand
            {
                InvoiceId = TestData.Invoice3Id,
                Amount    = 100,
            };
            var handler = new ProcessPaymentCommandHandler(InvoiceRepository);

            Assert.ThrowsAsync <Exceptions.InvalidOperationException>(async() => await handler.Handle(command, CancellationToken.None));
        }
Example #8
0
        public void ProcessPayment_Should_ThrowException_When_NoPaymentNeeded()
        {
            var command = new ProcessPaymentCommand
            {
                InvoiceId = TestData.Invoice4Id,
                Amount    = 10,
            };
            var handler = new ProcessPaymentCommandHandler(InvoiceRepository);

            Assert.ThrowsAsync <Exceptions.InvalidOperationException>(async() => await handler.Handle(command, CancellationToken.None));
        }
Example #9
0
        public void ProcessPayment_Should_ThrowException_When_NoInvoiceFoundForInvoiceId()
        {
            var command = new ProcessPaymentCommand
            {
                InvoiceId = Guid.NewGuid(),
                Amount    = 10,
            };
            var handler = new ProcessPaymentCommandHandler(InvoiceRepository);

            Assert.ThrowsAsync <NotFoundException>(async() => await handler.Handle(command, CancellationToken.None));
        }
Example #10
0
        public void Handle_WhenClosed_ShouldThrowException()
        {
            _mediator.Setup(m => m.Send(It.IsAny <ReduceBalanceCommand>(), It.IsAny <CancellationToken>()))
            .Returns(Task.FromResult(true));
            var sut     = new ProcessPaymentCommandHandler(_context, _mediator.Object, CurrentUser);
            var request = new ProcessPaymentCommand
            {
                Id = Guid.Parse("debf1d88-47ac-4fe4-a0b0-ce42f72ea66e")
            };

            Assert.ThrowsAsync <ValidationException>(() => sut.Handle(request, CancellationToken.None));
        }
        public PaymentViewModel()
        {
            _urlPathSegment = "Payment demo";

            var paymentService = Locator.Current.GetService <IPaymentProcessor>();

            var canPay = this.WhenAnyValue(_ => _.Amount, _ => !string.IsNullOrEmpty(_) && decimal.TryParse(_, NumberStyles.Currency, CultureInfo.InvariantCulture, out var amount) && amount > 0);

            ProcessPaymentCommand = ReactiveCommand
                                    .CreateFromObservable(() => Locator.Current.GetService <IPaymentProcessor>().BeginPay(decimal.Parse(Amount, NumberStyles.Currency, CultureInfo.InvariantCulture)), canPay);

            ProcessPaymentCommand.Subscribe(_ => Application.Current.MainPage
                                            .DisplayAlert(_.Success ? "Hooray!" : "Oops!", _.Message, "OK"));
        }
        public void Not_Allow_Non_Supported_Currencies()
        {
            var command = new ProcessPaymentCommand
            {
                Amount          = 100,
                Currency        = "AUS",
                CardExpiryYear  = "2021",
                CardExpiryMonth = "04",
            };

            var validator = new ProcessPaymentCommandValidator();
            var result    = validator.Validate(command);

            result.Errors.Select(x => x.ErrorMessage).Should().Contain("The currency is not support");
        }
        public void Not_Allow_Negative_Amount()
        {
            var command = new ProcessPaymentCommand
            {
                Amount          = -1,
                Currency        = "AUS",
                CardExpiryYear  = "xxxx",
                CardExpiryMonth = "xxx",
            };

            var validator = new ProcessPaymentCommandValidator();
            var result    = validator.Validate(command);

            result.Errors.Select(x => x.ErrorMessage).Should().Contain("amount must be greater than 0");
        }
Example #14
0
        public async Task <IActionResult> ProcessPayment([FromBody] PaymentRequest request)
        {
            var command = new ProcessPaymentCommand
            {
                Amount          = request.Amount,
                Currency        = request.Currency,
                CardExpiryYear  = request.CardExpiryYear,
                CardExpiryMonth = request.CardExpiryMonth,
                CardNumber      = request.CardNumber,
                CVV             = request.CVV,
                MerchantId      = request.MerchantId
            };

            return(Result.For(await _mediator.Send(command)));
        }
Example #15
0
        public async Task <ActionResult> ProcessPaymentAsync([FromHeader(Name = "ACCOUNT_KEY")] Guid accountId, Guid id)
        {
            var command = new ProcessPaymentCommand(accountId, id);

            try
            {
                var response = await _mediator.Send(command);

                return(Ok());
            }
            catch (KeyNotFoundException)
            {
                return(NotFound());
            }
        }
        public void Not_Allow_Expired_CreditCard()
        {
            var command = new ProcessPaymentCommand
            {
                Amount          = 100,
                Currency        = "AUS",
                CardExpiryYear  = "2020",
                CardExpiryMonth = "04",
            };

            var validator = new ProcessPaymentCommandValidator();
            var result    = validator.Validate(command);

            result.Errors.Select(x => x.ErrorMessage).Should().Contain("The credit card is expired");
        }
Example #17
0
        public async Task ProcessPayment_PayCorrectAmount_InvoicePaidOff()
        {
            var command = new ProcessPaymentCommand
            {
                InvoiceId = TestData.Invoice1Id,
                Amount    = 10,
            };
            var handler = new ProcessPaymentCommandHandler(InvoiceRepository);
            var result  = await handler.Handle(command, CancellationToken.None);

            var invoice = DbContext.Invoices.First(x => x.Id == command.InvoiceId);

            Assert.AreEqual(10, invoice.AmountPaid);
            Assert.AreEqual(10, invoice.Payments.Sum(x => x.Amount));
        }
        public void Not_Allow_String_As_CardYear_And_CardMonth()
        {
            var command = new ProcessPaymentCommand
            {
                Amount          = 100,
                Currency        = "AUS",
                CardExpiryYear  = "xxxx",
                CardExpiryMonth = "xxx",
            };

            var validator = new ProcessPaymentCommandValidator();
            var result    = validator.Validate(command);

            result.Errors.Select(x => x.ErrorMessage).Should().Contain("expiry year is not valid");
            result.Errors.Select(x => x.ErrorMessage).Should().Contain("expiry month is not valid");
        }
        public async Task Handle(CashInRemovedFromHistoryJobEvent evt, ICommandSender commandSender)
        {
            var assetToPayId = await _paymentResolver.Resolve(evt.AssetId);

            var processPaymentCommand = new ProcessPaymentCommand
            {
                Id          = evt.Id,
                ClientId    = evt.ClientId,
                AssetId     = assetToPayId,
                Amount      = evt.Amount,
                NewCashinId = Guid.NewGuid(),
                CashinId    = evt.CashInId
            };

            commandSender.SendCommand(processPaymentCommand, BoundedContext.ForwardWithdrawal);
        }
        public async Task <CommandHandlingResult> Handle(ProcessPaymentCommand command, IEventPublisher eventPublisher)
        {
            try
            {
                var asset = await _assetsServiceWithCache.TryGetAssetAsync(command.AssetId);

                var result = await _exchangeOperationsService.ExchangeOperations.TransferAsync(
                    new TransferRequestModel
                {
                    DestClientId     = command.ClientId,
                    SourceClientId   = _hotWalletId,
                    Amount           = command.Amount.TruncateDecimalPlaces(asset.Accuracy),
                    AssetId          = command.AssetId,
                    TransferTypeCode = "Common",
                    OperationId      = command.NewCashinId.ToString(),
                });

                if (result.IsOk())
                {
                    _log.Info($"Done processing: {command.ToJson()}");

                    eventPublisher.PublishEvent(new CashInProcesedEvent
                    {
                        ClientId    = command.ClientId,
                        OperationId = command.CashinId
                    });

                    return(CommandHandlingResult.Ok());
                }

                if (result.Code == (int)MeStatusCodes.Duplicate)
                {
                    _log.Warning($"Duplicate transfer attempt: {command.ToJson()}");

                    return(CommandHandlingResult.Ok());
                }

                throw new InvalidOperationException(
                          $"During transfer of {command.Id}, ME responded with: {result.Code}");
            }
            catch (Exception e)
            {
                _log.Error(e, context: command.ClientId);

                return(CommandHandlingResult.Fail(TimeSpan.FromMinutes(1)));
            }
        }
Example #21
0
        public void Handle_WhenPendingWithLowBalance_ShouldSetToClosed()
        {
            _mediator.Setup(m => m.Send(It.IsAny <ReduceBalanceCommand>(), It.IsAny <CancellationToken>()))
            .Returns(Task.FromResult(false));
            var sut     = new ProcessPaymentCommandHandler(_context, _mediator.Object, CurrentUser);
            var request = new ProcessPaymentCommand
            {
                Id = Guid.Parse("b162e88d-a3a6-4341-87da-725658d743f3")
            };

            var result = sut.Handle(request, CancellationToken.None).Result;

            Assert.AreEqual(Unit.Value, result);
            var record = _context.Payments.Single(i => i.Id == request.Id);

            Assert.AreEqual(PaymentStatus.Closed, record.Status);
        }
        public async Task <ProcessPaymentResult> HandleAsync(ProcessPaymentCommand command)
        {
            var bankPayemntResult = await _acuquiryBank.ProcessPayment(new BankPaymentRequest
            {
                Amount          = command.Amount,
                Currency        = command.Currency,
                CardExpiryYear  = command.CardExpiryYear,
                CardExpiryMonth = command.CardExpiryMonth,
                CardNumber      = command.CardNumber,
                CVV             = command.CVV,
                MerchantId      = Guid.NewGuid().ToString()
            });

            var encriptionKey       = Guid.NewGuid().ToString("N");
            var encriptedCardNumber = _cryptoService.Encrypt(command.CardNumber, encriptionKey);
            var encriptedCardMonth  = _cryptoService.Encrypt(command.CardExpiryMonth, encriptionKey);
            var encriptedCardDay    = _cryptoService.Encrypt(command.CardExpiryYear, encriptionKey);
            var encriptedCardCVV    = _cryptoService.Encrypt(command.CVV, encriptionKey);

            var payment = new Payment
            {
                Id              = Guid.NewGuid().ToString(),
                EncriptionKey   = encriptionKey,
                CardNumber      = encriptedCardNumber,
                CardExpiryMonth = encriptedCardMonth,
                CardExpiryYear  = encriptedCardDay,
                CVV             = encriptedCardCVV,
                Amount          = command.Amount,
                Currency        = command.Currency,
                MerchantId      = command.MerchantId,
            };

            payment.BankPaymentIdentifier = bankPayemntResult.PaymentIdentifier;
            payment.PaymentStatus         = bankPayemntResult.PaymentStatus;

            await _paymentRepository.Save(payment);

            if (bankPayemntResult.PaymentStatus == PaymentStatus.Success)
            {
                return(new SuccessResult(payment.Id));
            }
            else
            {
                return(new ErrorResult("The Bank was unable to process the payment"));
            }
        }
Example #23
0
        public async Task <IActionResult> Process(ProcessPaymentRequest request)
        {
            var command = new ProcessPaymentCommand(
                request.CardNumber,
                request.Expiry,
                request.Ccv,
                request.Amount,
                request.Currency);

            var result = await _mediator.Send(command);

            if (result.PaymentId is null)
            {
                return(BadRequest(result));
            }
            return(Ok(result));
        }
Example #24
0
        public async Task Proccess_And_Persist_Payment()
        {
            var mockPaymentRepository = new Mock <IPaymentRepository>();
            var mockCyptoService      = new Mock <ICryptoService>();

            mockCyptoService.Setup(x => x.Encrypt(It.IsAny <string>(), It.IsAny <string>()))
            .Returns("__encripted__");
            var sut = new ProcessPaymentCommandHandler(mockPaymentRepository.Object, mockCyptoService.Object);
            ProcessPaymentCommand command = new ProcessPaymentCommand
            {
                Amount          = 100,
                Currency        = "EUR",
                CardExpiryYear  = "24",
                CardExpiryMonth = "4",
                CardNumber      = "5564876598743467",
                CVV             = "782",
            };

            await sut.HandleAsync(command);

            mockCyptoService.Verify(x => x.Encrypt(command.CardNumber, It.IsAny <string>()), Times.Once);
            mockPaymentRepository.Verify(x => x.Save(It.Is <Payment>(y => y.CardNumber == "__encripted__")), Times.Once);
        }
        public async Task <IActionResult> ProcessPaymentAsync([FromBody] ProcessPaymentCommand payment)
        {
            await _mediator.Send(payment);

            return(Ok());
        }
Example #26
0
        public async Task <PaymentResponse> ProcessPaymentAsync([FromBody] ProcessPaymentRequest request)
        {
            var command = new ProcessPaymentCommand(request);

            return(await _mediator.Send(command));
        }
Example #27
0
 public async Task <IActionResult> Process([FromBody] ProcessPaymentCommand command) => Ok(await Mediator.Send(command));
        public async Task <ActionResult> ProcessPayment(ProcessPaymentCommand command)
        {
            await Mediator.Send(command);

            return(NoContent());
        }
Example #29
0
 public static Task <bool> ProcessPayment(ProcessPaymentCommand message)
 {
     _success = !_success;
     return(Task.FromResult(_success));
 }
Example #30
0
        public async Task <IActionResult> ProcessPayment([FromBody] ProcessPaymentCommand command)
        {
            var result = await _mediator.Send(command);

            return(CreatedAtAction("ProcessPayment", result));
        }