public void Cleanup(AppliedPaymentMethodCleanupContext context)
        {
            // Only finalize the process if this is an Amazon Payments order.
            if (context.PaymentMethod != AppLogic.ro_PMAmazonPayments)
            {
                return;
            }

            // Currently, Amazon only needs to clean up the checkout context if there's an error.
            //  Successful orders will trigger the checkout process to clear the context.
            if (context.Status == AppLogic.ro_OK)
            {
                return;
            }

            var updatedPersistedCheckoutContext = new PersistedCheckoutContextBuilder()
                                                  .From(PersistedCheckoutContextProvider.LoadCheckoutContext(context.Customer))
                                                  .WithoutAmazonPayments()
                                                  .WithoutAcceptJsCreditCard()
                                                  .WithoutAcceptJsECheck()
                                                  .WithoutOffsiteRequiredBillingAddressId()
                                                  .WithoutOffsiteRequiredShippingAddressId()
                                                  .Build();

            PersistedCheckoutContextProvider.SaveCheckoutContext(context.Customer, updatedPersistedCheckoutContext);
            context.Customer.UpdateCustomer(requestedPaymentMethod: string.Empty);
        }
        public ActionResult AmazonPayments(bool clearSession = false)
        {
            var customer = HttpContext.GetCustomer();

            if (!PaymentOptionProvider.PaymentMethodSelectionIsValid(AppLogic.ro_PMAmazonPayments, customer))
            {
                NoticeProvider.PushNotice(
                    message: AppLogic.GetString("checkout.paymentmethodnotallowed"),
                    type: NoticeType.Failure);
                return(RedirectToAction(ActionNames.Index, ControllerNames.Checkout));
            }

            var model = new AmazonPaymentsViewModel(
                residenceTypeOptions: SelectListBuilder.BuildResidenceTypeSelectList(ResidenceTypes.Residential.ToString()),
                clientId: AmazonPaymentsApiProvider.Configuration.ClientId,
                merchantId: AmazonPaymentsApiProvider.Configuration.MerchantId,
                scriptUrl: AmazonPaymentsApiProvider.Configuration.ScriptUrl);

            if (clearSession)
            {
                var updatedPersistedCheckoutContext = new PersistedCheckoutContextBuilder()
                                                      .From(PersistedCheckoutContextProvider.LoadCheckoutContext(customer))
                                                      .WithoutAmazonPayments()
                                                      .WithoutOffsiteRequiredBillingAddressId()
                                                      .WithoutOffsiteRequiredShippingAddressId()
                                                      .Build();

                PersistedCheckoutContextProvider.SaveCheckoutContext(customer, updatedPersistedCheckoutContext);
                customer.UpdateCustomer(requestedPaymentMethod: string.Empty);
                return(Redirect(Url.Action(ActionNames.Index, ControllerNames.Checkout)));
            }

            return(View(model));
        }
        public ActionResult AmazonPaymentsComplete(AmazonPaymentsViewModel model)
        {
            var customer = HttpContext.GetCustomer();

            var orderDetails = AmazonPaymentsApiProvider
                               .GetOrderDetails(model.AmazonOrderReferenceId)
                               .GetOrderReferenceDetailsResult
                               .OrderReferenceDetails;

            var shippingAddress = orderDetails
                                  .Destination
                                  .PhysicalDestination;

            var city              = shippingAddress.City;
            var countryCode       = shippingAddress.CountryCode;
            var countryName       = AppLogic.GetCountryNameFromTwoLetterISOCode(countryCode);
            var stateName         = shippingAddress.StateOrRegion ?? string.Empty;
            var stateAbbreviation = AppLogic.GetStateAbbreviation(stateName, countryName);
            var postalCode        = shippingAddress.PostalCode;

            if (!ModelState.IsValid)
            {
                var newModel = new AmazonPaymentsViewModel(
                    residenceTypeOptions: SelectListBuilder.BuildResidenceTypeSelectList(ResidenceTypes.Residential.ToString()),
                    clientId: model.ClientId,
                    merchantId: model.MerchantId,
                    scriptUrl: model.ScriptUrl);

                return(View(ViewNames.AmazonPayments, newModel));
            }

            var amazonAddress = Address.FindOrCreateOffSiteAddress(
                customerId: customer.CustomerID,
                city: city,
                stateAbbreviation: string.IsNullOrEmpty(stateAbbreviation)
                                        ? stateName
                                        : stateAbbreviation,
                postalCode: postalCode,
                countryName: string.IsNullOrEmpty(countryName)
                                        ? countryCode
                                        : countryName,
                offSiteSource: AppLogic.ro_PMAmazonPayments,
                residenceType: model.ResidenceType
                );

            customer.SetPrimaryAddress(amazonAddress.AddressID, AddressTypes.Billing);
            customer.SetPrimaryAddress(amazonAddress.AddressID, AddressTypes.Shipping);

            var updatedPersistedCheckoutContext = new PersistedCheckoutContextBuilder()
                                                  .From(PersistedCheckoutContextProvider.LoadCheckoutContext(customer))
                                                  .WithAmazonPayments(new AmazonPaymentsDetails(model.AmazonOrderReferenceId))
                                                  .WithOffsiteRequiredBillingAddressId(amazonAddress.AddressID)
                                                  .WithOffsiteRequiredShippingAddressId(amazonAddress.AddressID)
                                                  .Build();

            PersistedCheckoutContextProvider.SaveCheckoutContext(customer, updatedPersistedCheckoutContext);
            customer.UpdateCustomer(requestedPaymentMethod: AppLogic.ro_PMAmazonPayments);

            return(RedirectToAction(ActionNames.Index, ControllerNames.Checkout));
        }
