コード例 #1
0
        public async Task <IActionResult> CreatePaymentAsync(Guid merchantId, CardPaymentRequestDto cardPaymentRequestDto)
        {
            if (User.GetMerchantId() != merchantId)
            {
                _logger.LogCritical($"Access token for merchantId {User.GetMerchantId()} might be compromised. Request made using different merchant Id {merchantId}");
                return(Unauthorized());
            }
            ;

            if (cardPaymentRequestDto == null ||
                !_cardValidator.IsCardNumberValid(cardPaymentRequestDto.CardInformation.CardNumber) ||
                !_cardValidator.IsExpiryDateValid(cardPaymentRequestDto.CardInformation.ExpiryMonth, cardPaymentRequestDto.CardInformation.ExpiryYear))
            {
                //Todo give back a real error message
                _logger.LogInformation("cardPaymentRequestDto is null");
                return(BadRequest());
            }

            _logger.LogInformation("Incoming requestDto");

            var cardPayment = await _paymentService.CreateCardPaymentAsync(merchantId, cardPaymentRequestDto);

            var request = HttpContext.Request;

            return(Created($"{request.Scheme}://{request.Host.Value}/merchant/{merchantId}/payment/{cardPayment.PaymentId}", cardPayment));
        }
コード例 #2
0
        public async Task When_A_Payment_Is_Created_And_GetPaymentDetails_Is_Called_Then_PaymentDetails_Should_Be_Returned()
        {
            var accessToken = await TokenHelper.GetReferenceAccessToken();

            Guid merchantId    = Guid.Parse("b074e29b-54bc-4085-a97d-5a370cafa598");
            var  baseUri       = "https://localhost:5001";
            var  apiClient     = new HttpClient();
            var  paymentClient = new PaymentClient(apiClient, new PaymentRoutes(merchantId, baseUri), accessToken);

            var cardPaymentRequest = new CardPaymentRequestDto
            {
                Amount            = 100m,
                Currency          = Currency.GBP,
                BillingAddressDto = new AddressDto()
                {
                    AddressLine1 = "Random Flat in",
                    AddressLine2 = "Canary Wharf",
                    City         = "London",
                    Country      = "England",
                    FirstName    = "Joe",
                    LastName     = "Blogs"
                },
                CardInformation = new CardInformationDto()
                {
                    CardNumber  = "366252948156588",
                    FirstName   = "Joe",
                    LastName    = "Blogs",
                    Cvv         = "1011",
                    ExpiryMonth = "01",
                    ExpiryYear  = "24"
                }
            };

            var payment = await paymentClient.CreateCardPaymentAsync(cardPaymentRequest);

            var paymentDetails = await paymentClient.GetPaymentDetailsAsync(payment.PaymentId);


            var expectedResponse = new PaymentDetailResponseDto
            {
                PaymentStatus    = payment.PaymentStatus,
                PaymentId        = payment.PaymentId,
                MerchantId       = payment.MerchantId,
                Year             = "24",
                Month            = "01",
                MaskedCardNumber = "3662 52XX XXX6 588"
            };

            paymentDetails.Should().BeEquivalentTo(expectedResponse);
        }
        public async Task When_ValidCerditCard_Information_Used_Then_Payment_Is_Created()
        {
            var accessToken = await TokenHelper.GetReferenceAccessToken();

            Guid merchantId    = Guid.Parse("b074e29b-54bc-4085-a97d-5a370cafa598");
            var  baseUri       = "https://localhost:5001";
            var  apiClient     = new HttpClient();
            var  paymentClient = new PaymentClient(apiClient, new PaymentRoutes(merchantId, baseUri), accessToken);

            var cardPaymentRequest = new CardPaymentRequestDto
            {
                Amount            = 100m,
                Currency          = Currency.GBP,
                BillingAddressDto = new AddressDto()
                {
                    AddressLine1 = "Random Flat in",
                    AddressLine2 = "Canary Wharf",
                    City         = "London",
                    Country      = "England",
                    FirstName    = "Joe",
                    LastName     = "Blogs"
                },
                CardInformation = new CardInformationDto()
                {
                    CardNumber  = "366252948156588",
                    FirstName   = "Joe",
                    LastName    = "Blogs",
                    Cvv         = "1011",
                    ExpiryMonth = "01",
                    ExpiryYear  = "24"
                }
            };

            try
            {
                var response = await paymentClient.CreateCardPaymentAsync(cardPaymentRequest);

                response.PaymentId.Should().NotBeEmpty();
                response.MerchantId.Should().Be(merchantId);
                response.PaymentStatus.Should().Be(PaymentStatus.Created);
            }
            catch (CheckoutGatewayException gatewayException)
            {
                Assert.Fail();
            }
        }
