public PayPalResponse Capture(PayPalApiSettingsBase settings, PayPalSessionData session, CapturePaymentRequest request) { var data = new Dictionary <string, object>(); //var isAuthorize = request.Order.AuthorizationTransactionCode.IsCaseInsensitiveEqual("authorize"); var path = "/v1/payments/authorization/{0}/capture".FormatInvariant(request.Order.AuthorizationTransactionId); var store = _services.StoreService.GetStoreById(request.Order.StoreId); var amount = new Dictionary <string, object>(); amount.Add("total", request.Order.OrderTotal.FormatInvariant()); amount.Add("currency", store.PrimaryStoreCurrency.CurrencyCode); data.Add("amount", amount); var result = CallApi("POST", path, session.AccessToken, settings, JsonConvert.SerializeObject(data)); if (result.Success && result.Json != null) { result.Id = (string)result.Json.id; } return(result); }
private void DeleteWebhook(PayPalApiSettingsBase settings, string providerSystemName) { try { if (settings?.WebhookId.HasValue() ?? false) { var session = new PayPalSessionData { ProviderSystemName = providerSystemName }; var result = _payPalService.Value.EnsureAccessToken(session, settings); if (result.Success) { result = _payPalService.Value.DeleteWebhook(settings, session); } if (!result.Success) { Logger.Log(LogLevel.Error, null, result.ErrorMessage, null); } } } catch (Exception ex) { Logger.Log(LogLevel.Error, ex, null, null); } }
public PayPalResponse Refund(PayPalApiSettingsBase settings, PayPalSessionData session, RefundPaymentRequest request) { var data = new Dictionary <string, object>(); var store = _services.StoreService.GetStoreById(request.Order.StoreId); var isSale = request.Order.AuthorizationTransactionResult.Contains("(sale)"); var path = "/v1/payments/{0}/{1}/refund".FormatInvariant(isSale ? "sale" : "capture", request.Order.CaptureTransactionId); var amount = new Dictionary <string, object>(); amount.Add("total", request.AmountToRefund.FormatInvariant()); amount.Add("currency", store.PrimaryStoreCurrency.CurrencyCode); data.Add("amount", amount); var result = CallApi("POST", path, session.AccessToken, settings, data.Any() ? JsonConvert.SerializeObject(data) : null); if (result.Success && result.Json != null) { result.Id = (string)result.Json.id; } //Logger.InsertLog(LogLevel.Information, "PayPal Refund", JsonConvert.SerializeObject(data, Formatting.Indented) + "\r\n\r\n" + (result.Json != null ? result.Json.ToString() : "")); return(result); }
public PayPalResponse EnsureAccessToken(PayPalSessionData session, PayPalApiSettingsBase settings) { if (session.AccessToken.IsEmpty() || DateTime.UtcNow >= session.TokenExpiration) { var result = CallApi("POST", "/v1/oauth2/token", null, settings, "grant_type=client_credentials"); if (result.Success) { session.AccessToken = (string)result.Json.access_token; var expireSeconds = ((string)result.Json.expires_in).ToInt(5 * 60); session.TokenExpiration = DateTime.UtcNow.AddSeconds(expireSeconds); } else { return(result); } } return(new PayPalResponse { Success = session.AccessToken.HasValue() }); }
public PayPalResponse DeleteCheckoutExperience(PayPalApiSettingsBase settings, PayPalSessionData session) { var result = CallApi("DELETE", "/v1/payment-experience/web-profiles/" + settings.ExperienceProfileId, session.AccessToken, settings, null); if (result.Success && result.Json != null) { result.Id = (string)result.Json.id; } return(result); }
public PayPalResponse GetPayment(PayPalApiSettingsBase settings, PayPalSessionData session) { var result = CallApi("GET", "/v1/payments/payment/" + session.PaymentId, session.AccessToken, settings, null); if (result.Success && result.Json != null) { result.Id = (string)result.Json.id; } return(result); }
public PayPalResponse DeleteWebhook(PayPalApiSettingsBase settings, PayPalSessionData session) { var result = CallApi("DELETE", "/v1/notifications/webhooks/" + settings.WebhookId, session.AccessToken, settings, null); if (result.Success && result.Json != null) { result.Id = (string)result.Json.id; } return(result); }
protected CustomSecurityHeaderType GetApiCredentials(PayPalApiSettingsBase settings) { var customSecurityHeaderType = new CustomSecurityHeaderType(); customSecurityHeaderType.Credentials = new UserIdPasswordType(); customSecurityHeaderType.Credentials.Username = settings.ApiAccountName; customSecurityHeaderType.Credentials.Password = settings.ApiAccountPassword; customSecurityHeaderType.Credentials.Signature = settings.Signature; customSecurityHeaderType.Credentials.Subject = ""; return(customSecurityHeaderType); }
public PayPalResponse Void(PayPalApiSettingsBase settings, PayPalSessionData session, VoidPaymentRequest request) { var path = "/v1/payments/authorization/{0}/void".FormatInvariant(request.Order.AuthorizationTransactionId); var result = CallApi("POST", path, session.AccessToken, settings, null); if (result.Success && result.Json != null) { result.Id = (string)result.Json.id; } return(result); }
public PayPalResponse CreateWebhook(PayPalApiSettingsBase settings, PayPalSessionData session, string url) { var data = new Dictionary <string, object>(); var events = new List <Dictionary <string, object> >(); events.Add(new Dictionary <string, object> { { "name", "PAYMENT.AUTHORIZATION.VOIDED" } }); events.Add(new Dictionary <string, object> { { "name", "PAYMENT.CAPTURE.COMPLETED" } }); events.Add(new Dictionary <string, object> { { "name", "PAYMENT.CAPTURE.DENIED" } }); events.Add(new Dictionary <string, object> { { "name", "PAYMENT.CAPTURE.PENDING" } }); events.Add(new Dictionary <string, object> { { "name", "PAYMENT.CAPTURE.REFUNDED" } }); events.Add(new Dictionary <string, object> { { "name", "PAYMENT.CAPTURE.REVERSED" } }); events.Add(new Dictionary <string, object> { { "name", "PAYMENT.SALE.COMPLETED" } }); events.Add(new Dictionary <string, object> { { "name", "PAYMENT.SALE.DENIED" } }); events.Add(new Dictionary <string, object> { { "name", "PAYMENT.SALE.PENDING" } }); events.Add(new Dictionary <string, object> { { "name", "PAYMENT.SALE.REFUNDED" } }); events.Add(new Dictionary <string, object> { { "name", "PAYMENT.SALE.REVERSED" } }); data.Add("url", url); data.Add("event_types", events); var result = CallApi("POST", "/v1/notifications/webhooks", session.AccessToken, settings, JsonConvert.SerializeObject(data)); if (result.Success && result.Json != null) { result.Id = (string)result.Json.id; } return(result); }
public PayPalResponse ExecutePayment(PayPalApiSettingsBase settings, PayPalSessionData session) { var data = new Dictionary <string, object>(); data.Add("payer_id", session.PayerId); var result = CallApi("POST", "/v1/payments/payment/{0}/execute".FormatInvariant(session.PaymentId), session.AccessToken, settings, JsonConvert.SerializeObject(data)); if (result.Success && result.Json != null) { result.Id = (string)result.Json.id; //Logger.InsertLog(LogLevel.Information, "PayPal PLUS", JsonConvert.SerializeObject(data, Formatting.Indented) + "\r\n\r\n" + result.Json.ToString()); } return(result); }
public PayPalResponse UpsertCheckoutExperience(PayPalApiSettingsBase settings, PayPalSessionData session, Store store) { PayPalResponse result; var name = store.Name; var logo = _pictureService.Value.GetPictureById(store.LogoPictureId); var path = "/v1/payment-experience/web-profiles"; var data = new Dictionary <string, object>(); var presentation = new Dictionary <string, object>(); var inpuFields = new Dictionary <string, object>(); // find existing profile id, only one profile per profile name possible if (settings.ExperienceProfileId.IsEmpty()) { result = CallApi("GET", path, session.AccessToken, settings, null); if (result.Success && result.Json != null) { foreach (var profile in result.Json) { var profileName = (string)profile.name; if (profileName.IsCaseInsensitiveEqual(name)) { settings.ExperienceProfileId = (string)profile.id; break; } } } } presentation.Add("brand_name", name); presentation.Add("locale_code", _services.WorkContext.WorkingLanguage.UniqueSeoCode.EmptyNull().ToUpper()); if (logo != null) { presentation.Add("logo_image", _pictureService.Value.GetPictureUrl(logo, showDefaultPicture: false, storeLocation: store.Url)); } inpuFields.Add("allow_note", false); inpuFields.Add("no_shipping", 0); inpuFields.Add("address_override", 1); data.Add("name", name); data.Add("presentation", presentation); data.Add("input_fields", inpuFields); if (settings.ExperienceProfileId.HasValue()) { path = string.Concat(path, "/", HttpUtility.UrlPathEncode(settings.ExperienceProfileId)); } result = CallApi(settings.ExperienceProfileId.HasValue() ? "PUT" : "POST", path, session.AccessToken, settings, JsonConvert.SerializeObject(data)); if (result.Success) { if (result.Json != null) { result.Id = (string)result.Json.id; } else { result.Id = settings.ExperienceProfileId; } } return(result); }
public PayPalResponse CreatePayment( PayPalApiSettingsBase settings, PayPalSessionData session, List <OrganizedShoppingCartItem> cart, string providerSystemName, string returnUrl, string cancelUrl) { var store = _services.StoreContext.CurrentStore; var customer = _services.WorkContext.CurrentCustomer; var language = _services.WorkContext.WorkingLanguage; var currencyCode = store.PrimaryStoreCurrency.CurrencyCode; var dateOfBirth = customer.GetAttribute <DateTime?>(SystemCustomerAttributeNames.DateOfBirth); Discount orderAppliedDiscount; List <AppliedGiftCard> appliedGiftCards; int redeemedRewardPoints = 0; decimal redeemedRewardPointsAmount; decimal orderDiscountInclTax; decimal totalOrderItems = decimal.Zero; var includingTax = (_services.WorkContext.GetTaxDisplayTypeFor(customer, store.Id) == TaxDisplayType.IncludingTax); var shipping = (_orderTotalCalculationService.GetShoppingCartShippingTotal(cart) ?? decimal.Zero); var paymentFee = _paymentService.GetAdditionalHandlingFee(cart, providerSystemName); var total = (_orderTotalCalculationService.GetShoppingCartTotal(cart, out orderDiscountInclTax, out orderAppliedDiscount, out appliedGiftCards, out redeemedRewardPoints, out redeemedRewardPointsAmount) ?? decimal.Zero); var data = new Dictionary <string, object>(); var redirectUrls = new Dictionary <string, object>(); var payer = new Dictionary <string, object>(); var payerInfo = new Dictionary <string, object>(); var transaction = new Dictionary <string, object>(); var amount = new Dictionary <string, object>(); var amountDetails = new Dictionary <string, object>(); var items = new List <Dictionary <string, object> >(); var itemList = new Dictionary <string, object>(); // "PayPal PLUS only supports transaction type “Sale” (instant settlement)" if (providerSystemName == PayPalPlusProvider.SystemName) { data.Add("intent", "sale"); } else { data.Add("intent", settings.TransactMode == TransactMode.AuthorizeAndCapture ? "sale" : "authorize"); } if (settings.ExperienceProfileId.HasValue()) { data.Add("experience_profile_id", settings.ExperienceProfileId); } // redirect urls if (returnUrl.HasValue()) { redirectUrls.Add("return_url", returnUrl); } if (cancelUrl.HasValue()) { redirectUrls.Add("cancel_url", cancelUrl); } if (redirectUrls.Any()) { data.Add("redirect_urls", redirectUrls); } // payer, payer_info if (dateOfBirth.HasValue) { payerInfo.Add("birth_date", dateOfBirth.Value.ToString("yyyy-MM-dd")); } if (customer.BillingAddress != null) { payerInfo.Add("billing_address", CreateAddress(customer.BillingAddress, false)); } payer.Add("payment_method", "paypal"); payer.Add("payer_info", payerInfo); data.Add("payer", payer); // line items foreach (var item in cart) { decimal unitPriceTaxRate = decimal.Zero; decimal unitPrice = _priceCalculationService.GetUnitPrice(item, true); decimal productPrice = _taxService.GetProductPrice(item.Item.Product, unitPrice, includingTax, customer, out unitPriceTaxRate); var line = new Dictionary <string, object>(); line.Add("quantity", item.Item.Quantity); line.Add("name", item.Item.Product.GetLocalized(x => x.Name, language.Id, true, false).Truncate(127)); line.Add("price", productPrice.FormatInvariant()); line.Add("currency", currencyCode); line.Add("sku", item.Item.Product.Sku.Truncate(50)); items.Add(line); totalOrderItems += (productPrice * item.Item.Quantity); } var itemsPlusMisc = (totalOrderItems + shipping + paymentFee); if (total != itemsPlusMisc) { var line = new Dictionary <string, object>(); line.Add("quantity", "1"); line.Add("name", T("Plugins.SmartStore.PayPal.Other").Text.Truncate(127)); line.Add("price", (total - itemsPlusMisc).FormatInvariant()); line.Add("currency", currencyCode); items.Add(line); totalOrderItems += (total - itemsPlusMisc); } itemList.Add("items", items); if (customer.ShippingAddress != null) { itemList.Add("shipping_address", CreateAddress(customer.ShippingAddress, true)); } // transactions amountDetails.Add("shipping", shipping.FormatInvariant()); amountDetails.Add("subtotal", totalOrderItems.FormatInvariant()); if (!includingTax) { // "To avoid rounding errors we recommend not submitting tax amounts on line item basis. // Calculated tax amounts for the entire shopping basket may be submitted in the amount objects. // In this case the item amounts will be treated as amounts excluding tax. // In a B2C scenario, where taxes are included, no taxes should be submitted to PayPal." SortedDictionary <decimal, decimal> taxRates = null; var taxTotal = _orderTotalCalculationService.GetTaxTotal(cart, out taxRates); amountDetails.Add("tax", taxTotal.FormatInvariant()); } if (paymentFee != decimal.Zero) { amountDetails.Add("handling_fee", paymentFee.FormatInvariant()); } amount.Add("total", total.FormatInvariant()); amount.Add("currency", currencyCode); amount.Add("details", amountDetails); transaction.Add("amount", amount); transaction.Add("item_list", itemList); transaction.Add("invoice_number", session.OrderGuid.ToString()); data.Add("transactions", new List <Dictionary <string, object> > { transaction }); var result = CallApi("POST", "/v1/payments/payment", session.AccessToken, settings, JsonConvert.SerializeObject(data)); if (result.Success && result.Json != null) { result.Id = (string)result.Json.id; } //Logger.InsertLog(LogLevel.Information, "PayPal PLUS", JsonConvert.SerializeObject(data, Formatting.Indented) + "\r\n\r\n" + (result.Json != null ? result.Json.ToString() : "")); return(result); }
public PayPalResponse CallApi(string method, string path, string accessToken, PayPalApiSettingsBase settings, string data) { var isJson = (data.HasValue() && data.StartsWith("{")); var encoding = (isJson ? Encoding.UTF8 : Encoding.ASCII); var result = new PayPalResponse(); HttpWebResponse webResponse = null; var url = GetApiUrl(settings.UseSandbox) + path.EnsureStartsWith("/"); if (method.IsCaseInsensitiveEqual("GET") && data.HasValue()) { url = url.EnsureEndsWith("?") + data; } if (settings.SecurityProtocol.HasValue) { ServicePointManager.SecurityProtocol = settings.SecurityProtocol.Value; } var request = (HttpWebRequest)WebRequest.Create(url); request.Method = method; request.Accept = "application/json"; request.ContentType = (isJson ? "application/json" : "application/x-www-form-urlencoded"); try { if (HttpContext.Current != null && HttpContext.Current.Request != null) { request.UserAgent = HttpContext.Current.Request.UserAgent; } else { request.UserAgent = Plugin.SystemName; } } catch { } if (path.EmptyNull().EndsWith("/token")) { // see https://github.com/paypal/sdk-core-dotnet/blob/master/Source/SDK/OAuthTokenCredential.cs byte[] credentials = Encoding.UTF8.GetBytes("{0}:{1}".FormatInvariant(settings.ClientId, settings.Secret)); request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(credentials)); } else { request.Headers["Authorization"] = "Bearer " + accessToken.EmptyNull(); } if (data.HasValue() && (method.IsCaseInsensitiveEqual("POST") || method.IsCaseInsensitiveEqual("PUT") || method.IsCaseInsensitiveEqual("PATCH"))) { byte[] bytes = encoding.GetBytes(data); request.ContentLength = bytes.Length; using (var stream = request.GetRequestStream()) { stream.Write(bytes, 0, bytes.Length); } } else { request.ContentLength = 0; } try { webResponse = request.GetResponse() as HttpWebResponse; result.Success = ((int)webResponse.StatusCode < 400); } catch (WebException wexc) { result.Success = false; result.ErrorMessage = wexc.ToString(); webResponse = wexc.Response as HttpWebResponse; } catch (Exception exception) { result.Success = false; result.ErrorMessage = exception.ToString(); LogError(exception); } try { if (webResponse != null) { using (var reader = new StreamReader(webResponse.GetResponseStream(), Encoding.UTF8)) { var rawResponse = reader.ReadToEnd(); if (rawResponse.HasValue()) { if (webResponse.ContentType.IsCaseInsensitiveEqual("application/json")) { if (rawResponse.StartsWith("[")) { result.Json = JArray.Parse(rawResponse); } else { result.Json = JObject.Parse(rawResponse); } if (result.Json != null) { if (!result.Success) { var name = (string)result.Json.name; var message = (string)result.Json.message; if (name.IsEmpty()) { name = (string)result.Json.error; } if (message.IsEmpty()) { message = (string)result.Json.error_description; } result.ErrorMessage = "{0} ({1}).".FormatInvariant(message.NaIfEmpty(), name.NaIfEmpty()); } } } else if (!result.Success) { result.ErrorMessage = rawResponse; } } } if (!result.Success) { if (result.ErrorMessage.IsEmpty()) { result.ErrorMessage = webResponse.StatusDescription; } LogError(null, result.ErrorMessage, result.Json == null ? null : result.Json.ToString(), false); } } } catch (Exception exception) { LogError(exception); } finally { if (webResponse != null) { webResponse.Close(); webResponse.Dispose(); } } return(result); }
/// <remarks>return 503 (HttpStatusCode.ServiceUnavailable) to ask paypal to resend it at later time again</remarks> public HttpStatusCode ProcessWebhook( PayPalApiSettingsBase settings, NameValueCollection headers, string rawJson, string providerSystemName) { if (rawJson.IsEmpty()) { return(HttpStatusCode.OK); } dynamic json = JObject.Parse(rawJson); var eventType = (string)json.event_type; //foreach (var key in headers.AllKeys)"{0}: {1}".FormatInvariant(key, headers[key]).Dump(); //string data = JsonConvert.SerializeObject(json, Formatting.Indented);data.Dump(); // validating against PayPal SDK failing using sandbox, so better we do not use it: //var apiContext = new global::PayPal.Api.APIContext //{ // AccessToken = "I do not have one here", // Config = new Dictionary<string, string> // { // { "mode", settings.UseSandbox ? "sandbox" : "live" }, // { "clientId", settings.ClientId }, // { "clientSecret", settings.Secret }, // { "webhook.id", setting.WebhookId }, // } //}; //var result = global::PayPal.Api.WebhookEvent.ValidateReceivedEvent(apiContext, headers, rawJson, webhookId); //} var paymentId = (string)json.resource.parent_payment; if (paymentId.IsEmpty()) { LogError(null, T("Plugins.SmartStore.PayPal.FoundOrderForPayment", 0, "".NaIfEmpty()), JsonConvert.SerializeObject(json, Formatting.Indented), isWarning: true); return(HttpStatusCode.OK); } var orders = _orderRepository.Value.Table .Where(x => x.PaymentMethodSystemName == providerSystemName && x.AuthorizationTransactionCode == paymentId) .ToList(); if (orders.Count != 1) { LogError(null, T("Plugins.SmartStore.PayPal.FoundOrderForPayment", orders.Count, paymentId), JsonConvert.SerializeObject(json, Formatting.Indented), isWarning: true); return(HttpStatusCode.OK); } var order = orders.First(); var store = _services.StoreService.GetStoreById(order.StoreId); var total = decimal.Zero; var currency = (string)json.resource.amount.currency; var primaryCurrency = store.PrimaryStoreCurrency.CurrencyCode; if (!primaryCurrency.IsCaseInsensitiveEqual(currency)) { LogError(null, T("Plugins.SmartStore.PayPal.CurrencyNotEqual", currency.NaIfEmpty(), primaryCurrency), JsonConvert.SerializeObject(json, Formatting.Indented), isWarning: true); return(HttpStatusCode.OK); } eventType = eventType.Substring(eventType.LastIndexOf('.') + 1); var newPaymentStatus = GetPaymentStatus(eventType, "authorization", order.PaymentStatus); var isValidTotal = decimal.TryParse((string)json.resource.amount.total, NumberStyles.Currency, CultureInfo.InvariantCulture, out total); if (newPaymentStatus == PaymentStatus.Refunded && (Math.Abs(order.OrderTotal) - Math.Abs(total)) > decimal.Zero) { newPaymentStatus = PaymentStatus.PartiallyRefunded; } switch (newPaymentStatus) { case PaymentStatus.Pending: break; case PaymentStatus.Authorized: if (_orderProcessingService.CanMarkOrderAsAuthorized(order)) { _orderProcessingService.MarkAsAuthorized(order); } break; case PaymentStatus.Paid: if (_orderProcessingService.CanMarkOrderAsPaid(order)) { _orderProcessingService.MarkOrderAsPaid(order); } break; case PaymentStatus.Refunded: if (_orderProcessingService.CanRefundOffline(order)) { _orderProcessingService.RefundOffline(order); } break; case PaymentStatus.PartiallyRefunded: if (_orderProcessingService.CanPartiallyRefundOffline(order, Math.Abs(total))) { _orderProcessingService.PartiallyRefundOffline(order, Math.Abs(total)); } break; case PaymentStatus.Voided: if (_orderProcessingService.CanVoidOffline(order)) { _orderProcessingService.VoidOffline(order); } break; } order.HasNewPaymentNotification = true; AddOrderNote(settings, order, (string)ToInfoString(json)); return(HttpStatusCode.OK); }
protected bool SaveConfigurationModel( ApiConfigurationModel model, FormCollection form, Action <TSetting> map = null) { var storeDependingSettingHelper = new StoreDependingSettingHelper(ViewData); var storeScope = this.GetActiveStoreScopeConfiguration(Services.StoreService, Services.WorkContext); var settings = Services.Settings.LoadSetting <TSetting>(storeScope); var oldClientId = settings.ClientId; var oldSecret = settings.Secret; var oldProfileId = settings.ExperienceProfileId; var validator = new PayPalApiConfigValidator(T, x => { return(storeScope == 0 || storeDependingSettingHelper.IsOverrideChecked(settings, x, form)); }); validator.Validate(model, ModelState); // Additional validation. if (ModelState.IsValid) { // PayPal review: check if credentials are valid. var credentialChanged = model.ClientId.HasValue() && model.Secret.HasValue() && (!model.ClientId.IsCaseInsensitiveEqual(settings.ClientId) || !model.Secret.IsCaseInsensitiveEqual(settings.Secret)); if (credentialChanged) { var session = new PayPalSessionData { ProviderSystemName = ProviderSystemName }; var tmpSettings = new PayPalApiSettingsBase { UseSandbox = model.UseSandbox, ClientId = model.ClientId, Secret = model.Secret }; var result = PayPalService.EnsureAccessToken(session, tmpSettings); if (!result.Success) { ModelState.AddModelError("", T("Plugins.SmartStore.PayPal.InvalidCredentials")); ModelState.AddModelError("", result.ErrorMessage); } } } if (!ModelState.IsValid) { return(false); } ModelState.Clear(); model.TransactMode = TransactMode.AuthorizeAndCapture; MiniMapper.Map(model, settings); settings.ApiAccountName = model.ApiAccountName.TrimSafe(); settings.ApiAccountPassword = model.ApiAccountPassword.TrimSafe(); settings.ClientId = model.ClientId.TrimSafe(); settings.ExperienceProfileId = model.ExperienceProfileId.TrimSafe(); settings.Secret = model.Secret.TrimSafe(); settings.Signature = model.Signature.TrimSafe(); settings.WebhookId = model.WebhookId.TrimSafe(); // Additional mapping. map?.Invoke(settings); // Credentials changed: reset profile and webhook id to avoid errors. if (!oldClientId.IsCaseInsensitiveEqual(settings.ClientId) || !oldSecret.IsCaseInsensitiveEqual(settings.Secret)) { if (oldProfileId.IsCaseInsensitiveEqual(settings.ExperienceProfileId)) { settings.ExperienceProfileId = null; } settings.WebhookId = null; } using (Services.Settings.BeginScope()) { storeDependingSettingHelper.UpdateSettings(settings, form, storeScope, Services.Settings); } using (Services.Settings.BeginScope()) { // Multistore context not possible, see IPN handling. Services.Settings.SaveSetting(settings, x => x.UseSandbox, 0, false); } NotifySuccess(T("Admin.Common.DataSuccessfullySaved")); return(true); }