/// <summary> /// Prepare details to place an order. It also sets some properties to "processPaymentRequest" /// </summary> /// <param name="processPaymentRequest">Process payment request</param> /// <returns>Details</returns> protected override PlaceOrderContainter PreparePlaceOrderDetails(ProcessPaymentRequest processPaymentRequest) { var details = new PlaceOrderContainter(); //Recurring orders. Load initial order if (processPaymentRequest.IsRecurringPayment) { details.InitialOrder = _orderService.GetOrderById(processPaymentRequest.InitialOrderId); if (details.InitialOrder == null) throw new ArgumentException("Initial order is not set for recurring payment"); processPaymentRequest.PaymentMethodSystemName = details.InitialOrder.PaymentMethodSystemName; } //customer details.Customer = _customerService.GetCustomerById(processPaymentRequest.CustomerId); if (details.Customer == null) throw new ArgumentException("Customer is not set"); //affiliate var affiliate = _affiliateService.GetAffiliateById(details.Customer.AffiliateId); if (affiliate != null && affiliate.Active && !affiliate.Deleted) details.AffiliateId = affiliate.Id; //customer currency if (!processPaymentRequest.IsRecurringPayment) { var currencyTmp = _currencyService.GetCurrencyById(details.Customer.GetAttribute<int>(SystemCustomerAttributeNames.CurrencyId, processPaymentRequest.StoreId)); var customerCurrency = (currencyTmp != null && currencyTmp.Published) ? currencyTmp : _workContext.WorkingCurrency; details.CustomerCurrencyCode = customerCurrency.CurrencyCode; var primaryStoreCurrency = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId); details.CustomerCurrencyRate = customerCurrency.Rate / primaryStoreCurrency.Rate; } else { details.CustomerCurrencyCode = details.InitialOrder.CustomerCurrencyCode; details.CustomerCurrencyRate = details.InitialOrder.CurrencyRate; } //customer language if (!processPaymentRequest.IsRecurringPayment) { details.CustomerLanguage = _languageService.GetLanguageById(details.Customer.GetAttribute<int>( SystemCustomerAttributeNames.LanguageId, processPaymentRequest.StoreId)); } else { details.CustomerLanguage = _languageService.GetLanguageById(details.InitialOrder.CustomerLanguageId); } if (details.CustomerLanguage == null || !details.CustomerLanguage.Published) details.CustomerLanguage = _workContext.WorkingLanguage; //check whether customer is guest if (details.Customer.IsGuest() && !_orderSettings.AnonymousCheckoutAllowed) throw new NopException("Anonymous checkout is not allowed"); //billing address if (!processPaymentRequest.IsRecurringPayment) { if (details.Customer.BillingAddress == null) throw new NopException("Billing address is not provided"); if (!CommonHelper.IsValidEmail(details.Customer.BillingAddress.Email)) throw new NopException("Email is not valid"); //clone billing address details.BillingAddress = (Address)details.Customer.BillingAddress.Clone(); if (details.BillingAddress.Country != null && !details.BillingAddress.Country.AllowsBilling) throw new NopException(string.Format("Country '{0}' is not allowed for billing", details.BillingAddress.Country.Name)); } else { if (details.InitialOrder.BillingAddress == null) throw new NopException("Billing address is not available"); //clone billing address details.BillingAddress = (Address)details.InitialOrder.BillingAddress.Clone(); if (details.BillingAddress.Country != null && !details.BillingAddress.Country.AllowsBilling) throw new NopException(string.Format("Country '{0}' is not allowed for billing", details.BillingAddress.Country.Name)); } //checkout attributes if (!processPaymentRequest.IsRecurringPayment) { details.CheckoutAttributesXml = details.Customer.GetAttribute<string>(SystemCustomerAttributeNames.CheckoutAttributes, processPaymentRequest.StoreId); details.CheckoutAttributeDescription = _checkoutAttributeFormatter.FormatAttributes(details.CheckoutAttributesXml, details.Customer); } else { details.CheckoutAttributesXml = details.InitialOrder.CheckoutAttributesXml; details.CheckoutAttributeDescription = details.InitialOrder.CheckoutAttributeDescription; } //load and validate customer shopping cart if (!processPaymentRequest.IsRecurringPayment) { //load shopping cart details.Cart = details.Customer.ShoppingCartItems .Where(sci => sci.ShoppingCartType == ShoppingCartType.ShoppingCart) .LimitPerStore(processPaymentRequest.StoreId) .ToList(); if (details.Cart.Count == 0) throw new NopException("Cart is empty"); //validate the entire shopping cart var warnings = _shoppingCartService.GetShoppingCartWarnings(details.Cart, details.CheckoutAttributesXml, true); if (warnings.Count > 0) { var warningsSb = new StringBuilder(); foreach (string warning in warnings) { warningsSb.Append(warning); warningsSb.Append(";"); } throw new NopException(warningsSb.ToString()); } //validate individual cart items foreach (var sci in details.Cart) { var sciWarnings = _shoppingCartService.GetShoppingCartItemWarnings(details.Customer, sci.ShoppingCartType, sci.Product, processPaymentRequest.StoreId, sci.AttributesXml, sci.CustomerEnteredPrice, sci.RentalStartDateUtc, sci.RentalEndDateUtc, sci.Quantity, false); if (sciWarnings.Count > 0) { var warningsSb = new StringBuilder(); foreach (string warning in sciWarnings) { warningsSb.Append(warning); warningsSb.Append(";"); } throw new NopException(warningsSb.ToString()); } } } //min totals validation if (!processPaymentRequest.IsRecurringPayment) { bool minOrderSubtotalAmountOk = ValidateMinOrderSubtotalAmount(details.Cart); if (!minOrderSubtotalAmountOk) { decimal minOrderSubtotalAmount = _currencyService.ConvertFromPrimaryStoreCurrency(_orderSettings.MinOrderSubtotalAmount, _workContext.WorkingCurrency); throw new NopException(string.Format(_localizationService.GetResource("Checkout.MinOrderSubtotalAmount"), _priceFormatter.FormatPrice(minOrderSubtotalAmount, true, false))); } bool minOrderTotalAmountOk = ValidateMinOrderTotalAmount(details.Cart); if (!minOrderTotalAmountOk) { decimal minOrderTotalAmount = _currencyService.ConvertFromPrimaryStoreCurrency(_orderSettings.MinOrderTotalAmount, _workContext.WorkingCurrency); throw new NopException(string.Format(_localizationService.GetResource("Checkout.MinOrderTotalAmount"), _priceFormatter.FormatPrice(minOrderTotalAmount, true, false))); } } //tax display type if (!processPaymentRequest.IsRecurringPayment) { if (_taxSettings.AllowCustomersToSelectTaxDisplayType) details.CustomerTaxDisplayType = (TaxDisplayType)details.Customer.GetAttribute<int>(SystemCustomerAttributeNames.TaxDisplayTypeId, processPaymentRequest.StoreId); else details.CustomerTaxDisplayType = _taxSettings.TaxDisplayType; } else { details.CustomerTaxDisplayType = details.InitialOrder.CustomerTaxDisplayType; } //sub total if (!processPaymentRequest.IsRecurringPayment) { //sub total (incl tax) decimal orderSubTotalDiscountAmount1; decimal subTotalWithoutDiscountBase1; decimal subTotalWithDiscountBase1; global::Nop.Core.Domain.Discounts.Discount orderSubTotalAppliedDiscount1; // TODO: NOT ACTUALLY USED - confirm this, add interface with new signature? _orderTotalCalculationService.GetShoppingCartSubTotal(details.Cart, true, out orderSubTotalDiscountAmount1, out orderSubTotalAppliedDiscount1, out subTotalWithoutDiscountBase1, out subTotalWithDiscountBase1); details.OrderSubTotalInclTax = subTotalWithoutDiscountBase1; details.OrderSubTotalDiscountInclTax = orderSubTotalDiscountAmount1; //discount history if (orderSubTotalAppliedDiscount1 != null && !details.AppliedDiscounts.ContainsDiscount(orderSubTotalAppliedDiscount1)) details.AppliedDiscounts.Add(orderSubTotalAppliedDiscount1); //sub total (excl tax) decimal orderSubTotalDiscountAmount2; global::Nop.Core.Domain.Discounts.Discount orderSubTotalAppliedDiscount2; // TODO: NOT ACTUALLY USED - confirm this, add interface with new signature? decimal subTotalWithoutDiscountBase2; decimal subTotalWithDiscountBase2; _orderTotalCalculationService.GetShoppingCartSubTotal(details.Cart, false, out orderSubTotalDiscountAmount2, out orderSubTotalAppliedDiscount2, out subTotalWithoutDiscountBase2, out subTotalWithDiscountBase2); details.OrderSubTotalExclTax = subTotalWithoutDiscountBase2; details.OrderSubTotalDiscountExclTax = orderSubTotalDiscountAmount2; } else { details.OrderSubTotalInclTax = details.InitialOrder.OrderSubtotalInclTax; details.OrderSubTotalExclTax = details.InitialOrder.OrderSubtotalExclTax; } //shipping info bool shoppingCartRequiresShipping; if (!processPaymentRequest.IsRecurringPayment) { shoppingCartRequiresShipping = details.Cart.RequiresShipping(); } else { shoppingCartRequiresShipping = details.InitialOrder.ShippingStatus != ShippingStatus.ShippingNotRequired; } if (shoppingCartRequiresShipping) { if (!processPaymentRequest.IsRecurringPayment) { details.PickUpInStore = _shippingSettings.AllowPickUpInStore && details.Customer.GetAttribute<bool>(SystemCustomerAttributeNames.SelectedPickUpInStore, processPaymentRequest.StoreId); if (!details.PickUpInStore) { if (details.Customer.ShippingAddress == null) throw new NopException("Shipping address is not provided"); if (!CommonHelper.IsValidEmail(details.Customer.ShippingAddress.Email)) throw new NopException("Email is not valid"); //clone shipping address details.ShippingAddress = (Address)details.Customer.ShippingAddress.Clone(); if (details.ShippingAddress.Country != null && !details.ShippingAddress.Country.AllowsShipping) { throw new NopException(string.Format("Country '{0}' is not allowed for shipping", details.ShippingAddress.Country.Name)); } } var shippingOption = details.Customer.GetAttribute<ShippingOption>(SystemCustomerAttributeNames.SelectedShippingOption, processPaymentRequest.StoreId); if (shippingOption != null) { details.ShippingMethodName = shippingOption.Name; details.ShippingRateComputationMethodSystemName = shippingOption.ShippingRateComputationMethodSystemName; } } else { details.PickUpInStore = details.InitialOrder.PickUpInStore; if (!details.PickUpInStore) { if (details.InitialOrder.ShippingAddress == null) throw new NopException("Shipping address is not available"); //clone shipping address details.ShippingAddress = (Address)details.InitialOrder.ShippingAddress.Clone(); if (details.ShippingAddress.Country != null && !details.ShippingAddress.Country.AllowsShipping) { throw new NopException(string.Format("Country '{0}' is not allowed for shipping", details.ShippingAddress.Country.Name)); } } details.ShippingMethodName = details.InitialOrder.ShippingMethod; details.ShippingRateComputationMethodSystemName = details.InitialOrder.ShippingRateComputationMethodSystemName; } } details.ShippingStatus = shoppingCartRequiresShipping ? ShippingStatus.NotYetShipped : ShippingStatus.ShippingNotRequired; //shipping total if (!processPaymentRequest.IsRecurringPayment) { decimal taxRate; global::Nop.Core.Domain.Discounts.Discount shippingTotalDiscount; // TODO: NOT ACTUALLY USED - confirm this, add interface with new signature? decimal? orderShippingTotalInclTax = _orderTotalCalculationService.GetShoppingCartShippingTotal(details.Cart, true, out taxRate, out shippingTotalDiscount); decimal? orderShippingTotalExclTax = _orderTotalCalculationService.GetShoppingCartShippingTotal(details.Cart, false); if (!orderShippingTotalInclTax.HasValue || !orderShippingTotalExclTax.HasValue) throw new NopException("Shipping total couldn't be calculated"); details.OrderShippingTotalInclTax = orderShippingTotalInclTax.Value; details.OrderShippingTotalExclTax = orderShippingTotalExclTax.Value; if (shippingTotalDiscount != null && !details.AppliedDiscounts.ContainsDiscount(shippingTotalDiscount)) details.AppliedDiscounts.Add(shippingTotalDiscount); } else { details.OrderShippingTotalInclTax = details.InitialOrder.OrderShippingInclTax; details.OrderShippingTotalExclTax = details.InitialOrder.OrderShippingExclTax; } //payment total if (!processPaymentRequest.IsRecurringPayment) { decimal paymentAdditionalFee = _paymentService.GetAdditionalHandlingFee(details.Cart, processPaymentRequest.PaymentMethodSystemName); details.PaymentAdditionalFeeInclTax = _taxService.GetPaymentMethodAdditionalFee(paymentAdditionalFee, true, details.Customer); details.PaymentAdditionalFeeExclTax = _taxService.GetPaymentMethodAdditionalFee(paymentAdditionalFee, false, details.Customer); } else { details.PaymentAdditionalFeeInclTax = details.InitialOrder.PaymentMethodAdditionalFeeInclTax; details.PaymentAdditionalFeeExclTax = details.InitialOrder.PaymentMethodAdditionalFeeExclTax; } //tax total if (!processPaymentRequest.IsRecurringPayment) { //tax amount SortedDictionary<decimal, decimal> taxRatesDictionary; details.OrderTaxTotal = _orderTotalCalculationService.GetTaxTotal(details.Cart, out taxRatesDictionary); //VAT number var customerVatStatus = (VatNumberStatus)details.Customer.GetAttribute<int>(SystemCustomerAttributeNames.VatNumberStatusId); if (_taxSettings.EuVatEnabled && customerVatStatus == VatNumberStatus.Valid) details.VatNumber = details.Customer.GetAttribute<string>(SystemCustomerAttributeNames.VatNumber); //tax rates foreach (var kvp in taxRatesDictionary) { var taxRate = kvp.Key; var taxValue = kvp.Value; details.TaxRates += string.Format("{0}:{1}; ", taxRate.ToString(CultureInfo.InvariantCulture), taxValue.ToString(CultureInfo.InvariantCulture)); } } else { details.OrderTaxTotal = details.InitialOrder.OrderTax; //VAT number details.VatNumber = details.InitialOrder.VatNumber; } //order total (and applied discounts, gift cards, reward points) if (!processPaymentRequest.IsRecurringPayment) { List<AppliedGiftCard> appliedGiftCards = null; global::Nop.Core.Domain.Discounts.Discount orderAppliedDiscount; // TODO: NOT ACTUALLY USED - confirm this, add interface with new signature? decimal orderDiscountAmount; int redeemedRewardPoints; decimal redeemedRewardPointsAmount; var orderTotal = _orderTotalCalculationService.GetShoppingCartTotal(details.Cart, out orderDiscountAmount, out orderAppliedDiscount, out appliedGiftCards, out redeemedRewardPoints, out redeemedRewardPointsAmount); if (!orderTotal.HasValue) throw new NopException("Order total couldn't be calculated"); details.OrderDiscountAmount = orderDiscountAmount; details.RedeemedRewardPoints = redeemedRewardPoints; details.RedeemedRewardPointsAmount = redeemedRewardPointsAmount; details.AppliedGiftCards = appliedGiftCards; details.OrderTotal = orderTotal.Value; //discount history if (orderAppliedDiscount != null && !details.AppliedDiscounts.ContainsDiscount(orderAppliedDiscount)) details.AppliedDiscounts.Add(orderAppliedDiscount); } else { details.OrderDiscountAmount = details.InitialOrder.OrderDiscount; details.OrderTotal = details.InitialOrder.OrderTotal; } processPaymentRequest.OrderTotal = details.OrderTotal; //recurring or standard shopping cart? if (!processPaymentRequest.IsRecurringPayment) { details.IsRecurringShoppingCart = details.Cart.IsRecurring(); if (details.IsRecurringShoppingCart) { int recurringCycleLength; RecurringProductCyclePeriod recurringCyclePeriod; int recurringTotalCycles; string recurringCyclesError = details.Cart.GetRecurringCycleInfo(_localizationService, out recurringCycleLength, out recurringCyclePeriod, out recurringTotalCycles); if (!string.IsNullOrEmpty(recurringCyclesError)) throw new NopException(recurringCyclesError); processPaymentRequest.RecurringCycleLength = recurringCycleLength; processPaymentRequest.RecurringCyclePeriod = recurringCyclePeriod; processPaymentRequest.RecurringTotalCycles = recurringTotalCycles; } } else { details.IsRecurringShoppingCart = true; } return details; }
/// <summary> /// Save order and add order notes /// </summary> /// <param name="processPaymentRequest">Process payment request</param> /// <param name="processPaymentResult">Process payment result</param> /// <param name="details">Details</param> /// <returns>Order</returns> protected virtual Order SaveOrderDetails(ProcessPaymentRequest processPaymentRequest, ProcessPaymentResult processPaymentResult, PlaceOrderContainter details) { var order = new Order { StoreId = processPaymentRequest.StoreId, OrderGuid = processPaymentRequest.OrderGuid, CustomerId = details.Customer.Id, CustomerLanguageId = details.CustomerLanguage.Id, CustomerTaxDisplayType = details.CustomerTaxDisplayType, CustomerIp = _webHelper.GetCurrentIpAddress(), OrderSubtotalInclTax = details.OrderSubTotalInclTax, OrderSubtotalExclTax = details.OrderSubTotalExclTax, OrderSubTotalDiscountInclTax = details.OrderSubTotalDiscountInclTax, OrderSubTotalDiscountExclTax = details.OrderSubTotalDiscountExclTax, OrderShippingInclTax = details.OrderShippingTotalInclTax, OrderShippingExclTax = details.OrderShippingTotalExclTax, PaymentMethodAdditionalFeeInclTax = details.PaymentAdditionalFeeInclTax, PaymentMethodAdditionalFeeExclTax = details.PaymentAdditionalFeeExclTax, TaxRates = details.TaxRates, OrderTax = details.OrderTaxTotal, OrderTotal = details.OrderTotal, RefundedAmount = decimal.Zero, OrderDiscount = details.OrderDiscountAmount, CheckoutAttributeDescription = details.CheckoutAttributeDescription, CheckoutAttributesXml = details.CheckoutAttributesXml, CustomerCurrencyCode = details.CustomerCurrencyCode, CurrencyRate = details.CustomerCurrencyRate, AffiliateId = details.AffiliateId, OrderStatus = OrderStatus.Pending, AllowStoringCreditCardNumber = processPaymentResult.AllowStoringCreditCardNumber, CardType = processPaymentResult.AllowStoringCreditCardNumber ? _encryptionService.EncryptText(processPaymentRequest.CreditCardType) : string.Empty, CardName = processPaymentResult.AllowStoringCreditCardNumber ? _encryptionService.EncryptText(processPaymentRequest.CreditCardName) : string.Empty, CardNumber = processPaymentResult.AllowStoringCreditCardNumber ? _encryptionService.EncryptText(processPaymentRequest.CreditCardNumber) : string.Empty, MaskedCreditCardNumber = _encryptionService.EncryptText(_paymentService.GetMaskedCreditCardNumber(processPaymentRequest.CreditCardNumber)), CardCvv2 = processPaymentResult.AllowStoringCreditCardNumber ? _encryptionService.EncryptText(processPaymentRequest.CreditCardCvv2) : string.Empty, CardExpirationMonth = processPaymentResult.AllowStoringCreditCardNumber ? _encryptionService.EncryptText(processPaymentRequest.CreditCardExpireMonth.ToString()) : string.Empty, CardExpirationYear = processPaymentResult.AllowStoringCreditCardNumber ? _encryptionService.EncryptText(processPaymentRequest.CreditCardExpireYear.ToString()) : string.Empty, PaymentMethodSystemName = processPaymentRequest.PaymentMethodSystemName, AuthorizationTransactionId = processPaymentResult.AuthorizationTransactionId, AuthorizationTransactionCode = processPaymentResult.AuthorizationTransactionCode, AuthorizationTransactionResult = processPaymentResult.AuthorizationTransactionResult, CaptureTransactionId = processPaymentResult.CaptureTransactionId, CaptureTransactionResult = processPaymentResult.CaptureTransactionResult, SubscriptionTransactionId = processPaymentResult.SubscriptionTransactionId, PaymentStatus = processPaymentResult.NewPaymentStatus, PaidDateUtc = null, BillingAddress = details.BillingAddress, ShippingAddress = details.ShippingAddress, ShippingStatus = details.ShippingStatus, ShippingMethod = details.ShippingMethodName, PickUpInStore = details.PickUpInStore, PickupAddress = details.PickupAddress, ShippingRateComputationMethodSystemName = details.ShippingRateComputationMethodSystemName, CustomValuesXml = processPaymentRequest.SerializeCustomValues(), VatNumber = details.VatNumber, CreatedOnUtc = DateTime.UtcNow }; _orderService.InsertOrder(order); //reward points history if (details.RedeemedRewardPointsAmount > decimal.Zero) { _rewardPointService.AddRewardPointsHistoryEntry(details.Customer, -details.RedeemedRewardPoints, order.StoreId, string.Format(_localizationService.GetResource("RewardPoints.Message.RedeemedForOrder", order.CustomerLanguageId), order.Id), order, details.RedeemedRewardPointsAmount); _customerService.UpdateCustomer(details.Customer); } return order; }
/// <summary> /// Prepare details to place an order. It also sets some properties to "processPaymentRequest" /// </summary> /// <param name="processPaymentRequest">Process payment request</param> /// <returns>Details</returns> protected virtual PlaceOrderContainter PreparePlaceOrderDetails(ProcessPaymentRequest processPaymentRequest) { var details = new PlaceOrderContainter(); //customer details.Customer = _customerService.GetCustomerById(processPaymentRequest.CustomerId); if (details.Customer == null) throw new ArgumentException("Customer is not set"); //affiliate var affiliate = _affiliateService.GetAffiliateById(details.Customer.AffiliateId); if (affiliate != null && affiliate.Active && !affiliate.Deleted) details.AffiliateId = affiliate.Id; //check whether customer is guest if (details.Customer.IsGuest() && !_orderSettings.AnonymousCheckoutAllowed) throw new NopException("Anonymous checkout is not allowed"); //customer currency var currencyTmp = _currencyService.GetCurrencyById( details.Customer.GetAttribute<int>(SystemCustomerAttributeNames.CurrencyId, processPaymentRequest.StoreId)); var customerCurrency = (currencyTmp != null && currencyTmp.Published) ? currencyTmp : _workContext.WorkingCurrency; var primaryStoreCurrency = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId); details.CustomerCurrencyCode = customerCurrency.CurrencyCode; details.CustomerCurrencyRate = customerCurrency.Rate / primaryStoreCurrency.Rate; //customer language details.CustomerLanguage = _languageService.GetLanguageById( details.Customer.GetAttribute<int>(SystemCustomerAttributeNames.LanguageId, processPaymentRequest.StoreId)); if (details.CustomerLanguage == null || !details.CustomerLanguage.Published) details.CustomerLanguage = _workContext.WorkingLanguage; //billing address if (details.Customer.BillingAddress == null) throw new NopException("Billing address is not provided"); if (!CommonHelper.IsValidEmail(details.Customer.BillingAddress.Email)) throw new NopException("Email is not valid"); details.BillingAddress = (Address)details.Customer.BillingAddress.Clone(); if (details.BillingAddress.Country != null && !details.BillingAddress.Country.AllowsBilling) throw new NopException(string.Format("Country '{0}' is not allowed for billing", details.BillingAddress.Country.Name)); //checkout attributes details.CheckoutAttributesXml = details.Customer.GetAttribute<string>(SystemCustomerAttributeNames.CheckoutAttributes, processPaymentRequest.StoreId); details.CheckoutAttributeDescription = _checkoutAttributeFormatter.FormatAttributes(details.CheckoutAttributesXml, details.Customer); //load shopping cart details.Cart = details.Customer.ShoppingCartItems.Where(sci => sci.ShoppingCartType == ShoppingCartType.ShoppingCart) .LimitPerStore(processPaymentRequest.StoreId).ToList(); if (!details.Cart.Any()) throw new NopException("Cart is empty"); //validate the entire shopping cart var warnings = _shoppingCartService.GetShoppingCartWarnings(details.Cart, details.CheckoutAttributesXml, true); if (warnings.Any()) throw new NopException(warnings.Aggregate(string.Empty, (current, next) => string.Format("{0}{1};", current, next))); //validate individual cart items foreach (var sci in details.Cart) { var sciWarnings = _shoppingCartService.GetShoppingCartItemWarnings(details.Customer, sci.ShoppingCartType, sci.Product, processPaymentRequest.StoreId, sci.AttributesXml, sci.CustomerEnteredPrice, sci.RentalStartDateUtc, sci.RentalEndDateUtc, sci.Quantity, false); if (sciWarnings.Any()) throw new NopException(sciWarnings.Aggregate(string.Empty, (current, next) => string.Format("{0}{1};", current, next))); } //min totals validation if (!ValidateMinOrderSubtotalAmount(details.Cart)) { var minOrderSubtotalAmount = _currencyService.ConvertFromPrimaryStoreCurrency(_orderSettings.MinOrderSubtotalAmount, _workContext.WorkingCurrency); throw new NopException(string.Format(_localizationService.GetResource("Checkout.MinOrderSubtotalAmount"), _priceFormatter.FormatPrice(minOrderSubtotalAmount, true, false))); } if (!ValidateMinOrderTotalAmount(details.Cart)) { var minOrderTotalAmount = _currencyService.ConvertFromPrimaryStoreCurrency(_orderSettings.MinOrderTotalAmount, _workContext.WorkingCurrency); throw new NopException(string.Format(_localizationService.GetResource("Checkout.MinOrderTotalAmount"), _priceFormatter.FormatPrice(minOrderTotalAmount, true, false))); } //tax display type if (_taxSettings.AllowCustomersToSelectTaxDisplayType) details.CustomerTaxDisplayType = (TaxDisplayType)details.Customer.GetAttribute<int>(SystemCustomerAttributeNames.TaxDisplayTypeId, processPaymentRequest.StoreId); else details.CustomerTaxDisplayType = _taxSettings.TaxDisplayType; //sub total (incl tax) decimal orderSubTotalDiscountAmount; List<Discount> orderSubTotalAppliedDiscounts; decimal subTotalWithoutDiscountBase; decimal subTotalWithDiscountBase; _orderTotalCalculationService.GetShoppingCartSubTotal(details.Cart, true, out orderSubTotalDiscountAmount, out orderSubTotalAppliedDiscounts, out subTotalWithoutDiscountBase, out subTotalWithDiscountBase); details.OrderSubTotalInclTax = subTotalWithoutDiscountBase; details.OrderSubTotalDiscountInclTax = orderSubTotalDiscountAmount; //discount history foreach (var disc in orderSubTotalAppliedDiscounts) if (!details.AppliedDiscounts.ContainsDiscount(disc)) details.AppliedDiscounts.Add(disc); //sub total (excl tax) _orderTotalCalculationService.GetShoppingCartSubTotal(details.Cart, false, out orderSubTotalDiscountAmount, out orderSubTotalAppliedDiscounts, out subTotalWithoutDiscountBase, out subTotalWithDiscountBase); details.OrderSubTotalExclTax = subTotalWithoutDiscountBase; details.OrderSubTotalDiscountExclTax = orderSubTotalDiscountAmount; //shipping info if (details.Cart.RequiresShipping()) { var pickupPoint = details.Customer.GetAttribute<PickupPoint>(SystemCustomerAttributeNames.SelectedPickupPoint, processPaymentRequest.StoreId); if (_shippingSettings.AllowPickUpInStore && pickupPoint != null) { details.PickUpInStore = true; details.PickupAddress = new Address { Address1 = pickupPoint.Address, City = pickupPoint.City, Country = _countryService.GetCountryByTwoLetterIsoCode(pickupPoint.CountryCode), ZipPostalCode = pickupPoint.ZipPostalCode, CreatedOnUtc = DateTime.UtcNow, }; } else { if (details.Customer.ShippingAddress == null) throw new NopException("Shipping address is not provided"); if (!CommonHelper.IsValidEmail(details.Customer.ShippingAddress.Email)) throw new NopException("Email is not valid"); //clone shipping address details.ShippingAddress = (Address)details.Customer.ShippingAddress.Clone(); if (details.ShippingAddress.Country != null && !details.ShippingAddress.Country.AllowsShipping) throw new NopException(string.Format("Country '{0}' is not allowed for shipping", details.ShippingAddress.Country.Name)); } var shippingOption = details.Customer.GetAttribute<ShippingOption>(SystemCustomerAttributeNames.SelectedShippingOption, processPaymentRequest.StoreId); if (shippingOption != null) { details.ShippingMethodName = shippingOption.Name; details.ShippingRateComputationMethodSystemName = shippingOption.ShippingRateComputationMethodSystemName; } details.ShippingStatus = ShippingStatus.NotYetShipped; } else details.ShippingStatus = ShippingStatus.ShippingNotRequired; //shipping total decimal tax; List<Discount> shippingTotalDiscounts; var orderShippingTotalInclTax = _orderTotalCalculationService.GetShoppingCartShippingTotal(details.Cart, true, out tax, out shippingTotalDiscounts); var orderShippingTotalExclTax = _orderTotalCalculationService.GetShoppingCartShippingTotal(details.Cart, false); if (!orderShippingTotalInclTax.HasValue || !orderShippingTotalExclTax.HasValue) throw new NopException("Shipping total couldn't be calculated"); details.OrderShippingTotalInclTax = orderShippingTotalInclTax.Value; details.OrderShippingTotalExclTax = orderShippingTotalExclTax.Value; foreach(var disc in shippingTotalDiscounts) if (!details.AppliedDiscounts.ContainsDiscount(disc)) details.AppliedDiscounts.Add(disc); //payment total var paymentAdditionalFee = _paymentService.GetAdditionalHandlingFee(details.Cart, processPaymentRequest.PaymentMethodSystemName); details.PaymentAdditionalFeeInclTax = _taxService.GetPaymentMethodAdditionalFee(paymentAdditionalFee, true, details.Customer); details.PaymentAdditionalFeeExclTax = _taxService.GetPaymentMethodAdditionalFee(paymentAdditionalFee, false, details.Customer); //tax amount SortedDictionary<decimal, decimal> taxRatesDictionary; details.OrderTaxTotal = _orderTotalCalculationService.GetTaxTotal(details.Cart, out taxRatesDictionary); //VAT number var customerVatStatus = (VatNumberStatus)details.Customer.GetAttribute<int>(SystemCustomerAttributeNames.VatNumberStatusId); if (_taxSettings.EuVatEnabled && customerVatStatus == VatNumberStatus.Valid) details.VatNumber = details.Customer.GetAttribute<string>(SystemCustomerAttributeNames.VatNumber); //tax rates details.TaxRates = taxRatesDictionary.Aggregate(string.Empty, (current, next) => string.Format("{0}{1}:{2}; ", current, next.Key.ToString(CultureInfo.InvariantCulture), next.Value.ToString(CultureInfo.InvariantCulture))); //order total (and applied discounts, gift cards, reward points) List<AppliedGiftCard> appliedGiftCards; List<Discount> orderAppliedDiscounts; decimal orderDiscountAmount; int redeemedRewardPoints; decimal redeemedRewardPointsAmount; var orderTotal = _orderTotalCalculationService.GetShoppingCartTotal(details.Cart, out orderDiscountAmount, out orderAppliedDiscounts, out appliedGiftCards, out redeemedRewardPoints, out redeemedRewardPointsAmount); if (!orderTotal.HasValue) throw new NopException("Order total couldn't be calculated"); details.OrderDiscountAmount = orderDiscountAmount; details.RedeemedRewardPoints = redeemedRewardPoints; details.RedeemedRewardPointsAmount = redeemedRewardPointsAmount; details.AppliedGiftCards = appliedGiftCards; details.OrderTotal = orderTotal.Value; //discount history foreach (var disc in orderAppliedDiscounts) if (!details.AppliedDiscounts.ContainsDiscount(disc)) details.AppliedDiscounts.Add(disc); processPaymentRequest.OrderTotal = details.OrderTotal; //recurring or standard shopping cart? details.IsRecurringShoppingCart = details.Cart.IsRecurring(); if (details.IsRecurringShoppingCart) { int recurringCycleLength; RecurringProductCyclePeriod recurringCyclePeriod; int recurringTotalCycles; var recurringCyclesError = details.Cart.GetRecurringCycleInfo(_localizationService, out recurringCycleLength, out recurringCyclePeriod, out recurringTotalCycles); if (!string.IsNullOrEmpty(recurringCyclesError)) throw new NopException(recurringCyclesError); processPaymentRequest.RecurringCycleLength = recurringCycleLength; processPaymentRequest.RecurringCyclePeriod = recurringCyclePeriod; processPaymentRequest.RecurringTotalCycles = recurringTotalCycles; } return details; }
/// <summary> /// Prepare details to place order based on the recurring payment. /// </summary> /// <param name="processPaymentRequest">Process payment request</param> /// <returns>Details</returns> protected virtual PlaceOrderContainter PrepareRecurringOrderDetails(ProcessPaymentRequest processPaymentRequest) { var details = new PlaceOrderContainter(); details.IsRecurringShoppingCart = true; //Load initial order details.InitialOrder = _orderService.GetOrderById(processPaymentRequest.InitialOrderId); if (details.InitialOrder == null) throw new ArgumentException("Initial order is not set for recurring payment"); processPaymentRequest.PaymentMethodSystemName = details.InitialOrder.PaymentMethodSystemName; //customer details.Customer = _customerService.GetCustomerById(processPaymentRequest.CustomerId); if (details.Customer == null) throw new ArgumentException("Customer is not set"); //affiliate var affiliate = _affiliateService.GetAffiliateById(details.Customer.AffiliateId); if (affiliate != null && affiliate.Active && !affiliate.Deleted) details.AffiliateId = affiliate.Id; //check whether customer is guest if (details.Customer.IsGuest() && !_orderSettings.AnonymousCheckoutAllowed) throw new NopException("Anonymous checkout is not allowed"); //customer currency details.CustomerCurrencyCode = details.InitialOrder.CustomerCurrencyCode; details.CustomerCurrencyRate = details.InitialOrder.CurrencyRate; //customer language details.CustomerLanguage = _languageService.GetLanguageById(details.InitialOrder.CustomerLanguageId); if (details.CustomerLanguage == null || !details.CustomerLanguage.Published) details.CustomerLanguage = _workContext.WorkingLanguage; //billing address if (details.InitialOrder.BillingAddress == null) throw new NopException("Billing address is not available"); details.BillingAddress = (Address)details.InitialOrder.BillingAddress.Clone(); if (details.BillingAddress.Country != null && !details.BillingAddress.Country.AllowsBilling) throw new NopException(string.Format("Country '{0}' is not allowed for billing", details.BillingAddress.Country.Name)); //checkout attributes details.CheckoutAttributesXml = details.InitialOrder.CheckoutAttributesXml; details.CheckoutAttributeDescription = details.InitialOrder.CheckoutAttributeDescription; //tax display type details.CustomerTaxDisplayType = details.InitialOrder.CustomerTaxDisplayType; //sub total details.OrderSubTotalInclTax = details.InitialOrder.OrderSubtotalInclTax; details.OrderSubTotalExclTax = details.InitialOrder.OrderSubtotalExclTax; //shipping info if (details.InitialOrder.ShippingStatus != ShippingStatus.ShippingNotRequired) { details.PickUpInStore = details.InitialOrder.PickUpInStore; if (!details.PickUpInStore) { if (details.InitialOrder.ShippingAddress == null) throw new NopException("Shipping address is not available"); //clone shipping address details.ShippingAddress = (Address)details.InitialOrder.ShippingAddress.Clone(); if (details.ShippingAddress.Country != null && !details.ShippingAddress.Country.AllowsShipping) throw new NopException(string.Format("Country '{0}' is not allowed for shipping", details.ShippingAddress.Country.Name)); } else if (details.InitialOrder.PickupAddress != null) details.PickupAddress = (Address)details.InitialOrder.PickupAddress.Clone(); details.ShippingMethodName = details.InitialOrder.ShippingMethod; details.ShippingRateComputationMethodSystemName = details.InitialOrder.ShippingRateComputationMethodSystemName; details.ShippingStatus = ShippingStatus.NotYetShipped; } else details.ShippingStatus = ShippingStatus.ShippingNotRequired; //shipping total details.OrderShippingTotalInclTax = details.InitialOrder.OrderShippingInclTax; details.OrderShippingTotalExclTax = details.InitialOrder.OrderShippingExclTax; //payment total details.PaymentAdditionalFeeInclTax = details.InitialOrder.PaymentMethodAdditionalFeeInclTax; details.PaymentAdditionalFeeExclTax = details.InitialOrder.PaymentMethodAdditionalFeeExclTax; //tax total details.OrderTaxTotal = details.InitialOrder.OrderTax; //VAT number details.VatNumber = details.InitialOrder.VatNumber; //order total details.OrderDiscountAmount = details.InitialOrder.OrderDiscount; details.OrderTotal = details.InitialOrder.OrderTotal; processPaymentRequest.OrderTotal = details.OrderTotal; return details; }
/// <summary> /// Prepare details to place an order. It also sets some properties to "processPaymentRequest" /// </summary> /// <param name="processPaymentRequest">Process payment request</param> /// <returns>Details</returns> protected override PlaceOrderContainter PreparePlaceOrderDetails(ProcessPaymentRequest processPaymentRequest) { var details = new PlaceOrderContainter(); //customer details.Customer = _customerService.GetCustomerById(processPaymentRequest.CustomerId); if (details.Customer == null) { throw new ArgumentException("Customer is not set"); } //affiliate var affiliate = _affiliateService.GetAffiliateById(details.Customer.AffiliateId); if (affiliate != null && affiliate.Active && !affiliate.Deleted) { details.AffiliateId = affiliate.Id; } //check whether customer is guest if (details.Customer.IsGuest() && !_orderSettings.AnonymousCheckoutAllowed) { throw new NopException("Anonymous checkout is not allowed"); } //customer currency var currencyTmp = _currencyService.GetCurrencyById( details.Customer.GetAttribute <int>(SystemCustomerAttributeNames.CurrencyId, processPaymentRequest.StoreId)); var customerCurrency = (currencyTmp != null && currencyTmp.Published) ? currencyTmp : _workContext.WorkingCurrency; var primaryStoreCurrency = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId); details.CustomerCurrencyCode = customerCurrency.CurrencyCode; //START PATCH var coinServiceSettings = EngineContext.Current.ContainerManager.Resolve <CoinServiceSettings>(); string[] Cryptos; if (coinServiceSettings.SupportedCoins != null) { Cryptos = coinServiceSettings.SupportedCoins.Split(','); } else { Cryptos = new string[0]; } if (Cryptos.Contains(details.CustomerCurrencyCode)) { details.CustomerCurrencyRate = CoinMarketCapHelper.GetCoinMarketCapRate(details.CustomerCurrencyCode) / primaryStoreCurrency.Rate; } else { details.CustomerCurrencyRate = customerCurrency.Rate / primaryStoreCurrency.Rate; } //END PATCH //customer language details.CustomerLanguage = _languageService.GetLanguageById( details.Customer.GetAttribute <int>(SystemCustomerAttributeNames.LanguageId, processPaymentRequest.StoreId)); if (details.CustomerLanguage == null || !details.CustomerLanguage.Published) { details.CustomerLanguage = _workContext.WorkingLanguage; } //billing address if (details.Customer.BillingAddress == null) { throw new NopException("Billing address is not provided"); } if (!CommonHelper.IsValidEmail(details.Customer.BillingAddress.Email)) { throw new NopException("Email is not valid"); } details.BillingAddress = (Address)details.Customer.BillingAddress.Clone(); if (details.BillingAddress.Country != null && !details.BillingAddress.Country.AllowsBilling) { throw new NopException(string.Format("Country '{0}' is not allowed for billing", details.BillingAddress.Country.Name)); } //checkout attributes details.CheckoutAttributesXml = details.Customer.GetAttribute <string>(SystemCustomerAttributeNames.CheckoutAttributes, processPaymentRequest.StoreId); details.CheckoutAttributeDescription = _checkoutAttributeFormatter.FormatAttributes(details.CheckoutAttributesXml, details.Customer); //load shopping cart details.Cart = details.Customer.ShoppingCartItems.Where(sci => sci.ShoppingCartType == ShoppingCartType.ShoppingCart) .LimitPerStore(processPaymentRequest.StoreId).ToList(); if (!details.Cart.Any()) { throw new NopException("Cart is empty"); } //validate the entire shopping cart var warnings = _shoppingCartService.GetShoppingCartWarnings(details.Cart, details.CheckoutAttributesXml, true); if (warnings.Any()) { throw new NopException(warnings.Aggregate(string.Empty, (current, next) => string.Format("{0}{1};", current, next))); } //validate individual cart items foreach (var sci in details.Cart) { var sciWarnings = _shoppingCartService.GetShoppingCartItemWarnings(details.Customer, sci.ShoppingCartType, sci.Product, processPaymentRequest.StoreId, sci.AttributesXml, sci.CustomerEnteredPrice, sci.RentalStartDateUtc, sci.RentalEndDateUtc, sci.Quantity, false); if (sciWarnings.Any()) { throw new NopException(sciWarnings.Aggregate(string.Empty, (current, next) => string.Format("{0}{1};", current, next))); } } //min totals validation if (!ValidateMinOrderSubtotalAmount(details.Cart)) { var minOrderSubtotalAmount = _currencyService.ConvertFromPrimaryStoreCurrency(_orderSettings.MinOrderSubtotalAmount, _workContext.WorkingCurrency); throw new NopException(string.Format(_localizationService.GetResource("Checkout.MinOrderSubtotalAmount"), _priceFormatter.FormatPrice(minOrderSubtotalAmount, true, false))); } if (!ValidateMinOrderTotalAmount(details.Cart)) { var minOrderTotalAmount = _currencyService.ConvertFromPrimaryStoreCurrency(_orderSettings.MinOrderTotalAmount, _workContext.WorkingCurrency); throw new NopException(string.Format(_localizationService.GetResource("Checkout.MinOrderTotalAmount"), _priceFormatter.FormatPrice(minOrderTotalAmount, true, false))); } //tax display type if (_taxSettings.AllowCustomersToSelectTaxDisplayType) { details.CustomerTaxDisplayType = (TaxDisplayType)details.Customer.GetAttribute <int>(SystemCustomerAttributeNames.TaxDisplayTypeId, processPaymentRequest.StoreId); } else { details.CustomerTaxDisplayType = _taxSettings.TaxDisplayType; } //sub total (incl tax) decimal orderSubTotalDiscountAmount; List <DiscountForCaching> orderSubTotalAppliedDiscounts; decimal subTotalWithoutDiscountBase; decimal subTotalWithDiscountBase; _orderTotalCalculationService.GetShoppingCartSubTotal(details.Cart, true, out orderSubTotalDiscountAmount, out orderSubTotalAppliedDiscounts, out subTotalWithoutDiscountBase, out subTotalWithDiscountBase); details.OrderSubTotalInclTax = subTotalWithoutDiscountBase; details.OrderSubTotalDiscountInclTax = orderSubTotalDiscountAmount; //discount history foreach (var disc in orderSubTotalAppliedDiscounts) { if (!details.AppliedDiscounts.ContainsDiscount(disc)) { details.AppliedDiscounts.Add(disc); } } //sub total (excl tax) _orderTotalCalculationService.GetShoppingCartSubTotal(details.Cart, false, out orderSubTotalDiscountAmount, out orderSubTotalAppliedDiscounts, out subTotalWithoutDiscountBase, out subTotalWithDiscountBase); details.OrderSubTotalExclTax = subTotalWithoutDiscountBase; details.OrderSubTotalDiscountExclTax = orderSubTotalDiscountAmount; //shipping info if (details.Cart.RequiresShipping()) { var pickupPoint = details.Customer.GetAttribute <PickupPoint>(SystemCustomerAttributeNames.SelectedPickupPoint, processPaymentRequest.StoreId); if (_shippingSettings.AllowPickUpInStore && pickupPoint != null) { var country = _countryService.GetCountryByTwoLetterIsoCode(pickupPoint.CountryCode); var state = _stateProvinceService.GetStateProvinceByAbbreviation(pickupPoint.StateAbbreviation); details.PickUpInStore = true; details.PickupAddress = new Address { Address1 = pickupPoint.Address, City = pickupPoint.City, Country = country, StateProvince = state, ZipPostalCode = pickupPoint.ZipPostalCode, CreatedOnUtc = DateTime.UtcNow, }; } else { if (details.Customer.ShippingAddress == null) { throw new NopException("Shipping address is not provided"); } if (!CommonHelper.IsValidEmail(details.Customer.ShippingAddress.Email)) { throw new NopException("Email is not valid"); } //clone shipping address details.ShippingAddress = (Address)details.Customer.ShippingAddress.Clone(); if (details.ShippingAddress.Country != null && !details.ShippingAddress.Country.AllowsShipping) { throw new NopException(string.Format("Country '{0}' is not allowed for shipping", details.ShippingAddress.Country.Name)); } } var shippingOption = details.Customer.GetAttribute <ShippingOption>(SystemCustomerAttributeNames.SelectedShippingOption, processPaymentRequest.StoreId); if (shippingOption != null) { details.ShippingMethodName = shippingOption.Name; details.ShippingRateComputationMethodSystemName = shippingOption.ShippingRateComputationMethodSystemName; } details.ShippingStatus = ShippingStatus.NotYetShipped; } else { details.ShippingStatus = ShippingStatus.ShippingNotRequired; } //shipping total decimal tax; List <DiscountForCaching> shippingTotalDiscounts; var orderShippingTotalInclTax = _orderTotalCalculationService.GetShoppingCartShippingTotal(details.Cart, true, out tax, out shippingTotalDiscounts); var orderShippingTotalExclTax = _orderTotalCalculationService.GetShoppingCartShippingTotal(details.Cart, false); if (!orderShippingTotalInclTax.HasValue || !orderShippingTotalExclTax.HasValue) { throw new NopException("Shipping total couldn't be calculated"); } details.OrderShippingTotalInclTax = orderShippingTotalInclTax.Value; details.OrderShippingTotalExclTax = orderShippingTotalExclTax.Value; foreach (var disc in shippingTotalDiscounts) { if (!details.AppliedDiscounts.ContainsDiscount(disc)) { details.AppliedDiscounts.Add(disc); } } //payment total var paymentAdditionalFee = _paymentService.GetAdditionalHandlingFee(details.Cart, processPaymentRequest.PaymentMethodSystemName); details.PaymentAdditionalFeeInclTax = _taxService.GetPaymentMethodAdditionalFee(paymentAdditionalFee, true, details.Customer); details.PaymentAdditionalFeeExclTax = _taxService.GetPaymentMethodAdditionalFee(paymentAdditionalFee, false, details.Customer); //tax amount SortedDictionary <decimal, decimal> taxRatesDictionary; details.OrderTaxTotal = _orderTotalCalculationService.GetTaxTotal(details.Cart, out taxRatesDictionary); //VAT number var customerVatStatus = (VatNumberStatus)details.Customer.GetAttribute <int>(SystemCustomerAttributeNames.VatNumberStatusId); if (_taxSettings.EuVatEnabled && customerVatStatus == VatNumberStatus.Valid) { details.VatNumber = details.Customer.GetAttribute <string>(SystemCustomerAttributeNames.VatNumber); } //tax rates details.TaxRates = taxRatesDictionary.Aggregate(string.Empty, (current, next) => string.Format("{0}{1}:{2}; ", current, next.Key.ToString(CultureInfo.InvariantCulture), next.Value.ToString(CultureInfo.InvariantCulture))); //order total (and applied discounts, gift cards, reward points) List <AppliedGiftCard> appliedGiftCards; List <DiscountForCaching> orderAppliedDiscounts; decimal orderDiscountAmount; int redeemedRewardPoints; decimal redeemedRewardPointsAmount; var orderTotal = _orderTotalCalculationService.GetShoppingCartTotal(details.Cart, out orderDiscountAmount, out orderAppliedDiscounts, out appliedGiftCards, out redeemedRewardPoints, out redeemedRewardPointsAmount); if (!orderTotal.HasValue) { throw new NopException("Order total couldn't be calculated"); } details.OrderDiscountAmount = orderDiscountAmount; details.RedeemedRewardPoints = redeemedRewardPoints; details.RedeemedRewardPointsAmount = redeemedRewardPointsAmount; details.AppliedGiftCards = appliedGiftCards; details.OrderTotal = orderTotal.Value; //discount history foreach (var disc in orderAppliedDiscounts) { if (!details.AppliedDiscounts.ContainsDiscount(disc)) { details.AppliedDiscounts.Add(disc); } } processPaymentRequest.OrderTotal = details.OrderTotal; //recurring or standard shopping cart? details.IsRecurringShoppingCart = details.Cart.IsRecurring(); if (details.IsRecurringShoppingCart) { int recurringCycleLength; RecurringProductCyclePeriod recurringCyclePeriod; int recurringTotalCycles; var recurringCyclesError = details.Cart.GetRecurringCycleInfo(_localizationService, out recurringCycleLength, out recurringCyclePeriod, out recurringTotalCycles); if (!string.IsNullOrEmpty(recurringCyclesError)) { throw new NopException(recurringCyclesError); } processPaymentRequest.RecurringCycleLength = recurringCycleLength; processPaymentRequest.RecurringCyclePeriod = recurringCyclePeriod; processPaymentRequest.RecurringTotalCycles = recurringTotalCycles; } return(details); }