示例#1
0
        public async Task GivenASubmitPaymentRequest_WhenValidPayment_ShouldReturn200SuccessCode()
        {
            // given
            var submitPaymentRequest = new SubmitPaymentRequest
            {
                CardDetails = new CardDetails
                {
                    CVV        = 123,
                    Currency   = "Pound",
                    ExpiryDate = "01/2020",
                    CardNumber = 1234567890123456
                },
                MerchantDetails = new MerchantDetails
                {
                    MerchantId = Guid.NewGuid()
                },
                Amount = 12345
            };
            var jsonRequest = JsonConvert.SerializeObject(submitPaymentRequest);

            // when
            var submitPaymentResponse = await _httpClient.PostAsync("https://localhost:9901/paymentgateway",
                                                                    new StringContent(jsonRequest, Encoding.UTF8, "application/json"));

            // then
            submitPaymentResponse.IsSuccessStatusCode.ShouldBeTrue();

            var responseContent = await submitPaymentResponse.Content.ReadAsStringAsync();

            var paymentInformation = JsonConvert.DeserializeObject <SubmitPaymentResponse>(responseContent);

            paymentInformation.PaymentId.ShouldBeOfType <Guid>();
            paymentInformation.PaymentResponseStatus.ShouldBe("Successful");
        }
        public async Task <ActionResult <SubmitPaymentResponse> > CreatePaymentSync([FromBody] SubmitPaymentRequest paymentRequest)
        {
            Console.WriteLine($"Recieved message: {paymentRequest}");

            Payment payment = new Payment(paymentRequest.PaymentId, paymentRequest.AccountNumber, paymentRequest.PaymentAmount);

            // save payment to cache
            var cache = this._cacheConnection.GetDatabase();
            await cache.StringSetAsync($"payment.{payment.Id}", JsonConvert.SerializeObject(payment));

            // synchronously wait for external payment gateway
            PaymentGatewaySubmitPaymentRequest gatewayRequest = new PaymentGatewaySubmitPaymentRequest(payment.Id, payment.AccountNumber, payment.Amount);
            var serviceResponse = await this._httpClient.PostAsJsonAsync(ExternalPaymentGatewayUri, gatewayRequest);

            if (!serviceResponse.IsSuccessStatusCode)
            {
                throw new Exception("Error processing payment");
            }

            PaymentGatewaySubmitPaymentResponse gatewayResponse = await serviceResponse.Content.ReadAsAsync <PaymentGatewaySubmitPaymentResponse>();;

            // update payment in cache
            payment.Status = gatewayResponse.PaymentStatus;
            await cache.StringSetAsync($"payment.{payment.Id}", JsonConvert.SerializeObject(payment));

            return(new SubmitPaymentResponse(payment.Id, payment.Status));
        }
示例#3
0
        public async Task GivenASubmitPaymentRequest_WhenValidPayment_ShouldReturn200SuccessCode()
        {
            // given
            var submitPaymentRequest = new SubmitPaymentRequest
            {
                CardDetails = new CardDetails
                {
                    CVV        = 123,
                    Currency   = "Pound",
                    ExpiryDate = "01/2020",
                    CardNumber = 1234567890123456
                },
                MerchantDetails = new MerchantDetails
                {
                    MerchantId = Guid.NewGuid()
                },
                Amount = 12345
            };

            // when
            var submitPaymentResponse = await _sut.Post(submitPaymentRequest);

            // then
            submitPaymentResponse.ShouldBeOfType <OkObjectResult>();
            var paymentInformation = (submitPaymentResponse as OkObjectResult).Value as SubmitPaymentResponse;

            paymentInformation.PaymentId.ShouldBeOfType <Guid>();
            paymentInformation.PaymentResponseStatus.ShouldBe("Successful");
        }
