Ejemplo n.º 1
0
        public async Task Can_retrieve_payment_details_using_BankPaymentId(BankPaymentStatus paymentBankStatus, PaymentGateway.Domain.PaymentStatus expectedStatusInPaymentDetails)
        {
            var requestId      = Guid.NewGuid();
            var paymentRequest = new PaymentRequest(requestId, MerchantsRepository.Amazon, new Money("EUR", 42.66), new PaymentGateway.Infrastructure.Card("4524 4587 5698 1200", "05/19", "321"));

            var           gatewayPaymentId = Guid.NewGuid();
            IGenerateGuid guidGenerator    = new GuidGeneratorForTesting(gatewayPaymentId);

            var bankPaymentId = Guid.Parse("3ec8c76c-7dc2-4769-96f8-7e0649ecdfc0");
            var cqrs          = await PaymentCQRS.Build(paymentBankStatus, new BankPaymentIdGeneratorForTests(bankPaymentId), new AlwaysSuccessBankConnectionBehavior(), new DelayProviderForTesting(TimeSpan.FromMilliseconds(1)), PaymentCQRS.TimeoutProviderForBankResponseWaiting(TimeSpan.FromMilliseconds(200)), Substitute.For <IKnowBufferAndReprocessPaymentRequest>(), Substitute.For <IAmCircuitBreakers>());

            await cqrs.RequestsController.ProceedPaymentRequest(paymentRequest, guidGenerator, cqrs.PaymentRequestsMemory, cqrs.PaymentProcessor);


            var payment = (await cqrs.PaymentReadController.GetPaymentInfo(gatewayPaymentId)).Value;

            Check.That(payment.AcquiringBankPaymentId).HasAValue();
            var paymentDetails = (await cqrs.PaymentDetailsReadController.GetPaymentDetails(payment.AcquiringBankPaymentId.Value)).Value;

            // The response should include a masked card number and card details along with a
            // status code which indicates the result of the payment.
            Check.That(paymentDetails.Card.Number).IsEqualTo("4524 XXXX XXXX XXXX");
            Check.That(paymentDetails.Card.Expiry).IsEqualTo("05/19");
            Check.That(paymentDetails.Card.Cvv).IsEqualTo("321");
            Check.That(paymentDetails.Status).IsEqualTo(expectedStatusInPaymentDetails);
            Check.That(paymentDetails.Approved).IsEqualTo(expectedStatusInPaymentDetails == PaymentStatus.Success);
            Check.That(paymentDetails.AcquiringBankPaymentId).IsEqualTo(bankPaymentId);
        }
        public async Task Create_payment_When_handling_PaymentRequest()
        {
            var requestId      = Guid.NewGuid();
            var paymentRequest = TestsUtils.BuildPaymentRequest(requestId, MerchantsRepository.Apple);

            var           gatewayPaymentId = Guid.NewGuid();
            IGenerateGuid guidGenerator    = new GuidGeneratorForTesting(gatewayPaymentId);

            var cqrs = await PaymentCQRS.Build(BankPaymentStatus.Accepted, new BankPaymentIdGeneratorForTests(Guid.Parse("3ec8c76c-7dc2-4769-96f8-7e0649ecdfc0")), new AlwaysSuccessBankConnectionBehavior(), new DelayProviderForTesting(TimeSpan.FromMilliseconds(1)), PaymentCQRS.TimeoutProviderForBankResponseWaiting(TimeSpan.FromMilliseconds(200)), Substitute.For <IKnowBufferAndReprocessPaymentRequest>(), Substitute.For <IAmCircuitBreakers>());

            var response = await cqrs.RequestsController.ProceedPaymentRequest(paymentRequest, guidGenerator, new PaymentRequestsMemory(), cqrs.PaymentProcessor);

            CheckThatPaymentResourceIsCorrectlyCreated(response, gatewayPaymentId, requestId);
        }
        public async Task Return_all_payments_s_GatewayId()
        {
            var requestId      = Guid.NewGuid();
            var paymentRequest = TestsUtils.BuildPaymentRequest(requestId, MerchantsRepository.Amazon);

            var           gatewayPaymentId          = Guid.NewGuid();
            IGenerateGuid gatewayPaymentIdGenerator = new GuidGeneratorForTesting(gatewayPaymentId);

            var cqrs = await PaymentCQRS.Build(BankPaymentStatus.Accepted, new BankPaymentIdGeneratorForTests(Guid.Parse("3ec8c76c-7dc2-4769-96f8-7e0649ecdfc0")), new AlwaysSuccessBankConnectionBehavior(), new DelayProviderForTesting(TimeSpan.FromMilliseconds(1)), PaymentCQRS.TimeoutProviderForBankResponseWaiting(TimeSpan.FromMilliseconds(200)), Substitute.For <IKnowBufferAndReprocessPaymentRequest>(), Substitute.For <IAmCircuitBreakers>());

            await cqrs.RequestsController.ProceedPaymentRequest(paymentRequest, gatewayPaymentIdGenerator, new PaymentRequestsMemory(), cqrs.PaymentProcessor);

            var gatewayPaymentsIds = await cqrs.GatewayPaymentsIdsController.Get();

            Check.That(gatewayPaymentsIds).ContainsExactly(gatewayPaymentId);
        }
        //[Repeat(10)]
        public async Task Return_AcceptedAtRouteResult_And_have_correct_PaymentStatus_When_Processing_PaymentRequest_timeout()
        {
            var           requestId        = Guid.NewGuid();
            var           paymentRequest   = TestsUtils.BuildPaymentRequest(requestId, MerchantsRepository.Amazon);
            var           gatewayPaymentId = Guid.NewGuid();
            IGenerateGuid guidGenerator    = new GuidGeneratorForTesting(gatewayPaymentId);

            var bankPaymentId = Guid.Parse("3ec8c76c-7dc2-4769-96f8-7e0649ecdfc0");

            var timeoutTolerance         = TimeSpan.FromMilliseconds(80);
            var delayBiggerThanTolerance = timeoutTolerance * 5;

            var delayProvider = Substitute.For <IProvideBankResponseTime>();

            delayProvider.Delays().Returns(delayBiggerThanTolerance,   //timeout
                                           delayBiggerThanTolerance,   //timeout
                                           delayBiggerThanTolerance,   //timeout
                                           timeoutTolerance.Divide(20) // NO TIMEOUT
                                           );

            var knowBufferAndReprocessPaymentRequest = Substitute.For <IKnowBufferAndReprocessPaymentRequest>();
            var circuitBreakerRepository             = new CircuitBreakerRepository();

            var cqrs = await PaymentCQRS.Build(BankPaymentStatus.Accepted,
                                               new BankPaymentIdGeneratorForTests(bankPaymentId),
                                               new AlwaysSuccessBankConnectionBehavior(),
                                               delayProvider,
                                               PaymentCQRS.TimeoutProviderForBankResponseWaiting(timeoutTolerance),
                                               knowBufferAndReprocessPaymentRequest,
                                               circuitBreakerRepository);

            var actionResult = await cqrs.RequestsController.ProceedPaymentRequest(paymentRequest, guidGenerator, cqrs.PaymentRequestsMemory, cqrs.PaymentProcessor);

            Check.That(actionResult).IsInstanceOf <AcceptedAtRouteResult>();

            PaymentDto payment = (await cqrs.PaymentReadController.GetPaymentInfo(gatewayPaymentId)).Value;

            Check.That(payment.RequestId).IsEqualTo(requestId);
            Check.That(payment.GatewayPaymentId).IsEqualTo(gatewayPaymentId);

            Check.That(payment.Status).IsEqualTo(PaymentStatus.Pending); // circuit breaker should open
            Check.That(payment.Approved).IsNull();
            Check.That(payment.AcquiringBankPaymentId).IsNull();

            knowBufferAndReprocessPaymentRequest.ReceivedWithAnyArgs(1).Buffer(default, default);
        public async Task Not_handle_a_PaymentRequest_more_than_once()
        {
            var requestId      = Guid.NewGuid();
            var paymentRequest = TestsUtils.BuildPaymentRequest(requestId, MerchantsRepository.Amazon);

            var cqrs = await PaymentCQRS.Build(BankPaymentStatus.Accepted, new BankPaymentIdGeneratorForTests(Guid.Parse("3ec8c76c-7dc2-4769-96f8-7e0649ecdfc0")), new AlwaysSuccessBankConnectionBehavior(), new DelayProviderForTesting(TimeSpan.FromMilliseconds(1)), PaymentCQRS.TimeoutProviderForBankResponseWaiting(TimeSpan.FromMilliseconds(200)), Substitute.For <IKnowBufferAndReprocessPaymentRequest>(), Substitute.For <IAmCircuitBreakers>());

            var           gatewayPaymentId = Guid.NewGuid();
            IGenerateGuid guidGenerator    = new GuidGeneratorForTesting(gatewayPaymentId);
            await cqrs.RequestsController.ProceedPaymentRequest(paymentRequest, guidGenerator, cqrs.PaymentRequestsMemory, cqrs.PaymentProcessor);

            var actionResult = await cqrs.RequestsController.ProceedPaymentRequest(paymentRequest, guidGenerator, cqrs.PaymentRequestsMemory, cqrs.PaymentProcessor);

            Check.That(actionResult).IsInstanceOf <BadRequestObjectResult>();
            var badRequest = (BadRequestObjectResult)actionResult;
            var failDetail = (ProblemDetails)badRequest.Value;

            Check.That(failDetail.Detail).IsEqualTo("Identical payment request will not be handled more than once");
        }
        public async Task Return_PaymentFaulted_When_AcquiringBank_rejects_payment()
        {
            var           requestId        = Guid.NewGuid();
            var           paymentRequest   = TestsUtils.BuildPaymentRequest(requestId, MerchantsRepository.Amazon);
            var           gatewayPaymentId = Guid.NewGuid();
            IGenerateGuid guidGenerator    = new GuidGeneratorForTesting(gatewayPaymentId);

            var cqrs = await PaymentCQRS.Build(BankPaymentStatus.Accepted, new BankPaymentIdGeneratorForTests(Guid.Parse("3ec8c76c-7dc2-4769-96f8-7e0649ecdfc0")), new AlwaysSuccessBankConnectionBehavior(), new DelayProviderForTesting(TimeSpan.FromMilliseconds(1)), PaymentCQRS.TimeoutProviderForBankResponseWaiting(TimeSpan.FromMilliseconds(200)), Substitute.For <IKnowBufferAndReprocessPaymentRequest>(), Substitute.For <IAmCircuitBreakers>(), new SimulateGatewayException());

            await cqrs.RequestsController.ProceedPaymentRequest(paymentRequest, guidGenerator, cqrs.PaymentRequestsMemory, cqrs.PaymentProcessor);


            var payment = (await cqrs.PaymentReadController.GetPaymentInfo(gatewayPaymentId)).Value;

            Check.That(payment.RequestId).IsEqualTo(requestId);
            Check.That(payment.GatewayPaymentId).IsEqualTo(gatewayPaymentId);

            Check.That(payment.Status).IsEqualTo(PaymentStatus.FaultedOnGateway);
            Check.That(payment.Approved.Value).IsFalse();
            Check.That(payment.AcquiringBankPaymentId).IsNull();
        }
        public async Task Return_proper_payment_status_When_AcquiringBank_accepts_or_reject_payment(BankPaymentStatus bankPaymentStatus, PaymentStatus expectedPaymentStatusReturnedByGateway)
        {
            var           requestId        = Guid.NewGuid();
            var           paymentRequest   = TestsUtils.BuildPaymentRequest(requestId, MerchantsRepository.Apple);
            var           gatewayPaymentId = Guid.NewGuid();
            IGenerateGuid guidGenerator    = new GuidGeneratorForTesting(gatewayPaymentId);

            var bankPaymentId = Guid.Parse("3ec8c76c-7dc2-4769-96f8-7e0649ecdfc0");
            var cqrs          = await PaymentCQRS.Build(bankPaymentStatus, new BankPaymentIdGeneratorForTests(bankPaymentId), new AlwaysSuccessBankConnectionBehavior(), new DelayProviderForTesting(TimeSpan.FromMilliseconds(1)), PaymentCQRS.TimeoutProviderForBankResponseWaiting(TimeSpan.FromMilliseconds(200)), Substitute.For <IKnowBufferAndReprocessPaymentRequest>(), Substitute.For <IAmCircuitBreakers>());

            await cqrs.RequestsController.ProceedPaymentRequest(paymentRequest, guidGenerator, cqrs.PaymentRequestsMemory, cqrs.PaymentProcessor);


            var payment = (await cqrs.PaymentReadController.GetPaymentInfo(gatewayPaymentId)).Value;

            Check.That(payment.RequestId).IsEqualTo(requestId);
            Check.That(payment.GatewayPaymentId).IsEqualTo(gatewayPaymentId);

            Check.That(payment.Status).IsEqualTo(expectedPaymentStatusReturnedByGateway);
            Check.That(payment.Approved).IsEqualTo(payment.Status == PaymentGateway.Domain.PaymentStatus.Success);
            Check.That(payment.AcquiringBankPaymentId).IsEqualTo(bankPaymentId);
        }
        public async Task Return_BadRequest_When_PaymenRequest_Contains_a_merchant_not_onboarded_yet()
        {
            var validCard = new Infrastructure.Card("1234 5623 5489 1004", "05/19", "123");
            var systemNotAwareOfThisMerchant = Guid.NewGuid();

            var invalidRequest = new PaymentRequest(Guid.NewGuid(), merchantId: systemNotAwareOfThisMerchant,
                                                    amount: new Money("USD", 42), card: validCard);

            var           gatewayPaymentId = Guid.NewGuid();
            IGenerateGuid guidGenerator    = new GuidGeneratorForTesting(gatewayPaymentId);

            var cqrs = await PaymentCQRS.Build(BankPaymentStatus.Accepted, new BankPaymentIdGeneratorForTests(Guid.Parse("3ec8c76c-7dc2-4769-96f8-7e0649ecdfc0")), new AlwaysSuccessBankConnectionBehavior(), new DelayProviderForTesting(TimeSpan.FromMilliseconds(1)), PaymentCQRS.TimeoutProviderForBankResponseWaiting(TimeSpan.FromMilliseconds(200)), Substitute.For <IKnowBufferAndReprocessPaymentRequest>(), Substitute.For <IAmCircuitBreakers>(), new NullThrows());

            var actionResult = await cqrs.RequestsController.ProceedPaymentRequest(invalidRequest, guidGenerator, cqrs.PaymentRequestsMemory, cqrs.PaymentProcessor);

            Check.That(actionResult).IsInstanceOf <BadRequestObjectResult>();
            var badRequest = (BadRequestObjectResult)actionResult;
            var failDetail = (ProblemDetails)badRequest.Value;

            Check.That(failDetail.Detail).IsEqualTo($"Merchant {systemNotAwareOfThisMerchant} has not been onboarded");

            Check.That(await cqrs.PaymentRequestsMemory.AlreadyHandled(new PaymentRequestId(invalidRequest.RequestId)))
            .IsFalse();
        }