<commit_before>h2. Checkout Process

This guide covers the design of the checkout process and how to modify it.
After reading it, you should be familiar with:

* The basic architecture underlying the checkout code
* The functionality provided by the checkout system
* How to customize the logic or views for an existing checkout step
* How to add or remove steps to the checkout process

endprologue.

h3. Overview

The Spree checkout process has been designed for maximum flexibility.  Its been redesigned several times now, each iteration has benefited from the feedback of real world deployment experience.  It is relatively simple to customize the checkout process to suit your needs.  Secure transmission of customer information is possible via SSL and credit card information is not stored in the database by default.

h3. Default Checkout Steps

The Spree checkout process consists of the following steps (With the exception of the Registration step, each of these steps corresponds to a state of the +Order+ object):

* Registration (Optinal - can be changed through configuration setting)
* Address Information
* Delivery Options (Shipping Method)
* Payment
* Confirmation

The following sections will provide a walkthough of a checkout from a user's perspective, and offer some information on how to configure the default behaviour of the various steps.

h4. Registration

Prior to beginning the checkout process, the customer will be prompted to create a new account or to login to their existing account. By default, there is also a "guest checkout" option which allows users to specify only their email address if they do not wish to create an account.

Technically, the registration step is not an actual state in the +Order+ state machine.  The spree_auth gem, adds the +check_registration+ before filter to the all actions of the checkout controller +CheckoutController+ (except for obvious reasons the registration and update_registration actions) provides functionality to redirect to a registration page unless one of the following is true:
* +registration_step+ preference is not true
* user is already logged in
* the current order has an email address associated with it

<ruby>
def check_registration
  return unless Spree::Auth::Config[:registration_step]
  return if current_user or current_order.email
  store_location
  redirect_to checkout_registration_path
end
</ruby>

The configuration of the guest checkout option is done via "preferences":preferences.html.  Spree will allow guest checkout by default. Use the +allow_guest_checkout+ preference to change the default setting.

h4. Address Information

This step allows the customer to add both their billing and shipping information.  Customers can click the "use billing address" option to use the same address for both.  Selecting this option will have the effect of hiding the shipping address fields using javascript.  If users have disabled javascript, the section will not disappear but it will copy over the address information once submitted.  If you would like to automatically copy the address information via javascript on the client side, that is an exercise left to the developer.  We have found the server side approach to be simpler and easier to maintain.

The address fields include a select box for choosing state/province.  The list of states will be populated via javascript and will contain all of the states listed in the database for the currently selected country.  If there are no states configured for a particular country, or if the user has javascript disabled, the select box will be replaced by a text field instead.

