public ActionResult CreditCard(CheckoutCreditCardViewModel model) { // Convert model fields into validatable values var customer = HttpContext.GetCustomer(); var persistedCheckoutContext = PersistedCheckoutContextProvider.LoadCheckoutContext(customer); var number = !string.IsNullOrEmpty(model.Number) && model.Number.StartsWith("•") && persistedCheckoutContext.CreditCard != null ? persistedCheckoutContext.CreditCard.Number : model.Number.Replace(" ", ""); var issueNumber = !string.IsNullOrEmpty(model.IssueNumber) && model.IssueNumber.StartsWith("•") && persistedCheckoutContext.CreditCard != null ? persistedCheckoutContext.CreditCard.IssueNumber : model.IssueNumber; var expirationDate = ParseMonthYearString(model.ExpirationDate); var startDate = ParseMonthYearString(model.StartDate); var cvv = !string.IsNullOrEmpty(model.Cvv) && model.Cvv.StartsWith("•") && persistedCheckoutContext.CreditCard != null ? persistedCheckoutContext.CreditCard.Cvv : model.Cvv; // Run server-side credit card validation var validationConfiguration = new CreditCardValidationConfiguration( validateCreditCardNumber: AppLogic.AppConfigBool("ValidateCreditCardNumbers"), showCardStartDateFields: AppLogic.AppConfigBool("ShowCardStartDateFields"), cardExtraCodeIsOptional: AppLogic.AppConfigBool("CardExtraCodeIsOptional")); var validationContext = new CreditCardValidationContext( cardType: model.CardType, number: number, issueNumber: issueNumber, expirationDate: expirationDate, startDate: startDate, cvv: cvv); var validationResult = CreditCardValidationProvider.ValidateCreditCard(validationConfiguration, validationContext); // Update the ModelState with any validation issues if (!validationResult.Valid) { foreach (var field in validationResult.FieldErrors) { foreach (var error in field) { // This assumes that the model properties and the credit card validation field enum names match perfectly ModelState.AddModelError(field.Key.ToString(), error); } } } // Use POST redirect GET if there are any issues if (!ModelState.IsValid) { return(RedirectToAction(ActionNames.CreditCard, ControllerNames.CheckoutCreditCard)); } // Save the validated credit card details into the persisted checkout state var updatedPersistedCheckoutContext = new PersistedCheckoutContextBuilder() .From(persistedCheckoutContext) .WithCreditCard(new CreditCardDetails( name: model.Name, number: number, issueNumber: issueNumber, cardType: model.CardType, expirationDate: expirationDate, startDate: startDate, cvv: cvv)) .WithoutAmazonPayments() .WithoutOffsiteRequiredBillingAddressId() .WithoutOffsiteRequiredShippingAddressId() .Build(); PersistedCheckoutContextProvider.SaveCheckoutContext(customer, updatedPersistedCheckoutContext); // Save the StoreCCInDB setting if it was shown to the customer & their choice changed var siteIsStoringCCs = AppLogic.AppConfigBool("StoreCCInDB"); if (siteIsStoringCCs && model.SaveCreditCardNumber != customer.StoreCCInDB) { customer.UpdateCustomer(storeCreditCardInDb: siteIsStoringCCs && model.SaveCreditCardNumber); } // Update the customer record if (customer.RequestedPaymentMethod != AppLogic.ro_PMCreditCard) { customer.UpdateCustomer(requestedPaymentMethod: AppLogic.ro_PMCreditCard); } try { if (WalletProvider.WalletsAreEnabled() && model.SaveToWallet) { WalletProvider.CreatePaymentProfile( customer: customer, billingAddress: customer.PrimaryBillingAddress, cardType: model.CardType, number: number, cvv: cvv, expirationDate: expirationDate.Value); } } catch (WalletException walletException) { ModelState.AddModelError("SaveToWallet", walletException.Message); return(RedirectToAction(ActionNames.CreditCard, ControllerNames.CheckoutCreditCard)); } return(RedirectToAction(ActionNames.Index, ControllerNames.Checkout)); }