示例#4
0
        public async Task GivenASubmitPaymentRequest_WhenPaymentUnsuccessful_ShouldReturn400()
        {
            // given
            var submitPaymentRequest = new SubmitPaymentRequest
            {
                CardDetails = new CardDetails
                {
                    CVV        = 123,
                    Currency   = "Pound",
                    ExpiryDate = "01/2020",
                    CardNumber = 1234567890123456
                },
                MerchantDetails = new MerchantDetails
                {
                    MerchantId = Guid.NewGuid()
                },
                Amount = -1000
            };
            var jsonRequest = JsonConvert.SerializeObject(submitPaymentRequest);

            // when
            var submitPaymentResponse = await _httpClient.PostAsync("https://localhost:9901/paymentgateway",
                                                                    new StringContent(jsonRequest, Encoding.UTF8, "application/json"));

            // then
            submitPaymentResponse.StatusCode.ShouldBe(HttpStatusCode.BadRequest);
        }
示例#5
0
        public async Task GivenASubmitPaymentRequest_WhenUnsuccessful_ShouldReturn400()
        {
            // given
            var submitPaymentRequest = new SubmitPaymentRequest
            {
                CardDetails = new CardDetails
                {
                    CVV        = 123,
                    Currency   = "Pound",
                    ExpiryDate = "01/2020",
                    CardNumber = 1234567890123456
                },
                MerchantDetails = new MerchantDetails
                {
                    MerchantId = Guid.NewGuid()
                },
                Amount = -10000
            };

            // when
            var submitPaymentResponse = await _sut.Post(submitPaymentRequest);

            // then
            submitPaymentResponse.ShouldBeOfType <BadRequestResult>();
        }
示例#6
0
        public ActionResult <SubmitPaymentResponse> CreatePayment([FromBody] SubmitPaymentRequest paymentRequest)
        {
            // mock processing time
            Thread.Sleep(5000);

            // create response with "Completed" status
            var response = new SubmitPaymentResponse(paymentRequest.PaymentId, "Completed");

            return(response);
        }
示例#7
0
        private BankPaymentRequest GenerateBankPaymentRequest(SubmitPaymentRequest submitPaymentRequest, string correlationId)
        {
            var cardDetails = new Services.Models.CardDetails(submitPaymentRequest.CardDetails.CardNumber,
                                                              submitPaymentRequest.CardDetails.ExpiryDate,
                                                              submitPaymentRequest.CardDetails.Currency,
                                                              submitPaymentRequest.CardDetails.CVV);

            var merchantDetails =
                new Services.Models.MerchantDetails(submitPaymentRequest.MerchantDetails.MerchantId);

            return(new BankPaymentRequest(cardDetails, merchantDetails, submitPaymentRequest.Amount, correlationId));
        }
示例#8
0
 public IActionResult SubmitPayment([FromBody] SubmitPaymentRequest submitPaymentRequest)
 {
     try
     {
         var result = this.xServerManager.SubmitPayment(submitPaymentRequest);
         return(Json(result));
     }
     catch (Exception e)
     {
         this.logger.LogError("Exception occurred: {0}", e.ToString());
         return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString()));
     }
 }
示例#9
0
        public async Task <IActionResult> SubmitPayment([FromBody] SubmitPaymentRequest submitPaymentRequest)
        {
            xServer.Stats.IncrementPublicRequest();
            if (xServer.Stats.TierLevel == ServerNode.Tier.TierLevel.Three)
            {
                var submitPaymentResult = await priceFeature.SubmitPayment(submitPaymentRequest);

                return(Json(submitPaymentResult));
            }
            else
            {
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, "Tier 3 requirement not meet", "The node you requested is not a tier 3 node."));
            }
        }
