/// <summary> /// Processes a payment request /// </summary> /// <param name="paymentModel"></param> /// <returns></returns> public async Task <IExecutionResponse <PaymentResult> > ProcessPaymentAsync(PaymentModel paymentModel) { _logger.LogInformation($"Processing payment..."); PaymentResult paymentResult; string userName = GetLoggedInUser(); if (paymentModel.Amount < 0) { _logger.LogInformation("Cannot process payment for amounts less than 0"); paymentResult = PaymentResultMapping.CreateEntity(400, "An error occured"); return(_responseFactory.ExecutionResponse <PaymentResult>("Cannot process payment for amounts less than 0", paymentResult, statusCode: 400)); } // Default result PaymentResult thirdPartyResponse = new PaymentResult { Message = "An error occurred", StatusCode = 500 }; if (paymentModel.Amount < 20) { // Use ICheapPaymentGateway. No retry thirdPartyResponse = _cheapPaymentGateway.BankTransfer(paymentModel); } else if (paymentModel.Amount >= 21 && paymentModel.Amount <= 500) { // Use IExpensivePaymentGateway and retry once with ICheapPaymentGateway thirdPartyResponse = RetryWithCheapPaymentGateway(paymentModel); } else if (paymentModel.Amount > 500) { // Use PremiumPaymentService and retry 3 times thirdPartyResponse = RetryThriceWithPremiumGateway(paymentModel); } var payment = PaymentMapping.CreateEntity(paymentModel, userName, userName); // Map response from third party var paymentState = UpdatePaymentStateFromThirdParty(payment, thirdPartyResponse.StatusCode); // Save to DB _commandRepostory.Add(payment); _paymentStateCommandRepostory.Add(paymentState); await _commandRepostory.SaveAsync(); // Send thirdPartyResponse as the response data, in case an integrator wants to change transaction status based on status code _logger.LogInformation("Payment processed successfully."); return(_responseFactory.ExecutionResponse <PaymentResult>(thirdPartyResponse.Message, statusCode: thirdPartyResponse.StatusCode, data: thirdPartyResponse, status: true)); }