Exemple #4
0
        public ActionResult AcceptJsECheck(AcceptJsEcheckPostModel model)
        {
            var customer = HttpContext.GetCustomer();

            // Save the validated eCheck details into the persisted checkout state.
            // ECheckDetails are null because we have already sent data to AcceptJs.
            // All we need now is the DataValue and DataDescriptor to complete the transaction.
            var updatedPersistedCheckoutContext = new PersistedCheckoutContextBuilder()
                                                  .From(PersistedCheckoutContextProvider.LoadCheckoutContext(customer))
                                                  .WithECheck(
                eCheck: new ECheckDetails(
                    nameOnAccount: null,
                    accountNumber: null,
                    routingNumber: null,
                    accountType: null))
                                                  .WithAcceptJsECheck(
                acceptJsECheck: new AcceptJsDetailsECheck(
                    dataValue: model.DataValue,
                    dataDescriptor: model.DataDescriptor,
                    eCheckDisplayAccountNumberLastFour: model.ECheckDisplayAccountNumberLastFour,
                    eCheckDisplayAccountType: model.ECheckDisplayAccountType))
                                                  .WithoutOffsiteRequiredBillingAddressId()
                                                  .WithoutOffsiteRequiredShippingAddressId()
                                                  .Build();

            PersistedCheckoutContextProvider.SaveCheckoutContext(customer, updatedPersistedCheckoutContext);

            customer.UpdateCustomer(requestedPaymentMethod: AppLogic.ro_PMECheck);

            return(RedirectToAction(ActionNames.Index, ControllerNames.Checkout));
        }
Exemple #5
0
        public void Cleanup(AppliedPaymentMethodCleanupContext context)
        {
            // Only finalize the process if this is a PayPal Express order.
            if (context.PaymentMethod != AppLogic.ro_PMPayPalExpress)
            {
                return;
            }

            // Currently, PayPal Express only needs to clean up the checkout context if there's an error.
            //  Successful orders will trigger the checkout process to clear the context.
            if (context.Status == AppLogic.ro_OK)
            {
                return;
            }

            var updatedPersistedCheckoutContext = new PersistedCheckoutContextBuilder()
                                                  .From(PersistedCheckoutContextProvider.LoadCheckoutContext(context.Customer))
                                                  .WithoutPayPalExpress()
                                                  .Build();

            PersistedCheckoutContextProvider.SaveCheckoutContext(context.Customer, updatedPersistedCheckoutContext);

            DB.ExecuteSQL(
                sql: "update Customer set RequestedPaymentMethod = null where CustomerId = @customerId",
                parameters: new System.Data.SqlClient.SqlParameter("@customerId", context.Customer.CustomerID));
        }
        public ActionResult BraintreeCreditCard(FormCollection collection)
        {
            var customer = HttpContext.GetCustomer();

            var updatedPersistedCheckoutContext = new PersistedCheckoutContextBuilder()
                                                  .From(PersistedCheckoutContextProvider.LoadCheckoutContext(customer))
                                                  .WithCreditCard(new CreditCardDetails(
                                                                      name: customer.Name,
                                                                      number: null,
                                                                      issueNumber: null,
                                                                      cardType: collection["braintreeCardType"],
                                                                      expirationDate: null,
                                                                      startDate: null,
                                                                      cvv: null))
                                                  .WithBraintree(new BraintreeDetails(
                                                                     nonce: collection["braintreeNonce"],
                                                                     token: collection["braintreeToken"],
                                                                     paymentMethod: Gateway.BraintreeCreditCardKey, //This is the Braintree payment method, not ours
                                                                     threeDSecureApproved: false))
                                                  .WithoutOffsiteRequiredBillingAddressId()
                                                  .WithoutOffsiteRequiredShippingAddressId()
                                                  .Build();

            PersistedCheckoutContextProvider.SaveCheckoutContext(customer, updatedPersistedCheckoutContext);

            customer.UpdateCustomer(requestedPaymentMethod: AppLogic.ro_PMCreditCard);

            return(RedirectToAction(ActionNames.Index, ControllerNames.Checkout));
        }
