From e76b52006da176373fc5f9bded07aa3841a842a6 Mon Sep 17 00:00:00 2001 From: Mike Wajda Date: Tue, 26 Oct 2021 21:59:29 -0500 Subject: [PATCH] feat: upgrade to nopCommerce 4.40 --- .../Components/NmiViewComponent.cs | 36 ++- .../Controllers/PaymentNmiController.cs | 70 ++--- .../Nixtus.Plugin.Payments.Nmi.csproj | 2 +- .../NmiPaymentProcessor.cs | 282 ++++++++++-------- .../Views/Configure.cshtml | 63 ++-- Nixtus.Plugin.Payments.Nmi/plugin.json | 4 +- 6 files changed, 257 insertions(+), 200 deletions(-) diff --git a/Nixtus.Plugin.Payments.Nmi/Components/NmiViewComponent.cs b/Nixtus.Plugin.Payments.Nmi/Components/NmiViewComponent.cs index 5306b26..b4c5474 100644 --- a/Nixtus.Plugin.Payments.Nmi/Components/NmiViewComponent.cs +++ b/Nixtus.Plugin.Payments.Nmi/Components/NmiViewComponent.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Net.Http; +using System.Threading.Tasks; using System.Xml.Serialization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; @@ -36,19 +37,28 @@ public NmiViewComponent(IWorkContext workContext, ILogger logger, NmiPaymentSett _genericAttributeService = genericAttributeService; } - public IViewComponentResult Invoke() + /// + /// Invoke view component + /// + /// Widget zone name + /// Additional data + /// + /// A task that represents the asynchronous operation + /// The task result contains the view component result + /// + public async Task InvokeAsync(string widgetZone, object additionalData) { var model = new PaymentInfoModel { - IsGuest = _customerService.IsGuest(_workContext.CurrentCustomer), + IsGuest = await _customerService.IsGuestAsync(await _workContext.GetCurrentCustomerAsync()), AllowCustomerToSaveCards = _nmiPaymentSettings.AllowCustomerToSaveCards }; if (_nmiPaymentSettings.AllowCustomerToSaveCards) { - if (!string.IsNullOrEmpty(_genericAttributeService.GetAttribute(_workContext.CurrentCustomer, Constants.CustomerVaultIdKey))) + if (!string.IsNullOrEmpty(await _genericAttributeService.GetAttributeAsync(await _workContext.GetCurrentCustomerAsync(), Constants.CustomerVaultIdKey))) { - PopulateStoredCards(model); + await PopulateStoredCards(model); } model.StoredCards.Insert(0, new SelectListItem { Text = "Select a card...", Value = "0" }); @@ -57,7 +67,7 @@ public IViewComponentResult Invoke() return View("~/Plugins/Payments.Nmi/Views/PaymentInfo.cshtml", model); } - private void PopulateStoredCards(PaymentInfoModel model) + private async Task PopulateStoredCards(PaymentInfoModel model) { try { @@ -66,16 +76,16 @@ private void PopulateStoredCards(PaymentInfoModel model) { "username", _nmiPaymentSettings.Username }, { "password", _nmiPaymentSettings.Password }, { "report_type", "customer_vault" }, - { "customer_vault_id", _genericAttributeService.GetAttribute(_workContext.CurrentCustomer, Constants.CustomerVaultIdKey) }, + { "customer_vault_id", await _genericAttributeService.GetAttributeAsync(await _workContext.GetCurrentCustomerAsync(), Constants.CustomerVaultIdKey) }, // this is an undocumented variable which will make the API return multiple billings (aka credit cards) { "ver", "2" } }; - var response = _httpClient.PostAsync(NMI_QUERY_URL, new FormUrlEncodedContent(values)).Result; + var response = await _httpClient.PostAsync(NMI_QUERY_URL, new FormUrlEncodedContent(values)); if (response.IsSuccessStatusCode) { - var content = response.Content.ReadAsStringAsync().Result; - var nmiQueryResponse = DeserializeXml(content); + var content = await response.Content.ReadAsStringAsync(); + var nmiQueryResponse = await DeserializeXml(content); if (nmiQueryResponse?.CustomerVault != null) { @@ -92,18 +102,18 @@ private void PopulateStoredCards(PaymentInfoModel model) } else { - _logger.Warning($"No saved cards where found in the response from NMI, Response: {content}"); + await _logger.WarningAsync($"No saved cards where found in the response from NMI, Response: {content}"); } } } catch (Exception exception) { - _logger.Error("NMI Error querying customer vault records", exception); + await _logger.ErrorAsync("NMI Error querying customer vault records", exception); } } - private NmiQueryResponse DeserializeXml(string xml) + private async Task DeserializeXml(string xml) { try { @@ -116,7 +126,7 @@ private NmiQueryResponse DeserializeXml(string xml) } catch (Exception e) { - _logger.Error("Error parsing xml", e); + await _logger.ErrorAsync("Error parsing xml", e); return null; } } diff --git a/Nixtus.Plugin.Payments.Nmi/Controllers/PaymentNmiController.cs b/Nixtus.Plugin.Payments.Nmi/Controllers/PaymentNmiController.cs index 139f5ad..362b632 100644 --- a/Nixtus.Plugin.Payments.Nmi/Controllers/PaymentNmiController.cs +++ b/Nixtus.Plugin.Payments.Nmi/Controllers/PaymentNmiController.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Nixtus.Plugin.Payments.Nmi.Models; using Nop.Core; @@ -14,6 +15,9 @@ namespace Nixtus.Plugin.Payments.Nmi.Controllers { + [AuthorizeAdmin] + [Area(AreaNames.Admin)] + [AutoValidateAntiforgeryToken] public class PaymentNmiController : BasePaymentController { private readonly ILocalizationService _localizationService; @@ -39,16 +43,14 @@ public PaymentNmiController(ILocalizationService localizationService, _notificationService = notificationService; } - [AuthorizeAdmin] - [Area(AreaNames.Admin)] - public IActionResult Configure() + public async Task Configure() { - if (!_permissionService.Authorize(StandardPermissionProvider.ManagePaymentMethods)) + if (!await _permissionService.AuthorizeAsync(StandardPermissionProvider.ManagePaymentMethods)) return AccessDeniedView(); //load settings for a chosen store scope - var storeScope = _storeContext.ActiveStoreScopeConfiguration; - var nmiPaymentSettings = _settingService.LoadSetting(storeScope); + var storeScope = await _storeContext.GetActiveStoreScopeConfigurationAsync(); + var nmiPaymentSettings = await _settingService.LoadSettingAsync(storeScope); var model = new ConfigurationModel { @@ -59,7 +61,7 @@ public IActionResult Configure() SecurityKey = nmiPaymentSettings.SecurityKey, CollectJsTokenizationKey = nmiPaymentSettings.CollectJsTokenizationKey, TransactModeId = Convert.ToInt32(nmiPaymentSettings.TransactMode), - TransactModeValues = nmiPaymentSettings.TransactMode.ToSelectList(), + TransactModeValues = await nmiPaymentSettings.TransactMode.ToSelectListAsync(), AdditionalFee = nmiPaymentSettings.AdditionalFee, AdditionalFeePercentage = nmiPaymentSettings.AdditionalFeePercentage, ActiveStoreScopeConfiguration = storeScope @@ -67,34 +69,32 @@ public IActionResult Configure() if (storeScope > 0) { - model.Username_OverrideForStore = _settingService.SettingExists(nmiPaymentSettings, x => x.Username, storeScope); - model.Password_OverrideForStore = _settingService.SettingExists(nmiPaymentSettings, x => x.Password, storeScope); - model.UseUsernamePassword_OverrideForStore = _settingService.SettingExists(nmiPaymentSettings, x => x.UseUsernamePassword, storeScope); - model.AllowCustomerToSaveCards_OverrideForStore = _settingService.SettingExists(nmiPaymentSettings, x => x.AllowCustomerToSaveCards, storeScope); - model.SecurityKey_OverrideForStore = _settingService.SettingExists(nmiPaymentSettings, x => x.SecurityKey, storeScope); - model.CollectJsTokenizationKey_OverrideForStore = _settingService.SettingExists(nmiPaymentSettings, x => x.CollectJsTokenizationKey, storeScope); - model.TransactModeId_OverrideForStore = _settingService.SettingExists(nmiPaymentSettings, x => x.TransactMode, storeScope); - model.AdditionalFee_OverrideForStore = _settingService.SettingExists(nmiPaymentSettings, x => x.AdditionalFee, storeScope); - model.AdditionalFeePercentage_OverrideForStore = _settingService.SettingExists(nmiPaymentSettings, x => x.AdditionalFeePercentage, storeScope); + model.Username_OverrideForStore = await _settingService.SettingExistsAsync(nmiPaymentSettings, x => x.Username, storeScope); + model.Password_OverrideForStore = await _settingService.SettingExistsAsync(nmiPaymentSettings, x => x.Password, storeScope); + model.UseUsernamePassword_OverrideForStore = await _settingService.SettingExistsAsync(nmiPaymentSettings, x => x.UseUsernamePassword, storeScope); + model.AllowCustomerToSaveCards_OverrideForStore = await _settingService.SettingExistsAsync(nmiPaymentSettings, x => x.AllowCustomerToSaveCards, storeScope); + model.SecurityKey_OverrideForStore = await _settingService.SettingExistsAsync(nmiPaymentSettings, x => x.SecurityKey, storeScope); + model.CollectJsTokenizationKey_OverrideForStore = await _settingService.SettingExistsAsync(nmiPaymentSettings, x => x.CollectJsTokenizationKey, storeScope); + model.TransactModeId_OverrideForStore = await _settingService.SettingExistsAsync(nmiPaymentSettings, x => x.TransactMode, storeScope); + model.AdditionalFee_OverrideForStore = await _settingService.SettingExistsAsync(nmiPaymentSettings, x => x.AdditionalFee, storeScope); + model.AdditionalFeePercentage_OverrideForStore = await _settingService.SettingExistsAsync(nmiPaymentSettings, x => x.AdditionalFeePercentage, storeScope); } return View("~/Plugins/Payments.Nmi/Views/Configure.cshtml", model); } [HttpPost] - [AuthorizeAdmin] - [Area(AreaNames.Admin)] - public IActionResult Configure(ConfigurationModel model) + public async Task Configure(ConfigurationModel model) { - if (!_permissionService.Authorize(StandardPermissionProvider.ManagePaymentMethods)) + if (!await _permissionService.AuthorizeAsync(StandardPermissionProvider.ManagePaymentMethods)) return AccessDeniedView(); if (!ModelState.IsValid) - return Configure(); + return await Configure(); //load settings for a chosen store scope - var storeScope = _storeContext.ActiveStoreScopeConfiguration; - var nmiPaymentSettings = _settingService.LoadSetting(storeScope); + var storeScope = await _storeContext.GetActiveStoreScopeConfigurationAsync(); + var nmiPaymentSettings = await _settingService.LoadSettingAsync(storeScope); //save settings nmiPaymentSettings.Username = model.Username; @@ -110,22 +110,22 @@ public IActionResult Configure(ConfigurationModel model) /* We do not clear cache after each setting update. * This behavior can increase performance because cached settings will not be cleared * and loaded from database after each update */ - _settingService.SaveSettingOverridablePerStore(nmiPaymentSettings, x => x.Password, model.Password_OverrideForStore, storeScope, false); - _settingService.SaveSettingOverridablePerStore(nmiPaymentSettings, x => x.Username, model.Username_OverrideForStore, storeScope, false); - _settingService.SaveSettingOverridablePerStore(nmiPaymentSettings, x => x.SecurityKey, model.SecurityKey_OverrideForStore, storeScope, false); - _settingService.SaveSettingOverridablePerStore(nmiPaymentSettings, x => x.CollectJsTokenizationKey, model.CollectJsTokenizationKey_OverrideForStore, storeScope, false); - _settingService.SaveSettingOverridablePerStore(nmiPaymentSettings, x => x.AdditionalFee, model.AdditionalFee_OverrideForStore, storeScope, false); - _settingService.SaveSettingOverridablePerStore(nmiPaymentSettings, x => x.AdditionalFeePercentage, model.AdditionalFeePercentage_OverrideForStore, storeScope, false); - _settingService.SaveSettingOverridablePerStore(nmiPaymentSettings, x => x.TransactMode, model.TransactModeId_OverrideForStore, storeScope, false); - _settingService.SaveSettingOverridablePerStore(nmiPaymentSettings, x => x.UseUsernamePassword, model.UseUsernamePassword_OverrideForStore, storeScope, false); - _settingService.SaveSettingOverridablePerStore(nmiPaymentSettings, x => x.AllowCustomerToSaveCards, model.AllowCustomerToSaveCards_OverrideForStore, storeScope, false); + await _settingService.SaveSettingOverridablePerStoreAsync(nmiPaymentSettings, x => x.Password, model.Password_OverrideForStore, storeScope, false); + await _settingService.SaveSettingOverridablePerStoreAsync(nmiPaymentSettings, x => x.Username, model.Username_OverrideForStore, storeScope, false); + await _settingService.SaveSettingOverridablePerStoreAsync(nmiPaymentSettings, x => x.SecurityKey, model.SecurityKey_OverrideForStore, storeScope, false); + await _settingService.SaveSettingOverridablePerStoreAsync(nmiPaymentSettings, x => x.CollectJsTokenizationKey, model.CollectJsTokenizationKey_OverrideForStore, storeScope, false); + await _settingService.SaveSettingOverridablePerStoreAsync(nmiPaymentSettings, x => x.AdditionalFee, model.AdditionalFee_OverrideForStore, storeScope, false); + await _settingService.SaveSettingOverridablePerStoreAsync(nmiPaymentSettings, x => x.AdditionalFeePercentage, model.AdditionalFeePercentage_OverrideForStore, storeScope, false); + await _settingService.SaveSettingOverridablePerStoreAsync(nmiPaymentSettings, x => x.TransactMode, model.TransactModeId_OverrideForStore, storeScope, false); + await _settingService.SaveSettingOverridablePerStoreAsync(nmiPaymentSettings, x => x.UseUsernamePassword, model.UseUsernamePassword_OverrideForStore, storeScope, false); + await _settingService.SaveSettingOverridablePerStoreAsync(nmiPaymentSettings, x => x.AllowCustomerToSaveCards, model.AllowCustomerToSaveCards_OverrideForStore, storeScope, false); //now clear settings cache - _settingService.ClearCache(); + await _settingService.ClearCacheAsync(); - _notificationService.SuccessNotification(_localizationService.GetResource("Admin.Plugins.Saved")); + _notificationService.SuccessNotification(await _localizationService.GetResourceAsync("Admin.Plugins.Saved")); - return Configure(); + return await Configure(); } } } \ No newline at end of file diff --git a/Nixtus.Plugin.Payments.Nmi/Nixtus.Plugin.Payments.Nmi.csproj b/Nixtus.Plugin.Payments.Nmi/Nixtus.Plugin.Payments.Nmi.csproj index 08d572e..111be1f 100644 --- a/Nixtus.Plugin.Payments.Nmi/Nixtus.Plugin.Payments.Nmi.csproj +++ b/Nixtus.Plugin.Payments.Nmi/Nixtus.Plugin.Payments.Nmi.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + net5.0 Copyright © Nixtus, LLC Nixtus, LLC Nixtus, LLC diff --git a/Nixtus.Plugin.Payments.Nmi/NmiPaymentProcessor.cs b/Nixtus.Plugin.Payments.Nmi/NmiPaymentProcessor.cs index b979c66..1f884bd 100644 --- a/Nixtus.Plugin.Payments.Nmi/NmiPaymentProcessor.cs +++ b/Nixtus.Plugin.Payments.Nmi/NmiPaymentProcessor.cs @@ -3,6 +3,7 @@ using System.Collections.Specialized; using System.Globalization; using System.Linq; +using System.Threading.Tasks; using System.Net.Http; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Primitives; @@ -108,14 +109,14 @@ private void AddSecurityValues(IDictionary values) /// /// /// - /// True - if saving new customer is enabled, else False - private bool AddCustomerVaultValues(ProcessPaymentRequest processPaymentRequest, Customer customer, IDictionary values) + /// Task of boolean True - if saving new customer is enabled, else False + private async Task AddCustomerVaultValues(ProcessPaymentRequest processPaymentRequest, Customer customer, IDictionary values) { var saveCustomerKeySuccess = processPaymentRequest.CustomValues.TryGetValue(Constants.SaveCustomerKey, out object saveCustomerKey); var saveCustomer = Convert.ToBoolean(saveCustomerKeySuccess ? saveCustomerKey.ToString() : "false"); if (_nmiPaymentSettings.AllowCustomerToSaveCards && saveCustomer) { - var existingCustomerVaultId = _genericAttributeService.GetAttribute(customer, Constants.CustomerVaultIdKey); + var existingCustomerVaultId = await _genericAttributeService.GetAttributeAsync(customer, Constants.CustomerVaultIdKey); if (string.IsNullOrEmpty(existingCustomerVaultId)) { values.Add("customer_vault", "add_customer"); @@ -139,19 +140,19 @@ private bool AddCustomerVaultValues(ProcessPaymentRequest processPaymentRequest, /// /// /// - private void AddStoredCardValues(ProcessPaymentRequest processPaymentRequest, Customer customer, IDictionary values) + private async Task AddStoredCardValues(ProcessPaymentRequest processPaymentRequest, Customer customer, IDictionary values) { if (processPaymentRequest.CustomValues.TryGetValue(Constants.StoredCardKey, out object storedCardId) && !storedCardId.ToString().Equals("0")) { - var existingCustomerVaultId = _genericAttributeService.GetAttribute(customer, Constants.CustomerVaultIdKey); + var existingCustomerVaultId = await _genericAttributeService.GetAttributeAsync(customer, Constants.CustomerVaultIdKey); if (!string.IsNullOrEmpty(existingCustomerVaultId)) { values.Add("customer_vault_id", existingCustomerVaultId); } else { - _logger.Warning("Customer tried use a stored card but did not have a customer vault ID saved"); + await _logger.WarningAsync("Customer tried use a stored card but did not have a customer vault ID saved"); } values.Add("billing_id", storedCardId.ToString()); @@ -169,19 +170,22 @@ private void AddStoredCardValues(ProcessPaymentRequest processPaymentRequest, Cu /// Process a payment /// /// Payment info required for an order processing - /// Process payment result - public ProcessPaymentResult ProcessPayment(ProcessPaymentRequest processPaymentRequest) + /// + /// A task that represents the asynchronous operation + /// The task result contains the process payment result + /// + public async Task ProcessPaymentAsync(ProcessPaymentRequest processPaymentRequest) { var result = new ProcessPaymentResult(); - var customer = _customerService.GetCustomerById(processPaymentRequest.CustomerId); - var billingAddress = _customerService.GetCustomerBillingAddress(customer); + var customer = await _customerService.GetCustomerByIdAsync(processPaymentRequest.CustomerId); + var billingAddress = await _customerService.GetCustomerBillingAddressAsync(customer); if (customer == null || billingAddress == null) { throw new NopException("Could not retrieve customer or billing address"); } - var state = _stateProvinceService.GetStateProvinceById(billingAddress.StateProvinceId ?? 0); + var state = await _stateProvinceService.GetStateProvinceByIdAsync(billingAddress.StateProvinceId ?? 0); var values = new Dictionary { @@ -198,10 +202,10 @@ public ProcessPaymentResult ProcessPayment(ProcessPaymentRequest processPaymentR }; // save customer card if needed - var saveCustomer = AddCustomerVaultValues(processPaymentRequest, customer, values); + var saveCustomer = await AddCustomerVaultValues(processPaymentRequest, customer, values); // determine if we need to used the stored card or the token generated from the new card - AddStoredCardValues(processPaymentRequest, customer, values); + await AddStoredCardValues(processPaymentRequest, customer, values); // add security key or username/password AddSecurityValues(values); @@ -230,7 +234,7 @@ public ProcessPaymentResult ProcessPayment(ProcessPaymentRequest processPaymentR // save customer vault id, if needed if (saveCustomer) { - _genericAttributeService.SaveAttribute(customer, Constants.CustomerVaultIdKey, customer.CustomerGuid.ToString()); + await _genericAttributeService.SaveAttributeAsync(customer, Constants.CustomerVaultIdKey, customer.CustomerGuid.ToString()); } // remove custom values so that they don't get saved on the order and also won't display @@ -245,7 +249,7 @@ public ProcessPaymentResult ProcessPayment(ProcessPaymentRequest processPaymentR } catch (Exception exception) { - _logger.Error("NMI Direct Post Error", exception, customer); + await _logger.ErrorAsync("NMI Direct Post Error", exception, customer); result.AddError("Exception Occurred: " + exception.Message); return result; } @@ -257,41 +261,51 @@ public ProcessPaymentResult ProcessPayment(ProcessPaymentRequest processPaymentR /// Post process payment (used by payment gateways that require redirecting to a third-party URL) /// /// Payment info required for an order processing - public void PostProcessPayment(PostProcessPaymentRequest postProcessPaymentRequest) + /// A task that represents the asynchronous operation + public Task PostProcessPaymentAsync(PostProcessPaymentRequest postProcessPaymentRequest) { //nothing + return Task.CompletedTask; } /// /// Gets additional handling fee /// - /// Shoping cart - /// Additional handling fee - public decimal GetAdditionalHandlingFee(IList cart) + /// + /// A task that represents the asynchronous operation + /// The task result contains the additional handling fee + /// + public async Task GetAdditionalHandlingFeeAsync(IList cart) { - return _paymentService.CalculateAdditionalFee(cart, + return await _paymentService.CalculateAdditionalFeeAsync(cart, _nmiPaymentSettings.AdditionalFee, _nmiPaymentSettings.AdditionalFeePercentage); } /// /// Returns a value indicating whether payment method should be hidden during checkout /// - /// Shoping cart - /// true - hide; false - display. - public bool HidePaymentMethod(IList cart) + /// Shopping cart + /// + /// A task that represents the asynchronous operation + /// The task result contains the rue - hide; false - display. + /// + public Task HidePaymentMethodAsync(IList cart) { //you can put any logic here //for example, hide this payment method if all products in the cart are downloadable //or hide this payment method if current customer is from certain country - return false; + return Task.FromResult(false); } /// /// Captures payment /// /// Capture payment request - /// Capture payment result - public CapturePaymentResult Capture(CapturePaymentRequest capturePaymentRequest) + /// + /// A task that represents the asynchronous operation + /// The task result contains the capture payment result + /// + public async Task CaptureAsync(CapturePaymentRequest capturePaymentRequest) { var result = new CapturePaymentResult(); @@ -309,9 +323,10 @@ public CapturePaymentResult Capture(CapturePaymentRequest capturePaymentRequest) try { - var response = _httpClient.PostAsync(NMI_DIRECT_POST_URL, new FormUrlEncodedContent(values)).Result; + var response = await _httpClient.PostAsync(NMI_DIRECT_POST_URL, new FormUrlEncodedContent(values)); - var responseValues = ExtractResponseValues(response.Content.ReadAsStringAsync().Result); + var content = await response.Content.ReadAsStringAsync(); + var responseValues = ExtractResponseValues(content); var responseValue = responseValues["response"]; @@ -330,7 +345,7 @@ public CapturePaymentResult Capture(CapturePaymentRequest capturePaymentRequest) } catch (Exception exception) { - _logger.Error("NMI Direct Post Error", exception); + await _logger.ErrorAsync("NMI Direct Post Error", exception); result.AddError("Exception Occurred: " + exception.Message); return result; } @@ -342,8 +357,11 @@ public CapturePaymentResult Capture(CapturePaymentRequest capturePaymentRequest) /// Refunds a payment /// /// Request - /// Result - public RefundPaymentResult Refund(RefundPaymentRequest refundPaymentRequest) + /// + /// A task that represents the asynchronous operation + /// The task result contains the result + /// + public async Task RefundAsync(RefundPaymentRequest refundPaymentRequest) { var result = new RefundPaymentResult(); @@ -364,9 +382,10 @@ public RefundPaymentResult Refund(RefundPaymentRequest refundPaymentRequest) try { - var response = _httpClient.PostAsync(NMI_DIRECT_POST_URL, new FormUrlEncodedContent(values)).Result; + var response = await _httpClient.PostAsync(NMI_DIRECT_POST_URL, new FormUrlEncodedContent(values)); - var responseValues = ExtractResponseValues(response.Content.ReadAsStringAsync().Result); + var content = await response.Content.ReadAsStringAsync(); + var responseValues = ExtractResponseValues(content); var responseValue = responseValues["response"]; @@ -387,7 +406,7 @@ public RefundPaymentResult Refund(RefundPaymentRequest refundPaymentRequest) } catch (Exception exception) { - _logger.Error("NMI Direct Post Error", exception); + await _logger.ErrorAsync("NMI Direct Post Error", exception); result.AddError("Exception Occurred: " + exception.Message); return result; } @@ -399,8 +418,11 @@ public RefundPaymentResult Refund(RefundPaymentRequest refundPaymentRequest) /// Voids a payment /// /// Request - /// Result - public VoidPaymentResult Void(VoidPaymentRequest voidPaymentRequest) + /// + /// A task that represents the asynchronous operation + /// The task result contains the result + /// + public async Task VoidAsync(VoidPaymentRequest voidPaymentRequest) { var result = new VoidPaymentResult(); @@ -420,9 +442,10 @@ public VoidPaymentResult Void(VoidPaymentRequest voidPaymentRequest) try { - var response = _httpClient.PostAsync(NMI_DIRECT_POST_URL, new FormUrlEncodedContent(values)).Result; + var response = await _httpClient.PostAsync(NMI_DIRECT_POST_URL, new FormUrlEncodedContent(values)); - var responseValues = ExtractResponseValues(response.Content.ReadAsStringAsync().Result); + var content = await response.Content.ReadAsStringAsync(); + var responseValues = ExtractResponseValues(content); var responseValue = responseValues["response"]; @@ -439,7 +462,7 @@ public VoidPaymentResult Void(VoidPaymentRequest voidPaymentRequest) } catch (Exception exception) { - _logger.Error("NMI Direct Post Error", exception); + await _logger.ErrorAsync("NMI Direct Post Error", exception); result.AddError("Exception Occurred: " + exception.Message); return result; } @@ -451,20 +474,23 @@ public VoidPaymentResult Void(VoidPaymentRequest voidPaymentRequest) /// Process recurring payment /// /// Payment info required for an order processing - /// Process payment result - public ProcessPaymentResult ProcessRecurringPayment(ProcessPaymentRequest processPaymentRequest) + /// + /// A task that represents the asynchronous operation + /// The task result contains the process payment result + /// + public async Task ProcessRecurringPaymentAsync(ProcessPaymentRequest processPaymentRequest) { var result = new ProcessPaymentResult(); - var customer = _customerService.GetCustomerById(processPaymentRequest.CustomerId); - var billingAddress = _customerService.GetCustomerBillingAddress(customer); + var customer = await _customerService.GetCustomerByIdAsync(processPaymentRequest.CustomerId); + var billingAddress = await _customerService.GetCustomerBillingAddressAsync(customer); if (customer == null || billingAddress == null) { throw new NopException("Could not retrieve customer or billing address"); } - var state = _stateProvinceService.GetStateProvinceById(billingAddress.StateProvinceId ?? 0); + var state = await _stateProvinceService.GetStateProvinceByIdAsync(billingAddress.StateProvinceId ?? 0); var orderTotal = processPaymentRequest.OrderTotal.ToString("0.00", CultureInfo.InvariantCulture); @@ -483,10 +509,10 @@ public ProcessPaymentResult ProcessRecurringPayment(ProcessPaymentRequest proces }; // save customer card if needed - var saveCustomer = AddCustomerVaultValues(processPaymentRequest, customer, values); + var saveCustomer = await AddCustomerVaultValues(processPaymentRequest, customer, values); // determine if we need to used the stored card or the token generated from the new card - AddStoredCardValues(processPaymentRequest, customer, values); + await AddStoredCardValues(processPaymentRequest, customer, values); // add security key or username/password AddSecurityValues(values); @@ -526,9 +552,10 @@ public ProcessPaymentResult ProcessRecurringPayment(ProcessPaymentRequest proces try { - var response = _httpClient.PostAsync(NMI_DIRECT_POST_URL, new FormUrlEncodedContent(values)).Result; + var response = await _httpClient.PostAsync(NMI_DIRECT_POST_URL, new FormUrlEncodedContent(values)); - var responseValues = ExtractResponseValues(response.Content.ReadAsStringAsync().Result); + var content = await response.Content.ReadAsStringAsync(); + var responseValues = ExtractResponseValues(content); var responseValue = responseValues["response"]; @@ -547,7 +574,7 @@ public ProcessPaymentResult ProcessRecurringPayment(ProcessPaymentRequest proces // save customer vault id, if needed if (saveCustomer) { - _genericAttributeService.SaveAttribute(customer, Constants.CustomerVaultIdKey, customer.CustomerGuid.ToString()); + await _genericAttributeService.SaveAttributeAsync(customer, Constants.CustomerVaultIdKey, customer.CustomerGuid.ToString()); } // remove custom values so that they don't get saved on the order and also won't display @@ -562,7 +589,7 @@ public ProcessPaymentResult ProcessRecurringPayment(ProcessPaymentRequest proces } catch (Exception exception) { - _logger.Error("NMI Direct Post Error", exception, customer); + await _logger.ErrorAsync("NMI Direct Post Error", exception, customer); result.AddError("Exception Occurred: " + exception.Message); return result; } @@ -574,8 +601,11 @@ public ProcessPaymentResult ProcessRecurringPayment(ProcessPaymentRequest proces /// Cancels a recurring payment /// /// Request - /// Result - public CancelRecurringPaymentResult CancelRecurringPayment(CancelRecurringPaymentRequest cancelPaymentRequest) + /// + /// A task that represents the asynchronous operation + /// The task result contains the result + /// + public async Task CancelRecurringPaymentAsync(CancelRecurringPaymentRequest cancelPaymentRequest) { var result = new CancelRecurringPaymentResult(); var values = new Dictionary @@ -590,9 +620,10 @@ public CancelRecurringPaymentResult CancelRecurringPayment(CancelRecurringPaymen try { - var response = _httpClient.PostAsync(NMI_DIRECT_POST_URL, new FormUrlEncodedContent(values)).Result; + var response = await _httpClient.PostAsync(NMI_DIRECT_POST_URL, new FormUrlEncodedContent(values)); - var responseValues = ExtractResponseValues(response.Content.ReadAsStringAsync().Result); + var content = await response.Content.ReadAsStringAsync(); + var responseValues = ExtractResponseValues(content); var responseValue = responseValues["response"]; @@ -609,7 +640,7 @@ public CancelRecurringPaymentResult CancelRecurringPayment(CancelRecurringPaymen } catch (Exception exception) { - _logger.Error("NMI Direct Post Error", exception); + await _logger.ErrorAsync("NMI Direct Post Error", exception); result.AddError("Exception Occurred: " + exception.Message); return result; } @@ -621,39 +652,53 @@ public CancelRecurringPaymentResult CancelRecurringPayment(CancelRecurringPaymen /// Gets a value indicating whether customers can complete a payment after order is placed but not completed (for redirection payment methods) /// /// Order - /// Result - public bool CanRePostProcessPayment(Order order) + /// + /// A task that represents the asynchronous operation + /// The task result contains the result + /// + public Task CanRePostProcessPaymentAsync(Order order) { if (order == null) throw new ArgumentNullException(nameof(order)); //it's not a redirection payment method. So we always return false - return false; + return Task.FromResult(false); } /// /// Validate payment form /// /// The parsed form values - /// List of validating errors - public IList ValidatePaymentForm(IFormCollection form) + /// + /// A task that represents the asynchronous operation + /// The task result contains the list of validating errors + /// + public Task> ValidatePaymentFormAsync(IFormCollection form) { if (form == null) throw new ArgumentException(nameof(form)); + + var warnings = new List(); + //try to get errors if (form.TryGetValue("Errors", out StringValues errorsString) && !StringValues.IsNullOrEmpty(errorsString)) - return new[] { errorsString.ToString() }.ToList(); + { + warnings.Add(errorsString.ToString()); + } - return new List(); + return Task.FromResult>(warnings); } /// /// Get payment information /// /// The parsed form values - /// Payment info holder - public ProcessPaymentRequest GetPaymentInfo(IFormCollection form) + /// + /// A task that represents the asynchronous operation + /// The task result contains the payment info holder + /// + public Task GetPaymentInfoAsync(IFormCollection form) { var paymentRequest = new ProcessPaymentRequest(); @@ -667,7 +712,7 @@ public ProcessPaymentRequest GetPaymentInfo(IFormCollection form) if (form.TryGetValue("SaveCustomer", out StringValues saveCustomerValue) && !StringValues.IsNullOrEmpty(saveCustomerValue) && bool.TryParse(saveCustomerValue[0], out bool saveCustomer) && saveCustomer) paymentRequest.CustomValues.Add(Constants.SaveCustomerKey, saveCustomer); - return paymentRequest; + return Task.FromResult(paymentRequest); } /// @@ -690,9 +735,10 @@ public string GetPublicViewComponentName() } /// - /// Install plugin + /// Install the plugin /// - public override void Install() + /// A task that represents the asynchronous operation + public override async Task InstallAsync() { //settings var settings = new NmiPaymentSettings @@ -702,66 +748,63 @@ public override void Install() UseUsernamePassword = false, TransactMode = TransactMode.AuthorizeAndCapture }; - _settingService.SaveSetting(settings); + await _settingService.SaveSettingAsync(settings); //locales - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Payments.Nmi.Fields.Username", "Username"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Payments.Nmi.Fields.Username.Hint", "Username assigned to the merchant account"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Payments.Nmi.Fields.Password", "Password"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Payments.Nmi.Fields.Password.Hint", "Password assigned to the merchant account"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Payments.Nmi.Fields.SecurityKey", "Security Key"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Payments.Nmi.Fields.SecurityKey.Hint", "API security key assigned to the merchant account, using this combined with username/password will result in an error. If you want to save cards, then select that checkbox and enter username/password"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Payments.Nmi.Fields.CollectJsTokenizationKey", "Collect JS Tokenization Key"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Payments.Nmi.Fields.CollectJsTokenizationKey.Hint", "Tokenization key used for Collect.js library"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Payments.Nmi.Fields.TransactModeValues", "Transaction mode"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Payments.Nmi.Fields.TransactModeValues.Hint", "Choose transaction mode."); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Payments.Nmi.Fields.AdditionalFee", "Additional fee"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Payments.Nmi.Fields.AdditionalFee.Hint", "Enter additional fee to charge your customers."); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Payments.Nmi.Fields.AdditionalFeePercentage", "Additional fee. Use percentage"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Payments.Nmi.Fields.AdditionalFeePercentage.Hint", "Determines whether to apply a percentage additional fee to the order total. If not enabled, a fixed value is used."); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Payments.Nmi.Fields.UseUsernamePassword", "Use username/password"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Payments.Nmi.Fields.UseUsernamePassword.Hint", "If enabled username/password will be used for authentication to the payment API instead of the security key"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Payments.Nmi.Fields.AllowCustomerToSaveCards", "Allow Customers To Store Cards"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Payments.Nmi.Fields.AllowCustomerToSaveCards.Hint", "If enabled registered customers will be able to save cards for future use. Also, you must enter the username/password for this functionality to be available."); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Payments.Nmi.PaymentMethodDescription", "Pay by credit / debit card"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Payments.Nmi.SaveCustomer", "Save card information"); - _localizationService.AddOrUpdatePluginLocaleResource("Plugins.Payments.Nmi.Fields.StoredCard", "Use a previously saved card"); - - base.Install(); + await _localizationService.AddLocaleResourceAsync(new Dictionary + { + ["Plugins.Payments.Nmi.Fields.Username"] = "Username", + ["Plugins.Payments.Nmi.Fields.Username.Hint"] = "Username assigned to the merchant account", + ["Plugins.Payments.Nmi.Fields.Password"] = "Password", + ["Plugins.Payments.Nmi.Fields.Password.Hint"] = "Password assigned to the merchant account", + ["Plugins.Payments.Nmi.Fields.SecurityKey"] = "Security Key", + ["Plugins.Payments.Nmi.Fields.SecurityKey.Hint"] = "API security key assigned to the merchant account, using this combined with username/password will result in an error. If you want to save cards, then select that checkbox and enter username/password", + ["Plugins.Payments.Nmi.Fields.CollectJsTokenizationKey"] = "Collect JS Tokenization Key", + ["Plugins.Payments.Nmi.Fields.CollectJsTokenizationKey.Hint"] = "Tokenization key used for Collect.js library", + ["Plugins.Payments.Nmi.Fields.TransactModeValues"] = "Transaction mode", + ["Plugins.Payments.Nmi.Fields.TransactModeValues.Hint"] = "Choose transaction mode.", + ["Plugins.Payments.Nmi.Fields.AdditionalFee"] = "Additional fee", + ["Plugins.Payments.Nmi.Fields.AdditionalFee.Hint"] = "Enter additional fee to charge your customers.", + ["Plugins.Payments.Nmi.Fields.AdditionalFeePercentage"] = "Additional fee. Use percentage", + ["Plugins.Payments.Nmi.Fields.AdditionalFeePercentage.Hint"] = "Determines whether to apply a percentage additional fee to the order total. If not enabled, a fixed value is used.", + ["Plugins.Payments.Nmi.Fields.UseUsernamePassword"] = "Use username/password", + ["Plugins.Payments.Nmi.Fields.UseUsernamePassword.Hint"] = "If enabled username/password will be used for authentication to the payment API instead of the security key", + ["Plugins.Payments.Nmi.Fields.AllowCustomerToSaveCards"] = "Allow Customers To Store Cards", + ["Plugins.Payments.Nmi.Fields.AllowCustomerToSaveCards.Hint"] = "If enabled registered customers will be able to save cards for future use. Also, you must enter the username/password for this functionality to be available.", + ["Plugins.Payments.Nmi.PaymentMethodDescription"] = "Pay by credit / debit card", + ["Plugins.Payments.Nmi.SaveCustomer"] = "Save card information", + ["Plugins.Payments.Nmi.Fields.StoredCard"] = "Use a previously saved card" + }); + + await base.InstallAsync(); } /// - /// Uninstall plugin + /// Uninstall the plugin /// - public override void Uninstall() + /// A task that represents the asynchronous operation + public override async Task UninstallAsync() { //settings - _settingService.DeleteSetting(); + await _settingService.DeleteSettingAsync(); //locales - _localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.Fields.Username"); - _localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.Fields.Username.Hint"); - _localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.Fields.Password"); - _localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.Fields.Password.Hint"); - _localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.Fields.SecurityKey"); - _localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.Fields.SecurityKey.Hint"); - _localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.Fields.CollectJsTokenizationKey"); - _localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.Fields.CollectJsTokenizationKey.Hint"); - _localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.Fields.TransactModeValues"); - _localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.Fields.TransactModeValues.Hint"); - _localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.Fields.AdditionalFee"); - _localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.Fields.AdditionalFee.Hint"); - _localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.Fields.AdditionalFeePercentage"); - _localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.Fields.AdditionalFeePercentage.Hint"); - _localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.Fields.UseUsernamePassword"); - _localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.Fields.UseUsernamePassword.Hint"); - _localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.PaymentMethodDescription"); - _localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.SaveCustomer"); - _localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.Fields.AllowCustomerToSaveCards"); - _localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.Fields.AllowCustomerToSaveCards.Hint"); - _localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.Fields.StoredCard"); - - base.Uninstall(); + await _localizationService.DeleteLocaleResourcesAsync("Plugins.Payments.Nmi"); + + await base.UninstallAsync(); + } + + /// + /// Gets a payment method description that will be displayed on checkout pages in the public store + /// + /// + /// return description of this payment method to be display on "payment method" checkout step. good practice is to make it localizable + /// for example, for a redirection payment method, description may be like this: "You will be redirected to PayPal site to complete the payment" + /// + /// A task that represents the asynchronous operation + public async Task GetPaymentMethodDescriptionAsync() + { + return await _localizationService.GetResourceAsync("Plugins.Payments.Nmi.PaymentMethodDescription"); } #endregion @@ -803,11 +846,6 @@ public override void Uninstall() /// public bool SkipPaymentInfo => false; - /// - /// Gets a payment method description that will be displayed on checkout pages in the public store - /// - public string PaymentMethodDescription => _localizationService.GetResource("Plugins.Payments.Nmi.PaymentMethodDescription"); - #endregion } } diff --git a/Nixtus.Plugin.Payments.Nmi/Views/Configure.cshtml b/Nixtus.Plugin.Payments.Nmi/Views/Configure.cshtml index b906fe6..818d909 100644 --- a/Nixtus.Plugin.Payments.Nmi/Views/Configure.cshtml +++ b/Nixtus.Plugin.Payments.Nmi/Views/Configure.cshtml @@ -7,12 +7,13 @@ @await Component.InvokeAsync("StoreScopeConfiguration")
-
-
-
-
+
+
+
+
- +
@@ -21,9 +22,11 @@
-
+
- +
@@ -32,9 +35,10 @@
-
+
- +
@@ -42,9 +46,10 @@
-
+
- +
@@ -52,10 +57,11 @@
- -
+ +
- +
@@ -64,9 +70,11 @@
-
+
- +
@@ -75,9 +83,10 @@
-
+
- +
@@ -85,9 +94,10 @@
-
+
- +
@@ -96,9 +106,11 @@
-
+
- +
@@ -107,11 +119,8 @@
-
-
-   -
-
+
+
diff --git a/Nixtus.Plugin.Payments.Nmi/plugin.json b/Nixtus.Plugin.Payments.Nmi/plugin.json index cfd034b..e5adf4a 100644 --- a/Nixtus.Plugin.Payments.Nmi/plugin.json +++ b/Nixtus.Plugin.Payments.Nmi/plugin.json @@ -2,8 +2,8 @@ "Group": "Payment methods", "FriendlyName": "Credit Card", "SystemName": "Payments.Nmi", - "Version": "1.30", - "SupportedVersions": ["4.30"], + "Version": "1.40", + "SupportedVersions": ["4.40"], "Author": "Nixtus, LLC", "DisplayOrder": 1, "FileName": "Nixtus.Plugin.Payments.Nmi.dll",