コード例 #4
0
        public async Task <Payment> CreateCardPaymentAsync(Guid merchantId, CardPaymentRequestDto requestDto)
        {
            //Depending on the card payment we may want to route to different acquirers
            //in this example we only have bankOfIreland but in future we can add more here
            var acquirerBankToUse = _acquirerBankSelectionService.GetAcquirerBankToUse(requestDto);

            var payment = await _paymentRepository.AddPaymentAsync(acquirerBankToUse, merchantId, requestDto);

            switch (acquirerBankToUse)
            {
            case AcquirerBank.BankOfIreland:
                return(await _bankOfIrelandAcquiringBankService.CreatePaymentAsync(merchantId : merchantId, paymentId : payment.PaymentId, requestDto));

            default:
                throw new ArgumentException($"Unable able to support AcquirerBank {acquirerBankToUse}");
            }
        }
コード例 #5
0
        public async Task <CardPaymentResponseDto> CreateCardPaymentAsync(CardPaymentRequestDto cardPaymentRequestDto)
        {
            var response = await _httpClient.SendAsync(new HttpRequestMessage
            {
                Headers =
                {
                    Authorization = new AuthenticationHeaderValue(Bearer, _accessToken),
                },
                RequestUri = _paymentRoutes.GetCreateCardPaymentUri(),
                Method     = HttpMethod.Post,
                Content    = new StringContent(JsonSerializer.Serialize(cardPaymentRequestDto), Encoding.UTF8, "application/json")
            });

            if (!response.IsSuccessStatusCode)
            {
                throw new CheckoutGatewayException(response);
            }

            var content = await response.Content.ReadAsStringAsync();

            return(JsonSerializer.Deserialize <CardPaymentResponseDto>(content, new JsonSerializerOptions {
                PropertyNameCaseInsensitive = true
            }));
        }
コード例 #6
0
 //I think this would be a pure function, which would allow easier testability
 public AcquirerBank GetAcquirerBankToUse(CardPaymentRequestDto cardPaymentRequestDto)
 {
     return(AcquirerBank.BankOfIreland);
 }
コード例 #7
0
        public Task <Payment> AddPaymentAsync(AcquirerBank acquirerBank, Guid merchantId, CardPaymentRequestDto cardPaymentRequest)
        {
            var maskedCardNumber = _cardMaskingService.MaskCardNumber(cardPaymentRequest.CardInformation.CardNumber);
            var card             = cardPaymentRequest.CardInformation;
            var hashedCardNumber = _hashService.GetHash(card.CardNumber);

            //this would be calling a stored proc which would do all this within a transaction at the database level
            var address         = _addressDataStore.AddAddress();
            var cardInformation = _cardInformationDataStore.AddCardInformation(firstName: card.FirstName, lastName: card.LastName, expiryMonth: card.ExpiryMonth, expiryYear: card.ExpiryYear, hashedCardNumber: hashedCardNumber, maskedCardNumber: maskedCardNumber);
            var payment         = _paymentDataStore.AddPayment(merchantId, address.AddressId, cardInformation.CardInformationId, acquirerBank, cardPaymentRequest.Amount, cardPaymentRequest.Currency);

            return(Task.FromResult(payment));
        }
