This is the last part of the long tutorial on the Magento checkout customization. here, I will describe the last checkout section “Order Review” and explain how the OneStep checkout link can be added to the Magento front-end.

Step 11: Order Review

This is the last section in the OneStep checkout. It contains an overview of the order contents: item list and order totals. In Magento OnePage checkout the Order Review is rendered in the last stage, when all the step data has already been submitted. The OneStep checkout must be showing an Order Review since the very beginning of the checkout process. But when a customer opens the OneStep checkout page, the current quote may not have enough data to generate an order summary. This is why the Order Review JavaScript attempts to fetch a section update HTML from the controller immediately after the OneStep checkout page is opened.

The JavaScript class representing the Order Review section is Review (classes/Review.js). To fetch the section update when the checkout page is displayed, the onestep.js script calls the updateReview method of the Review class (Listing 58).

review.updateReview(this, true);

Listing 58. Updating the Order Review section, /skin/frontend/base/default/js/solvingmagento/onestepcheckout/onestep.js, line 36.

The OneStep checkout calls updateReview in two modes: with and without validation. The “with validation” mode is on when a customer is about to submit the order and the checkout must make sure that the data in every section form is complete and valid. The “without validation” mode skips checking the checkout data in the client to avoid displaying the validation error messages. The data is posted “as is” and the controller has to render a section update using whatever data it has. The “without validation” mode is necessary to allow the checkout JavaScript to update the Order Review section when the checkout page is opened for the first time and most of the section forms are empty. Trying to validate the update request at this stage will display validation error messages next to nearly every input element, which may scary customers off.

In Listing 58, the updateReview method receives a noValidation parameter. If this parameter is true then the checkout instance will return true when calling its method validateReview. Next, the updateReview method serializes every checkout form into a parameters string which it then posts per Ajax to the OneStep controller method updateOrderReviewAction.

In Listing 59, the updateOrderReviewAction method processes the posted checkout data. The controller and checkout model perform the server-side data validation but any errors that may have been produced must not displayed in the response. For this reason I pass false as the last parameter when calling methods saveAddressData, saveShippingMethodData, and savePayment. These methods have a response parameter that controls the writing of validation errors to the controller response.

The example in Listing 60 shows the saveShippingMethodData function that saves the selected shipping method. If the checkout model returns an error array, the saveShippingMethodData method will use the response parameter to decide whether to write the error message to the JSON output object or not. Passing false to the data saving methods in function updateOrderReviewAction allows the controller to produce an HTML update for the Order Review section without showing any validation error messages.

Method _getReviewHtml that generates the section HTML uses a layout update under handle checkout_onestep_review, which defines child blocks in the Order Review section template (Listing 61).

Listing 61. Layout configuration of the Order Review section, /app/design/frontend/base/default/layout/solvingmagento/onestepcheckout.xml, line 140.

The block classes and template files I use for the OneStep Order Review are the same ones used by Magento OnePage checkout with only one exception. The original OnePage checkout template for the checkout/onepage_review_info block contains the code for the “Order Submit” button. The specifics of the OneStep checkout required that I removed that code and implemented the submit button in its own block. I assigned the button block as a child to the Order Review container (Listing 62).

A <div> with ID checkout-load-review where the JavaScript will insert the section update fetched from the controller

A line that will output a “checkout agreements” form

A line that will display the child button block containing the submit button.

The submit button of the OneStep checkout has two states: “Update order before placing” and “Place order”. The “Update order before placing” state is necessary because a customer can make changes to any checkout section any time and can never be sure that the Order Review display is accurate. To get a definite checkout state before placing the order, the customer must explicitly update the review section and validate the checkout data. If the validation is successful, the controller returns an updated Order Review section and the submit button changes its label to “Place Order”. This state change is reflected in the Review class property readyToSave which has value false unless the checkout data is valid.

