public async Task ThatCanProcessFailedPayment()
        {
            var request = TestDataProvider.GetValidPaymentRequest();

            var expectedResponse = new BankPaymentResponse
            {
                Identifier = Guid.NewGuid().ToString(),
                Error      = "Payment failed",
            };

            this.bankMock.Setup(x => x.ProcessPaymentAsync(It.IsAny <BankPaymentRequest>())).ReturnsAsync(expectedResponse);
            this.paymentStorageMock.Setup(x => x.SavePaymentDetailsAsync(It.IsAny <PaymentRequest>(), It.IsAny <PaymentResponse>())).ReturnsAsync(true);

            var actualResponse = await this.paymentGateway.ProcessPaymentRequestAsync(request);

            actualResponse.Identifier.ShouldBe(expectedResponse.Identifier);
            actualResponse.Success.ShouldBe(expectedResponse.Success);
            actualResponse.Error.ShouldBe(expectedResponse.Error);
        }
        public async Task CompletePaymentAsync_WithStatus_UpdatesRecord()
        {
            var command             = CreateValidAddPaymentCommand();
            var repository          = new InMemoryPaymentsRepository(NullLogger <InMemoryPaymentsRepository> .Instance);
            var bankPaymentResponse = new BankPaymentResponse()
            {
                BankPaymentId = "TEST",
                Result        = PaymentStatus.Paid
            };

            var paymentId = await repository.StartPaymentAsync(1, command);

            await repository.CompletePaymentAsync(paymentId, bankPaymentResponse);

            var result = await repository.GetPaymentDetailsByPaymentIdAsync(paymentId);

            Assert.NotNull(result.BankPaymentId);
            Assert.Equal(bankPaymentResponse.Result, result.Status);
            Assert.True(result.ResponseReceivedDate > DateTime.MinValue);
        }
        public static Transaction MapResponse(string rawResponse)
        {
            Transaction transaction = new Transaction();

            if (!string.IsNullOrEmpty(rawResponse))
            {
                JsonDoc json = JsonDoc.Parse(rawResponse);

                transaction.TransactionId     = json.GetValue <string>("ob_trans_id");
                transaction.PaymentMethodType = PaymentMethodType.BankPayment;
                transaction.OrderId           = json.Get("order")?.GetValue <string>("id");
                transaction.ResponseMessage   = json.GetValue <string>("status");

                BankPaymentResponse obResponse = new BankPaymentResponse();
                obResponse.RedirectUrl          = json.GetValue <string>("redirect_url");
                obResponse.PaymentStatus        = json.GetValue <string>("status");
                obResponse.Id                   = json.GetValue <string>("ob_trans_id");
                transaction.BankPaymentResponse = obResponse;
            }

            return(transaction);
        }