示例#10
0
        public async Task <SubmitPaymentResult> SubmitPayment(SubmitPaymentRequest submitPaymentRequest)
        {
            var result = new SubmitPaymentResult();

            if (Guid.TryParse(submitPaymentRequest.PriceLockId, out Guid validPriceLockId))
            {
                var payeeValidationResult = await ValidateNewPriceLockPayee(submitPaymentRequest);

                if (payeeValidationResult == PaymentErrorCodes.None)
                {
                    using (X42DbContext dbContext = new X42DbContext(databaseSettings.ConnectionString))
                    {
                        var priceLock = dbContext.PriceLocks.Where(p => p.PriceLockId == validPriceLockId).FirstOrDefault();
                        if (priceLock != null)
                        {
                            if (priceLock.Status == (int)Status.New)
                            {
                                priceLock.PayeeSignature = submitPaymentRequest.PayeeSignature;
                                priceLock.TransactionId  = submitPaymentRequest.TransactionId;
                                priceLock.Status         = (int)Status.WaitingForConfirmation;
                                priceLock.Relayed        = false;
                                dbContext.SaveChanges();
                                if (!string.IsNullOrEmpty(submitPaymentRequest.TransactionHex))
                                {
                                    await networkFeatures.SendTransaction(submitPaymentRequest.TransactionHex);
                                }
                                result.Success = true;
                            }
                            else
                            {
                                result.ErrorCode = (int)PaymentErrorCodes.NotNew;
                            }
                        }
                        else
                        {
                            result.ErrorCode = (int)PaymentErrorCodes.PriceLockNotFound;
                        }
                    }
                }
                else
                {
                    result.ErrorCode = (int)payeeValidationResult;
                }
            }
            return(result);
        }
示例#11
0
        public async Task <ActionResult <SubmitPaymentResponse> > CreatePaymentAsync([FromBody] SubmitPaymentRequest paymentRequest)
        {
            PaymentProcessorSubmitPaymentRequest paymentProcessorRequest = new PaymentProcessorSubmitPaymentRequest(paymentRequest.AccountNumber, paymentRequest.PaymentAmount);

            var request = new HttpRequestMessage(HttpMethod.Post, AmqpSidecarUri);

            request.Content = new ObjectContent <PaymentProcessorSubmitPaymentRequest>(paymentProcessorRequest, new JsonMediaTypeFormatter());
            var serviceResponse = await this._httpClient.SendAsync(request);

            if (!serviceResponse.IsSuccessStatusCode)
            {
                Console.WriteLine($"Error in request: {serviceResponse}");
                return(new SubmitPaymentResponse(String.Empty, "Error"));
            }

            // an asynchronous call is marked here as Pending because we don't know the result. downstream services will handle updating
            return(new SubmitPaymentResponse(paymentProcessorRequest.PaymentId, "Pending"));
        }
示例#12
0
        public async Task <bool> UpdatePriceLock(PriceLockResult priceLockData)
        {
            bool result = false;

            if (Guid.TryParse(priceLockData.PriceLockId, out Guid validPriceLockId))
            {
                // Create price lock if it doesn't exist.
                var priceLock = networkFeatures.GetPriceLockData(validPriceLockId);
                if (priceLock == null)
                {
                    var priceLockCreateRequest = new CreatePriceLockRequest()
                    {
                        DestinationAddress = priceLockData.DestinationAddress,
                        ExpireBlock        = priceLockData.ExpireBlock,
                        RequestAmount      = priceLockData.RequestAmount,
                        RequestAmountPair  = priceLockData.RequestAmountPair
                    };
                    var createResult = await CreatePriceLock(priceLockCreateRequest, validPriceLockId.ToString());

                    if (!createResult.Success)
                    {
                        return(false);
                    }
                }

                // Update payment information.
                if (!string.IsNullOrEmpty(priceLockData.TransactionId) && !string.IsNullOrEmpty(priceLockData.PayeeSignature))
                {
                    var paymentSubmit = new SubmitPaymentRequest()
                    {
                        PayeeSignature = priceLockData.PayeeSignature,
                        PriceLockId    = priceLockData.PriceLockId,
                        TransactionId  = priceLockData.TransactionId
                    };
                    var submitPaymentResult = await SubmitPayment(paymentSubmit);

                    if (!submitPaymentResult.Success)
                    {
                        result = true;
                    }
                }
            }
            return(result);
        }
