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));
        }