Exemple #7
0
        public ActionResult AcceptJsCreditCard(AcceptJsCreditCardViewModel model)
        {
            var customer = HttpContext.GetCustomer();

            // Save the validated credit card details into the persisted checkout state
            var updatedPersistedCheckoutContext = new PersistedCheckoutContextBuilder()
                                                  .From(PersistedCheckoutContextProvider.LoadCheckoutContext(customer))
                                                  .WithCreditCard(
                creditCard: new CreditCardDetails(
                    name: customer.Name,
                    number: model.LastFour,                         //Put this here so that it can display in the payment summary section of the checkout page
                    issueNumber: null,
                    cardType: null,
                    expirationDate: null,
                    startDate: null,
                    cvv: null))
                                                  .WithAcceptJsCreditCard(
                acceptJsCreditCard: new AcceptJsDetailsCreditCard(
                    dataValue: model.DataValue,
                    dataDescriptor: model.DataDescriptor,
                    lastFour: model.LastFour,
                    expirationMonth: model.ExpirationDate.Split('/')[0],                        //No special handling to check for empty values here.
                    expirationYear: model.ExpirationDate.Split('/')[1]))                        // Better to explode here because expiration dates are required.
                                                  .WithoutOffsiteRequiredBillingAddressId()
                                                  .WithoutOffsiteRequiredShippingAddressId()
                                                  .Build();

            PersistedCheckoutContextProvider.SaveCheckoutContext(customer, updatedPersistedCheckoutContext);

            customer.UpdateCustomer(requestedPaymentMethod: AppLogic.ro_PMCreditCard);

            return(RedirectToAction(ActionNames.Index, ControllerNames.Checkout));
        }