示例#13
0
        public async Task GivenAPaymentRequest_WhenPaymentExists_ShouldReturn200SuccessCodeAndPaymentInformation()
        {
            // given
            var submitPaymentRequest = new SubmitPaymentRequest
            {
                CardDetails = new CardDetails
                {
                    CVV        = 123,
                    Currency   = "Pound",
                    ExpiryDate = "01/2020",
                    CardNumber = 1234567890123456
                },
                MerchantDetails = new MerchantDetails
                {
                    MerchantId = Guid.NewGuid()
                },
                Amount = 12345
            };

            var jsonRequest           = JsonConvert.SerializeObject(submitPaymentRequest);
            var submitPaymentResponse = await _httpClient.PostAsync("https://localhost:9901/paymentgateway",
                                                                    new StringContent(jsonRequest, Encoding.UTF8, "application/json"));

            var responseContent = await submitPaymentResponse.Content.ReadAsStringAsync();

            var paymentInformation = JsonConvert.DeserializeObject <SubmitPaymentResponse>(responseContent);

            // when
            var retrievePaymentResponse = await _httpClient.GetAsync($"https://localhost:9901/paymentgateway?paymentId={paymentInformation.PaymentId}&merchantId={submitPaymentRequest.MerchantDetails.MerchantId}");

            // then
            retrievePaymentResponse.IsSuccessStatusCode.ShouldBeTrue();
            var content = await retrievePaymentResponse.Content.ReadAsStringAsync();

            var retrievedPayment = JsonConvert.DeserializeObject <RetrievePaymentResponse>(content);

            retrievedPayment.Amount.ShouldBe(submitPaymentRequest.Amount);
            retrievedPayment.CVV.ShouldBe("***");
            retrievedPayment.CardNumber.ShouldBe("1234********3456");
            retrievedPayment.ExpiryDate.ShouldBe(submitPaymentRequest.CardDetails.ExpiryDate);
            retrievedPayment.Currency.ShouldBe(submitPaymentRequest.CardDetails.Currency);
            retrievedPayment.PaymentResponseStatus.ShouldBe("Successful");
        }
示例#14
0
        public async Task <ActionResult <SubmitPaymentResponse> > CreatePaymentSync([FromBody] SubmitPaymentRequest paymentRequest)
        {
            PaymentProcessorSubmitPaymentRequest paymentProcessorRequest = new PaymentProcessorSubmitPaymentRequest(paymentRequest.AccountNumber, paymentRequest.PaymentAmount);

            var request = new HttpRequestMessage(HttpMethod.Post, PaymentProcessorUri);

            request.Content = new ObjectContent <PaymentProcessorSubmitPaymentRequest>(paymentProcessorRequest, new JsonMediaTypeFormatter());
            var serviceResponse = await this._httpClient.SendAsync(request);

            if (!serviceResponse.IsSuccessStatusCode)
            {
                Console.WriteLine($"Error in request: {serviceResponse}");
                return(new SubmitPaymentResponse(String.Empty, "Error"));
            }

            // because this call is synchronous, we can return the actual values from the finished process
            PaymentProcessorSubmitPaymentResponse paymentProcessorResponse = await serviceResponse.Content.ReadAsAsync <PaymentProcessorSubmitPaymentResponse>();

            return(new SubmitPaymentResponse(paymentProcessorResponse.PaymentId, paymentProcessorResponse.PaymentStatus));
        }
示例#15
0
        public async Task <IActionResult> Post([FromBody] SubmitPaymentRequest submitPaymentRequest, [FromHeader] string correlationId = null)
        {
            _logger.LogInformation($"Submit Payment request with correlationId {correlationId} received");

            var bankPaymentRequest  = GenerateBankPaymentRequest(submitPaymentRequest, correlationId);
            var bankPaymentResponse = _paymentOrchestrator.ProcessPayment(bankPaymentRequest);

            if (bankPaymentResponse.BankPaymentResponseStatus == BankPaymentResponseStatus.Successful)
            {
                return(Ok(new SubmitPaymentResponse
                {
                    PaymentId = bankPaymentResponse.PaymentId,
                    PaymentResponseStatus = bankPaymentResponse.BankPaymentResponseStatus.ToString()
                }));
            }
            else
            {
                return(BadRequest());
            }
        }
