Skip to content

Commit

Permalink
feat: ability for a customer to enter their specific name from their …
Browse files Browse the repository at this point in the history
…credit card, rather than always using the billing address name
  • Loading branch information
mewajda committed Nov 10, 2021
1 parent 7724185 commit 9ddb383
Show file tree
Hide file tree
Showing 10 changed files with 163 additions and 34 deletions.
3 changes: 2 additions & 1 deletion Nixtus.Plugin.Payments.Nmi/Components/NmiViewComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ public IViewComponentResult Invoke()
var model = new PaymentInfoModel
{
IsGuest = _customerService.IsGuest(_workContext.CurrentCustomer),
AllowCustomerToSaveCards = _nmiPaymentSettings.AllowCustomerToSaveCards
AllowCustomerToSaveCards = _nmiPaymentSettings.AllowCustomerToSaveCards,
UseNameOnCardField = _nmiPaymentSettings.UseNameOnCardField
};

if (_nmiPaymentSettings.AllowCustomerToSaveCards)
Expand Down
2 changes: 2 additions & 0 deletions Nixtus.Plugin.Payments.Nmi/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@ public static class Constants
public static string SaveCustomerKey = "Nmi.SaveCustomer";
public static string CustomerVaultIdKey = "Nmi.Customer.Vault.Id";
public static string StoredCardKey = "Nmi.StoredCard.Id";
public static string FirstNameOnCardKey = "Nmi.FirstNameOnCard";
public static string LastNameOnCardKey = "Nmi.LastNameOnCard";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ public IActionResult Configure()
TransactModeValues = nmiPaymentSettings.TransactMode.ToSelectList(),
AdditionalFee = nmiPaymentSettings.AdditionalFee,
AdditionalFeePercentage = nmiPaymentSettings.AdditionalFeePercentage,
ActiveStoreScopeConfiguration = storeScope
ActiveStoreScopeConfiguration = storeScope,
UseNameOnCardField = nmiPaymentSettings.UseNameOnCardField
};

if (storeScope > 0)
Expand All @@ -76,6 +77,7 @@ public IActionResult Configure()
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.UseNameOnCardField_OverrideForStore = _settingService.SettingExists(nmiPaymentSettings, x => x.UseNameOnCardField, storeScope);
}

return View("~/Plugins/Payments.Nmi/Views/Configure.cshtml", model);
Expand Down Expand Up @@ -106,6 +108,7 @@ public IActionResult Configure(ConfigurationModel model)
nmiPaymentSettings.SecurityKey = model.SecurityKey;
nmiPaymentSettings.CollectJsTokenizationKey = model.CollectJsTokenizationKey;
nmiPaymentSettings.TransactMode = (TransactMode)model.TransactModeId;
nmiPaymentSettings.UseNameOnCardField = model.UseNameOnCardField;