Exemple #8
0
        public ActionResult SagePayPiCreditCard(FormCollection collection)
        {
            var cardErrorSegments = collection["sagePayPiCardError"]
                                    .ParseAsDelimitedList('|');

            if (cardErrorSegments.FirstOrDefault() == "ERROR")
            {
                var error = cardErrorSegments
                            .Skip(1)
                            .FirstOrDefault();

                if (string.IsNullOrEmpty(error) || error.Contains("\"httpErrorCode\":401"))
                {
                    NoticeProvider.PushNotice(StringResourceProvider.GetString("sagepaypi.payment.addingdetailserror"), NoticeType.Failure);
                    return(RedirectToAction(ActionNames.Index, ControllerNames.Checkout));
                }

                var sagePayPi    = new SagePayPi();
                var errorObject  = Newtonsoft.Json.Linq.JObject.Parse(error);
                var errorDetails = sagePayPi.GetResponseError(errorObject, "errors");
                var errorMessage = string.Format("{0} {1}", StringResourceProvider.GetString("sagepaypi.payment.carderrorprompt"), errorDetails);

                NoticeProvider.PushNotice(errorMessage, NoticeType.Failure);
                return(RedirectToAction(ActionNames.Index, ControllerNames.Checkout));
            }

            var customer = HttpContext.GetCustomer();
            var session  = new CustomerSession(customer.CustomerID);

            session[AppLogic.SagePayPiMerchantSessionKey] = collection["sagePayPiMerchantSessionKey"];

            var updatedPersistedCheckoutContext = new PersistedCheckoutContextBuilder()
                                                  .From(PersistedCheckoutContextProvider.LoadCheckoutContext(customer))
                                                  .WithCreditCard(new CreditCardDetails(
                                                                      name: null,
                                                                      number: null,
                                                                      issueNumber: null,
                                                                      cardType: collection["sagePayPiCardType"],
                                                                      expirationDate: null,
                                                                      startDate: null,
                                                                      cvv: null))
                                                  .WithSagePayPi(new SagePayPiDetails(
                                                                     cardIdentifier: collection["sagePayPiCardIdentifier"],
                                                                     merchantSessionId: collection["sagePayPiMerchantSessionKey"],
                                                                     paymentMethod: Gateway.SagePayPiCreditCardKey, //This is the Sage Pay PI payment method, not ours
                                                                     threeDSecureApproved: false))
                                                  .WithoutOffsiteRequiredBillingAddressId()
                                                  .WithoutOffsiteRequiredShippingAddressId()
                                                  .Build();

            PersistedCheckoutContextProvider.SaveCheckoutContext(customer, updatedPersistedCheckoutContext);

            customer.UpdateCustomer(requestedPaymentMethod: AppLogic.ro_PMCreditCard);

            return(RedirectToAction(ActionNames.Index, ControllerNames.Checkout));
        }
        void UpdateOver13(bool?over13Selected, Customer customer)
        {
            if (!over13Selected.HasValue)
            {
                return;
            }

            var updatedPersistedCheckoutContext = new PersistedCheckoutContextBuilder()
                                                  .From(PersistedCheckoutContextProvider.LoadCheckoutContext(customer))
                                                  .WithOver13Checked(over13Selected.Value)
                                                  .Build();

            PersistedCheckoutContextProvider.SaveCheckoutContext(customer, updatedPersistedCheckoutContext);
        }
        void UpdateTermsAndConditions(bool?termsAndConditionAccepted, Customer customer)
        {
            if (!termsAndConditionAccepted.HasValue)
            {
                return;
            }

            var updatedPersistedCheckoutContext = new PersistedCheckoutContextBuilder()
                                                  .From(PersistedCheckoutContextProvider.LoadCheckoutContext(customer))
                                                  .WithTermsAndConditionsAccepted(termsAndConditionAccepted.Value)
                                                  .Build();

            PersistedCheckoutContextProvider.SaveCheckoutContext(customer, updatedPersistedCheckoutContext);
        }
        public ActionResult AmazonPaymentsCallback(string session, string access_token, string token_type, string expires_in, string scope)
        {
            // Get an email back from amazon and update the checkout context with it if we don't already have an email on the checkout context.
            var customer = HttpContext.GetCustomer();
            var persistedCheckoutContext = PersistedCheckoutContextProvider.LoadCheckoutContext(customer);

            if (string.IsNullOrEmpty(persistedCheckoutContext.Email))
            {
                if (string.IsNullOrEmpty(access_token))
                {
                    return(View(ViewNames.AmazonPayments, new { clearSession = true }));
                }

                var userProfile = AmazonPaymentsApiProvider.GetUserProfile(access_token);
                if (userProfile != null && !string.IsNullOrEmpty(userProfile.Email))
                {
                    var updatedPersistedCheckoutContext = new PersistedCheckoutContextBuilder()
                                                          .From(persistedCheckoutContext)
                                                          .WithEmail(userProfile.Email)
                                                          .Build();

                    PersistedCheckoutContextProvider.SaveCheckoutContext(customer, updatedPersistedCheckoutContext);
                }
            }

            var residenceType = ResidenceTypes.Residential;

            if (customer.PrimaryShippingAddress != null &&
                customer.PrimaryShippingAddress.ResidenceType != ResidenceTypes.Unknown)
            {
                residenceType = customer.PrimaryShippingAddress.ResidenceType;
            }

            var model = new AmazonPaymentsViewModel(
                residenceTypeOptions: SelectListBuilder.BuildResidenceTypeSelectList(residenceType.ToString()),
                clientId: AmazonPaymentsApiProvider.Configuration.ClientId,
                merchantId: AmazonPaymentsApiProvider.Configuration.MerchantId,
                scriptUrl: AmazonPaymentsApiProvider.Configuration.ScriptUrl)
            {
                ResidenceType = residenceType,
                CheckoutStep  = AmazonPaymentsCheckoutStep.SelectAddress
            };

            return(View(ViewNames.AmazonPayments, model));
        }
