/// <summary> /// make payment at payment gateway api /// </summary> /// <param name="processPaymentViewModel"></param> /// <returns></returns> private async Task <string> MakePayment(ProcessPaymentViewModel paymentViewModel) { //TO DO: make payment using payment gateway API switch (paymentViewModel.PaymentGatewayId) { case 1: //CheapPaymentGateway break; case 2: //ExpensivePaymentGateway break; case 3: //PremiumPaymentGateway break; default: break; } return(Extentions.GetDescription(EnumClass.PaymentResponse.Processed)); }
public async Task <ProcessPaymentViewModel> ProcessPayment(ProcessPaymentViewModel paymentViewModel) { paymentViewModel.messageViewModel = new MessageViewModel(); paymentViewModel.messageViewModel.Status = true; if (paymentViewModel.Amount < 0) //The request is invalid: 400 bad request { paymentViewModel.messageViewModel.Status = false; paymentViewModel.messageViewModel.Message = Extentions.GetDescription(EnumClass.PaymentResponse.InvalidRequest); return(paymentViewModel); } try { #region local variables string paymentGateway = string.Empty; int retryPayment = 0; string paymentGatewayResponse = Extentions.GetDescription(EnumClass.PaymentResponse.Processed); PaymentDetailModel paymentDetailModel = new PaymentDetailModel(); PaymentDetailModel _paymentDetailModel = new PaymentDetailModel(); UsersCreditCardDetailModel usersCreditCardDetailModel = new UsersCreditCardDetailModel(); bool isCardValid = true; #endregion local variables #region choose payment gateway if (paymentViewModel.Amount <= 20) //If the amount to be paid is less than £20, use ICheapPaymentGateway. { paymentViewModel.PaymentGatewayName = Extentions.GetDescription(EnumClass.PaymentGateways.CheapPaymentGateway); paymentViewModel.PaymentGatewayId = (int)EnumClass.PaymentGateways.CheapPaymentGateway; } else if (paymentViewModel.Amount > 20 && paymentViewModel.Amount <= 500) //If the amount to be paid is £21 - 500, use IExpensivePaymentGateway { paymentViewModel.PaymentGatewayName = Extentions.GetDescription(EnumClass.PaymentGateways.ExpensivePaymentGateway); paymentViewModel.PaymentGatewayId = (int)EnumClass.PaymentGateways.ExpensivePaymentGateway; //use IExpensivePaymentGateway if available. Otherwise, retry only once with ICheapPaymentGateway. if (!ValidatePaymentGateway(paymentViewModel.PaymentGatewayName)) { paymentViewModel.PaymentGatewayName = Extentions.GetDescription(EnumClass.PaymentGateways.CheapPaymentGateway); if (!ValidatePaymentGateway(paymentViewModel.PaymentGatewayName)) //Any error: 500 internal server error { paymentViewModel.messageViewModel.Status = false; paymentViewModel.messageViewModel.Message = Extentions.GetDescription(EnumClass.PaymentResponse.Failed); return(paymentViewModel); } } } else //If the amount is > £500, try only PremiumPaymentService { paymentViewModel.PaymentGatewayName = Extentions.GetDescription(EnumClass.PaymentGateways.PremiumPaymentGateway); paymentViewModel.PaymentGatewayId = (int)EnumClass.PaymentGateways.PremiumPaymentGateway; } #endregion choose payment gateway #region Validate & Save new CC detail //validate card isCardValid = ValidateCreditCard(paymentViewModel); //return here if CC detail is not valid if (!isCardValid) //400 bad request : Invaild Card Detail { paymentViewModel.messageViewModel.Status = isCardValid; paymentViewModel.messageViewModel.Message = Extentions.GetDescription(EnumClass.PaymentResponse.InvaildCardDetail); return(paymentViewModel); } //save card detail into database usersCreditCardDetailModel = await SaveUserCCDetail(paymentViewModel); if (usersCreditCardDetailModel == null) { paymentViewModel.messageViewModel.Status = false; paymentViewModel.messageViewModel.Message = Extentions.GetDescription(EnumClass.PaymentResponse.Failed); return(paymentViewModel); } #endregion Save/Update CC detail #region make payment //get payment gateway response paymentGatewayResponse = await MakePayment(paymentViewModel); #endregion make payment #region Save payment detail paymentDetailModel.Amount = paymentViewModel.Amount; paymentDetailModel.CCUsed = usersCreditCardDetailModel; paymentDetailModel.PaymentDate = DateTime.UtcNow; paymentDetailModel.CartId = paymentViewModel.CartId; paymentDetailModel.PaymentGateway = paymentViewModel.PaymentGatewayName; paymentDetailModel.PaymentStatus = paymentGatewayResponse; await _unitOfWork.PaymentDetailModelRepository.InsertAsync(paymentDetailModel); _paymentDetailModel = _mapper.Map <PaymentDetailModel>(paymentDetailModel); #endregion Save payment detail #region check payment status and update entity as completed //If the amount is > £500, try only PremiumPaymentService and retry up to 3 times in case payment does not get processed while (paymentViewModel.Amount > 500 && paymentGatewayResponse != Extentions.GetDescription(EnumClass.PaymentResponse.Processed)) { if (ValidatePaymentGateway(paymentViewModel.PaymentGatewayName)) { paymentGatewayResponse = await MakePayment(paymentViewModel); } if (retryPayment == 3 || paymentGatewayResponse == Extentions.GetDescription(EnumClass.PaymentResponse.Processed)) { break; } retryPayment = retryPayment + 1; } //Store/update the payment and payment state entities created previously once the processing is completed if (paymentDetailModel.PaymentStatus == Extentions.GetDescription(EnumClass.PaymentResponse.Processed)) { //Use of eager loading var paymentDetail = _unitOfWork.PaymentDetailModelRepository.FindAllByQuery(c => c.Id == paymentDetailModel.Id) .Include(c => c.CCUsed) .FirstOrDefault(); paymentDetail.PaymentStatus = Extentions.GetDescription(EnumClass.PaymentResponse.Completed); await _unitOfWork.PaymentDetailModelRepository.UpdateAsync(paymentDetail); } #endregion check payment status paymentViewModel.messageViewModel.Id = paymentDetailModel.Id; paymentViewModel.messageViewModel.Message = paymentGatewayResponse; //200 Ok } catch (Exception ex) //500 internal server error { paymentViewModel.messageViewModel.Status = false; paymentViewModel.messageViewModel.Message = Extentions.GetDescription(EnumClass.PaymentResponse.Failed); } return(paymentViewModel); }