Exemple #4
0
        public void Initialize()
        {
            _paymentRepositoryMock = new Mock <IPaymentRepository>();
            _merchantServiceMock   = new Mock <IMerchantService>();
            _bankServiceMock       = new Mock <IBankService>();
            _cardValidatorProvider = new CardValidatorProvider();

            _merchantServiceMock.Setup(m => m.GetMerchantById(It.IsAny <Guid>()))
            .Returns(Task.FromResult(
                         new MerchantResponse
            {
                MerchantId = Guid.NewGuid()
            }));

            bankPaymentResponse = new BankPaymentResponse
            {
                BankPaymentRef = Guid.NewGuid(),
                PaymentStatus  = AppCodes.PaymentStatus.Successful
            };

            _bankServiceMock.Setup(b => b.MakeBankPayment(It.IsAny <BankPaymentRequest>()))
            .Returns(Task.FromResult(bankPaymentResponse));

            payment = new Payment
            {
                BankPaymentRef = bankPaymentResponse.BankPaymentRef,
                PaymentStaus   = (short)bankPaymentResponse.PaymentStatus
            };

            _paymentRepositoryMock.Setup(p => p.AddAsync(It.IsAny <Payment>()))
            .Returns(Task.FromResult(payment));

            paymentService = new PaymentService(
                _paymentRepositoryMock.Object,
                _merchantServiceMock.Object,
                _bankServiceMock.Object,
                _cardValidatorProvider);
        }
        public async Task ProcessPaymentAsync_HappyPath_ReportsToTelemetry()
        {
            // arrange
            var command             = Fixture.Create <SubmitPaymentCommand>();
            var payment             = Fixture.Create <Payment>();
            var bankPaymentResponse = new BankPaymentResponse {
                IsSuccessful = true, Id = Guid.NewGuid()
            };

            PaymentRepositoryMock
            .Setup(m => m.GetByIdAsync(command.PaymentId))
            .ReturnsAsync(payment);
            BankServiceClientMock
            .Setup(m => m.CreateOrderAsync(command))
            .ReturnsAsync(bankPaymentResponse);

            // act
            await SUT.ProcessPaymentAsync(command);

            // assert
            TelemetrySubmitterMock
            .Verify(m => m.SubmitAsync(It.IsAny <ServiceOperation>()));
        }
        public async Task ProcessPaymentAsync_HappyPath_SetsTransactionId()
        {
            // arrange
            var command             = Fixture.Create <SubmitPaymentCommand>();
            var payment             = Fixture.Create <Payment>();
            var bankPaymentResponse = new BankPaymentResponse {
                IsSuccessful = true, Id = Guid.NewGuid()
            };

            PaymentRepositoryMock
            .Setup(m => m.GetByIdAsync(command.PaymentId))
            .ReturnsAsync(payment);
            BankServiceClientMock
            .Setup(m => m.CreateOrderAsync(command))
            .ReturnsAsync(bankPaymentResponse);

            // act
            await SUT.ProcessPaymentAsync(command);

            // assert
            PaymentRepositoryMock
            .Verify(m => m.UpdateAsync(It.Is <Payment>(p => p.Id == payment.Id && p.BankTransactionId == bankPaymentResponse.Id)));
        }
        public async Task ProcessPaymentAsync_OnBankError_ReportsToTelemetry()
        {
            // arrange
            var command             = Fixture.Create <SubmitPaymentCommand>();
            var payment             = Fixture.Create <Payment>();
            var bankPaymentResponse = new BankPaymentResponse {
                IsSuccessful = true, Id = Guid.NewGuid()
            };

            PaymentRepositoryMock
            .Setup(m => m.GetByIdAsync(command.PaymentId))
            .ReturnsAsync(payment);
            BankServiceClientMock
            .Setup(m => m.CreateOrderAsync(command))
            .ThrowsAsync(new InvalidOperationException());

            // act
            await SUT.ProcessPaymentAsync(command);

            // assert
            TelemetrySubmitterMock
            .Verify(m => m.SubmitAsync(It.Is <ServiceOperation>(o => o.IsFaulted == 1)));
        }
        public BankPaymentResponse InvoicePayment(Invoice invoice, BankPayment bankPayment)
        {
            var           response = new BankPaymentResponse();
            List <string> errors   = new List <string>();

            if (bankPayment == null)
            {
                response.Errors.Add("Payment details invalid");
                return(response);
            }

            if (bankPayment.Bank == "XYZ")
            {
                response.Errors.Add("Payment through bank XYZ is not allowed");
                return(response);
            }

            invoice.ClosedOn = DateTime.Now;
            invoice.Status   = InvoiceStatus.Closed;
            response.PaymentConfirmatitonNumber = $"{bankPayment.Bank}{DateTime.Now:ssyymmhh}";

            return(response);
        }
        public PaymentGatewayServiceShould()
        {
            paymentReference   = Guid.NewGuid();
            paymentRequest     = CreatePaymentRequest();
            bankPaymentRequest = new BankPaymentRequest("4485063526474709", "01/20", 20.00m, "GBP", 123);
            bankApiMock        = new Mock <IBankApiClient>();
            var bankPaymentDetail   = new BankPaymentDetail(paymentReference, "Accepted", "4485063526474709", "01/20", 20.00m, "GBP", 123);
            var bankPaymentResponse = new BankPaymentResponse(paymentReference, "Accepted");
            var paymentResponse     = new PaymentResponse(paymentReference, "Accepted");
            var paymentDetail       = new PaymentDetail(paymentReference, "Accepted", "4***********4709", "01/20", 20.00m, "GBP", 123);

            bankApiMock.Setup(service => service.Process(It.IsAny <BankPaymentRequest>()))
            .Returns(Task.FromResult(bankPaymentResponse));
            bankApiMock.Setup(service => service.GetPaymentDetail(paymentReference)).Returns(Task.FromResult(bankPaymentDetail));
            bankPaymentMapperMock = new Mock <IBankPaymentMapper>();
            bankPaymentMapperMock.Setup(mapper => mapper.MapRequest(It.IsAny <PaymentRequest>())).Returns(bankPaymentRequest);
            bankPaymentMapperMock.Setup(mapper => mapper.MapResponse(It.IsAny <BankPaymentResponse>()))
            .Returns(paymentResponse);
            bankPaymentMapperMock.Setup(mapper => mapper.MapDetail(It.IsAny <BankPaymentDetail>()))
            .Returns(paymentDetail);
            applicationLoggerMock = new Mock <IApplicationLogger>();
            paymentGatewayService = new PaymentGatewayService(bankApiMock.Object, bankPaymentMapperMock.Object, applicationLoggerMock.Object);
        }
 private static PaymentResponse CreatePaymentResponse(BankPaymentResponse bankPaymentResponse)
 {
     return(new PaymentResponse(bankPaymentResponse.PaymentReference, bankPaymentResponse.Status));
 }
        public PaymentResponse ProcessPayment(ProcessPaymentRequest request, string merchantApiKey)
        {
            //Get merchant
            var merchant = _merchantDao.GetMerchantBasedOnApiKey(merchantApiKey);

            if (merchant == null)
            {
                Logger.Info("Request from an unknown merchant received");
                throw new RequestValidationException("Unknown Merchant");
            }

            if (string.IsNullOrWhiteSpace(request.CardNumber))
            {
                Logger.Info($"Bad Request from MerchantId :{merchant.ID}, Missing Card Number");
                throw new RequestValidationException("Missing Card Number");
            }

            if (!(request.CardNumber.Length == 19 || request.CardNumber.Length == 16))
            {
                Logger.Info($"Bad Request from MerchantId :{merchant.ID}, Invalid Card Number");
                throw new RequestValidationException("Invalid Card Number");
            }

            if (string.IsNullOrWhiteSpace(request.CardCvv))
            {
                Logger.Info($"Bad Request from MerchantId :{merchant.ID}, Missing Card CVV Number");
                throw new RequestValidationException("Missing Card CVV Number");
            }

            if (request.CardCvv.Length != 4)
            {
                Logger.Info($"Bad Request from MerchantId :{merchant.ID}, Invalid Card Card CVV Number");
                throw new RequestValidationException("Invalid Card Card CVV Number");
            }

            if (request.PaymentAmount == 0)
            {
                Logger.Info($"Bad Request from MerchantId :{merchant.ID}, Invalid Payment Amount");
                throw new RequestValidationException("Payment Amount should be greater than zero");
            }

            if (string.IsNullOrWhiteSpace(request.ExpiryDate))
            {
                Logger.Info($"Bad Request from MerchantId :{merchant.ID}, Missing Card Expiry Date");
                throw new RequestValidationException("Missing Card Card Expiry Date");
            }

            DateTime expiryDate;

            try
            {
                expiryDate = DateTime.ParseExact(request.ExpiryDate, _expiryDateFormat, CultureInfo.InvariantCulture);
            }
            catch (Exception e)
            {
                Logger.Info($"Bad Request from MerchantId :{merchant.ID}, Invalid ExpiryDate provided");
                throw new RequestValidationException("Invalid ExpiryDate provided");
            }

            if (string.IsNullOrWhiteSpace(request.Currency))
            {
                Logger.Info($"Bad Request from MerchantId :{merchant.ID}, Missing Currency");
                throw new RequestValidationException("Missing Currency");
            }



            var currency = GetCurrency(request);

            if (currency == null)
            {
                Logger.Info($"Bad Request from MerchantId :{merchant.ID}, Unknown currency");
                throw new RequestValidationException("Unknown Currency");
            }



            var card = GetOrCreateCard(request, expiryDate);

            var paymentRequest = new PaymentRequest
            {
                MerchantId    = merchant.ID,
                CardId        = card.ID,
                CurrencyId    = currency.ID,
                Amount        = request.PaymentAmount,
                DateTimeAdded = DateTime.UtcNow
            };

            _paymentRequestDao.InsertPaymentRequest(paymentRequest);

            paymentRequest =
                _paymentRequestDao.GetPaymentRequestBasedOnMerchantIdCardIdCurrencyIdAndAmount(paymentRequest);
            Logger.Info($"Payment request from Merchant: {merchant.ID} logged. PaymentRequestId : {paymentRequest.Id}");

            var acquiringBankRequest = new  AcquiringBankRequest
            {
                CardNumber    = request.CardNumber,
                CardCvv       = request.CardCvv,
                PaymentAmount = request.PaymentAmount,
                ExpiryDate    = request.ExpiryDate,
                Currency      = request.Currency,
                MerchantId    = merchant.ID
            };
            var response = _acquiringBankService.ProcessPayment(acquiringBankRequest);

            var bankPaymentResponse = new BankPaymentResponse
            {
                PaymentRequestId      = paymentRequest.Id,
                Status                = response.PaymentStatus,
                BankPaymentIdentifier = response.PaymentIdentifier,
                DateTimeAdded         = DateTime.UtcNow
            };

            _bankPaymentResponseDao.InsertBankPaymentResponse(bankPaymentResponse);

            return(new PaymentResponse
            {
                Status = response.PaymentStatus,
                PaymentUniqueId = response.PaymentIdentifier
            });
        }
 public PaymentResponse MapResponse(BankPaymentResponse bankPaymentResponse)
 {
     return(new PaymentResponse(bankPaymentResponse.PaymentReference, bankPaymentResponse.Status));
 }
        private PaymentInformation GenerateRepositoryPayment(BankPaymentRequest bankPaymentRequest, BankPaymentResponse bankPaymentResponse)
        {
            var payment = new PaymentInformation
            {
                Amount      = bankPaymentRequest.Amount,
                Id          = bankPaymentResponse.PaymentId,
                CardDetails = new CardDetails(bankPaymentRequest.CardDetails.CardNumber.ToString(), bankPaymentRequest.CardDetails.ExpiryDate,
                                              bankPaymentRequest.CardDetails.Currency, bankPaymentRequest.CardDetails.CVV.ToString()),
                MerchantDetails = new MerchantDetails(bankPaymentRequest.MerchantDetails.MerchantId),
                PaymentStatus   = bankPaymentResponse.BankPaymentResponseStatus == BankPaymentResponseStatus.Unsuccessful ? "Unsuccessful" : "Successful"
            };

            payment.CardDetails.Obfuscate(_dataObfuscator);

            return(payment);
        }