コード例 #8
0
        public async Task When_ValidMerchant_And_CardPaymentDetails_Are_Passed_Then_Should_Return_Created()
        {
            Guid merchantId = Guid.Parse("7e903c63-e75b-4788-b80d-d14d12fb5deb");

            var cardPaymentRequest = new CardPaymentRequestDto
            {
                Amount            = 100m,
                Currency          = Currency.GBP,
                BillingAddressDto = new AddressDto()
                {
                    AddressLine1 = "Random Flat in",
                    AddressLine2 = "Canary Wharf",
                    City         = "London",
                    Country      = "England",
                    FirstName    = "Joe",
                    LastName     = "Blogs"
                },
                CardInformation = new CardInformationDto()
                {
                    //https://saijogeorge.com/dummy-credit-card-generator/
                    CardNumber  = "366252948156588",
                    FirstName   = "Joe",
                    LastName    = "Blogs",
                    Cvv         = "1011",
                    ExpiryMonth = "01",
                    ExpiryYear  = "24"
                }
            };

            var paymentId = Guid.Parse("34aa9bf1-1df6-49c5-bd1f-e385a88ba2a9");

            var moqPaymentRepository = new Mock <IPaymentRepository>();

            moqPaymentRepository.Setup(p => p.AddPaymentAsync(AcquirerBank.BankOfIreland, merchantId, cardPaymentRequest))
            .ReturnsAsync(new Payment
            {
                AcquirerBank          = AcquirerBank.BankOfIreland,
                PaymentId             = paymentId,
                PaymentStatus         = PaymentStatus.Created,
                CardInformationId     = 1,
                MerchantId            = merchantId,
                AcquirerPaymentStatus = null,
                AcquirerPaymentId     = null,
                BillingAddressId      = 1,
                Amount       = 100m,
                CurrencyCode = Currency.GBP
            });

            var moqBankOfIrelandAcquiringClient = new Mock <IBankOfIrelandClient>();
            var bankOfIrelandPaymentId          = "f5b9d23b-27a1-4724-9da5-be34e928e78f";
            var bankOfIrelandStatus             = "Approved";

            moqBankOfIrelandAcquiringClient.Setup(c => c.CreatePaymentAsync(It.IsAny <BankOfIrelandPaymentRequest>()))
            .ReturnsAsync(new BankOfIrelandPaymentResponse
            {
                PaymentId     = bankOfIrelandPaymentId,
                PaymentStatus = bankOfIrelandStatus
            });

            moqPaymentRepository.Setup(p => p.UpdatePaymentAsync(merchantId, paymentId, bankOfIrelandPaymentId, bankOfIrelandStatus))
            .ReturnsAsync(new Payment
            {
                AcquirerBank          = AcquirerBank.BankOfIreland,
                PaymentId             = paymentId,
                PaymentStatus         = PaymentStatus.Approved,
                CardInformationId     = 1,
                MerchantId            = merchantId,
                AcquirerPaymentStatus = bankOfIrelandStatus,
                AcquirerPaymentId     = bankOfIrelandPaymentId,
                BillingAddressId      = 1,
                Amount       = 100m,
                CurrencyCode = Currency.GBP
            });

            moqBankOfIrelandAcquiringClient.Setup(c => c.CreatePaymentAsync(It.IsAny <BankOfIrelandPaymentRequest>()))
            .ReturnsAsync(new BankOfIrelandPaymentResponse
            {
                PaymentId     = bankOfIrelandPaymentId,
                PaymentStatus = bankOfIrelandStatus
            });

            var moqDatetimeService = new Mock <IDatetimeService>();

            moqDatetimeService.Setup(d => d.GetUtc()).Returns(DateTime.ParseExact("01/05/2020", "dd/MM/yyyy", CultureInfo.InvariantCulture));

            var controller = CreatePaymentController(merchantId, moqPaymentRepository.Object, moqBankOfIrelandAcquiringClient.Object, moqDatetimeService.Object);

            var result = await controller.CreatePaymentAsync(merchantId, cardPaymentRequest);

            result.Should().BeOfType <CreatedResult>();
            var createdResult = result as CreatedResult;

            createdResult.Should().NotBe(null);
            createdResult.StatusCode.Should().Be(201);

            var expectedResponse = new CardPaymentResponseDto
            {
                MerchantId    = merchantId,
                PaymentId     = paymentId,
                PaymentStatus = PaymentStatus.Approved
            };

            var cardPaymentResponse = createdResult.Value as CardPaymentResponseDto;

            expectedResponse.Should().BeEquivalentTo(expectedResponse);
        }
コード例 #9
0
        public async Task <CardPaymentResponseDto> CreateCardPaymentAsync(Guid merchantId, CardPaymentRequestDto requestDto)
        {
            var payment = await _cardPaymentService.CreateCardPaymentAsync(merchantId, requestDto);

            return(_cardPaymentResponseMapper.Map(payment));
        }
コード例 #10
0
        public async Task <Payment> CreatePaymentAsync(Guid merchantId, Guid paymentId, CardPaymentRequestDto cardPaymentRequestDto)
        {
            var request = _cardPaymentRequestMapper.Map(cardPaymentRequestDto);

            var bankOfIrelandResponse = await _bankOfIrelandClient.CreatePaymentAsync(request);

            return(await _paymentRepository.UpdatePaymentAsync(paymentId : paymentId,
                                                               merchantId : merchantId,
                                                               acquirerPaymentId : bankOfIrelandResponse.PaymentId,
                                                               acquirerPaymentStatus : bankOfIrelandResponse.PaymentStatus));
        }