示例#16
0
        /// <inheritdoc />
        public SubmitPaymentResult SubmitPayment(SubmitPaymentRequest submitPaymentRequest)
        {
            var result = new SubmitPaymentResult();
            var t3Node = this.xServerPeerList.GetPeers().Where(n => n.Tier == (int)TierLevel.Three).OrderBy(n => n.ResponseTime).FirstOrDefault();

            if (t3Node != null)
            {
                string xServerURL = Utils.GetServerUrl(t3Node.NetworkProtocol, t3Node.NetworkAddress, t3Node.NetworkPort);
                var    client     = new RestClient(xServerURL);
                client.UseNewtonsoftJson();
                var paymentRequest = new RestRequest("/submitpayment", Method.POST);
                var request        = JsonConvert.SerializeObject(submitPaymentRequest);
                paymentRequest.AddParameter("application/json; charset=utf-8", request, ParameterType.RequestBody);
                paymentRequest.RequestFormat = DataFormat.Json;

                var submitPaymentResult = client.Execute <SubmitPaymentResult>(paymentRequest);
                if (submitPaymentResult.StatusCode == HttpStatusCode.OK)
                {
                    result = submitPaymentResult.Data;
                }
                else
                {
                    var errorResponse = JsonConvert.DeserializeObject <ErrorResponse>(submitPaymentResult.Content);
                    if (errorResponse != null)
                    {
                        result.ResultMessage = errorResponse.errors[0].message;
                    }
                    else
                    {
                        result.ResultMessage = "Failed to access xServer";
                    }
                    result.Success = false;
                }
            }
            else
            {
                result.ResultMessage = "Not connected to any tier 3 servers";
            }
            return(result);
        }
示例#17
0
        public async Task GivenAPaymentRequest_WhenPaymentExists_ShouldReturn200SuccessCodeAndPaymentInformation()
        {
            // given
            var submitPaymentRequest = new SubmitPaymentRequest
            {
                CardDetails = new CardDetails
                {
                    CVV        = 123,
                    Currency   = "Pound",
                    ExpiryDate = "01/2020",
                    CardNumber = 1234567890123456
                },
                MerchantDetails = new MerchantDetails
                {
                    MerchantId = Guid.NewGuid()
                },
                Amount = 12345
            };
            var response = await _sut.Post(submitPaymentRequest);

            var submitPaymentResponse = (response as OkObjectResult).Value as SubmitPaymentResponse;

            // when
            var retrievePaymentResponse = await _sut.Get(new RetrievePaymentRequest
            {
                PaymentId  = submitPaymentResponse.PaymentId,
                MerchantId = submitPaymentRequest.MerchantDetails.MerchantId
            });

            // then
            retrievePaymentResponse.ShouldBeOfType <OkObjectResult>();
            var retrievedPayment = (retrievePaymentResponse as OkObjectResult).Value as RetrievePaymentResponse;

            retrievedPayment.Amount.ShouldBe(submitPaymentRequest.Amount);
            retrievedPayment.CVV.ShouldBe("***");
            retrievedPayment.CardNumber.ShouldBe("1234********3456");
            retrievedPayment.ExpiryDate.ShouldBe(submitPaymentRequest.CardDetails.ExpiryDate);
            retrievedPayment.Currency.ShouldBe(submitPaymentRequest.CardDetails.Currency);
            retrievedPayment.PaymentResponseStatus.ShouldBe("Successful");
        }
