|
||
Here you will learn how to create a custom checkout process step to enhance the purchase process to best fit your needs.
1.Create a new web user control (*.ascx) and place your own form controls into it.
2.Go to its code behind and set the control class to inherit from CMS.EcommerceProvider.ShoppingCartStep.
3.There are several methods you can override to reach the required functionality:
•IsValid() - validates the current step custom data and returns a validation result. True - all step data is correct and can be processed, False - some step data is not correct or missing and cannot be processed. In this case an appropriate error message should be displayed. By default, True is returned.
•ProcessStep() - processes the current step information (updates the shopping cart data) and returns a result of this action. True - the shopping cart data was updated successfully and the customer can be moved to the next checkout process step, False – the shopping cart update failed and the customer cannot be moved to the next step. In this case an appropriate error message should be displayed. By default, True is returned.
•ButtonBackClickAction() - defines an action which is run after the Back button is clicked. By default, the parent shopping cart control method ButtonBackClickAction() is called, which moves the customer one step backward in the checkout process.
•ButtonNextClickAction() - defines an action which is run after the Next button is clicked. By default, the parent shopping cart control method ButtonNextClickAction() is called, which moves the customer one step forward in the checkout process when the current step data is valid and processed successfully.
4.There are several properties you should use to get or set the required information:
•ShoppingCartControl - the parent shopping cart control to which the step belongs.
•ShoppingCartInfoObj - the shopping cart object which stores all data during the checkout process.
•CheckoutProcessStep - the checkout process step information.
5.The step control is created and can be registered as your custom checkout process step.
If a control represents checkout process steps in different checkout process types and these steps differ from each other only slightly, you can create one control and specify different behavior depending on the checkout process type as follows:
[C#]
using System; using CMS.EcommerceProvider; using CMS.GlobalHelper;
switch (this.ShoppingCartControl.CheckoutProcessType) { case CheckoutProcessEnum.LiveSite: // Here comes the code which will be run only // when it is a checkout process on the live site break;
case CheckoutProcessEnum.CMSDeskOrder: // Here comes the code which will be run only // when it is a checkout process in the section CMSDesk/Tools/E-commerce/Orders break;
default: // Here comes the code which will be run in all other cases break; } |
The following example shows a simple checkout process step definition. The step displays the total price and an editable field to insert a customer comment. After the Next button is clicked, the editable field is checked for emptiness. If it is not empty, the customer comment is saved and the shopping cart data is updated. Otherwise, an appropriate error message is displayed. If the customer is a member of the VipCustomers role, an extra step with an additional form for VIP customers is loaded (MyVipStep.ascx). The Back button action is not overridden.
|
Please note
If you installed the Kentico CMS project as a web application, you need to rename the CodeFile property on the first line to Codebehind for the code example to be functional.
|
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="MyStep.ascx.cs" Inherits="MyStep" %> <asp:Label ID="lblError" runat="server" EnableViewState="false" Visible="false"></asp:Label> <table> <tr> <td><asp:Label ID="lblTotalPrice" runat="server" /></td> <td><asp:Label ID="lblTotalPriceValue" runat="server" /></td> </tr> <tr> <td><asp:Label ID="lblComment" runat="server" /></td> <td><asp:TextBox ID="txtComment" runat="server" TextMode="MultiLine" Rows="3" /></td> </tr> </table> |
[C#]
using System; using System.Data; using System.Configuration; using System.Collections; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls;
using CMS.GlobalHelper; using CMS.Ecommerce; using CMS.EcommerceProvider;
public partial class MyStep : ShoppingCartStep { protected void Page_Load(object sender, EventArgs e) { // Initialize labels lblTotalPrice.Text = ResHelper.GetString("MyStep.TotalPrice"); lblComment.Text = ResHelper.GetString("MyStep.Comment");
// Display rounded and formatted total price lblTotalPriceValue.Text = CurrencyInfoProvider.GetFormattedPrice(ShoppingCart.RoundedTotalPrice, ShoppingCart.Currency);
if (!ShoppingCartControl.IsCurrentStepPostBack) { // Load customer comment txtComment.Text = ValidationHelper.GetString(ShoppingCart.ShoppingCartCustomData["CustomerComment"], String.Empty); } }
/// <summary> /// Validates current step data. /// </summary> /// <returns></returns> public override bool IsValid() { // Check customer comment for emptiness if (txtComment.Text.Trim() == "") { // Display error message lblError.Text = ResHelper.GetString("MyStep.Error.CommentMissing"); lblError.Visible = true;
// Data are not correct - customer comment missing return false; } else { // Data are correct return true; } }
/// <summary> /// Process current step data /// </summary> /// <returns></returns> public override bool ProcessStep() { // Update shopping cart with customer comment ShoppingCart.ShoppingCartCustomData["CustomerComment"] = txtComment.Text.Trim();
try { // Update shopping cart in database ShoppingCartInfoProvider.SetShoppingCartInfo(ShoppingCart);
// Current step data were processed and saved succesfully return true; } catch { // Display error message lblError.Text = ResHelper.GetString("MyStep.Error.ShoppingCartUpdate"); lblError.Visible = true;
// Current step data update failed return false; } }
/// <summary> /// Action after the "Next button" is clicked /// </summary> public override void ButtonNextClickAction() { // If customer is registered and is a member of role "VipCustomers" if ((ShoppingCart.User != null) && (ShoppingCart.User.IsInRole("VipCustomers", ShoppingCart.SiteName))) { if (IsValid() && ProcessStep()) { try { // Load extra step for VIP customers which is not included // in standard checkout process definition ShoppingCartStep ctrl = (ShoppingCartStep)Page.LoadControl("~/CMSEcommerce/ShoppingCart/MyVipStep.ascx"); ShoppingCartControl.LoadStep(ctrl);
// Note: Current step index is not increased } catch { // Error while loading extra step control -> Do standard action base.ButtonNextClickAction(); } } } else { // Do standard action (validate step data, process step data, load next step) base.ButtonNextClickAction(); } } } |
This is an external checkout process step, which is not included in a standard checkout process definition. It is loaded only when the current customer is a member of the VipCustomers role. However, you will need to use your own condition to load your external steps. There is no data validation (i.e. the Vip customer comment can be empty). Neither the Back button action nor the Next button one is overridden, which means that the standard methods are called after the Back button or the Next button is clicked.
|
Please note
If you installed the Kentico CMS project as a web application, you need to rename the CodeFile property on the first line to Codebehind for the code example to be functional.
|
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="MyVipStep.ascx.cs" Inherits="MyVipStep" %> <asp:Label ID="lblError" runat="server" EnableViewState="false" Visible="false"></asp:Label> <asp:Label ID="lblComment" runat="server" /> <asp:TextBox ID="txtComment" runat="server" TextMode="MultiLine" Rows="3" /> |
[C#]
using System; using System.Data; using System.Configuration; using System.Collections; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls;
using CMS.GlobalHelper; using CMS.Ecommerce; using CMS.EcommerceProvider;
public partial class MyVipStep : ShoppingCartStep { protected void Page_Load(object sender, EventArgs e) { // Initialize label lblComment.Text = ResHelper.GetString("MyVipStep.Comment");
if (!ShoppingCartControl.IsCurrentStepPostBack) { // Load VIP customer extra comment txtComment.Text = ValidationHelper.GetString(ShoppingCart.ShoppingCartCustomData["VipComment"], String.Empty); } }
/// <summary> /// Process current step data /// </summary> /// <returns></returns> public override bool ProcessStep() { // Update shopping cart with VIP customer extra comment ShoppingCart.ShoppingCartCustomData["VipComment"] = txtComment.Text.Trim();
try { // Update shopping cart in database ShoppingCartInfoProvider.SetShoppingCartInfo(ShoppingCart);
// Current step data were processed and saved succesfully return true; } catch { // Display error message lblError.Text = ResHelper.GetString("MyStep.Error.ShoppingCartUpdate"); lblError.Visible = true;
// Current step data update failed return false; } } } |
Notice that data of all steps (including Kentico CMS standard shopping cart steps) is always processed by itself, not by the parent shopping cart control. It means that if you reorder the standard checkout process steps, you can experience strange behavior because of missing information or omitting some important action.
For example, if you move the Order preview step in the standard checkout process definition for the live site before the Select billing and shipping address and the Select payment and shipping methods steps, some order preview data will be missing (billing and shipping addresses, payment method and shipping option) because it has not been entered yet. What is more, the data entered during the following two steps (i.e. the Select billing and shipping address step and the Select payment and shipping methods step) will not be saved.
This occurs because the order is saved after the Next button of the Order preview step is clicked, while the two above mentioned steps include completely different actions after their Next buttons are clicked.