In Listing 63, the submit method observes the readyToSave property to decide to which controller action the data must be posted. This property is true when the checkout data is validated and the Order Review section is updated. In this case, the submit method will post to the controller’s submitOrderAction method, otherwise the JavaScript will attempt to fetch an Order Review update by posting to the updateOrderReviewAction method. In both cases, the submit method calls checkout.validateReview with parameter true, which enables the client-side validation. If any of the checkout data is missing or incorrect, the JavaScript will display a validation error message next to the respective input element.

It may happen that a customer clicks the “Update order before placing” button, receives an Order Review update and then decides to change something in one of the checkout inputs. In this case, submitting an order must not be allowed until the checkout data is validated again. The Checkout class has a method observeChanges that registers a observer for the “change” event on every form input element in the OneStep checkout. The handler of this event sets the readyToSave property to false and changes the submit button’s label from “Place order” back to “Update order before placing” (Listing 64).

The observeChanges method is also called from the Checkout class setResponse function (Listing 30, last line). The setResponse method uses the section updates delivered by the controller to update the DOM. The input elements in the update HTML have no “change” event observers, which is why the Checkout class has to call observeChanges after each such update.

When a customer clicks the “Place order” button, the JavaScript posts the serialized checkout form data to the OneStep controller method submitOrderAction. The composition of this method is similar to that of the updateOrderReviewAction in Listing 59 – the method receives the POST request data, parses it, and saves the section form data to the current quote using a checkout model instance. One thing different in the submitOrderAction method is checking if the customer has agreed to the required agreements (Listing 65).

The submitOrderAction method doesn’t ignore validation errors and adds error arrays returned by data saving methods to the $results variable. If this error list is not empty, the submitOrderAction method merges its entries into a single message and throws an exception. This exception is caught and the controller returns the error message to the checkout JavaScript which shows it in an alert; the order is not submitted (Listing 66).

Listing 67. submitting a new order, /app/code/local/Solvingmagento/OneStepCheckout/controllers/OnestepController.php, line 539.

It may happen that the selected payment method (e.g., PayPal Standard) requires a redirect to the payment provider website, where the customer must submit payment details. For this case, the controller checks if there is a redirectUrl property set to the checkout. If a redirect is required, the controller returns the URL to the checkout JavaScript that performs the redirect.

At the end, the OneStep checkout redirects to the “checkout success” page, which is the same used by the OnePage checkout. The checkout is complete.

Step 12: Making the OneStep checkout option visible in the front-end

This last step should’ve actually been the first because here I set up a link in the front-end, which customers can use to access the OneStep checkout. At the moment the “Proceed to Checkout” button takes the customer to the standard OnePage checkout. My extension doesn’t replace the OnePage checkout, so I will leave this button as is. The link to the OneStep checkout will be shown in the shop header next to the “My Cart” and “Login” links (Figure 11).

Figure 11. The “Checkout in One Step” link.

To output this link, I use a block of type Solvingmagento_OneStepCheckout_Block_Link. This block implements a single function, which checks if the OneStep checkout is enabled and, if yes, adds a link to this checkout to its parent block (Listing 68).

Listing 69. Adding the link to the top.link block, /app/design/frontend/base/default/layout/solvingmagento/onestepcheckout.xml, line 19.

The <action> node triggers the addOnestepCheckoutLink method of the Link block, which adds the link to the OneStep checkout to the front-end.

Conclusion

Building a OneStep checkout has been a long and difficult journey. While the finished extension is a working solution, it is a product of many compromises which were necessary to make this OneStep checkout work for the same scenarios as the standard OnePage checkout. As I’ve explained at the beginning of the tutorial, OneStep works best in situations where checkout forms are short and simple. The form I’ve had to deal with when building this extension is nothing like that. If you decide to use this extension in a real project, be prepared to reconsider some of the compromises I made and adapt the code and layout to the specific needs of your shop.

Checkout is the most completed part in magento. Your onestep checkout tutorials and onepage checkout tutorials give me enough power to modify checkout flow to fit my client’s need. Thank you very much!

hi , i have a big problem since 2 week in my website , unable to order now …
im in magento 1.9 , in one page checkout, after choosing all required step, you clik on ” continue ” to review order, nothint happen,
please help, the website is : http://www.egeriestyle.com