示例#18
0
        public void PublishMessageBodyWithNullParmaters(
            [Values("", "payments", "")] string exchange,
            [Values("", "", "payments.create")] string routingKey)
        {
            // arrange
            var controller  = new amqp_sidecar.Controllers.Controller(this._connectionfactory.CreateConnection(), new HttpClient());
            var messageBody = new SubmitPaymentRequest
            {
                AccountNumber = "12345",
                PaymentAmount = 100
            };

            // act
            ActionResult <string> actionResult = controller.EnqueueMessage(messageBody, exchange, routingKey);

            // assert
            var result = actionResult.Result as BadRequestObjectResult;

            Assert.That(result, Is.Not.Null, "Result is not BadRequestObjectResult");
            Assert.That(result.StatusCode, Is.EqualTo((int)HttpStatusCode.BadRequest), "Result should be status code 400");
            Assert.That(this._rabbitServer.Exchanges.ContainsKey(exchange), Is.EqualTo(false), "Exchange should not be created");
        }
        /// <summary>
        /// Submits a payment
        /// </summary>
        /// <param name="client">A RippleRestClient used for this request.</param>
        /// <param name="payment">Payment object</param>
        /// <returns>Original Payment object with Client Resource Id filled</returns>
        /// <exception cref="RippleRestException">Request failed.</exception>
        public Payment SubmitPayment(RippleRestClient client, Payment payment)
        {
            payment.ClientResourceId = client.GenerateUUID();
            payment.SourceAccount = this.Address;
            var data = new SubmitPaymentRequest
            {
                Payment = payment,
                Secret = this.Secret,
                ClientResourceId = payment.ClientResourceId
            };

            var result = client.RestClient.Execute<SubmitPaymentResponse>(client.CreatePostRequest(data, "v1/payments", Address));
            client.HandleRestResponseErrors(result);
            payment.ClientResourceId = result.Data.ClientResourceId;
            return payment;
        }
示例#20
0
        public async Task <PaymentErrorCodes> ValidateNewPriceLockPayee(SubmitPaymentRequest submitPaymentRequest)
        {
            PaymentErrorCodes result;

            var priceLockData = networkFeatures.GetPriceLockData(new Guid(submitPaymentRequest.PriceLockId));

            if (priceLockData != null)
            {
                if (priceLockData.TransactionId == null && priceLockData.PayeeSignature == null)
                {
                    RawTransactionResponse paymentTransaction;
                    if (string.IsNullOrEmpty(submitPaymentRequest.TransactionHex))
                    {
                        paymentTransaction = await networkFeatures.GetRawTransaction(submitPaymentRequest.TransactionId, true);
                    }
                    else
                    {
                        paymentTransaction = await networkFeatures.DecodeRawTransaction(submitPaymentRequest.TransactionHex);
                    }
                    if (paymentTransaction != null)
                    {
                        bool validDestinationFound = false;
                        bool validFeeFound         = false;

                        foreach (var output in paymentTransaction.VOut)
                        {
                            if (output.ScriptPubKey.Addresses.Count() == 1 && output.ScriptPubKey.Addresses[0] == priceLockData.DestinationAddress && output.Value == priceLockData.DestinationAmount)
                            {
                                validDestinationFound = true;
                            }
                            else if (output.ScriptPubKey.Addresses.Count() == 1 && output.ScriptPubKey.Addresses[0] == priceLockData.FeeAddress && output.Value == priceLockData.FeeAmount)
                            {
                                validFeeFound = true;
                            }
                        }
                        if (!validDestinationFound)
                        {
                            return(PaymentErrorCodes.TransactionDestNotFound);
                        }
                        if (!validFeeFound)
                        {
                            return(PaymentErrorCodes.TransactionFeeNotFound);
                        }

                        var isPayeeValid = await priceLockValidation.IsPayeeSignatureValid(paymentTransaction, submitPaymentRequest.PriceLockId, submitPaymentRequest.PayeeSignature);

                        if (isPayeeValid)
                        {
                            result = PaymentErrorCodes.None;
                        }
                        else
                        {
                            result = PaymentErrorCodes.InvalidSignature;
                        }
                    }
                    else
                    {
                        result = PaymentErrorCodes.TransactionError;
                    }
                }
                else
                {
                    result = PaymentErrorCodes.AlreadyExists;
                }
            }
            else
            {
                result = PaymentErrorCodes.PriceLockNotFound;
            }
            return(result);
        }