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)); }
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(); } }
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}"); } }
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 })); }
//I think this would be a pure function, which would allow easier testability public AcquirerBank GetAcquirerBankToUse(CardPaymentRequestDto cardPaymentRequestDto) { return(AcquirerBank.BankOfIreland); }
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)); }
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); }
public async Task <CardPaymentResponseDto> CreateCardPaymentAsync(Guid merchantId, CardPaymentRequestDto requestDto) { var payment = await _cardPaymentService.CreateCardPaymentAsync(merchantId, requestDto); return(_cardPaymentResponseMapper.Map(payment)); }
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)); }