The online ordering system's information gathering takes place over three pages with a fourth page at the end displaying a final summary of the order which the user can accept or go back and alter if they are not happy. At some point in the checkout process, prior to any credit card details being transmitted to the server, we would normally switch to a secure connection using Secure Sockets Layer (SSL) which encrypts all data before it's sent to the web server.
The first of the four screens splits the main frame into two more frames
- The top frame contains the 'welcome to the online ordering system' blurb and buttons to go to the next screen.
- The bottom frame contains our shopping basket and serves the dual purpose of confirming what the user is about to buy and giving them an opportunity to change their mind about the quantities.
First we need to create the frameset page and save it as checkout_frame.htm
<HTML> <FRAMESET FRAMEBORDER=0 BORDER=0 ROWS="140,*"> <FRAME SCROLLING="NO" SRC="checkout.asp" FRAMEBORDER="NO" NAME="fraCheckoutTop" NORESIZE> <FRAME SCROLLING="AUTO" SRC="checkoutbasket.asp" FRAMEBORDER="NO" NAME="fraCheckoutBottom" NORESIZE> </FRAMESET> </HTML>
Now lets create Checkout.asp, which is displayed in the top
part of the frameset. For the cmdNext button a function has been created for
the onClick event. Here we check that there is still something left in the basket
to buy (after user changes to the basket's contents) using the shopping basket
in the lower frame. If there is still something in the basket then we continue
to the next page.
The cmdBrowse button gives the shopper another opportunity to shop themselves
penniless by going back to the category list page. The JavaScript has been included
in the event definition itself as it's just one line so there's little point
creating a separate function.
<!--#include file="ServerSideGlobalDef.inc"--> <HTML> <HEAD> <SCRIPT language='javascript'> function cmdNext_onClick() { // if as a result of changes to the basket it's empty, inform user if (parent.parent.getCookie("Basket") == "") { alert("Your basket is empty - click Continue Shopping to fill it _ up with our excellent bargains"); } else { // go to page 2 of checkout process this.parent.location.href="personaldetails.asp"; } return true; } </SCRIPT> </HEAD> <BODY> <CENTER> <FONT FACE="Comic Sans MS" SIZE="3" color="Navy"> Welcome to our secure online ordering system. Your current basket contents are listed below. <FORM> Once you're happy with its contents click <INPUT NAME="cmdNext" TYPE="button" VALUE="Next" ALIGN=top onClick="cmdNext_onClick()"> to continue <BR> or click <INPUT NAME="cmdBrowse" TYPE="button" VALUE="Continue Shopping" ALIGN=top onClick="parent.location.href='home.asp'"> to return to the main screen. </FORM> </FONT> </CENTER> </BODY> </HTML>
Save the page as Checkout.asp
The final page in the checkout frameset is the shopping basket. It's very similar
to the main shopping basket and uses the same code by incorporating the Basket.inc
file, which does most of the work of displaying the basket. bReadOnly has been
set to false so that the user can update the contents of the basket.
<!--#include file="ServerSideGlobalDef.inc"--> <% bReadOnly = false; %> <HTML> <HEAD> </HEAD> <BODY> <FORM METHOD=POST ACTION="UpdateQty.asp" NAME="frmItems" onSubmit="return checkQtys(this)"> <!--#include file="basket.inc"--> </FORM> </BODY> </HTML>
Save the page as CheckoutBasket.asp
Obtaining the User's Details
The next two pages obtain the necessary information about the customer to process
their order.
The first page obtains information regarding name and delivery
address. We also obtain their e-mail address as we use that later to send them
conformation of their order.
In between the <HEAD> tags we include a new include file - checkout_validate.inc - into this page which we'll create shortly. As its name suggests, this file contains a number of client-side JavaScript functions which will be used to validate the form's content when the user clicks the submit button. We have added an event handler for the form's onSubmit event which calls one of the validate functions inside checkout_validate.inc. The value returned by this function will prove important: if false is returned then the form's submit action will be cancelled. Also note that in the onSubmit event handler we call checkCompleted and pass it one argument - this, which in this context refers to the element that is the cause of the event firing. Here, it is the form itself.
<% @LANGUAGE="JScript" %> <HTML> <HEAD> <!--#include file="checkout_validate.inc"--> </HEAD> <BODY> <CENTER> <FORM METHOD=POST ACTION="checkoutcredit.asp" onSubmit="return checkCompleted(this)">
The remainder of the page consists of the form elements contained
within a table for formatting. At the top is a group of radio buttons for selecting
the customer's title. When the form is submitted only the value of the radio
button that has been selected by the user will be sent.
The remainder of the form consists of input boxes, each of which has its maxlength
property set to match the maximum size of the relevant database field which acts
as a basic form of validation. At least we know the user has not entered a string
value length greater than we can store. The problem comes if we change the size
of the database fields, as we must remember to update the page. This problem
could be overcome by building the page dynamically using ASP script. Using ADO
we could obtain the correct sizes of each field and populate the maxlengths on
the basis of this information. This would increase maintainability but at the
expense of scalability as server processing load would be increased significantly.
Here I have gone for scalability by having static values.
The last input element in the form is a text box for the customer's country.
It would help ensure valid data if we changed this to a select element with a
drop down list of countries rather than a text box. For this example I kept it
as a text box to save typing a long list of countries!
<FONT FACE="Comic Sans MS" SIZE="3" color="Navy"> Please enter your NAME, address and e-mail address below.<BR> </FONT> <TABLE> <TR> <TD><FONT FACE="Comic Sans MS" SIZE="2">Title</FONT></TD> <TD> <FONT FACE="Comic Sans MS" SIZE="2"> Mr<INPUT NAME="radTitle" TYPE="radio" VALUE="Mr"> Mrs<INPUT NAME="radTitle" TYPE="radio" VALUE="Mrs"> Miss<INPUT NAME="radTitle" TYPE="radio" VALUE="Miss"> Ms.<INPUT NAME="radTitle" TYPE="radio" VALUE="Ms."> Dr.<INPUT NAME="radTitle" TYPE="radio" VALUE="Dr."> </FONT> </TD> </TR> <TR> <TD><FONT FACE="Comic Sans MS" SIZE="2">First Name</FONT> <TD><INPUT TYPE="Text" NAME="txtFirstName" maxlength="50"> </TR> <TR> <TD><FONT FACE="Comic Sans MS" SIZE="2">Last Name</FONT> <TD><INPUT TYPE="Text" NAME="txtLastName" maxlength="50"> </TR> <TR> <TD><FONT FACE="Comic Sans MS" SIZE="2">E-mail Address</FONT> <TD><INPUT TYPE="Text" NAME="txtEmail" maxlength="75"> </TR> <TR> <TD><FONT FACE="Comic Sans MS" SIZE="2">Street</FONT> <TD><INPUT TYPE="Text" NAME="txtStreet" maxlength="75"> </TR> <TR> <TD><FONT FACE="Comic Sans MS" SIZE="2">City</FONT> <TD><INPUT TYPE="Text" NAME="txtCity" maxlength="50"> </TR> <TR> <TD><FONT FACE="Comic Sans MS" SIZE="2">County/State</FONT> <TD><INPUT TYPE="Text" NAME="txtLocality" maxlength="50"> </TR> <TR> <TD><FONT FACE="Comic Sans MS" SIZE="2">Post/Zip Code</FONT> <TD><INPUT TYPE="Text" NAME="txtPostCode" maxlength="15"> </TR> <TR> <TD><FONT FACE="Comic Sans MS" SIZE="2">Country</FONT> <TD><INPUT TYPE="Text" NAME="txtCountry" maxlength="50"> </TR> <TR> <TD COLSPAN=2> <INPUT TYPE="reset" NAME="cmdReset" VALUE="Clear form"> <INPUT TYPE="button" NAME="cmdPrevious" VALUE=" Back " onClick="window.location.href='checkout_frame.htm'"> <INPUT TYPE="submit" NAME="cmdSubmit" VALUE="Continue"> </TD> </TR> </TABLE> </FORM> </CENTER> </BODY> </HTML>
Save the page as PersonalDetails.asp
The final page, as far as inputting user details is concerned,
is CheckoutCredit.asp which gets that all important information we need to get
our hands on the user's money!
It's smaller in terms of number of visible page elements, but more complex in
terms of validation as we have a radio group, a couple of select elements with
dates that need validating and a text box which must contain a valid number only.
Again, all of the validation functions are in the checkout_validate.inc file
we include inside the head of this page. Because there is more to check in this
form than on the personal details page form, a separate function has been created
to handle the onSubmit event. Using functions defined in checkout_validate.inc,
it checks that the form is fully completed, the credit card number actually contains
numbers and that the card expiry date is valid. If any of these checks fails
then the form submit event is cancelled by returning false. As in the previous
page's onSubmit, we are passing a reference to the form as a parameter of the
function handling the onSubmit.
<% @LANGUAGE="JScript" %> <HTML> <HEAD> <!--#include file="checkout_validate.inc"--> <SCRIPT LANGUAGE="JavaScript"> function frmCredit_onsubmit(theForm) { // Check form fully filled in if (checkCompleted(theForm) == false) { return false; } // Remove everything except numbers from CardNo theForm.txtCardNo.VALUE = numericOnly(theForm.txtCardNo.VALUE); // If removing all but numbers results in nothing then alert user if (theForm.txtCardNo.VALUE == "") { alert("Your have entered your credit card number incorrectly"); theForm.txtCardNo.focus(); return false; } // check credit card expiry date is valid if (checkCardExpDate(theForm.cboExpMonth,theForm.cboExpYear) == false) { return false; } } </SCRIPT> </HEAD> <BODY> <FONT FACE="Comic Sans MS" SIZE="3" color="Navy"> <P align="center"> Please enter your credit card details below. </P> </FONT> <FORM METHOD=POST NAME="frmCredit" ACTION="checkoutconfirm.asp" onSubmit="return frmCredit_onsubmit(this)">
The next form elements are hidden input boxes that we populate using ASP script with the values the user submitted in the personal details page. This is how we maintain state over the course of the four pages involved in obtaining customer details except for the items ordered which remain in the basket cookie until the very last page.
<INPUT TYPE="HIDDEN" NAME="txtTitle" VALUE="<%=Request.Form("radTitle")%>"> <INPUT TYPE="HIDDEN" NAME="txtFirstName" VALUE="<%=Request.Form("txtFirstName")%>"> <INPUT TYPE="HIDDEN" NAME="txtLastName" VALUE="<%=Request.Form("txtLastName")%>"> <INPUT TYPE="HIDDEN" NAME="txtEmail" VALUE="<%=Request.Form("txtEmail")%>"> <INPUT TYPE="HIDDEN" NAME="txtStreet" VALUE="<%=Request.Form("txtStreet")%>"> <INPUT TYPE="HIDDEN" NAME="txtCity" VALUE="<%=Request.Form("txtCity")%>"> <INPUT TYPE="HIDDEN" NAME="txtLocality" VALUE="<%=Request.Form("txtLocality")%>"> <INPUT TYPE="HIDDEN" NAME="txtPostCode" VALUE="<%=Request.Form("txtPostCode")%>"> <INPUT TYPE="HIDDEN" NAME="txtCountry" VALUE="<%=Request.Form("txtCountry")%>">
The remainder of the page consists of the form elements into which the customers enter their credit card details. Card expiry date has been based upon two drop down select elements: one for the month and one for the year. This ensures that the user can enter only valid values, which is particularly important for dates as there are so many variations possible. For example, if we just used a text box, 11/1999, 11-99,11 01 are all valid but would cause us headaches if we had to deal with each possibility.
Comments