Exemple #12
0
        public ActionResult SetPaymentMethod(string selectedPaymentMethod = null)
        {
            var customer = HttpContext.GetCustomer();

            var updatedPersistedCheckoutContext = new PersistedCheckoutContextBuilder()
                                                  .From(PersistedCheckoutContextProvider.LoadCheckoutContext(customer))
                                                  .WithoutOffsiteRequiredBillingAddressId()
                                                  .WithoutOffsiteRequiredShippingAddressId()
                                                  .Build();

            PersistedCheckoutContextProvider.SaveCheckoutContext(customer, updatedPersistedCheckoutContext);

            //Update the customer record
            if (selectedPaymentMethod != null && selectedPaymentMethod != customer.RequestedPaymentMethod)
            {
                customer.UpdateCustomer(requestedPaymentMethod: selectedPaymentMethod);
            }

            return(RedirectToAction(ActionNames.Index, ControllerNames.Checkout));
        }
        public ActionResult PurchaseOrder(PurchaseOrderViewModel model)
        {
            if (!ModelState.IsValid)
            {
                return(RedirectToAction(ActionNames.Index, ControllerNames.Checkout));
            }

            var customer = HttpContext.GetCustomer();

            var updatedPersistedCheckoutContext = new PersistedCheckoutContextBuilder()
                                                  .From(PersistedCheckoutContextProvider.LoadCheckoutContext(customer))
                                                  .WithPurchaseOrder(new PurchaseOrderDetails(model.PONumber))
                                                  .WithoutAmazonPayments()
                                                  .WithoutOffsiteRequiredBillingAddressId()
                                                  .WithoutOffsiteRequiredShippingAddressId()
                                                  .Build();

            PersistedCheckoutContextProvider.SaveCheckoutContext(customer, updatedPersistedCheckoutContext);
            customer.UpdateCustomer(requestedPaymentMethod: AppLogic.ro_PMPurchaseOrder);

            return(RedirectToAction(ActionNames.Index, ControllerNames.Checkout));
        }
        public ActionResult BraintreeThreeDSecurePass(string nonce)
        {
            var customer        = HttpContext.GetCustomer();
            var checkoutContext = PersistedCheckoutContextProvider.LoadCheckoutContext(customer);
            var cart            = CachedShoppingCartProvider.Get(customer, CartTypeEnum.ShoppingCart, AppLogic.StoreID());
            var orderNumber     = customer.ThisCustomerSession.SessionUSInt("3Dsecure.OrderNumber");

            var updatedCheckoutContext = new PersistedCheckoutContextBuilder()
                                         .From(checkoutContext)
                                         .WithBraintree(new BraintreeDetails(
                                                            nonce: nonce, //We got a new nonce after the 3dSecure request
                                                            token: checkoutContext.Braintree.Token,
                                                            paymentMethod: checkoutContext.Braintree.PaymentMethod,
                                                            threeDSecureApproved: true))
                                         .WithoutOffsiteRequiredBillingAddressId()
                                         .WithoutOffsiteRequiredShippingAddressId()
                                         .Build();

            PersistedCheckoutContextProvider.SaveCheckoutContext(customer, updatedCheckoutContext);

            customer.ThisCustomerSession[AppLogic.Braintree3dSecureKey]   = "true";
            customer.ThisCustomerSession[AppLogic.BraintreeNonceKey]      = nonce;
            customer.ThisCustomerSession[AppLogic.BraintreePaymentMethod] = checkoutContext.Braintree.PaymentMethod;

            var status = Gateway.MakeOrder(string.Empty, AppLogic.TransactionMode(), cart, orderNumber, string.Empty, string.Empty, string.Empty, string.Empty);

            ClearThreeDSecureSessionInfo(customer);

            if (status == AppLogic.ro_OK)
            {
                return(RedirectToAction(
                           ActionNames.Confirmation,
                           ControllerNames.CheckoutConfirmation,
                           new { orderNumber = orderNumber }));
            }

            NoticeProvider.PushNotice(string.Format(StringResourceProvider.GetString("secureprocess.aspx.5"), status), NoticeType.Failure);
            return(RedirectToAction(ActionNames.Index, ControllerNames.Checkout));
        }
        public ActionResult BraintreeThreeDSecureFail()
        {
            var customer = HttpContext.GetCustomer();
            var persistedCheckoutContext = PersistedCheckoutContextProvider.LoadCheckoutContext(customer);

            var updatedPersistedCheckoutContext = new PersistedCheckoutContextBuilder()
                                                  .From(persistedCheckoutContext)
                                                  .WithBraintree(new BraintreeDetails(
                                                                     nonce: persistedCheckoutContext.Braintree.Nonce,
                                                                     token: persistedCheckoutContext.Braintree.Token,
                                                                     paymentMethod: persistedCheckoutContext.Braintree.PaymentMethod,
                                                                     threeDSecureApproved: false))
                                                  .WithoutOffsiteRequiredBillingAddressId()
                                                  .WithoutOffsiteRequiredShippingAddressId()
                                                  .Build();

            PersistedCheckoutContextProvider.SaveCheckoutContext(customer, updatedPersistedCheckoutContext);

            NoticeProvider.PushNotice(StringResourceProvider.GetString("braintree.liabilityshiftfailed"), NoticeType.Failure);

            return(RedirectToAction(ActionNames.Index, ControllerNames.Checkout));
        }
        public ActionResult ShippingEstimate(ShippingEstimateViewModel model)
        {
            if (!ModelState.IsValid)
            {
                return(RedirectToAction(ActionNames.Index, ControllerNames.Checkout));
            }

            // Add the estimate partial address to the checkout context so that we can use that later to display rates if there is no customer address
            var customer = HttpContext.GetCustomer();
            var shippingEstimateDetails = new ShippingEstimateDetails(
                country: model.Country,
                city: model.City,
                state: model.State,
                postalCode: model.PostalCode);

            var updatedPersistedCheckoutContext = new PersistedCheckoutContextBuilder()
                                                  .From(PersistedCheckoutContextProvider.LoadCheckoutContext(customer))
                                                  .WithShippingEstimate(shippingEstimateDetails)
                                                  .Build();

            PersistedCheckoutContextProvider.SaveCheckoutContext(customer, updatedPersistedCheckoutContext);

            return(RedirectToAction(ActionNames.Index, ControllerNames.Checkout));
        }
        public ActionResult SagePayPiPaRes(string paRes, string mD)
        {
            var orderStatus         = StringResourceProvider.GetString("sagepaypi.error.unknownerror");
            var sagePayPi           = new SagePayPi();
            var customer            = HttpContext.GetCustomer();
            var session             = new CustomerSession(customer.CustomerID);
            var orderNumber         = customer.ThisCustomerSession.SessionUSInt("3Dsecure.OrderNumber");
            var useLiveTransactions = AppConfigProvider.GetAppConfigValue <bool>("UseLiveTransactions");

            var transactionUrl = string.Format(
                "{0}transactions/{1}",
                useLiveTransactions
                                        ? AppConfigProvider.GetAppConfigValue("SagePayPi.LiveUrl")
                                        : AppConfigProvider.GetAppConfigValue("SagePayPi.TestUrl"),
                session[AppLogic.SagePayPiMd]);

            var threeDSecureTransactionUrl = $"{transactionUrl}/3d-secure";

            var jsonObject = new JObject(
                new JProperty("paRes", paRes)
                );

            var formattedResponse           = JObject.Parse(sagePayPi.SagePayPiApiCall(jsonObject.ToString(), threeDSecureTransactionUrl, "POST"));
            var transactionResponseHasError = sagePayPi.ResponseHasError(formattedResponse, "status", "authenticated") &&
                                              sagePayPi.ResponseHasError(formattedResponse, "status", "attemptonly");

            if (transactionResponseHasError)
            {
                if (AppConfigProvider.GetAppConfigValue <bool>("sagepaypi.customerfriendlyerrors"))
                {
                    NoticeProvider.PushNotice(string.Format(
                                                  "{0} {1}",
                                                  StringResourceProvider.GetString("sagepaypi.threedsecure.didnotauthenticate"),
                                                  StringResourceProvider.GetString("sagepaypi.error.reentercarddetails")), NoticeType.Failure);
                }
                else
                {
                    orderStatus = sagePayPi.GetResponseError(formattedResponse, "status");

                    if (orderStatus.EqualsIgnoreCase(StringResourceProvider.GetString("sagepaypi.error.unknownresponseerror")))
                    {
                        orderStatus = sagePayPi.GetResponseError(formattedResponse, "statusDetail");
                    }
                    else
                    {
                        orderStatus = sagePayPi.GetThreeDSecureStatus(sagePayPi.GetResponseError(formattedResponse, "status"));
                    }

                    if (orderStatus.EqualsIgnoreCase(StringResourceProvider.GetString("sagepaypi.error.unknownresponseerror")))
                    {
                        orderStatus = sagePayPi.GetResponseError(formattedResponse, "description");
                    }

                    //display error when 3-D secure does not authenticate
                    NoticeProvider.PushNotice(string.Format(
                                                  "{0} {1} {2} {3}.",
                                                  StringResourceProvider.GetString("sagepaypi.threedsecure.didnotauthenticate"),
                                                  StringResourceProvider.GetString("sagepaypi.error.reentercarddetails"),
                                                  StringResourceProvider.GetString("sagepaypi.status.reason"),
                                                  orderStatus.TrimEnd('.')), NoticeType.Failure);
                }

                if (orderNumber > 0)
                {
                    sagePayPi.LogFailedTransaction($"URL: {threeDSecureTransactionUrl}, Request: {jsonObject}", formattedResponse.ToString(), orderNumber);
                }

                sagePayPi.ClearPaymentMethod(customer.CustomerID);
                return(RedirectToAction(ActionNames.Index, ControllerNames.Checkout));
            }

            //retrieve transaction
            var emptyObject = "{}";
            var formattedTransactionResponse         = JObject.Parse(sagePayPi.SagePayPiApiCall(emptyObject.ToString(), transactionUrl, "GET"));
            var formattedTransactionResponseHasError = sagePayPi.ResponseHasError(formattedTransactionResponse, "status", "ok") &&
                                                       sagePayPi.ResponseHasError(formattedTransactionResponse, "status", "attemptonly");

            //if the transaction did not submit properly, return early, display an error from sage pay and do not make the order
            if (formattedTransactionResponseHasError)
            {
                var threeDSecureStatus = sagePayPi.GetThreeDSecureStatus(string.Empty);

                if (formattedTransactionResponse != null && formattedTransactionResponse["3DSecure"] != null && formattedTransactionResponse["3DSecure"]["status"] != null)
                {
                    threeDSecureStatus = sagePayPi.GetThreeDSecureStatus(formattedTransactionResponse["3DSecure"]["status"].ToString());
                }

                orderStatus = sagePayPi.GetResponseError(formattedTransactionResponse, "statusDetail");

                if (orderStatus.EqualsIgnoreCase(StringResourceProvider.GetString("sagepaypi.error.unknownresponseerror")))
                {
                    orderStatus = sagePayPi.GetResponseError(formattedTransactionResponse, "description");
                }

                if (AppConfigProvider.GetAppConfigValue <bool>("sagepaypi.customerfriendlyerrors"))
                {
                    NoticeProvider.PushNotice(string.Format(
                                                  "{0} {1}",
                                                  StringResourceProvider.GetString("sagepaypi.threedsecure.didnotauthenticate"),
                                                  StringResourceProvider.GetString("sagepaypi.error.reentercarddetails")), NoticeType.Failure);
                }
                else
                {
                    NoticeProvider.PushNotice(string.Format(
                                                  "{0}. {1} {2}. {3}",
                                                  orderStatus.TrimEnd('.'),
                                                  StringResourceProvider.GetString("sagepaypi.status.threedsecure"),
                                                  threeDSecureStatus.TrimEnd('.'),
                                                  StringResourceProvider.GetString("sagepaypi.error.reentercarddetails")), NoticeType.Failure);
                }

                if (orderNumber > 0)
                {
                    sagePayPi.LogFailedTransaction($"GET Method - URL: {transactionUrl}", formattedTransactionResponse.ToString(), customer.ThisCustomerSession.SessionUSInt("3Dsecure.OrderNumber"));
                }

                sagePayPi.ClearPaymentMethod(customer.CustomerID);
                return(RedirectToAction(ActionNames.Index, ControllerNames.Checkout));
            }

            var persistedCheckoutContext = PersistedCheckoutContextProvider.LoadCheckoutContext(customer);
            var cart = CachedShoppingCartProvider.Get(customer, CartTypeEnum.ShoppingCart, AppLogic.StoreID());

            var updatedPersistedCheckoutContext = new PersistedCheckoutContextBuilder()
                                                  .From(persistedCheckoutContext)
                                                  .WithCreditCard(new CreditCardDetails(
                                                                      name: persistedCheckoutContext.CreditCard.Name,
                                                                      number: persistedCheckoutContext.CreditCard.Number,
                                                                      issueNumber: persistedCheckoutContext.CreditCard.IssueNumber,
                                                                      cardType: formattedTransactionResponse["paymentMethod"]["card"]["cardType"].ToString(),
                                                                      expirationDate: persistedCheckoutContext.CreditCard.ExpirationDate,
                                                                      startDate: persistedCheckoutContext.CreditCard.StartDate,
                                                                      cvv: persistedCheckoutContext.CreditCard.Cvv))
                                                  .WithSagePayPi(new SagePayPiDetails(
                                                                     cardIdentifier: persistedCheckoutContext.SagePayPi.CardIdentifier,
                                                                     merchantSessionId: persistedCheckoutContext.SagePayPi.MerchantSessionId,
                                                                     paymentMethod: persistedCheckoutContext.SagePayPi.PaymentMethod, //This is the Sage Pay PI payment method, not ours
                                                                     threeDSecureApproved: true))
                                                  .WithoutOffsiteRequiredBillingAddressId()
                                                  .WithoutOffsiteRequiredShippingAddressId()
                                                  .Build();

            PersistedCheckoutContextProvider.SaveCheckoutContext(customer, updatedPersistedCheckoutContext);

            customer.ThisCustomerSession[AppLogic.SagePayPi3dSecureKey]   = "true";
            customer.ThisCustomerSession[AppLogic.SagePayPiPaymentMethod] = persistedCheckoutContext.SagePayPi.PaymentMethod;

            orderStatus = Gateway.MakeOrder(string.Empty, AppLogic.TransactionMode(), cart, orderNumber, string.Empty, string.Empty, string.Empty, string.Empty);
            ClearThreeDSecureSessionInfo(customer);

            if (orderStatus == AppLogic.ro_OK)
            {
                return(RedirectToAction(
                           ActionNames.Confirmation,
                           ControllerNames.CheckoutConfirmation,
                           new { orderNumber = orderNumber }));
            }

            //display error if we reach this point, we should have redirected by now
            if (AppConfigProvider.GetAppConfigValue <bool>("sagepaypi.customerfriendlyerrors"))
            {
                NoticeProvider.PushNotice(string.Format(
                                              "{0} {1}",
                                              StringResourceProvider.GetString("sagepaypi.threedsecure.didnotauthenticate"),
                                              StringResourceProvider.GetString("sagepaypi.error.reentercarddetails")), NoticeType.Failure);
            }
            else
            {
                NoticeProvider.PushNotice(string.Format(
                                              "{0} {1}",
                                              string.Format(StringResourceProvider.GetString("secureprocess.aspx.5"), orderStatus.TrimEnd('.')),
                                              StringResourceProvider.GetString("sagepaypi.error.reentercarddetails")), NoticeType.Failure);
            }

            if (orderNumber > 0)
            {
                sagePayPi.LogFailedTransaction($"URL: {threeDSecureTransactionUrl}, Request: {jsonObject}", formattedResponse.ToString(), orderNumber);
            }

            sagePayPi.ClearPaymentMethod(customer.CustomerID);
            return(RedirectToAction(ActionNames.Index, ControllerNames.Checkout));
        }
        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));
        }
