Skip to content
This repository has been archived by the owner on Sep 4, 2018. It is now read-only.

Latest commit

 

History

History
156 lines (112 loc) · 7.31 KB

checkout.textile

File metadata and controls

156 lines (112 loc) · 7.31 KB

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 functionality provided by the checkout system
  • Checkout as a RESTful resource
  • How to add or remove stages from the checkout process
  • Testing your modified checkout process

endprologue.

INFO. The next version of Spree will contain additional improvements to simplify customization even further. With each release and real world Spree deployment, we gain new insight into how to do things better.

Overview

The Spree checkout page is designed as a series of self-contained units
which can be run in any order and individually over-ridden with
a customized style or contents. Stages can be disabled or new ones
added. It is also straightforward to modify the processing steps
used in checkout, e.g. to update the checkout page mid-flow or
to change what information is stored from a transaction.

General Design

In Spree, the checkout is modeled as its own object which belongs to an Order. If you have custom checkout logic, you are most likely going to need to provide custom logic in the CheckoutsController. The idea behind the design is to keep complicated business logic out of the controller. For the most part, CheckoutsController acts just like any other REST controller in Rails. It populates resources, performs validation, etc. It does not have any specific knowledge of which checkout steps are needed nor in what order they should be performed.

The lib/spree/checkout.rb file

At present, this contains two items: a checkout method and the order of
sections in the checkout page. This code is injected into the Orders
controller; putting it in this separate module avoids messy monkey patching
in extension initializer code.

To over-ride this file, an alternative version should be placed in one
of your project’s extensions, typically in your main ‘site’ extension.
Remember that it should go in lib/spree in an extension.

Specifying an order of stages

The method load_checkout_steps sets the instance variable @checkout_steps
with a list of sections to include.
This list is also used to build the page that is served (and passed to
the view): no further configuration is required.
This method is run at the start of the checkout method, which is itself
run at entry to the checkout process and at each point when a major
section of the form has been completed.

NOTE. Once the checkout process has begun, you should probably avoid changing the list that is set!

You can also omit sections from the checkout process, though this may require
modifications to the checkout method to compensate for missing information.
Observe that the registration step is omitted by default if a user is
already logged in.

The standard steps of processing

Possible changes to processing include collecting more information or
leaving some out. The following is an overview of the core checkout
method.
This method is called several times during the checkout process: first
at entry (to set up defaults), then after each major step – the last of
which triggers the final processing and completion.
The effect is to capture the full set of order information incrementally.
(This helps retain information on certain sections in the case where the user
navigates away and returns later with a possibly modified order, i.e. saves
them re-entering earlier details.)

  1. the first few lines load incoming data (in params) into instance variables -
    note that the new Rails nested attributes feature is used to pull in the
    full set of data from the form;
    e.g. to set the address(es) associated with the order;
  2. the next few lines establish default values for objects not yet set by
    the incoming data (which is particularly important on the first
    pass – as a GET – when no form data will be available);
  3. for calls which arise from (possibly intermediate) form posts, we next
    set up ‘derived’ information for the order which isn’t immediately given
    on the form – including order totals – which might include updates to
    current values if some of the form data has changed;
  4. if the resulting order (and its associated data) is not valid, then
    an error is flagged. Observe that some client-side verification is done,
    so this occurrence should be rare;
  5. incomplete (non-final) orders are saved to retain the information so far;
  6. otherwise, final orders are sent for payment authorization and then the
    order is completed and the final state saved;
  7. otherwise, gateway exceptions during this last step are caught and reported.

Conventions and requirements in the Html

  • The div#inner wrapper and the name of the continue button are used in
    the section transition mechanism, and must be retained.
  • The end-of-stage button needs to follow the pattern “continue_STAGE” where
    STAGE is the name of your new stage
  • Compulsory fields are marked by class=‘required’. JQuery’s validation mechanism is used to check that all such fields are non-empty.

Customizations

Recall that @checkout_steps is used to construct the view page, so
this is the only place where configuration is required.

Over-riding a stage

Changing the appearance of a section is straightforward: just copy the relevant
partial to app/views/orders in one of your extensions, and edit – but
remember to follow the Html conventions.

Removing a section

As well as editing @checkout_steps, you may need to alter checkout
to compensate for the missing information. If you want to change what
information is stored, e.g. another kind of payment method from credit
cards, you may need to change:

  • checkout (at least replacing the call to payment_gateway’s authorize)
  • relevant parts of the admin pages (which currently assume credit cards)

Inserting a new section

If collecting new information that does not fit in an existing section,
you will need to create a partial that follows the style of existing partials
and add the name of your section to the list in load_checkout_steps.
Rails’ nested attributes mechanism will handle most of the complexity
as long as you have suitable associations in the relevant models and
are using the appropriate format of names in your partial’s form elements.

Testing your modified checkout process

INFO. Can someone else write something about automated testing if you think it will help here? Or perhaps we just point to a general section?

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.

  • 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.