-
Notifications
You must be signed in to change notification settings - Fork 7
The checkout process
Stall comes with a default checkout process and the ability to customize it entirely by different means.
The checkout consists in 4 simple steps :
- Informations : The customer fills in shipping and billing informations
- Shipping method : The customer chooses its shipping method
- Payment method : The customer chooses its payment method
- Payment : The customer sees a cart recap and proceeds to payment
The only things needed here are :
- Shipping methods : Shipping methods are created in the database and associated to shipping calculator
- Payment methods : Payment methods are created in the database and associated to payment gateways
You can find more informations on creating and using shipping calculators and payment methods in the wiki.
You can override the templates used by each step by overriding the following templates :
app/views/checkout/steps/_informations.html.haml
app/views/checkout/steps/_shipping_method.html.haml
app/views/checkout/steps/_payment_method.html.haml
app/views/checkout/steps/_payment.html.haml
The checkout workflow is handled by what Stall calls "Wizards". A default wizard is generated with the install generator and can be found in your app at : lib/default_checkout_wizard.rb
.
Wizards manages the general workflow checkout. By default, you'll see that your default wizard looks like the following :
class DefaultCheckoutWizard < Stall::Checkout::Wizard
steps :informations, :shipping_method, :payment_method, :payment
end
The .steps
macro defines the general workflow, while the Stall::Checkout::Wizard
parent class ensures that those steps flow during the checkout.
If you need to reorder or delete steps, you can do it by editing this steps list.
Often, you'll need to create steps yourself to adapt to the shop's desired checkout workflow.
Here, we'll imagine a new step called authentication
where we'll want to authenticate the customer before he fills his informations.
We'll start by generating a step :
rails g stall:checkout:step authentication
which will create the lib/authentication_checkout_step.rb
file with the #prepare
and #process
methods, and a view template at app/views/checkout/steps/_authentication.html.haml
with a default form inside.
You now need to implement the methods to handle cart preparation and params processing for the current step, and the form or other control you want in your template.
Now just add this step to your default checkout wizard in lib/default_checkout_wizard.rb
:
class DefaultCheckoutWizard < Stall::Checkout::Wizard
steps :authentication, :informations, :shipping_method, :payment_method, :payment
end
When in the checkout process, the steps have access to the following controller-bound variables : params
, session
, request
and flash
.
The steps are not controllers, but often you need to access some specific data which is request-bound, or pass user flash messages to describe error reasons or success messages.
Often, you'll want to avoid adding to much validations in the cart or its associated models.
Validations are often contextual to the current step and should be written for each step.
You can add such step-specific validations to the cart by using the validations
macro in your step :
class MyStep < Stall::Checkout::Step
validations do
validates :customer, presence: true
end
end
If you need to validate nested models, you can use the .nested
method inside the validations
block. Note that this works for single and collection relations :
class MyStep < Stall::Checkout::Step
validations do
nested :customer do
validates :email, presence: true
end
nested :addresses do
validates :city, presence: true
end
end
end
You can also use custom validations by adding a validation method to : the validations block, the step class or the cart object itself.
Note that the preferred way is inside the step class, in a private method, which is more readable.
class MyStep < Stall::Checkout::Step
validations do
validate :customer_is_authorized
end
private
def date_is_future
unless check_customer_authorization_here
cart.errors(:customer, 'not authorized to place orders')
end
end
end
You can override existing steps code by subclassing them in your app, Stall will find your step instead of the lib's one.
For instance, now that you have an authentication
step, you may want to retrieve data from your authenticated user in your informations
step.
Create a lib/informations_checkout_step.rb
file and override the #prepare
and #process
methods :
class InformationsCheckoutStep < Stall::Checkout::InformationsCheckoutStep
def prepare
cart.customer = current_user.customer
super
end
end
In addition to the default controller data injected into the step, you may want to inject other specific informations, like, for instance, the current_user.
You can do this by using the config.steps_initialization
hook in your config/initializers/stall.rb
initializer :
Stall.configure do |config|
config.steps_initialization do |step|
# Add the `current_user` in all steps
step.inject(:current_user, current_user)
end
end