/* We do not clear cache after each setting update.
* This behavior can increase performance because cached settings will not be cleared
Expand All @@ -119,6 +122,7 @@ public IActionResult Configure(ConfigurationModel model)
_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);
_settingService.SaveSettingOverridablePerStore(nmiPaymentSettings, x => x.UseNameOnCardField, model.UseNameOnCardField_OverrideForStore, storeScope, false);

//now clear settings cache
_settingService.ClearCache();
Expand Down
4 changes: 4 additions & 0 deletions Nixtus.Plugin.Payments.Nmi/Models/ConfigurationModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,9 @@ public class ConfigurationModel
[NopResourceDisplayName("Plugins.Payments.Nmi.Fields.AdditionalFeePercentage")]
public bool AdditionalFeePercentage { get; set; }
public bool AdditionalFeePercentage_OverrideForStore { get; set; }

[NopResourceDisplayName("Plugins.Payments.Nmi.Fields.UseNameOnCardField")]
public bool UseNameOnCardField { get; set; }
public bool UseNameOnCardField_OverrideForStore { get; set; }
}
}
8 changes: 8 additions & 0 deletions Nixtus.Plugin.Payments.Nmi/Models/PaymentInfoModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,13 @@ public PaymentInfoModel()
public bool IsGuest { get; set; }

public bool AllowCustomerToSaveCards { get; set; }

[NopResourceDisplayName("Plugins.Payments.Nmi.Fields.FirstNameOnCard")]
public string FirstNameOnCard { get; set; }

[NopResourceDisplayName("Plugins.Payments.Nmi.Fields.LastNameOnCard")]
public string LastNameOnCard { get; set; }

public bool UseNameOnCardField { get; set; }
}
}
72 changes: 66 additions & 6 deletions Nixtus.Plugin.Payments.Nmi/NmiPaymentProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Microsoft.Extensions.Primitives;
using Nop.Core;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Common;
using Nop.Core.Domain.Customers;
using Nop.Core.Domain.Orders;
using Nop.Core.Domain.Payments;
Expand Down Expand Up @@ -161,6 +162,31 @@ private void AddStoredCardValues(ProcessPaymentRequest processPaymentRequest, Cu
values.Add("payment_token", processPaymentRequest.CustomValues[Constants.CardToken].ToString());
}
}

/// <summary>
/// Add name values based on if the "Name on card" fields are enabled, otherwise use the name from the billing address
/// </summary>
/// <param name="processPaymentRequest"></param>
/// <param name="billingAddress"></param>
/// <param name="values"></param>
private void AddNameValues(ProcessPaymentRequest processPaymentRequest, Address billingAddress, IDictionary<string, string> values)
{
// if use name on card is enabled and has values then use that name for the transaction
// otherwise use the billing address name
if (_nmiPaymentSettings.UseNameOnCardField)
{
processPaymentRequest.CustomValues.TryGetValue(Constants.FirstNameOnCardKey, out object firstNameValue);
processPaymentRequest.CustomValues.TryGetValue(Constants.LastNameOnCardKey, out object lastNameValue);

values.Add("firstname", firstNameValue.ToString());
values.Add("lastname", lastNameValue.ToString());
}
else
{
values.Add("firstname", billingAddress.FirstName);
values.Add("lastname", billingAddress.LastName);
}
}
#endregion

#region Methods
Expand All @@ -187,8 +213,6 @@ public ProcessPaymentResult ProcessPayment(ProcessPaymentRequest processPaymentR
{
{ "payment", "creditcard" },
{ "type", _nmiPaymentSettings.TransactMode == TransactMode.AuthorizeAndCapture ? "sale" : "auth" },
{ "firstname", billingAddress.FirstName },
{ "lastname", billingAddress.LastName },
{ "address1", billingAddress.Address1 },
{ "city", billingAddress.City },
{ "state", state?.Abbreviation },
Expand All @@ -197,6 +221,9 @@ public ProcessPaymentResult ProcessPayment(ProcessPaymentRequest processPaymentR
{ "orderid", processPaymentRequest.OrderGuid.ToString() }
};

// add name values
AddNameValues(processPaymentRequest, billingAddress, values);

// save customer card if needed
var saveCustomer = AddCustomerVaultValues(processPaymentRequest, customer, values);

Expand Down Expand Up @@ -472,8 +499,6 @@ public ProcessPaymentResult ProcessRecurringPayment(ProcessPaymentRequest proces
{
{ "payment", "creditcard" },
{ "type", _nmiPaymentSettings.TransactMode == TransactMode.AuthorizeAndCapture ? "sale" : "auth" },
{ "firstname", billingAddress.FirstName },
{ "lastname", billingAddress.LastName },
{ "address1", billingAddress.Address1 },
{ "city", billingAddress.City },
{ "state", state?.Abbreviation },
Expand All @@ -482,6 +507,9 @@ public ProcessPaymentResult ProcessRecurringPayment(ProcessPaymentRequest proces
{ "orderid", processPaymentRequest.OrderGuid.ToString() }
};

// add name values
AddNameValues(processPaymentRequest, billingAddress, values);

// save customer card if needed
var saveCustomer = AddCustomerVaultValues(processPaymentRequest, customer, values);

Expand Down Expand Up @@ -641,11 +669,29 @@ public IList<string> ValidatePaymentForm(IFormCollection form)
if (form == null)
throw new ArgumentException(nameof(form));

var warnings = new List<string>();

if (_nmiPaymentSettings.UseNameOnCardField)
{
var firstName = form["FirstNameOnCard"].ToString();
var lastName = form["LastNameOnCard"].ToString();

if (string.IsNullOrEmpty(firstName))
{
warnings.Add("First name cannot be empty");
}

if (string.IsNullOrEmpty(lastName))
{
warnings.Add("Last name cannot be empty");
}
}

//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<string>();
return warnings;
}

/// <summary>
Expand All @@ -667,6 +713,12 @@ 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);

if (form.TryGetValue("FirstNameOnCard", out StringValues firstNameOnCardValue) && !StringValues.IsNullOrEmpty(firstNameOnCardValue))
paymentRequest.CustomValues.Add(Constants.FirstNameOnCardKey, firstNameOnCardValue.ToString());

if (form.TryGetValue("LastNameOnCard", out StringValues lastNameOnCardValue) && !StringValues.IsNullOrEmpty(lastNameOnCardValue))
paymentRequest.CustomValues.Add(Constants.LastNameOnCardKey, lastNameOnCardValue.ToString());

return paymentRequest;
}

Expand Down Expand Up @@ -726,6 +778,10 @@ public override void Install()
_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");
_localizationService.AddOrUpdatePluginLocaleResource("Plugins.Payments.Nmi.Fields.FirstNameOnCard", "First name on card");
_localizationService.AddOrUpdatePluginLocaleResource("Plugins.Payments.Nmi.Fields.LastNameOnCard", "Last name on card");
_localizationService.AddOrUpdatePluginLocaleResource("Plugins.Payments.Nmi.Fields.UseNameOnCardField", "Use 'Name on card' field");
_localizationService.AddOrUpdatePluginLocaleResource("Plugins.Payments.Nmi.Fields.UseNameOnCardField.Hint", "Enables the 'Name on card' field during the payment checkout, instead of using the customers billing address name");

base.Install();
}
Expand Down Expand Up @@ -760,6 +816,10 @@ public override void Uninstall()
_localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.Fields.AllowCustomerToSaveCards");
_localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.Fields.AllowCustomerToSaveCards.Hint");
_localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.Fields.StoredCard");
_localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.Fields.FirstNameOnCard");
_localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.Fields.LastNameOnCard");
_localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.Fields.UseNameOnCardField");
_localizationService.DeletePluginLocaleResource("Plugins.Payments.Nmi.Fields.UseNameOnCardField.Hint");

base.Uninstall();
}
Expand Down
5 changes: 5 additions & 0 deletions Nixtus.Plugin.Payments.Nmi/NmiPaymentSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,10 @@ public class NmiPaymentSettings : ISettings
/// Additional fee
/// </summary>
public decimal AdditionalFee { get; set; }

/// <summary>
/// Enable the "Name on Card" field on the UI during checkout
/// </summary>
public bool UseNameOnCardField { get; set; }
}
}
44 changes: 34 additions & 10 deletions Nixtus.Plugin.Payments.Nmi/Views/Configure.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
<div class="panel-body">
<div class="form-group">
<div class="col-md-3">
<nop-override-store-checkbox asp-for="UseUsernamePassword_OverrideForStore" asp-input="UseUsernamePassword" asp-store-scope="@Model.ActiveStoreScopeConfiguration" />
<nop-override-store-checkbox asp-for="UseUsernamePassword_OverrideForStore"
asp-input="UseUsernamePassword" asp-store-scope="@Model.ActiveStoreScopeConfiguration" />
<nop-label asp-for="UseUsernamePassword" />
</div>
<div class="col-md-9">
Expand All @@ -23,7 +24,9 @@

<div class="form-group">
<div class="col-md-3">
<nop-override-store-checkbox asp-for="AllowCustomerToSaveCards_OverrideForStore" asp-input="AllowCustomerToSaveCards" asp-store-scope="@Model.ActiveStoreScopeConfiguration" />
<nop-override-store-checkbox asp-for="AllowCustomerToSaveCards_OverrideForStore"
asp-input="AllowCustomerToSaveCards"
asp-store-scope="@Model.ActiveStoreScopeConfiguration" />
<nop-label asp-for="AllowCustomerToSaveCards" />
</div>
<div class="col-md-9">
Expand All @@ -34,7 +37,8 @@

<div class="form-group" id="username">
<div class="col-md-3">
<nop-override-store-checkbox asp-for="Username_OverrideForStore" asp-input="Username" asp-store-scope="@Model.ActiveStoreScopeConfiguration" />
<nop-override-store-checkbox asp-for="Username_OverrideForStore" asp-input="Username"
asp-store-scope="@Model.ActiveStoreScopeConfiguration" />
<nop-label asp-for="Username" />
</div>
<div class="col-md-9">
Expand All @@ -44,18 +48,20 @@

<div class="form-group" id="password">
<div class="col-md-3">
<nop-override-store-checkbox asp-for="Password_OverrideForStore" asp-input="Password" asp-store-scope="@Model.ActiveStoreScopeConfiguration" />
<nop-override-store-checkbox asp-for="Password_OverrideForStore" asp-input="Password"
asp-store-scope="@Model.ActiveStoreScopeConfiguration" />
<nop-label asp-for="Password" />
</div>
<div class="col-md-9">
<nop-editor asp-for="Password" />
<span asp-validation-for="Password"></span>
</div>
</div>

<div class="form-group" id="security-key">
<div class="col-md-3">
<nop-override-store-checkbox asp-for="SecurityKey_OverrideForStore" asp-input="SecurityKey" asp-store-scope="@Model.ActiveStoreScopeConfiguration" />
<nop-override-store-checkbox asp-for="SecurityKey_OverrideForStore" asp-input="SecurityKey"
asp-store-scope="@Model.ActiveStoreScopeConfiguration" />
<nop-label asp-for="SecurityKey" />
</div>
<div class="col-md-9">
Expand All @@ -66,7 +72,9 @@

<div class="form-group">
<div class="col-md-3">
<nop-override-store-checkbox asp-for="CollectJsTokenizationKey_OverrideForStore" asp-input="CollectJsTokenizationKey" asp-store-scope="@Model.ActiveStoreScopeConfiguration" />
<nop-override-store-checkbox asp-for="CollectJsTokenizationKey_OverrideForStore"
asp-input="CollectJsTokenizationKey"
asp-store-scope="@Model.ActiveStoreScopeConfiguration" />
<nop-label asp-for="CollectJsTokenizationKey" />
</div>
<div class="col-md-9">
Expand All @@ -77,7 +85,8 @@

<div class="form-group">
<div class="col-md-3">
<nop-override-store-checkbox asp-for="TransactModeId_OverrideForStore" asp-input="TransactModeId" asp-store-scope="@Model.ActiveStoreScopeConfiguration" />
<nop-override-store-checkbox asp-for="TransactModeId_OverrideForStore"
asp-input="TransactModeId" asp-store-scope="@Model.ActiveStoreScopeConfiguration" />
<nop-label asp-for="TransactModeId" />
</div>
<div class="col-md-9">
Expand All @@ -87,7 +96,8 @@

<div class="form-group">
<div class="col-md-3">
<nop-override-store-checkbox asp-for="AdditionalFee_OverrideForStore" asp-input="AdditionalFee" asp-store-scope="@Model.ActiveStoreScopeConfiguration" />
<nop-override-store-checkbox asp-for="AdditionalFee_OverrideForStore" asp-input="AdditionalFee"
asp-store-scope="@Model.ActiveStoreScopeConfiguration" />
<nop-label asp-for="AdditionalFee" />
</div>
<div class="col-md-9">
Expand All @@ -98,7 +108,9 @@

<div class="form-group">
<div class="col-md-3">
<nop-override-store-checkbox asp-for="AdditionalFeePercentage_OverrideForStore" asp-input="AdditionalFeePercentage" asp-store-scope="@Model.ActiveStoreScopeConfiguration" />
<nop-override-store-checkbox asp-for="AdditionalFeePercentage_OverrideForStore"
asp-input="AdditionalFeePercentage"
asp-store-scope="@Model.ActiveStoreScopeConfiguration" />
<nop-label asp-for="AdditionalFeePercentage" />
</div>
<div class="col-md-9">
Expand All @@ -107,6 +119,18 @@
</div>
</div>

<div class="form-group">
<div class="col-md-3">
<nop-override-store-checkbox asp-for="UseNameOnCardField_OverrideForStore"
asp-input="UseNameOnCardField" asp-store-scope="@Model.ActiveStoreScopeConfiguration" />
<nop-label asp-for="UseNameOnCardField" />
</div>
<div class="col-md-9">
<nop-editor asp-for="UseNameOnCardField" />
<span asp-validation-for="UseNameOnCardField"></span>
</div>
</div>

<div class="form-group">
<div class="col-md-3">
&nbsp;
Expand Down
Loading

0 comments on commit 9ddb383

Please sign in to comment.