{exp:store:checkout}
<!-- checkout form -->
{/exp:store:checkout}
This tag handles the entire checkout process, from updating item quantities, to billing and shipping details, through to submitting and paying for the order. It is extremely flexible, and you can template the process however you like - either as a single, or as a multi step process. You can also choose which step of the process will require users to log in, or simply allow anonymous orders.
Think of the user’s cart as being like a session. With Expresso Store, your visitors add items to their cart. When they get to the checkout, they update their cart with billing and shipping details, and the cart totals are recalculated to reflect their relevant tax and shipping costs.
When the user reaches the final step of your checkout, the cart is converted in to an order. At this point, if any payment details were submitted on the final page of the checkout, these are sent to the relevant payment gateway, and the user will be taken to your payment success (or failure) page.
The next step of a multi step checkout. If the user clicks an input button with name=”next”, and current form validates, the user will be redirected to this location.
{exp:store:checkout next="checkout/confirm"}
<input type="submit" name="next" value="Confirm Order" />
{/exp:store:checkout}
Where to redirect the user to once the order is submitted. You only need to add this parameter to the last step of your checkout process. The order will only be submitted when the user clicks an input button with name=”submit”, this is to differentiate between other buttons in the form.
Optionally, you may redirect to an order-specific confirmation page (this is the normal setup). The variables ORDER_ID and ORDER_HASH can be used in this parameter to customize your return location.
{exp:store:checkout return="order/ORDER_HASH"}
<input type="submit" name="submit" value="Place Order" />
{/exp:store:checkout}
Alternatively, since 1.3.0 you may name your submit button “commit”. This allows compatibility when using javascript to interact with your form on certain browsers.
Set an id attribute on the generated HTML form.
Set a name attribute on the generated HTML form.
Set a class attribute on the generated HTML form.
Set the payment method of the current cart. This can also be specified via a hidden input or select drop-down if you would like to give the user a choice of payment methods.
If set to yes
, create a member account for this user when the order is complete. This can also be specified as a form input field.
If set to yes
, ensures the current page is displayed over a secure SSL (HTTPS) connection. If the page was not displayed over HTTPS, the user is redirected to a secure version. The current form action is also submitted over HTTPS. If you accept inline credit card details on the final page of the checkout, this option must be set. If you configure “Require SSL connection for checkout and order tags” in the Store settings, all tags will have this option by default.
Specify a pipe-separated list of required fields. All order fields can be made required using this tag. In addition, a shorthand syntax is available if both billing and shipping details are required. For example, the following parameter:
{exp:store:checkout require="name|address1|address2|region|country|postcode"}
is equivalent to typing:
{exp:store:checkout require="billing_name|billing_address1|billing_address2|billing_region|billing_country|billing_postcode|
shipping_name|shipping_address1|shipping_address2|shipping_region|shipping_country|shipping_postcode"}
Much nicer, right?
As well as using the require=”field_name” parameter, the longer SafeCracker-style syntax is also available. For each field, any of the CodeIgniter Form Validation Rules may be specified. If this syntax is used in addition to the require=”field_name” parameter, both will apply. Note that the order_email field is already run through the valid_email rule, you don’t need to manually specify it.
rules:billing_name="required"
rules:billing_phone="numeric"
rules:billing_postcode="required|min_length[5]|max_length[5]"
By default, validation errors are displayed using the ugly standard ExpressionEngine error template. To alleviate this issue, add error_handling=”inline” to your template. Field-specific error messages will then become available in the form {error:field_name}, which you can add to your template code in appropriate places. If you are having trouble with your form not submitting, the first thing you should try is removing the error_handling=”inline” parameter from your template, as often this is caused by validation errors which you have forgotten to display error messages for.
You can optionally specify HTML to wrap around your inline error messages. This should be specified as two pipe-separated elements. If do not have error_handling=”inline” on your checkout tag, this parameter will have no effect.
error_delimiters='<span class="notice">|</span>'
When set to yes
, this disables any automatic javascript output by the tag.
Loop through the order items. Inside the items loop, most product variables are available. All prices may be appended with _val to display the unformatted value, _inc_tax to display the tax-inclusive price, and _inc_tax_val if you want to get really fancy.
{items}
<!-- item details -->
{/items}
Inside the {items} loop, you can use the following variables.
The entry id of this item. If you need to access other custom fields associated with this item, you can feed the entry id into a channel entries loop:
{items}
{exp:channel:entries entry_id="{entry_id}"}
{my_custom_field}
{/exp:channel:entries}
{/items}
The product SKU.
The product entry title.
The product entry URL title.
The applicable price of the product, (equal to the sale price if the product is on sale, otherwise the regular price).
The regular price of the product, regardless of whether it is currently on sale.
The sale price of the product, regardless of whether it is currently on sale.
True if the product is currently on sale.
The applicable handling surcharge (if the user has purchased multiple items, the handling surcharge will be multiplied by the item quantity).
True if the product has free shipping selected.
Displays the selected item modifiers for the product. Inside the modifiers loop, you can use the following variables:
The dollar discount value if the product is on sale.
The percentage discount value if the product is on sale, rounded to the nearest whole number.
The number of this product the user has in their cart.
The item price multiplied by the item quantity.
The total tax applicable to this item.
The total for this item, including tax and any handling charges.
To update quantities of existing line items in the cart, you must template inputs on your checkout form, inside the {items}
loop. Normally you would display this in a table layout.
The special {key}
variable is available inside the {items}
loop to use as an index for your input name. This is required, as it tells Store which line item you want to update the quantity of.
<table>
{items}
<tr>
<td>{title}</td>
<td>{price}</td>
<td>
<input name="items[{key}][item_qty]" value="{item_qty}" />
</td>
<td>{item_subtotal}</td>
</tr>
{/items}
</table>
To remove items from your cart, there are two options. You can either submit the item_qty
field above as 0
, or alternatively, you can use the remove_items
input field. The remove_items
input is useful if you want to display a checkbox:
<table>
{items}
<tr>
<td>{title}</td>
<td>
<input type="checkbox" name="remove_items[{key}]" value="1" /> Remove {title}
</td>
</tr>
{/items}
</table>
Always set the checkbox value to 1
. If the customer doesn’t check the field, the value won’t be submitted, so it won’t cause any unexpected side effects on your checkout form.
You could also template the remove_items
input as a form submit button, using the same name.
The total number of items in the cart.
The total of all items in the cart.
The total tax applicable to the order’s subtotal.
The order subtotal plus any shipping and handling charges.
The total shipping and handling charges.
The tax applicable to shipping charges.
The total discount given by any applicable promo codes.
The total tax saved by applicable promo codes.
The total tax applicable to this order.
The final order total, including all shipping, discounts and taxes.
The email address for this order (required).
If you require your customers to accept terms & conditions before placing an order, you can use this checkbox. Simply include it on any page of the checkout, like so:
<input type="hidden" name="accept_terms" value="0">
<input type="checkbox" name="accept_terms" value="1" {accept_terms_checked} >
Or more simply:
{field:accept_terms} <label for="accept_terms">I accept the terms & conditions</label>
The hidden field is required and must be placed before the checkbox, because per the html specifications, if a checkbox is unticked then nothing is submitted (and Store wouldn’t be able to tell whether the checkbox existed on your page in the first place).
If you don’t want the checkbox to be automatically checked when customers click the back button, simply template it yourself, without using the {accept_terms_checked}
helper.
All billing details are stored in the cart, and you can submit them using standard html inputs.
To display a simple text/drop-down input where appropriate, use the following code:
{field:billing_name}
{field:billing_country}
To customize your inputs, you can simply template them as regular html inputs:
<input type="text" name="billing_name" value="{billing_name}" />
The following fields are available:
The billing name.
The first line of the billing address.
The second line of the billing address (usually this field is optional).
The third line of the billing address (usually used for the city).
The code of the currently selected region.
The name of the currently selected region.
Generates a list of <option>
elements to put inside your select tag. For example:
<select name="billing_region">
{billing_region_options}
</select>
The two digit country code.
The full country name.
Generates a list of <option>
elements to put inside your select tag. For example:
<select name="billing_country">
{billing_country_options}
</select>
All shipping details fields mirror the billing details. You can display and submit them in the same way.
Most order processes will have a “Shipping same as Billing” checkbox. Using these fields, you can copy the billing details to the shipping details, or vice versa.
To display a simple “Shipping same as Billing” checkbox, use the following code:
<label for="shipping_same_as_billing">
{field:shipping_same_as_billing} Same as Billing Details
</label>
If you want to customize the checkbox, you can template it yourself:
<label for="shipping_same_as_billing">
<input type="hidden" name="shipping_same_as_billing" value="0" />
<input type="checkbox" id="shipping_same_as_billing" name="shipping_same_as_billing" value="1" {shipping_same_as_billing_checked} />
Same as Billing Details
</label>
The hidden field must be placed before the checkbox, so that if it is unchecked, “0” will be submitted.
Usually you would combine this checkbox with some simple javascript to hide the shipping details when checked:
<h3>Shipping Details</h3>
<label for="shipping_same_as_billing">
{field:shipping_same_as_billing} Same as Billing Details
</label>
<div id="shipping_details_drawer">
<!-- shipping details here -->
</div>
<script type="text/javascript">
$(function() {
// handle the checkbox change event
$('#shipping_same_as_billing').change(function() {
if (this.checked) {
$('#shipping_details_drawer').slideUp();
} else {
$('#shipping_details_drawer').slideDown();
}
});
// hide on page load if already checked
if ($('#shipping_same_as_billing').is(':checked')) {
$('#shipping_details_drawer').hide();
}
});
</script>
True if the current cart has the “shipping address same as billing address” option applied.
Shorthand for {if shipping_same_as_billing}checked=”checked”{/if}
True if the current cart has the “billing address same as shipping address” option applied.
Shorthand for {if billing_same_as_shipping}checked=”checked”{/if}
Shipping methods are specified by ID (found in the Store Settings page). You can template the shipping method as a drop-down or hidden fields in your template.
To display a simple shipping method drop-down, use the following code:
{field:shipping_method}
To display a custom shipping method drop-down, simply submit the shipping_method
field along with your form:
<select name="shipping_method">
<option value="">Select shipping method...</option>
{shipping_method_options}
</select>
The name of the currently selected shipping method.
If the shipping plugin returned an error, you can use this variable to display it inline.
The ID of the currently selected shipping method.
The plugin being used for this shipping method.
A helper variable to display all available shipping methods as HTML <option>
elements.
Loop through the available shipping methods (useful if you want to display something other than a select menu). Inside the loop, the following variables are available:
To give the user a choice between payment methods, you can either use the payment_method=""
parameter, or submit a payment_method
field on the last page of your checkout.
All payment methods must be configured in the settings. Orders must have a valid payment method before they can be submitted. If payment fails, the customer will be returned to the current page so that they may try again.
For more information about supported payment gateways, and which fields they require, see Payment Gateways.
To display a simple payment method drop-down, use the following code:
{field:payment_method}
To customize your payment method options, simply submit a payment_method
parameter with your form:
How would you like to pay for your order?
<label><input type="radio" name="payment_method" value="manual"> Cheque / Bank Deposit</label>
<label><input type="radio" name="payment_method" value="paypal"> Paypal</label>
<label><input type="radio" name="payment_method" value="authorize_net"> Credit Card</label>
<!-- optionally you could use javascript to display a credit card form here when necessary -->
Displays the short name of the currently selected payment method. This is useful in conditional statements.
Displays the full name of the currently selected payment method.
If the payment gateway returns an error, you can use this variable to display it inline.
Some payment gateways require you to submit the credit card details directly, rather than redirecting the user to a secure payment page. For these gateways, you will need to template additional inputs. You will also need to ensure that your web server is correctly set up with an SSL certificate, as credit card details must always be submitted over a secure connection.
All inputs names should be in the format payment[field_name]
. For example:
<input type="text" name="payment[card_no]" value="" />
The exact fields required depends on the particular gateway. All gateways require the following fields:
The credit card number.
The credit card holder’s name.
This should be submitted as 2 digis (e.g. “04”).
This should be submitted as 4 digits (e.g. “2011”)
The card security code (also known as the CVC or CVV)
The exp_month and exp_year fields are usually templated as select menus. To help with this, the {exp_month_options} and {exp_year_options} variables are available to you:
<select name="payment[exp_month]">
<option value=""></option>
{exp_month_options}
</select>
<select name="payment[exp_year]">
<option value=""></option>
{exp_year_options}
</select>
This will automatically generate a list of HTML option elements, based on the current date.
In addition, the PayPal Pro and SagePay Direct gateways require the following fields:
The card_type field should be templated as a select menu - as a starting point, you could use the following code (delete any cards which your merchant account does not support):
<select name="payment[card_type]">
<option value="">Select one...</option>
<option value="visa">Visa</option>
<option value="mastercard">MasterCard</option>
<option value="amex">American Express</option>
<option value="discover">Discover</option>
<option value="maestro">Maestro (UK)</option>
<option value="solo">Solo (UK)</option>
</select>
If your merchant supports Maestro or Solo cards, you will also need to template the following fields:
The card issue number.
The card issue month.
The card issue year.
Tax Rates are configured under Settings » Tax Rates. The tax rate is decided based on the billing region and country. Only one tax may apply per order.
In general, you can display the tax applicable to any price by appending “_tax” to the variable. You can also display the tax-inclusive price, by appending “_inc_tax”. For example, {price_inc_tax}
, {order_subtotal_tax}
, and {order_shipping_inc_tax}
are all valid variables.
The tax name as defined in the Settings.
The tax rate as a decimal (e.g. “0.15”).
The tax rate as a percentage (e.g. “15”).
True if the current tax rate is applied to shipping costs.
The tax applicable to an individual order item. Must be used inside the {items} loop.
The tax applicable to your order items.
The tax applicable to your shipping charges.
The tax discounted by any promo codes.
The total order tax
To display a simple input for customers to enter a promo code, use the following code:
{field:promo_code}
If you want to customize the input, simply submit a promo_code
field with your checkout form:
<input type="text" name="promo_code" value="{promo_code}" />
Only one promo code may be entered per order. To remove promo codes from the cart, you can either submit a blank promo_code
field, or use a checkbox or button to submit a remove_promo_code
field:
<label>
<input type="checkbox" name="remove_promo_code" value="1" /> Remove Promo Code
</label>
<input type="submit" name="remove_promo_code" value="Remove Promo Code" />
The promo code currently associated with this cart.
The discount specified for the promo code (either a percentage or absolute value).
”p” if the promo code is a percentage discount, “v” if the promo code is an absolute value discount.
TRUE if the current promo code triggers free shipping for the order.
The total discount applied to this order.
Most stores will allow anonymous orders. However, Store provides a simple way for members to create an account during checkout. To enable member registration, you can either use the register_member="yes"
parameter, or submit a the register_member
field. To display a register member checkbox field, use the following code:
{field:register_member}
Member accounts will be created based on the order_email
, and the email address must not already be used for a member account. After creating the member account, any existing orders tied to that email address will be assigned to the new member.
Member accounts will only be created if a password
fields is submitted. In addition, the username
and screen_name
fields are optional. For example:
{field:register_member} <label for="register_member">Register Member Account?</label>
<!-- These fields are optional -->
<div class="toggle">
<div>
<label for="password">Password</label>
{field:password}
</div>
<div>
<label for="password_confirm">Confirm Password</label>
{field:password_confirm}
</div>
<div>
<label for="username">Username</label>
{field:username}
</div>
<div>
<label for="screen_name">Screen Name</label>
{field:screen_name}
</div>
</div>
TRUE if the register member option is enabled for the current cart.
This field can be submitted to set a password for the new member account.
This field can be submitted to confirm the customer typed their password correctly.
The username for the new member account. This will default to the value of the order_email
field, and must be unique.
The screen name for the new member account. This will default to the value of the order_email
field.
Orders can have up to 9 custom fields associated with them. As with other order fields, you can submit them using the field helper:
{field:order_custom1}
You may also template them as regular form inputs. You can give these fields a custom name under Settings » Order Fields, which will appear on the Order Details page in the control panel.
The following error variables are available when you use the error_handling=”inline” parameter:
Different actions can be taken when your checkout form is submitted, depending on which button the customer clicks. You can have multiple buttons in your checkout form, which each perform different actions.
To update your cart totals, your submit button should be named “update_cart”. In addition, if your submit button name doesn’t match any of the other options below, it will be treated as an update cart button.
{exp:store:checkout}
<input type="submit" name="update_cart" value="Update Cart" />
{exp:store:checkout}
To move to the next step in your checkout, your submit button should be named “next”. For example, the following code will take the user to “checkout/confirm”:
{exp:store:checkout next="checkout/confirm"}
<input type="submit" name="next" value="Confirm Order" />
{exp:store:checkout}
To move to the previous step of your checkout, you should not use a button, as you do not want to submit and validate the current form. Just use a regular A element instead (which you can style like a button using CSS if you like):
{exp:store:checkout}
<a href="{path='checkout/cart'}">Back</a>
{exp:store:checkout}
On the first page of your checkout, you may wish to have a “Continue Shopping” button, which takes the customer back to the most recent product they were viewing. For this, we provide the {previous_url} variable, which contains a URL linking to the most recent page the user viewed on your site:
{exp:store:checkout}
<a href="{previous_url}">Continue Shopping</a>
{exp:store:checkout}
To provide an empty cart function, simply submit your checkout using a button named “empty_cart”:
{exp:store:checkout}
<input type="submit" name="empty_cart" value="Empty Cart" />
{exp:store:checkout}
On the final page of your checkout, you want to submit the order. You can do this by naming your button either “submit” or “commit”:
{exp:store:checkout return="order/ORDER_HASH"}
<input type="submit" name="submit" value="Place Order" />
{exp:store:checkout}
When the cart is submitted on the final page of your checkout, a valid payment method must be specified. If the payment is successful, the customer will be redirected to the URL specified in the return=""
parameter. If payment is unsuccessful, the customer will be returned to the final page of your checkout, and the error can be displayed using the {error:payment_method}
variable.