| Shopping Cart/E-Commerce Tutorial |
| Using Arrays & Structures -Part 3 of 3- |
| By Michael Bamberger |
| Tutorial Index | |
| # | Section Title |
| 1. | Database Layout |
| 2. | Member Sign Up |
| 3. | *Main Shopping Cart Page |
| 4. | *Product Display - "Add to Cart" |
| 5. | Checkout - Order Processing |
| 6. | Supplemental Coding - Navigation Include |
| Section 5 - Checkout - Order Processing |
<table cellpadding="3" cellspacing="0" border="0" align="center" width="100%">
<tr>
<td valign="top">
<div>Customer Sign In</div>
<form name="CustSignIn" action="checkout_signin.cfm" method="post">
<table width="350" border="0" align="center" cellspacing="0" cellpadding="5" style="font-weight:bold;border:2px
solid #DDDDDD;">
<tr>
<td><b>E-mail Address:</b></td>
<td><input type="text" name="username" value="" size="25"></td>
</tr>
<tr>
<td><b>Password:</b></td>
<td><input type="password" name="password" value="" size="25"></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value="Sign
In"></td>
</tr>
</table>
</form>
</td>
<td>
<div>New Customer Sign Up</div>
*****SAME FORM AS ABOVE SIGN UP PAGE*****
</td>
</tr>
</table>
<cfelse>
<script>
self.location="confirmorder.cfm";
</script>
</cfif>
<cfquery name="logMem" datasource="test">
SELECT *
FROM LCustomers
WHERE username = '#session.username#'
</cfquery>
<cfinclude template="ordertotals.cfm">
<div>Order Confirmation</div>
<div style="font-size:8pt;">
Your order information is outlined below. To process this order, please click
the button below. The expenses will be charged to the credit card listed on
file.<br>
<form name="ConfirmOrder" action="processorder.cfm" method="post">
<input type="submit" value="Click Here to Process This Order">
</form>
</div>
<cfoutput>
<table width="320" border="0" cellpadding="3" cellspacing="0" style="border:2px
solid ##DDDDDD;font-size:8pt;">
<tr>
<td colspan="2" style="font-size:11pt;font-weight:bold;background-color:##DDDDDD;">Customer
Information</td>
</tr>
<tr style="background-color:##FFFFFF;">
<td valign="top"><b>Customer Name</b>:</td><td>#logMem.c_fname#
#logMem.c_lname#</td>
</tr>
<tr style="background-color:##FFFFFF;">
<td valign="top"><b>Address</b>:</td><td>#logMem.c_street#<br>#logMem.c_city#,
#logMem.c_state# #logMem.c_zip#</td>
</tr>
<tr style="background-color:##FFFFFF;">
<td valign="top"><b>Credit Card:</b></td><td>#logMem.cc_type#<br>xxxx-xxxx-xxxx-#Right(logMem.cc_num,4)#</td>
</tr>
</table>
</cfoutput><br>
<table width="90%" border="0" align="center" cellpadding="2" cellspacing="0" style="border:2px
solid #DDDDDD;">
<tr>
<td colspan="6" style="font-size:11pt;font-weight:bold;background-color:#DDDDDD;">Order
Breakdown</td>
</tr>
<tr>
<td><b>#</b></td><td><b>Product</b></td><td><b>Size</b></td><td><b>Unit
Price</b></td><td><b>Quantity</b></td><td><b>Total</b></td>
</tr>
<cfoutput>
<cfloop from="1" to="#arrayLen(session.shoppingcart)#" index="i">
<cfset total[i] = session.shoppingcart[i].price * session.shoppingcart[i].quantity>
<tr style="background-color:##<cfif i MOD 2>EFEFEF<cfelse>FFFFFF</cfif>;">
<td>#i#</td>
<td>#session.shoppingcart[i].name#</td>
<td>#session.shoppingcart[i].size#</td>
<td>#DollarFormat(session.shoppingcart[i].price)#</td>
<td>#session.shoppingcart[i].quantity#</td>
<td>#DollarFormat(total[i])#</td>
</tr>
</cfloop>
</cfoutput>
<tr style="background-color:#DDDDDD;font-size:9pt;">
<td colspan="6" align="right">
Subtotal: <cfoutput>#DollarFormat(variables.subtotal)#</cfoutput><br>
<cfif logMem.c_state EQ "FL">
Tax: <cfoutput>#DollarFormat(variables.tax)#</cfoutput>
</cfif>
Shipping:<cfoutput>#DollarFormat(variables.shipping)#</cfoutput>
<b>Order Total: <cfoutput>#DollarFormat(variables.totalprice)#</cfoutput></b></td>
</tr>
</table><p>
Total Items in Order: <cfoutput>#variables.totalItems#</cfoutput><br>
<b>Order Total: <cfoutput>#DollarFormat(variables.totalprice)#</cfoutput></b>
</cfif>
</cfif>
This page is slightly complex, but not too bad once we look into it. We start
off doing some error checking. First, we check to see if the user is logged
in. We don't want someone who hasn't logged in stumbling upon this page.
You can
use this snippet on all of the order processing pages. Then, we check to make
sure we have all the credit card information we need after making a database
query to get the session user information. If we don't, the user cannot move
forward and process their order. If the user passes all the tests, they can
then move on to the next part of the coding.
We then do a virutally identical loop to the one in our cart.cfm page. We find and display all of the products in the user's shopping cart. Next, several variables are displayed regarding the order: the subtotal, tax, shipping, and the combined total. Now, you may be wondering, where do all these variables come from? Well, if you notice the <cfinclude> tag, that is your answer. In the page ordettotals.cfm we create several variables that we need on this page and the processing page subsequent to this one. Below is the ordertotals page:
<cfset totalprice = 0>
<cfloop from="1" to="#arrayLen(session.shoppingcart)#" index="i">
<cfset totalprice = variables.totalprice + total[i]>
<cfset subtotal = variables.totalprice>
</cfloop>
<cfset shipping = variables.totalprice * .1>
<cfif logMem.c_state EQ "FL">
<cfset tax = variables.totalprice * .06>
<cfset fulltotal = variables.totalprice + variables.shipping + variables.tax>
<cfset totalprice = variables.fulltotal>
<cfelse>
<cfset fulltotal = variables.totalprice + variables.shipping>
<cfset totalprice = variables.fulltotal>
</cfif>
<cfset totalItems = 0>
<cfloop from="1" to="#arrayLen(session.shoppingcart)#" index="i">
<cfset totalItems = variables.totalItems + session.shoppingcart[i].quantity>
</cfloop>
We set a few variables on this page: total price per item, total
price, shipping
price, tax (if applicable), and the
fulltotal.
Like in our cart, we loop through to find the price of each item. Then, like
before, we add up the prices to get our subtotal. Next, we figure out the shipping.
Here, it is configured as 10%. This page is helpful because if you ever want
to change the shipping right, the only place you have to change it is here.
A commonly disregarded item is the tax. On the Internet, the only time you ahev to charge tax is when it is an intrastate purchase (within the selling state). In this case, the homestate is Florida (make sure you use a select box in the sign up page to guarantee the state is input as "FL" to maintain consistency. In Florida, sales tax is 6%. Depending on whether or not the customer is in our home state, it sets the next 2 varibales: totalprice, and fulltotal. Full total is the total item price + the shipping price + the tax price (if necessary). You see the cfif tag is used to determine whether or not tax is to be added.
Lastly, we figure out the total items in the cart. You should recognize this code from the cart.cfm page.
Now, the last, and possibly most important part - processing the order.
<cfinclude template="ordertotals.cfm">
<!--- Insert into Orders Database --->
<cfquery name="addOrder" datasource="test">
INSERT INTO LOrders (o_cust, o_total, o_items)
VALUES ('#logMem.c_id#','#variables.totalprice#', '<cfoutput><cfloop
from="1" to="#arrayLen(session.shoppingcart)#" index="i"><cfif
i eq arrayLen(session.shoppingcart)>#session.shoppingcart[i].name#<cfelse>#session.shoppingcart[i].name#, </cfif></cfloop></cfoutput>')
</cfquery>
<!--- E-mail order to Administration --->
<cfmail
from="order@yoursite.com"
to="CustomerService@yoursite.com"
subject="YourSite.com - Order" type="html">
<html>
<head>
<style type="text/css">
Body, table, td {font-family:Arial;font-size:9pt;color:##000000;}
</style>
</head>
<body>
<div>Order To Be Processed</div>
<table width="350" border="0" cellpadding="3" cellspacing="0" style="border:2px
solid ##DDDDDD;font-size:8pt;">
<tr style="background-color:##EFEFEF;">
<td><b>Date/Time:</b></td><td>#DateFormat(now(),
'mm/dd/yyyy')# #TimeFormat(Now(), 'hh:mm tt')#</td>
</tr>
<tr style="background-color:##FFFFFF;">
<td valign="top"><b>Customer Name</b>:</td><td>#logMem.c_fname#
#logMem.c_lname#</td>
</tr>
<tr style="background-color:##EFEFEF;">
<td valign="top"><b>Address</b>:</td><td>#logMem.c_street#<br>#logMem.c_city#,
#logMem.c_state# #logMem.c_zip#</td>
</tr>
<tr style="background-color:##FFFFFF;">
<td valign="top"><b>Credit Card:<br>Number:<br>CVV2:<br>Expiration:</b></td>
<td>#logMem.cc_type#<br>#logMem.cc_num#<br>#logMem.cc_verify#<br>#logMem.cc_expir_m#/#logMem.cc_expir_y#</td>
</tr>
</table><br><br>
<table width="90%" border="0" align="center" cellpadding="2" cellspacing="0" style="border:2px
solid ##DDDDDD;">
<tr>
<td colspan="6" style="font-size:11pt;font-weight:bold;background-color:##DDDDDD;">Order
Breakdown</td>
</tr>
<tr>
<td><b>Item</b></td><td><b>Product</b></td><td><b>Size</b></td><td><b>Unit
Price</b></td><td><b>Quantity</b></td><td><b>Total</b></td>
</tr>
<cfloop from="1" to="#arrayLen(session.shoppingcart)#" index="i">
<cfset total[i] = session.shoppingcart[i].price * session.shoppingcart[i].quantity>
<tr style="background-color:##<cfif i MOD 2>EFEFEF<cfelse>FFFFFF</cfif>;">
<td>#session.shoppingcart[i].productID#</td>
<td>#session.shoppingcart[i].name#</td>
<td>#session.shoppingcart[i].size#</td>
<td>#DollarFormat(session.shoppingcart[i].price)#</td>
<td>#session.shoppingcart[i].quantity#</td>
<td>#DollarFormat(total[i])#</td>
</tr>
</cfloop>
<tr>
<td colspan="6" style="font-size:11pt;font-weight:bold;background-color:##DDDDDD;" align="right">
<div style="font-size:9pt;">
<b>Subtotal</b>: #DollarFormat(variables.subtotal)#<br>
<cfif logMem.c_state EQ "FL">
Tax: #DollarFormat(variables.tax)#<br>
</cfif>
<b>Shipping</b>: #DollarFormat(variables.shipping)#</div>
Order Total: #DollarFormat(variables.totalprice)#</td>
</tr>
</table>
</body>
</html>
</cfmail>
<!--- E-mail order to customer --->
<cfmail
from="order@yoursite.com"
to="#logMem.c_email#"
subject="YourSite.com - Thank You for Your Order" type="html">
********SIMILAR E-MAIL BODY TO ABOVE & BELOW (DO NOT USE CFOUTPUT TAGS)********
</cfmail>
<!--- Show Order Information page to Customer --->
<div>Order Information</div>
Your order has been processed. This information has been e-mailed to <b><cfoutput
query="logMem">#logMem.c_email#</cfoutput></b>.
<br>Please print this page for your records.<p>
<table width="250">
<tr>
<td valign="top"><b>Customer Name</b>:</td><td><cfoutput
query="logMem">#logMem.c_fname# #logMem.c_lname#</cfoutput></td>
</tr>
<tr>
<td valign="top"><b>Address</b>:</td><td><cfoutput
query="logMem">#logMem.c_street#<br>#logMem.c_city#, #logMem.c_state#
#logMem.c_zip#</cfoutput></td>
</tr>
<tr>
<td valign="top"><b>Credit Card:</b></td><td><cfoutput
query="logMem">#logMem.cc_type#<br>xxxx-xxxx-xxxx-#Right(logMem.cc_num,4)#</cfoutput></td>
</tr>
</table><br><br>
<table width="90%" border="0" align="center" cellpadding="2" cellspacing="0" style="border:2px
solid #DDDDDD;">
<tr>
<td><b>#</b></td><td><b>Product</b></td><td><b>Size</b></td><td><b>Unit
Price</b></td><td><b>Quantity</b></td><td><b>Total</b></td>
</tr>
<cfoutput>
<cfloop from="1" to="#arrayLen(session.shoppingcart)#" index="i">
<cfset total[i] = session.shoppingcart[i].price * session.shoppingcart[i].quantity>
<tr style="background-color:##<cfif i MOD 2>EFEFEF<cfelse>FFFFFF</cfif>;">
<td>#i#</td>
<td>#session.shoppingcart[i].name#</td>
<td>#session.shoppingcart[i].size#</td>
<td>#DollarFormat(session.shoppingcart[i].price)#</td>
<td>#session.shoppingcart[i].quantity#</td>
<td>#DollarFormat(total[i])#</td>
</tr>
</cfloop>
</cfoutput>
<tr style="background-color:#DDDDDD;font-size:11pt;">
<td colspan="6" align="right">
<div style="font-size:9pt;">
Subtotal: <cfoutput>#DollarFormat(variables.subtotal)#</cfoutput><br>
<cfif logMem.c_state EQ "FL">
Tax: <cfoutput>#DollarFormat(variables.tax)#</cfoutput><br>
</cfif>
Shipping: <cfoutput>#DollarFormat(variables.shipping)#</cfoutput></div>
<b>Order Total: <cfoutput>#DollarFormat(variables.fulltotal)#</cfoutput></b></td>
</tr>
</table><br>
<div align="left">
<a href="Javascript:window.print();">Print This Page</a></div>
<cfscript>
ArrayClear(session.shoppingcart);
</cfscript>
</cfif>
<cfquery name="addOrder" datasource="test">
INSERT INTO LOrders (o_cust, o_total, o_items)
VALUES ('#logMem.c_id#','#variables.totalprice#', '<cfoutput><cfloop
from="1" to="#arrayLen(session.shoppingcart)#" index="i"><cfif
i eq arrayLen(session.shoppingcart)>#session.shoppingcart[i].name#<cfelse>#session.shoppingcart[i].name#, </cfif></cfloop></cfoutput>')
</cfquery>
Now we add our order into our database table. This should all be familiar to you, with perhaps the exception of the loop. We look over our shopping cart one more time. This time, we output our item names as a comma delimited list. Look closely to understand precisely how the list is created.
At this point, we just have 3 things left to do: send the e-mail to ourselves to process it, send the e-mail to our customer as confirmation, and show the order confirmation page to the customer on our site after they process their order. There is nothing new in the code with the exception of the Right() function. This simply gets the 4 last digits of the customer's credit card number and displays it to them with Xs for the first 11 digits.
Our order information table is formatted just like on the cart.cfm page and the confirmorder.cfm page. By this point, you should have that loop over our shopping cart array virtually memorized. You see we again show all of our variables back to the user and input them in our e-mails. In your e-mail to your customer, use the Right() function for the credit card, just for security.
Sending an e-mail is of course just one way to process your order. This is assuming each order is processed by hand. You can of course use all differenet kinds of processing (online merchant processing, PayPal, sending the order via FTP to another computer). No matter what you do, it's all the same concept and you can use the same output coding.
Well, that is all there is to an e-commerce system with a fully functional
shopping cart. Below, you will find some supplemental coding as well as
quick snippets so you can quickly refer back to this page to get those
coding bits.
| Section 6 - Supplemental Coding - Navigation Include |
Here you can find some useful and some necessary snippets and page coding information.
The first thing is the Application.cfm page. Our whole shopping cart and user log in systems are dependent on the application and session variables, so this is our Application.cfm file:
<cfparam name="session.allowin" default="false">
Easy and painless. Just a basic Application.cfm page with session management. If you need to understand this further, view Pablo's User Area tutorial.