Exemple #19
0
        public ActionResult PayPalExpressReturn(string token)
        {
            var customer = HttpContext.GetCustomer();
            var expressCheckoutDetails = Gateway.GetExpressCheckoutDetails(token, customer.CustomerID);

            if (string.IsNullOrEmpty(expressCheckoutDetails))
            {
                // If nothing returned, abort the transaction.
                return(RedirectToAction(ActionNames.Index, ControllerNames.Checkout));
            }

            if (expressCheckoutDetails.Equals("AVSFAILED", StringComparison.OrdinalIgnoreCase))
            {
                NoticeProvider.PushNotice(AppLogic.GetString("paypal.express.avsconfirmedaddress.error"), NoticeType.Failure);
                return(RedirectToAction(ActionNames.Index, ControllerNames.Checkout));
            }

            if (!customer.IsRegistered && !customer.IsOver13)
            {
                // Set the Over13Checked flag since PayPal is permitting the order process, so they don't get rejected.
                DB.ExecuteSQL(
                    "update Customer set Over13Checked = 1 where CustomerID = @customerId",
                    new SqlParameter("customerId", customer.CustomerID));
            }

            if (customer.PrimaryBillingAddress.PaymentMethodLastUsed == AppLogic.ro_PMPayPalEmbeddedCheckout)
            {
                var orderNumber = DB.GetSqlN(
                    "select max(OrderNumber) N from dbo.Orders where CustomerID = @customerId",
                    new SqlParameter("customerId", customer.CustomerID));

                return(RedirectToAction(
                           ActionNames.Confirmation,
                           ControllerNames.CheckoutConfirmation,
                           new { orderNumber = orderNumber }));
            }

            customer.UpdateCustomer(requestedPaymentMethod: AppLogic.ro_PMPayPalExpress);

            var checkoutContext = PersistedCheckoutContextProvider.LoadCheckoutContext(customer);

            // During our call for customer details from paypal above we set the email on the customer record if they are not signed in already.
            // So let's pull that customer email into the checkout context
            var email = !string.IsNullOrEmpty(checkoutContext.Email)
                                ? checkoutContext.Email
                                : customer.EMail;

            var updatedPersistedCheckoutContext = new PersistedCheckoutContextBuilder()
                                                  .From(PersistedCheckoutContextProvider.LoadCheckoutContext(customer))
                                                  .WithPayPalExpress(new PayPalExpressDetails(
                                                                         token: token,
                                                                         payerId: expressCheckoutDetails))
                                                  .WithoutAmazonPayments()
                                                  .WithOffsiteRequiredBillingAddressId(customer.PrimaryBillingAddressID)   //This was set while processing the PayPal return info earlier
                                                  .WithOffsiteRequiredShippingAddressId(customer.PrimaryShippingAddressID) //This was set while processing the PayPal return info earlier
                                                  .WithEmail(email)
                                                  .Build();

            PersistedCheckoutContextProvider.SaveCheckoutContext(customer, updatedPersistedCheckoutContext);

            return(RedirectToAction(ActionNames.Index, ControllerNames.Checkout));
        }