INFO. The default "seed" data for Spree only includes the U.S. states.  Its easy enough to add states or provinces for other countries but beyond the scope of the project to maintain such a list.  Feel free to add your own seed data for the states you require (and to share your seed scripts with others via "Gist":http://gist.github.com.)

NOTE. The state field can be disabled entirely by using the +address_requires_state+ preference.  You can also allow for an "alternate phone" field by using the +alternative_billing_phone+ and +alternative_shipping+ fields.

The list of countries that appear in the country select box can also be configured.  Spree will list all countries by default but you can configure exactly which countries you would like to appear.  The list can be limited to a specific set of countries by configuring the new +:checkout_zone+ preference and setting its value to the name of a "zone":/zones.html containing the countries you wish to use.  Spree assumes that the list of billing and shipping countries will be the same.  You can always change this logic via an extension if this does not suit your needs.

h4. Delivery Options

During this step, the user may choose a delivery method. Spree assumes the list of shipping methods to be dependent on the shipping address.  This is one of the reasons why it is difficult to support single page checkout for customers who have disabled javascript.  Spree allows you to configure any number of custom "shipping methods":shipping.html.  Each shipping method must be configured with a "zone":zones.html.  The available shipping methods shown during this step will reflect those whose zone overlaps with the specified shipping address.  The shipping methods will also list the associated shipping charge based on the logic provided by their "calculators":calculators.html.

INFO. at least one shipping method and corresponding zone must be configured in order to show shipping methods during checkout.

NOTE. The delivery step is an excellent place to add information on gift options (wrapping paper, etc.)  See the "gift-options":http://github.com/calas/spree-gift-options extension for one possible implementation of this.

h4. Payment

This step is where the customer provides payment infomation.  This step is intentionally placed last in order to minimize security issues with credit card information.  Credit card information is never stored in the database so it would be impossible to have a subsequent step and still be able to submit the information to the "payment gateway":payment_gateways.html.  Spree submits the information to the gateway before saving the model so that the sensitive information can be discarded before saving the checkout information.

WARNING. Spree discards the credit card number after this step is processed.  If you do not have a gateway with payment profiles enabled then your card information will be lost before its time to authorize the card (which is done after the "Confirmation" step.)

INFO. Spree stores only the last four digits of the credit card number along with the expiration information.  The full credit card number and verification code are never stored in the database.  There is an extension for storing this data using PGP encryption,however, this violates PCI standards and is strongly discouraged in production

INFO. The advantage of using a credit card profile is that you can ask for confirmation in a separate step without sacrificing security

NOTE. Several gateways such as ActiveMerchant and Beanstream provide a secure method for storing a credit card "profile" in your database.  This approach typically involves the use of a "token" which can be used for subsequent purchases but only with your merchant account.  If you are using a secure payment profile it would then be possible to show a final "confirmation" step after payment information is entered.

NOTE. If you do not want to use a gateway with payment profiles then you will need to customize the checkout process so that your final step submits the credit card information.  You can then perform an authorization before the +Order+ is saved.  This is perfectly secure because the credit card information is not ever saved.  Its transmitted to the gateway and then discarded like normal.


h4. Confirmation

This is the final opportunity for the customer to review their order before submitting it to be processed.  Users have the opportunity to return to any step in the process using either the back button or by clicking on the appropriate step in the "progress breadcrumb."

h3. Checkout Architecture

The following is a detailed summary of the checkout architecture.  A complete understanding of this architecture will allow you to be able to customize the checkout process to handle just about any scenario you can think of.  Feel free to skip this section and come back to it later if you require a deeper understanding of the design in order to customize your checkout.

h4. Checkout Routes

Three custom routes in spree_core handle all of the routing for a checkout:

<ruby>
   match '/checkout/update/:state' => 'checkout#update', :as => :update_checkout
   match '/checkout/:state' => 'checkout#edit', :as => :checkout_state
   match '/checkout' => 'checkout#edit', :state => 'address', :as => :checkout
</ruby>

The '/checkout' route maps to the +edit+ action of the +CheckoutController+ and provides the default state of 'address'.  The '/checkout/:state' route also maps to the +edit+ action of +CheckoutController+, however the state is supplied in the url.  The '/checkout/update/:state' route maps to the +CheckoutController#update+ action

h4. CheckoutController

The +CheckoutController+ drives the state of an +Order+ object during checkout. Since there is no "checkout" model, the +CheckoutController+ is not a typical RESTful controller. spree_core and spree_auth expose a few actions for the +CheckoutController+. The +edit+ action renders the checkout/edit.html.erb template. The +update+ action serves several purposes:

* update the +current_order+ with the paramaters passed in from the current step.
* transition the order state machine using the +next+ event after successfully updating the order.
* execute callbacks based on the new state after successfully transitioning.
* redirect to the next checkout step if the +current_order.state+ is anything other than +complete+, else redirect to the +order_path+ for +current_order+

h5. filters

+spree_core+ and +spree_auth+ define several before_filter's for the +CheckoutController+:

* load_order (spree_core): The main purpose of this filter is to assign the @order instance variable and set the @order.state to the params[:state]. This filter also runs the "before" callbacks for @order's state.
* check_authorization (spree_auth): verifies the +current_user+ has access to the +current_order+
* check_registration (spree_auth): checks the registration status of +current_user+ and redirects to the registration step if necessary.
h4. The Order Model and State Machine

 The +Order+ state machine is the foundation of the checkout process.  Spree makes use of the "state_machine":http://github.com/pluginaweek/state_machine gem in the +Order+ model as well as in several other places (such as +Shipment+ and +InventoryUnit+.)
An +Order+ object has an initial state of 'cart'.  From there any number of events transition the +Order+ to different states.  Spree does not have a separate model or database table for the shopping cart.  We reached this decision when taking a REST approach to modeling our resources.  What the user considers a "shopping cart" is actually an in-progress +Order+.  An order is considered in-progress, or incomplete when its completed_at attribute is null.  Incomplete orders can be easily filtered during reporting and its also simple enough to write a quick script to periodically purge incomplete orders from the system.  The end result is a simplified data model along with the ability for store owners to search and report on incomplete/abandoned orders.

The default state machine for the +Order+ model is defined in +order.rb+ of spree_core as follows:

<ruby>
state_machine :initial => 'cart', :use_transactions => false do

  event :next do
    transition :from => 'cart', :to => 'address'
    transition :from => 'address', :to => 'delivery'
    transition :from => 'delivery', :to => 'payment'
    transition :from => 'payment', :to => 'confirm'
    transition :from => 'confirm', :to => 'complete'
  end

  before_transition :to => 'complete' do |order|
    begin
      order.process_payments!
    rescue Spree::GatewayError
      if Spree::Config[:allow_checkout_on_gateway_error]
        true
      else
        false
      end
    end
  end

  after_transition :to => 'complete', :do => :finalize!
  after_transition :to => 'delivery', :do => :create_tax_charge!
  after_transition :to => 'payment', :do => :create_shipment!
end
</ruby>

NOTE. There are a few other events and transitions omitted for clarity.  For example the 'cancel' event transitions the state to the 'canceled' state.

INFO. For more information on the state machine gem please see the "README":http://github.com/pluginaweek/state_machine

h4. Checkout Partials

spree_core contains several partials located within +app/views/checkout/+.  Each checkout step automatically renders the +edit.html.erb+ template. The edit template renders a partial with a name based on the state with the current step.  For example, in the delivery step the +_delivery.html.erb+ partial is rendered.

h4. Javascript and CSS

Spree does not require javascript for checkout but the user experience will be slightly more pleasing if they have javascript enabled in their browser.  Spree automatically includes the +checkout.js+ file located in the default theme.  This file can be replaced in its entirety through use of a site extension. There are two stylesheet files used by the Spree checkout process.  Both +_checkout.less+ and +_checkout_progress.less+ can be found in the default theme.

[TODO - Add brief mention of and link to CSS customization using Less once that guide becomes available. ]

h3. Checkout Customization

It is possible to to override the default checkout workflow to meet your store's needs.

h4. Customizing an Existing Step

Spree allows you to customize the individual steps of the checkout process.  There are a few distinct scenarios that we'll cover here.

* Adding before or after a particular step.
* Customizing the view for a particular step.

h5. Adding Logic Before or After a Particular Step

The state_machine gem allows you to callbacks before or after transitioning to a particular step. These callbacks work similarly to "Active Record Callbacks":http://guides.rubyonrails.org/active_record_validations_callbacks.html#callbacks-overview in that you can specify a method or block of code to be executed prior to or after a transition. If the method executed in a in a before_transition returns false, then the transition will not execute.

So, for example, if you wanted to verify that the user provides a valid zip code before transitioning to the delivery step, you would first implement a +valid_zip_code?+ method, and then add the following transition callback to your state_machine definition:

<ruby>
  before_transition :to => 'delivery', :do => :valid_zip_code?
</ruby>

This callback would prevent transitioning to the +delivery+ step if +valid_zip_code?+ returns false.

h5. Customizing the View for a Particular Step

Each of the default checkout steps has its own partial defined in the spree_core.  Changing the view for an existing step is as simple as overriding the relevant partial in your site extension.  Its also possible the default partial in question defines a usable theme hook, in which case you could add your functionality via +hooks.rb+.

[TODO - Add link to hook theming writeup once complete]

INFO. See also the brief discussion in "checkout partials":#checkout-partials for additional information.

h4. Adding or Removing Steps

Spree allows you to easily add or remove checkout steps.  We will outline the basic instructions for doing so here.  If you require more information, please read the detailed overview of "checkout architecture":#checkout-architecture.  Spree comes with a predefined series of checkout steps.  To make changes to this default flow you will need to alter the state machine for +Order+.  State machines are tricky to modify - the recommended approach is to simply define an entirely new state machine as shown in the following two examples:

h5. Removing a checkout step

Here we are removing the address step from the checkout workflow:

<ruby>
module SpreeCustomExtension
  class Engine < Rails::Engine
    def self.activate
      Order.class_eval do

        # customize the checkout state machine
        Order.state_machines[:state] = StateMachine::Machine.new(Order, :initial => 'cart') do
          after_transition :to => 'complete', :do => :complete_order
          before_transition :to => 'complete', :do => :process_payment
          event :next do
            transition :from => 'cart', :to => 'delivery'
            transition :from => 'delivery', :to => 'payment'
            transition :from => 'payment', :to => 'confirm'
            transition :from => 'confirm', :to => 'complete'
          end

           #
           # YOU MUST ALSO DEFINE OTHER EVENTS, TRANSITIONS AND CALLBACKS
           #

        end

      end
    end
  end
end
</ruby>

INFO. This completely overwrites the default +Order+ +state_machine+.  This means it is necessary to explicitly define all of the events, transitions, callbacks etc associated with the +Order+ +state_machine+. In this example we ommited everything except the definition of the +next+ event.

h5. Registering new checkout steps

You can also easily modify the state machine in your extension in order to add a new checkout step.  For instance, maybe you want to ask your user to select a calling plan if they are purchasing a cell phone:

<ruby>
module SpreeCustomExtension
  class Engine < Rails::Engine
    def self.activate
      Order.class_eval do

        # customize the checkout state machine
        Order.state_machines[:state] = StateMachine::Machine.new(Order, :initial => 'cart') do

          after_transition :to => 'complete', :do => :complete_order
          before_transition :to => 'complete', :do => :process_payment

          event :next do
            transition :from => 'cart', :to => 'address'
            transition :from => 'address', :to => 'delivery'
            transition :from => 'delivery', :to => 'calling_plan'
            transition :from => 'calling_plan', :to => 'payment'
            transition :from => 'payment', :to => 'confirm'
            transition :from => 'confirm', :to => 'complete'
          end

           #
           # YOU MUST ALSO DEFINE OTHER EVENTS, TRANSITIONS AND CALLBACKS
           #

        end

      end
    end
  end
end
</ruby>

INFO. You also need a custom +_calling_plan.html.erb+ partial and a migration to create any custom db fields required for the new step.

INFO. This completely overwrites the default +Order+ +state_machine+.  This means it is necessary to explicitly define all of the events, transitions, callbacks etc associated with the +Order+ +state_machine+. In this example we ommited everything except the definition of the +next+ event.

h4. The Checkout "Breadcrumb"

The Spree code automatically creates a progress "breadcrumb" based on the available checkout states.  If you add a new state you'll want to add a translation for that state in the relevant translation file located in the +config/locales+ directory of your extension.

<ruby>
---
en-US:
  checkout_steps:
    # keys correspond to Checkout state names:
    calling_plan: Calling Plan
</ruby>

INFO. The default use of the breadcrumb is entirely optional.  It does not need to correspond to checkout states, nor does every state need to be represented.  Feel free to customize this behavior to meet your exact requirements.

h3. Coupons

Spree allows you to apply a coupon at any time during the checkout.  In order to process a coupon code during checkout you simply need to post a value for the +coupon_code+ attribute.  Spree does this by default in its checkout forms.

h3. Payment Profiles

The default checkout process in Spree assumes a gateway that allows for some form of third party support for payment profiles.  An example of such a service would be "Authorize.net CIM":http://www.authorize.net/solutions/merchantsolutions/merchantservices/cim/.  Such a service allows for a secure and PCI compliant means of storing the users credit card information.  This allows merchants to issue refunds to the credit card or to make changes to an existing order without having to leave Spree and use the gateway provider's website.  More importantly, it allows us to have a final "confirmation" step before the order is processed since the number is stored securely on the payment step and can still be used to perform the standard authorization/capture via the secure token provided by the gateway.

Spree provides a wrapper around the standard active merchant API in order to provide a common abstraction for dealing with payment profiles.  All +Gateway+ classes now have a +payment_profiles_supported?+ method which indicates whether or not payment profiles are supported.  If you are adding Spree support to a +Gateway+ you should also implement the +create_profile+ method.  The following is an example of the implementation of +create_profile+ used in the +AuthorizeNetCim+ class:

<ruby>
# Create a new CIM customer profile ready to accept a payment
def create_profile(creditcard, gateway_options)
  if creditcard.gateway_customer_profile_id.nil?
    profile_hash = create_customer_profile(creditcard, gateway_options)
    creditcard.update_attributes(:gateway_customer_profile_id => profile_hash[:customer_profile_id], :gateway_payment_profile_id => profile_hash[:customer_payment_profile_id])
  end
end
</ruby>

WARNING. Most gateways do not yet support payment profiles but the default checkout process of Spree assumes that you have selected a gateway that supports this feature.  This allows users to enter credit card information during the checkout without having to store it in the database.  Spree has never stored credit card information in the database but prior to the use of profiles, the only safe way to handle this was to post the credit card information in the final step.  It should be possible to customize the checkout so that the credit card information is entered on the final step and then you can authorize the card before Spree automatically discards the sensitive data before saving.

<html>
<input name="checkout[coupon_code]"/>
</html>

INFO. If you need information on how to configure coupons please the detailed section on "coupons and discounts":coupons_and_discounts.html.

h3. Google Checkout and Paypal Express

It is possible to configure Spree to work with third party payment services such as Google Checkout and Paypal Express.  In this case you would simply configure your site theme to add the relevant buttons to your cart page (see the +README+ instructions for each of these extensions for more details.)  If you want to disable normal checkout you could also override the hook for the checkout button.

[TODO - detailed instructions on overriding the hook]

INFO. Spree does not automatically support Google Checkout or Paypal Express.  You will need to install the relevant third party extension if you wish to use these services.

h3. Data Security Issues

We end with a summary of how Spree protects sensitive data. Modifications in
your projects should aim to meet the same standards. You should also be aware
of relevant card processing recommendations or requirements, e.g.
"PCI":https://www.pcisecuritystandards.org/.

* The checkout steps are processed via SSL, so sensitive data is never
  transmitted in clear text.
* By default, sensitive credit card details are NOT stored in the database.
  Spree uses Rails hooks to blank out such sensitive data before containing
  records are saved. (However: this can be changed with the preference
  settings +Spree::Config[:store_cc]+ and +Spree::Config[:store_cvv]+ -
  but this is not recommended).
* Most gateways use Active Merchant, and this itself uses appropriate
  techniques for secure transmission, e.g. submitting authorization
  requests only via SSL.
<commit_msg>Fixed spacing issue that caused rake task to complain about broken link<commit_after>h2. Checkout Process

This guide covers the design of the checkout process and how to modify it.
After reading it, you should be familiar with:

* The basic architecture underlying the checkout code
* The functionality provided by the checkout system
* How to customize the logic or views for an existing checkout step
* How to add or remove steps to the checkout process

endprologue.

h3. Overview

The Spree checkout process has been designed for maximum flexibility.  Its been redesigned several times now, each iteration has benefited from the feedback of real world deployment experience.  It is relatively simple to customize the checkout process to suit your needs.  Secure transmission of customer information is possible via SSL and credit card information is not stored in the database by default.

h3. Default Checkout Steps

The Spree checkout process consists of the following steps (With the exception of the Registration step, each of these steps corresponds to a state of the +Order+ object):

* Registration (Optinal - can be changed through configuration setting)
* Address Information
* Delivery Options (Shipping Method)
* Payment
* Confirmation

The following sections will provide a walkthough of a checkout from a user's perspective, and offer some information on how to configure the default behaviour of the various steps.

h4. Registration

Prior to beginning the checkout process, the customer will be prompted to create a new account or to login to their existing account. By default, there is also a "guest checkout" option which allows users to specify only their email address if they do not wish to create an account.

Technically, the registration step is not an actual state in the +Order+ state machine.  The spree_auth gem, adds the +check_registration+ before filter to the all actions of the checkout controller +CheckoutController+ (except for obvious reasons the registration and update_registration actions) provides functionality to redirect to a registration page unless one of the following is true:
* +registration_step+ preference is not true
* user is already logged in
* the current order has an email address associated with it

<ruby>
def check_registration
  return unless Spree::Auth::Config[:registration_step]
  return if current_user or current_order.email
  store_location
  redirect_to checkout_registration_path
end
</ruby>

The configuration of the guest checkout option is done via "preferences":preferences.html.  Spree will allow guest checkout by default. Use the +allow_guest_checkout+ preference to change the default setting.

h4. Address Information

This step allows the customer to add both their billing and shipping information.  Customers can click the "use billing address" option to use the same address for both.  Selecting this option will have the effect of hiding the shipping address fields using javascript.  If users have disabled javascript, the section will not disappear but it will copy over the address information once submitted.  If you would like to automatically copy the address information via javascript on the client side, that is an exercise left to the developer.  We have found the server side approach to be simpler and easier to maintain.

The address fields include a select box for choosing state/province.  The list of states will be populated via javascript and will contain all of the states listed in the database for the currently selected country.  If there are no states configured for a particular country, or if the user has javascript disabled, the select box will be replaced by a text field instead.

INFO. The default "seed" data for Spree only includes the U.S. states.  Its easy enough to add states or provinces for other countries but beyond the scope of the project to maintain such a list.  Feel free to add your own seed data for the states you require (and to share your seed scripts with others via "Gist":http://gist.github.com.)

NOTE. The state field can be disabled entirely by using the +address_requires_state+ preference.  You can also allow for an "alternate phone" field by using the +alternative_billing_phone+ and +alternative_shipping+ fields.

The list of countries that appear in the country select box can also be configured.  Spree will list all countries by default but you can configure exactly which countries you would like to appear.  The list can be limited to a specific set of countries by configuring the new +:checkout_zone+ preference and setting its value to the name of a "zone":/zones.html containing the countries you wish to use.  Spree assumes that the list of billing and shipping countries will be the same.  You can always change this logic via an extension if this does not suit your needs.

h4. Delivery Options

During this step, the user may choose a delivery method. Spree assumes the list of shipping methods to be dependent on the shipping address.  This is one of the reasons why it is difficult to support single page checkout for customers who have disabled javascript.  Spree allows you to configure any number of custom "shipping methods":shipping.html.  Each shipping method must be configured with a "zone":zones.html.  The available shipping methods shown during this step will reflect those whose zone overlaps with the specified shipping address.  The shipping methods will also list the associated shipping charge based on the logic provided by their "calculators":calculators.html.

INFO. at least one shipping method and corresponding zone must be configured in order to show shipping methods during checkout.

NOTE. The delivery step is an excellent place to add information on gift options (wrapping paper, etc.)  See the "gift-options":http://github.com/calas/spree-gift-options extension for one possible implementation of this.

h4. Payment

This step is where the customer provides payment infomation.  This step is intentionally placed last in order to minimize security issues with credit card information.  Credit card information is never stored in the database so it would be impossible to have a subsequent step and still be able to submit the information to the "payment gateway":payment_gateways.html.  Spree submits the information to the gateway before saving the model so that the sensitive information can be discarded before saving the checkout information.

WARNING. Spree discards the credit card number after this step is processed.  If you do not have a gateway with payment profiles enabled then your card information will be lost before its time to authorize the card (which is done after the "Confirmation" step.)

INFO. Spree stores only the last four digits of the credit card number along with the expiration information.  The full credit card number and verification code are never stored in the database.  There is an extension for storing this data using PGP encryption,however, this violates PCI standards and is strongly discouraged in production

INFO. The advantage of using a credit card profile is that you can ask for confirmation in a separate step without sacrificing security

NOTE. Several gateways such as ActiveMerchant and Beanstream provide a secure method for storing a credit card "profile" in your database.  This approach typically involves the use of a "token" which can be used for subsequent purchases but only with your merchant account.  If you are using a secure payment profile it would then be possible to show a final "confirmation" step after payment information is entered.

NOTE. If you do not want to use a gateway with payment profiles then you will need to customize the checkout process so that your final step submits the credit card information.  You can then perform an authorization before the +Order+ is saved.  This is perfectly secure because the credit card information is not ever saved.  Its transmitted to the gateway and then discarded like normal.


h4. Confirmation

This is the final opportunity for the customer to review their order before submitting it to be processed.  Users have the opportunity to return to any step in the process using either the back button or by clicking on the appropriate step in the "progress breadcrumb."

h3. Checkout Architecture

The following is a detailed summary of the checkout architecture.  A complete understanding of this architecture will allow you to be able to customize the checkout process to handle just about any scenario you can think of.  Feel free to skip this section and come back to it later if you require a deeper understanding of the design in order to customize your checkout.

h4. Checkout Routes

Three custom routes in spree_core handle all of the routing for a checkout:

<ruby>
   match '/checkout/update/:state' => 'checkout#update', :as => :update_checkout
   match '/checkout/:state' => 'checkout#edit', :as => :checkout_state
   match '/checkout' => 'checkout#edit', :state => 'address', :as => :checkout
</ruby>

The '/checkout' route maps to the +edit+ action of the +CheckoutController+ and provides the default state of 'address'.  The '/checkout/:state' route also maps to the +edit+ action of +CheckoutController+, however the state is supplied in the url.  The '/checkout/update/:state' route maps to the +CheckoutController#update+ action

h4. CheckoutController

The +CheckoutController+ drives the state of an +Order+ object during checkout. Since there is no "checkout" model, the +CheckoutController+ is not a typical RESTful controller. spree_core and spree_auth expose a few actions for the +CheckoutController+. The +edit+ action renders the checkout/edit.html.erb template. The +update+ action serves several purposes:

* update the +current_order+ with the paramaters passed in from the current step.
* transition the order state machine using the +next+ event after successfully updating the order.
* execute callbacks based on the new state after successfully transitioning.
* redirect to the next checkout step if the +current_order.state+ is anything other than +complete+, else redirect to the +order_path+ for +current_order+

h5. filters

+spree_core+ and +spree_auth+ define several before_filter's for the +CheckoutController+:

* load_order (spree_core): The main purpose of this filter is to assign the @order instance variable and set the @order.state to the params[:state]. This filter also runs the "before" callbacks for @order's state.
* check_authorization (spree_auth): verifies the +current_user+ has access to the +current_order+
* check_registration (spree_auth): checks the registration status of +current_user+ and redirects to the registration step if necessary.

h4. The Order Model and State Machine

 The +Order+ state machine is the foundation of the checkout process.  Spree makes use of the "state_machine":http://github.com/pluginaweek/state_machine gem in the +Order+ model as well as in several other places (such as +Shipment+ and +InventoryUnit+.)
An +Order+ object has an initial state of 'cart'.  From there any number of events transition the +Order+ to different states.  Spree does not have a separate model or database table for the shopping cart.  We reached this decision when taking a REST approach to modeling our resources.  What the user considers a "shopping cart" is actually an in-progress +Order+.  An order is considered in-progress, or incomplete when its completed_at attribute is null.  Incomplete orders can be easily filtered during reporting and its also simple enough to write a quick script to periodically purge incomplete orders from the system.  The end result is a simplified data model along with the ability for store owners to search and report on incomplete/abandoned orders.

The default state machine for the +Order+ model is defined in +order.rb+ of spree_core as follows:

<ruby>
state_machine :initial => 'cart', :use_transactions => false do

  event :next do
    transition :from => 'cart', :to => 'address'
    transition :from => 'address', :to => 'delivery'
    transition :from => 'delivery', :to => 'payment'
    transition :from => 'payment', :to => 'confirm'
    transition :from => 'confirm', :to => 'complete'
  end

  before_transition :to => 'complete' do |order|
    begin
      order.process_payments!
    rescue Spree::GatewayError
      if Spree::Config[:allow_checkout_on_gateway_error]
        true
      else
        false
      end
    end
  end

  after_transition :to => 'complete', :do => :finalize!
  after_transition :to => 'delivery', :do => :create_tax_charge!
  after_transition :to => 'payment', :do => :create_shipment!
end
</ruby>

NOTE. There are a few other events and transitions omitted for clarity.  For example the 'cancel' event transitions the state to the 'canceled' state.

INFO. For more information on the state machine gem please see the "README":http://github.com/pluginaweek/state_machine

h4. Checkout Partials

spree_core contains several partials located within +app/views/checkout/+.  Each checkout step automatically renders the +edit.html.erb+ template. The edit template renders a partial with a name based on the state with the current step.  For example, in the delivery step the +_delivery.html.erb+ partial is rendered.

h4. Javascript and CSS

Spree does not require javascript for checkout but the user experience will be slightly more pleasing if they have javascript enabled in their browser.  Spree automatically includes the +checkout.js+ file located in the default theme.  This file can be replaced in its entirety through use of a site extension. There are two stylesheet files used by the Spree checkout process.  Both +_checkout.less+ and +_checkout_progress.less+ can be found in the default theme.

[TODO - Add brief mention of and link to CSS customization using Less once that guide becomes available. ]

h3. Checkout Customization

It is possible to to override the default checkout workflow to meet your store's needs.

h4. Customizing an Existing Step

Spree allows you to customize the individual steps of the checkout process.  There are a few distinct scenarios that we'll cover here.

* Adding before or after a particular step.
* Customizing the view for a particular step.

h5. Adding Logic Before or After a Particular Step

The state_machine gem allows you to callbacks before or after transitioning to a particular step. These callbacks work similarly to "Active Record Callbacks":http://guides.rubyonrails.org/active_record_validations_callbacks.html#callbacks-overview in that you can specify a method or block of code to be executed prior to or after a transition. If the method executed in a in a before_transition returns false, then the transition will not execute.

So, for example, if you wanted to verify that the user provides a valid zip code before transitioning to the delivery step, you would first implement a +valid_zip_code?+ method, and then add the following transition callback to your state_machine definition:

<ruby>
  before_transition :to => 'delivery', :do => :valid_zip_code?
</ruby>

This callback would prevent transitioning to the +delivery+ step if +valid_zip_code?+ returns false.

h5. Customizing the View for a Particular Step

Each of the default checkout steps has its own partial defined in the spree_core.  Changing the view for an existing step is as simple as overriding the relevant partial in your site extension.  Its also possible the default partial in question defines a usable theme hook, in which case you could add your functionality via +hooks.rb+.

[TODO - Add link to hook theming writeup once complete]

INFO. See also the brief discussion in "checkout partials":#checkout-partials for additional information.

h4. Adding or Removing Steps

Spree allows you to easily add or remove checkout steps.  We will outline the basic instructions for doing so here.  If you require more information, please read the detailed overview of "checkout architecture":#checkout-architecture.  Spree comes with a predefined series of checkout steps.  To make changes to this default flow you will need to alter the state machine for +Order+.  State machines are tricky to modify - the recommended approach is to simply define an entirely new state machine as shown in the following two examples:

h5. Removing a checkout step

Here we are removing the address step from the checkout workflow:

<ruby>
module SpreeCustomExtension
  class Engine < Rails::Engine
    def self.activate
      Order.class_eval do

        # customize the checkout state machine
        Order.state_machines[:state] = StateMachine::Machine.new(Order, :initial => 'cart') do
          after_transition :to => 'complete', :do => :complete_order
          before_transition :to => 'complete', :do => :process_payment
          event :next do
            transition :from => 'cart', :to => 'delivery'
            transition :from => 'delivery', :to => 'payment'
            transition :from => 'payment', :to => 'confirm'
            transition :from => 'confirm', :to => 'complete'
          end

           #
           # YOU MUST ALSO DEFINE OTHER EVENTS, TRANSITIONS AND CALLBACKS
           #

        end

      end
    end
  end
end
</ruby>

INFO. This completely overwrites the default +Order+ +state_machine+.  This means it is necessary to explicitly define all of the events, transitions, callbacks etc associated with the +Order+ +state_machine+. In this example we ommited everything except the definition of the +next+ event.

h5. Registering new checkout steps

You can also easily modify the state machine in your extension in order to add a new checkout step.  For instance, maybe you want to ask your user to select a calling plan if they are purchasing a cell phone:

<ruby>
module SpreeCustomExtension
  class Engine < Rails::Engine
    def self.activate
      Order.class_eval do

        # customize the checkout state machine
        Order.state_machines[:state] = StateMachine::Machine.new(Order, :initial => 'cart') do

          after_transition :to => 'complete', :do => :complete_order
          before_transition :to => 'complete', :do => :process_payment

          event :next do
            transition :from => 'cart', :to => 'address'
            transition :from => 'address', :to => 'delivery'
            transition :from => 'delivery', :to => 'calling_plan'
            transition :from => 'calling_plan', :to => 'payment'
            transition :from => 'payment', :to => 'confirm'
            transition :from => 'confirm', :to => 'complete'
          end

           #
           # YOU MUST ALSO DEFINE OTHER EVENTS, TRANSITIONS AND CALLBACKS
           #

        end

      end
    end
  end
end
</ruby>

INFO. You also need a custom +_calling_plan.html.erb+ partial and a migration to create any custom db fields required for the new step.

INFO. This completely overwrites the default +Order+ +state_machine+.  This means it is necessary to explicitly define all of the events, transitions, callbacks etc associated with the +Order+ +state_machine+. In this example we ommited everything except the definition of the +next+ event.

h4. The Checkout "Breadcrumb"

The Spree code automatically creates a progress "breadcrumb" based on the available checkout states.  If you add a new state you'll want to add a translation for that state in the relevant translation file located in the +config/locales+ directory of your extension.

<ruby>
---
en-US:
  checkout_steps:
    # keys correspond to Checkout state names:
    calling_plan: Calling Plan
</ruby>

INFO. The default use of the breadcrumb is entirely optional.  It does not need to correspond to checkout states, nor does every state need to be represented.  Feel free to customize this behavior to meet your exact requirements.

h3. Coupons

Spree allows you to apply a coupon at any time during the checkout.  In order to process a coupon code during checkout you simply need to post a value for the +coupon_code+ attribute.  Spree does this by default in its checkout forms.

h3. Payment Profiles

The default checkout process in Spree assumes a gateway that allows for some form of third party support for payment profiles.  An example of such a service would be "Authorize.net CIM":http://www.authorize.net/solutions/merchantsolutions/merchantservices/cim/.  Such a service allows for a secure and PCI compliant means of storing the users credit card information.  This allows merchants to issue refunds to the credit card or to make changes to an existing order without having to leave Spree and use the gateway provider's website.  More importantly, it allows us to have a final "confirmation" step before the order is processed since the number is stored securely on the payment step and can still be used to perform the standard authorization/capture via the secure token provided by the gateway.

Spree provides a wrapper around the standard active merchant API in order to provide a common abstraction for dealing with payment profiles.  All +Gateway+ classes now have a +payment_profiles_supported?+ method which indicates whether or not payment profiles are supported.  If you are adding Spree support to a +Gateway+ you should also implement the +create_profile+ method.  The following is an example of the implementation of +create_profile+ used in the +AuthorizeNetCim+ class:

<ruby>
# Create a new CIM customer profile ready to accept a payment
def create_profile(creditcard, gateway_options)
  if creditcard.gateway_customer_profile_id.nil?
    profile_hash = create_customer_profile(creditcard, gateway_options)
    creditcard.update_attributes(:gateway_customer_profile_id => profile_hash[:customer_profile_id], :gateway_payment_profile_id => profile_hash[:customer_payment_profile_id])
  end
end
</ruby>

WARNING. Most gateways do not yet support payment profiles but the default checkout process of Spree assumes that you have selected a gateway that supports this feature.  This allows users to enter credit card information during the checkout without having to store it in the database.  Spree has never stored credit card information in the database but prior to the use of profiles, the only safe way to handle this was to post the credit card information in the final step.  It should be possible to customize the checkout so that the credit card information is entered on the final step and then you can authorize the card before Spree automatically discards the sensitive data before saving.

<html>
<input name="checkout[coupon_code]"/>
</html>

INFO. If you need information on how to configure coupons please the detailed section on "coupons and discounts":coupons_and_discounts.html.

h3. Google Checkout and Paypal Express

It is possible to configure Spree to work with third party payment services such as Google Checkout and Paypal Express.  In this case you would simply configure your site theme to add the relevant buttons to your cart page (see the +README+ instructions for each of these extensions for more details.)  If you want to disable normal checkout you could also override the hook for the checkout button.

[TODO - detailed instructions on overriding the hook]

INFO. Spree does not automatically support Google Checkout or Paypal Express.  You will need to install the relevant third party extension if you wish to use these services.

h3. Data Security Issues

We end with a summary of how Spree protects sensitive data. Modifications in
your projects should aim to meet the same standards. You should also be aware
of relevant card processing recommendations or requirements, e.g.
"PCI":https://www.pcisecuritystandards.org/.

* The checkout steps are processed via SSL, so sensitive data is never
  transmitted in clear text.
* By default, sensitive credit card details are NOT stored in the database.
  Spree uses Rails hooks to blank out such sensitive data before containing
  records are saved. (However: this can be changed with the preference
  settings +Spree::Config[:store_cc]+ and +Spree::Config[:store_cvv]+ -
  but this is not recommended).
* Most gateways use Active Merchant, and this itself uses appropriate
  techniques for secure transmission, e.g. submitting authorization
  requests only via SSL.

{'fraction_non_alphanumeric': 0.04846859853562958, 'fraction_numerical': 0.0011137465195421264, 'mean_word_length': 4.315864488542923, 'pattern_counts': {'":': 32, '<': 45, '<?xml version=': 0, '>': 161, 'https://': 2, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3078098', 'n_tokens_mistral': 11851, 'n_tokens_neox': 11397, 'n_words': 6837}