Autopay
Autopay allows the logged in users to the site, to save the credit card in PayEx, and later use it without having to re-enter it again. This is the same functionality of "one click payment" found in most websites, where the saved credit card is selected and clicking buying button makes the purchase against that saved credit card.
To Enable
Use PayEx version 2.7 or later. PayEx need to individually enable this setting in your payEx account. Set the autoPayEnabled attribute to true in the Litium.Studio.AddOns.PayEx.dll.config file.
You need to modify the checkout page to show the already saved credit cards, and get the users preference to save a new card or not.
User must be logged into the site to use saved cards, or to save a new card.
Sample code
Following is a modified code from Litium Accelerator B2C. The PaymentMethodSelection.ascx file and its code behind file is changed in following way.
ascx
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="PaymentMethodSelectionPayEx.ascx.cs"
Inherits="Site.CMS.Templates.B2C.UserControls.CheckOut.PaymentMethodSelectionPayEx" %>
<div class="paymentmethodselection">
<div class="paymentmethodscontainer hide-for-small">
<Ecom:PaymentMethodRepeater runat="server" ID="PaymentMethodRepeater" OnItemDataBound="PaymentMethodRepeaterOnItemDataBound">
<ItemTemplate>
<asp:Panel runat="server" ID="PaymentMethodContainer">
<div class="paymentmethod row">
<div class="large-10 column">
<div class="checkbox">
<asp:RadioButton data-customformname="PaymentMethod" OnCheckedChanged="RadioButtonOnChecked" runat="server" AutoPostBack="True" id="PaymentMethodRadioButton" />
</div>
<div class="name">
<strong>
<asp:Label runat="server" AssociatedControlID="PaymentMethodRadioButton">
<Ecom:PaymentMethodDisplayName runat="server" />
</asp:Label>
</strong>
</div>
<div class="cost">
<Ecom:ShoppingCartPanel runat="server">
<Klarna:IsKlarnaPartPayment runat="server">
<OnTrue>
<Klarna:IsPartialPaymentsAsSeperateMethods runat="server" OnPreRender="KlarnaExistPreRender">
<OnFalse>
<Klarna:PartPaymentOptionsDropDownList ID="PartPaymentOptionsDropDownListKlarna" runat="server"
Visible="true" AutoPostBack="true" DisplayCurrencySymbol="true" OnSelectedIndexChanged="PartPaymentChangedKlarna" />
</OnFalse>
</Klarna:IsPartialPaymentsAsSeperateMethods>
</OnTrue>
<OnFalse>
-
<web:WebSiteString Name="PaymentMethodCost" runat="server" />
<Ecom:PaymentMethodCost DisplayCurrencySymbol="True" runat="server" />
</OnFalse>
</Klarna:IsKlarnaPartPayment>
<PayEx:CanSaveCardAtPayEx runat="server" ID="CanSaveCardAtPayEx">
<OnTrue>
<PayEx:HasSavedCards runat="server" OnPreRender="PayExExistPreRender">
<OnTrue>
<PayEx:SavedCardsDropDownList runat="server" ID="PayExSavedCardsDropDownList" ShowPayWithNewCardOption="true" AutoPostBack="true" OnSelectedIndexChanged="PaymentOptionsChanged"/>
</br>
<PayEx:SavedCardInfoRepeater runat="server">
<ItemTemplate>
<PayEx:SavedCardInfoCategory runat="server" />
<PayEx:SavedCardInfoMaskedCardNumber runat="server" />
<PayEx:SavedCardInfoExpM runat="server" />
<PayEx:SavedCardInfoExpY runat="server" />
</br>
</ItemTemplate>
</PayEx:SavedCardInfoRepeater>
</OnTrue>
</PayEx:HasSavedCards>
<div>
<PayEx:SaveCardAtPayEx Text="Save card at PayEx" runat="server" OnCheckedChanged="PaymentOptionsChanged" AutoPostBack="True" />
</div>
</OnTrue>
</PayEx:CanSaveCardAtPayEx>
</Ecom:ShoppingCartPanel>
</div>
<div class="description">
<Ecom:PaymentMethodDescription runat="server">
</Ecom:PaymentMethodDescription>
</div>
</div>
<div class="large-2 column">
<Ecom:PaymentMethodImage runat="server" RenderSize="False" />
</div>
</div>
</asp:Panel>
</ItemTemplate>
</Ecom:PaymentMethodRepeater>
</div>
<div class="mobile show-for-small">
<Ecom:PaymentMethodRepeater runat="server" ID="PaymentMethodMobileRepeater" OnItemDataBound="PaymentMethodRepeaterOnItemDataBound">
<ItemTemplate>
<asp:Panel runat="server" ID="PaymentMethodContainer">
<div>
<div>
<asp:RadioButton data-customformname="PaymentMethod" Visible="False" OnCheckedChanged="RadioButtonOnChecked" runat="server" AutoPostBack="True" id="PaymentMethodRadioButton" />
<div class="name">
<strong>
<Ecom:PaymentMethodDisplayName runat="server" ID="PaymentMethodDisplayName" />
</strong>
</div>
<Ecom:ShoppingCartPanel runat="server">
<Klarna:IsKlarnaPartPayment runat="server">
<OnTrue>
<Klarna:IsPartialPaymentsAsSeperateMethods runat="server" OnPreRender="KlarnaExistPreRender">
<OnFalse>
<div class="cost small-12">
<Klarna:PartPaymentOptionsDropDownList ID="PartPaymentOptionsDropDownListKlarna" runat="server"
Visible="true" AutoPostBack="true" DisplayCurrencySymbol="true" OnSelectedIndexChanged="PartPaymentChangedKlarna" />
</div>
</OnFalse>
</Klarna:IsPartialPaymentsAsSeperateMethods>
</OnTrue>
<OnFalse>
<div class="cost">
-
<web:WebSiteString Name="PaymentMethodCost" runat="server" />
<Ecom:PaymentMethodCost DisplayCurrencySymbol="True" runat="server" />
</div>
</OnFalse>
</Klarna:IsKlarnaPartPayment>
</Ecom:ShoppingCartPanel>
</div>
<div class="description">
<Ecom:PaymentMethodDescription runat="server">
</Ecom:PaymentMethodDescription>
</div>
</div>
</asp:Panel>
</ItemTemplate>
</Ecom:PaymentMethodRepeater>
</div>
<web:Text runat="server" Name="PaymentMethodsText" />
<div class="paymentmethodscontainer reveal-modal paymentmethodspopupcontainer ">
<a class="close-reveal-modal">×</a>
<Ecom:PaymentMethodRepeater runat="server" ID="PaymentMethodPopupRepeater" OnItemDataBound="PaymentMethodRepeaterOnItemDataBound">
<ItemTemplate>
<asp:Panel runat="server" ID="PaymentMethodContainer" CssClass="row">
<div class="small-12 columns">
<div class="paymentmethod row">
<div class="image small-2 columns">
<Ecom:PaymentMethodImage Width="50" runat="server" />
</div>
<div class="small-9 columns">
<div class="name">
<strong>
<asp:Label runat="server" AssociatedControlID="PaymentMethodRadioButton"><Ecom:PaymentMethodDisplayName runat="server" ID="PaymentMethodDisplayName" /></asp:Label>
</strong>
</div>
<div class="description">
<Ecom:PaymentMethodDescription runat="server" LimitLength="22">
</Ecom:PaymentMethodDescription>
</div>
<Ecom:ShoppingCartPanel runat="server">
<Klarna:IsKlarnaPartPayment runat="server">
<OnFalse>
<div class="cost">
<web:WebSiteString Name="PaymentMethodCost" runat="server" />
<Ecom:PaymentMethodCost DisplayCurrencySymbol="True" runat="server" />
</div>
</OnFalse>
</Klarna:IsKlarnaPartPayment>
</Ecom:ShoppingCartPanel>
</div>
<div class="radio small-1">
<asp:RadioButton data-customformname="PaymentMethod" OnCheckedChanged="RadioButtonOnChecked" runat="server" AutoPostBack="True" id="PaymentMethodRadioButton" />
</div>
<Ecom:ShoppingCartPanel runat="server">
<Klarna:IsKlarnaPartPayment ID="IsKlarnaPartPayment1" runat="server">
<OnTrue>
<Klarna:IsPartialPaymentsAsSeperateMethods ID="IsPartialPaymentsAsSeperateMethods1" runat="server" OnPreRender="KlarnaExistPreRender">
<OnFalse>
<div class="row">
<div class="small-7 small-offset-2 columns">
<Klarna:PartPaymentOptionsDropDownList ID="PartPaymentOptionsDropDownListKlarna" runat="server"
Visible="true" AutoPostBack="true" DisplayCurrencySymbol="true" OnSelectedIndexChanged="PartPaymentChangedKlarna" />
</div>
</div>
</OnFalse>
</Klarna:IsPartialPaymentsAsSeperateMethods>
</OnTrue>
</Klarna:IsKlarnaPartPayment>
</Ecom:ShoppingCartPanel>
</div>
</div>
</asp:Panel>
</ItemTemplate>
</Ecom:PaymentMethodRepeater>
</div>
</div>
<div class="small-12 show-for-small">
<a class="button small small-12 paymentmethodspopuplink"><web:WebSiteString runat="server" Name="ChangePaymentMethod" /></a>
</div>
code behind
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
using Litium.Foundation.Data.MSSQL.Utilities;
using Litium.Foundation.Modules.CMS;
using Litium.Foundation.Modules.ECommerce;
using Litium.Foundation.Modules.ECommerce.Carriers;
using Litium.Foundation.Modules.ECommerce.WebControls;
using Litium.Foundation.Modules.WebControls;
using Litium.Studio.Accelerator.CMS.Panels;
using Litium.Studio.Accelerator.UI.UserControls;
using Litium.Studio.Accelerator.Utilities;
using Litium.Studio.AddOns.PayEx;
using KlarnaCtrl = Litium.Studio.AddOns.Klarna.WebControls;
using PaymentMethod = Litium.Foundation.Modules.ECommerce.Payments.PaymentMethod;
using PayExCtrl = Litium.Studio.AddOns.PayEx.WebControls;
namespace Site.CMS.Templates.B2C.UserControls.CheckOut
{
public partial class PaymentMethodSelectionPayEx : BaseUserControl
{
private const string _panelData = "_paymentSettingsPanelData";
private const string _paymentMethodId = "data-paymentMethodId";
public event EventHandler PaymentMethodChanged;
private void OnPaymentMethodChanged(EventArgs e)
{
if (PaymentMethodChanged != null)
{
PaymentMethodChanged(this, e);
}
}
/// <summary>
/// Gets or sets the panel data.
/// </summary>
/// <value>
/// The panel data.
/// </value>
public List<PaymentMethodSettingsPanelData> PanelData
{
get
{
if (ViewState[_panelData] == null)
ViewState[_panelData] = GetPaymentMethodsFromPanel();
return (List<PaymentMethodSettingsPanelData>)ViewState[_panelData];
}
set
{
ViewState[_panelData] = value;
}
}
protected void Page_Init(object sender, EventArgs e)
{
InitializeControls();
InitializeMobileControls();
}
protected void PaymentOptionsChanged(object sender, EventArgs e)
{
var partPaymentsList = sender as WebControl;
if (partPaymentsList != null)
{
var parent = partPaymentsList.Parent;
if (parent != null)
{
while (parent.ID != "PaymentMethodContainer")
{
parent = parent.Parent;
}
var paymentMethodRadioButton = (RadioButton) parent.FindControl("PaymentMethodRadioButton");
var paymentMethodId = paymentMethodRadioButton.Attributes[_paymentMethodId];
ChangePaymentMethod(paymentMethodId);
}
}
}
private void InitializeControls()
{
var paymentMethodsFromPanel = new List<PaymentMethod>();
if (PanelData.Count > 0)
{
var paymentMethodData = PanelData.OrderBy(x => x.Index);
foreach (var item in paymentMethodData)
{
if (!string.IsNullOrEmpty(item.PaymentProviderName) && !string.IsNullOrEmpty(item.PaymentMethodName))
{
//check whether item exists.
var paymentMethod = ModuleECommerce.Instance.PaymentMethods.Get(item.PaymentMethodName, item.PaymentProviderName, ModuleECommerce.Instance.AdminToken);
if (paymentMethod != null)
paymentMethodsFromPanel.Add(paymentMethod);
}
}
}
PaymentMethodRepeater.DataSource = paymentMethodsFromPanel;
PaymentMethodRepeater.DataBind();
PaymentMethodPopupRepeater.DataSource = paymentMethodsFromPanel;
PaymentMethodPopupRepeater.DataBind();
}
private List<PaymentMethodSettingsPanelData> GetPaymentMethodsFromPanel()
{
List<PaymentMethodSettingsPanelData> panaeData = new List<PaymentMethodSettingsPanelData>();
var paymentMethodSettings = PropertyUtilities.GetStringPropertyValue(WebControlState.CMS.CurrentPage.Settings,
PanelsConstants.PaymentMethodSettingsPanelData);
if (!string.IsNullOrEmpty(paymentMethodSettings))
{
panaeData = MSSQLUtilities.ConvertJsonToObject<List<PaymentMethodSettingsPanelData>>(paymentMethodSettings);
}
return panaeData;
}
protected void PayExExistPreRender(object sender, EventArgs e)
{
var hasDibsSavedCards = (PayExCtrl.HasSavedCards)sender;
if (hasDibsSavedCards.IsTrue)
{
foreach (Control control in hasDibsSavedCards.Controls)
{
if (control is OnTrueFalseControl.OnTrueFalseTemplateItem)
{
var savedCardsDropDown = (PayExCtrl.SavedCardsDropDownList)control.FindControl("PayExSavedCardsDropDownList");
Control parent = savedCardsDropDown.Parent;
while (!(parent is PaymentMethodRepeaterItem))
{
parent = parent.Parent;
}
if (parent is PaymentMethodRepeaterItem)
{
var paymentMethodId = ((PaymentMethodRepeaterItem)parent).CurrentPaymentMethod.ID;
PaymentInfoCarrier paymentInfoCarrier =
CurrentState.Current.ShoppingCart.OrderCarrier.PaymentInfo.FirstOrDefault();
if (paymentInfoCarrier != null)
{
PaymentMethod selectedPaymentMethod =
ModuleECommerce.Instance.PaymentMethods.Get(paymentInfoCarrier.PaymentMethod,
paymentInfoCarrier.PaymentProvider,
WebControlState.Token);
if (selectedPaymentMethod.ID != paymentMethodId)
{
savedCardsDropDown.Style["display"] = "none";
savedCardsDropDown.Attributes["data-customforms"] = "disabled";
}
var container = (Panel)parent.FindControl("PaymentMethodContainer");
savedCardsDropDown.DataBind();
if (savedCardsDropDown.Items.Count <= 0)
{
container.Style["display"] = "none";
}
else
{
container.Style["display"] = "block";
}
}
}
}
}
}
}
protected void PaymentMethodRepeaterOnItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
var paymentMethodRadioButton = (RadioButton)e.Item.FindControl("PaymentMethodRadioButton");
if (paymentMethodRadioButton != null)
{
PaymentInfoCarrier paymentInfoCarrier = CurrentState.Current.ShoppingCart.OrderCarrier.PaymentInfo.FirstOrDefault();
var paymentMethod = (PaymentMethod)e.Item.DataItem;
bool isSelected;
if (paymentInfoCarrier != null)
{
PaymentMethod selectedPaymentMethod =
ModuleECommerce.Instance.PaymentMethods.Get(paymentInfoCarrier.PaymentMethod, paymentInfoCarrier.PaymentProvider,
WebControlState.Token);
isSelected = selectedPaymentMethod.ID.Equals(paymentMethod.ID);
}
else
{
ModuleECommerce.Instance.CheckoutFlow.AddPaymentInfo(CurrentState.Current.ShoppingCart.OrderCarrier,
paymentMethod.PaymentProviderName,
paymentMethod.Name, new AddressCarrier(),
WebControlState.Token);
ModuleECommerce.Instance.Orders.CalculateOrderTotals(CurrentState.Current.ShoppingCart.OrderCarrier,
WebControlState.Token);
isSelected = true;
}
paymentMethodRadioButton.Attributes.Add(_paymentMethodId, paymentMethod.ID.ToString());
paymentMethodRadioButton.Checked = isSelected;
}
}
}
protected void RadioButtonOnChecked(object sender, EventArgs e)
{
var radioButton = (RadioButton)sender;
string paymentMethodId = radioButton.Attributes[_paymentMethodId];
ChangePaymentMethod(paymentMethodId);
}
protected void KlarnaExistPreRender(object sender, EventArgs e)
{
var isKlarnaPartPayment = (KlarnaCtrl.IsPartialPaymentsAsSeperateMethods)sender;
if (!isKlarnaPartPayment.IsTrue)
{
foreach (Control control in isKlarnaPartPayment.Controls)
{
if (control is OnTrueFalseControl.OnTrueFalseTemplateItem)
{
var partpaymentDropDown = (KlarnaCtrl.PartPaymentOptionsDropDownList)control.FindControl("PartPaymentOptionsDropDownListKlarna");
Control parent = partpaymentDropDown.Parent;
while (!(parent is PaymentMethodRepeaterItem))
{
parent = parent.Parent;
}
if (parent is PaymentMethodRepeaterItem)
{
var paymentMethodId = ((PaymentMethodRepeaterItem)parent).CurrentPaymentMethod.ID;
PaymentInfoCarrier paymentInfoCarrier =
CurrentState.Current.ShoppingCart.OrderCarrier.PaymentInfo.FirstOrDefault();
if (paymentInfoCarrier != null)
{
PaymentMethod selectedPaymentMethod =
ModuleECommerce.Instance.PaymentMethods.Get(paymentInfoCarrier.PaymentMethod,
paymentInfoCarrier.PaymentProvider,
WebControlState.Token);
if (selectedPaymentMethod.ID != paymentMethodId)
{
partpaymentDropDown.Style["display"] = "none";
partpaymentDropDown.Attributes["data-customforms"] = "disabled";
}
var container = (Panel)parent.FindControl("PaymentMethodContainer");
partpaymentDropDown.DataBind();
if (partpaymentDropDown.Items.Count <= 0)
{
container.Style["display"] = "none";
}
else
{
container.Style["display"] = "block";
}
}
}
}
}
}
}
protected void PartPaymentChangedKlarna(object sender, EventArgs e)
{
var partPaymentsList = sender as KlarnaCtrl.PartPaymentOptionsDropDownList;
var parent = partPaymentsList.Parent;
while (parent.ID != "PaymentMethodContainer")
{
parent = parent.Parent;
}
var paymentMethodRadioButton = (RadioButton)parent.FindControl("PaymentMethodRadioButton");
var paymentMethodId = paymentMethodRadioButton.Attributes[_paymentMethodId];
ChangePaymentMethod(paymentMethodId);
}
private void InitializeMobileControls()
{
var paymentMethodsFromPanel = new List<PaymentMethod>();
if (PanelData.Count > 0)
{
var paymentMethodData = PanelData.OrderBy(x => x.Index);
foreach (var item in paymentMethodData)
{
//check whether item exists.
var paymentMethod = ModuleECommerce.Instance.PaymentMethods.Get(item.PaymentMethodName, item.PaymentProviderName, ModuleECommerce.Instance.AdminToken);
if (paymentMethod != null)
{
paymentMethodsFromPanel.Add(paymentMethod);
}
}
}
if (paymentMethodsFromPanel.Count > 0)
{
PaymentMethod paymentMethod;
var mobilePaymentMethods = new List<PaymentMethod>();
bool selectedPaymentMethodExist = false;
PaymentInfoCarrier paymentInfoCarrier = CurrentState.Current.ShoppingCart.OrderCarrier.PaymentInfo.FirstOrDefault();
if (paymentInfoCarrier != null)
{
PaymentMethod selectedPaymentMethod =
ModuleECommerce.Instance.PaymentMethods.Get(paymentInfoCarrier.PaymentMethod, paymentInfoCarrier.PaymentProvider,
WebControlState.Token);
if (selectedPaymentMethod != null)
{
paymentMethod = paymentMethodsFromPanel.FirstOrDefault(payment => payment.ID.Equals(selectedPaymentMethod.ID));
if (paymentMethod != null)
{
mobilePaymentMethods = new List<PaymentMethod> { paymentMethod };
selectedPaymentMethodExist = true;
}
}
}
if (!selectedPaymentMethodExist)
{
mobilePaymentMethods = new List<PaymentMethod> { paymentMethodsFromPanel[0] };
}
PaymentMethodMobileRepeater.DataSource = mobilePaymentMethods;
PaymentMethodMobileRepeater.DataBind();
}
}
private void ChangePaymentMethod(string id)
{
if (string.IsNullOrEmpty(id)) return;
PaymentMethod paymentMethod = ModuleECommerce.Instance.PaymentMethods.Get(new Guid(id), WebControlState.Token);
ModuleECommerce.Instance.CheckoutFlow.AddPaymentInfo(
CurrentState.Current.ShoppingCart.OrderCarrier, paymentMethod.PaymentProviderName,
paymentMethod.Name,
new AddressCarrier(), WebControlState.Token);
ModuleECommerce.Instance.Orders.CalculateOrderTotals(CurrentState.Current.ShoppingCart.OrderCarrier, CurrentState.Current.Token);
InitializeControls();
InitializeMobileControls();
OnPaymentMethodChanged(new EventArgs());
}
}
}