E-Commerce for WordPress and Proper Integration
Live Chat

(214) 937-1638

E-Commerce for WordPress and Proper Integration

Posted on December 11th, 2012 by | Google+

When discussing WordPress projects involving E-Commerce, many people cringe because of all the bad rap out there in the developer world regarding WordPress as E-Commerce. Additionally, you can find yourself diving head first in the WordPress E-Commerce world by downloading many popular plugins, only to find that there are things you do not like about the plugins (or even they lack functionality that you need). It’s pretty safe to say that most E-Commerce plugins for WordPress tackle the job, but it also depends on the scale of the store you wish to build.

Many E-Commerce platforms that are not WordPress and are hosted (meaning they host your site, and you run your store through their software) can be overkill, or overpriced. Everything is proprietary and moving away from it will be a big mess. I have found that it can be easy to integrate E-Commerce into your custom WordPress theme without using a plugin. I prefer to not use many plugins, if any at all, as many plugins are not EXACTLY what I want. Also, integration can be a big factor. You may be launching a pretty big store for a client who can run their store through WordPress, but it may not work well with the design you have. I find myself customizing plugins through a very time consuming process, just to end up with a product that I find flawed for what I need. I feel to integrate, we need simplicity. I created two classes to handle the back-end work of a shopping cart system within WordPress, and I feel this can be used for large-scale stores (or even tweaked for new features).

We will be using the WordPress ID of the post to your custom post type for your products. This will be easily accessible since many WordPress native functions rely on having the ID of the post (or in our case, a product) in question.

There are two classes:

One class to manage the actual shopping cart itself:

class APT_Cart {
    public $quantity;
    public $basket;
    public $master;
    public $shipping;
    public $shipping_type;

    function __construct() {
        $this->quantity = 0;
        $this->basket = array();
        $this->master = 0;
    }

    function add($id, $quantity=1, $args = null) {
        $m = $this->master + $quantity;
        if($this->basket[$m]) {
            $count = 0;
            while($count < $quantity) {
                 $this->quantity++;
                $this->master++;
                $count++;
            }
            $this->basket[$m]->update($quantity);
        }
        else {
            if(!is_array($args)) { $args = null; }
            $this->quantity = $this->quantity + $quantity;
            $this->master = $this->master + $quantity;
            $this->basket[$m] = new APT_Product($id, $quantity, $this->master, $args);
        }
    }

    function update($master, $quantity) {
        if($quantity !== $this->basket[$master]->quantity) {
            $this->quantity = $this->quantity - $this->basket[$master]->quantity;
            $this->quantity = $this->quantity + $quantity;
            $this->basket[$master]->update($quantity);
        }
    }

    function remove($master) {
        $tmp_qty = $this->basket[$master]->quantity;
        $this->quantity = $this->quantity - $tmp_qty;
        unset($this->basket[$master]);
    }
}

The other class is to manage each individual product within the shopping cart.

class APT_Product {
    public $id;
    public $quantity;
    public $attributes;
    public $master;

    function __construct($id, $quantity=1, $master=null, $args=null) {
        if(is_array($args)) {
            $apt_attributes = array();
            foreach($args as $key=>$value) {
                $apt_attributes[$key] = $value;
            }
            $this->attributes = $apt_attributes;
        }
        $this->quantity = $quantity;
        $this->id = $id;
        $this->master = $master;
    }

    function update($quantity=1) {
        $this->quantity = $quantity;
    }
}

When creating a WordPress custom theme, you want to be able to control every aspect of your theme if you are like me. Many people resort to plugins as an alternative or an “easy way” out of completing a job on their own. Plus, you get a stripped down version of what you NEED, rather than all the bells and whistles that are EXTRA. When integrating E-Commerce, you would like to be able to customize your own product pages, category pages, and even the shopping cart status “box” that usually goes on each page displaying the number of items in the cart. If we have two classes that are managing the shopping cart on the back end, it’s completely up to the developer on how he wants things to be displayed.

Most experienced WordPress developers will wonder how two classes will manage the shopping cart in WordPress, which is a “session-less” piece of software. Lucky for us, we can have our theme use WordPress to create sessions as well. By using a shopping cart object stored in a session variable, we can easily keep shopping cart data stored throughout the entire user’s visit. How long we keep the session alive is up to you and your server settings, of course. The main thing to realize as well is that we will not be storing user’s information in this session object until the end, but we just need to store simple product information. Only specific product information at that, such as the product’s ID and the quantity being stored. We do not want to store certain data like pricing because of a malicious user injecting or attempting to manipulate the session variables. The price will always be stored on the server, and never will be given to the user in a way that it could be modified. Also, we will not collect any user information until the very end, where we are finalizing the cart. After all, this is when data will need to be retrieved.

Before we begin examining these two classes that manage the cart, let’s check out how we are going to store session data:

// Create our function for the WordPress action
function apt_session_start() {

    // Check to see if a session ID does not exist.
    // If not, create a session using a specific timeout

    if(!session_id()) {

        // Calculate number of seconds to keep session alive
        // I used 48 hours here. (2days * 24hours * 60minutes * 60seconds)

        $apt_seconds = 2 * 24 * 60 * 60;
        ini_set('session.gc_maxlifetime', $apt_seconds);
        session_start();
    }

    // Check to see if a current session is active for our cart.
    // If not, create a brand new session object for our cart.

    if(!$_SESSION['apt_cart']) { $_SESSION['apt_cart'] = new APT_Cart(); }
}

// We want to create this action in 'init', when WordPress first loads

add_action('init', 'apt_session_start', 1);

Now that our session object will always be created, regardless if empty, we are good to start integrating our shopping cart. Before we do this, I recommend creating a custom post type (if you haven’t already) for your products. You can then create multiple custom taxonomies if you wish, in order to categorize and group your products. How to create these post types and taxonomies is a topic for another post, but right now we are focusing on integrating the E-Commerce with your current WordPress site. I usually would create a “product” post type, with a taxonomy “brands” or something to group them. Either way, the shopping cart functions are only going to be used on the actual products themselves, rather than their categories. After all, when a user wants to add something to their cart, they are adding the product.

Let’s start with our Cart class. First we need to create our class, and its variables:

class APT_Cart {
    public $quantity;
    public $basket;
    public $master;
    public $shipping;
    public $shipping_type;
}

These variables are perfect for what we need for this project. This can be customized and extended later at any point. That’s the beauty of this. We have our $quantity variable, which will be a whole number 0 or higher. Our $basket variable is an array of Product objects, which will be the second class we discuss. The $master variable will be an ID counter if you will, so each item within the $basket variable gets an ID number separate from the actual Product/Post ID within WordPress. This is necessary to accurately keep track of all objects within the $basket, and will help later in manipulating the basket using your HTML, Javascript/jQuery, CSS, AJAX, etc. code. The $shipping variable is one I created to store the shipping information of the user. This is collected immediately prior to creating the cart, and I use it to output the shipping information and keep stored for a “Final Review” order screen. Even if this data is manipulated, it will only affect the user trying to manipulate it since it contains the address to ship the product they are about to pay for to. The $shipping_type variable is optional, and I included for the ability to select multiple shipping methods/speeds, such as overnight, rush, standard, etc. This does not have to be used, but is created so the shipping type can be stored within this session variable later.

Next, we need to create our construct function. This function will run when a new object of the APT_Cart class is created, and basically sets up everything we need for integration. You can also customize this function in order to add you own modifications.

function __construct() {
    $this->quantity = 0;
    $this->basket = array();
    $this->master = 0;
}

What we have done here is set the quantity of the basket to 0, and reset the master counter to 0. Additionally, we want to create an empty array for our basket, so we can insert objects into it from our custom WordPress theme.

Now, we want to create the function that adds products to our cart. We will be referencing the APT_Product class, and will explain that class in further detail as we go along. The full code to the class is listed above for reference if you need, and in the snippet below we will be passing variables to that class.

// We want to accept the product ID, a quantity, and any extra attributes for this product

function add($id, $quantity=1, $args = null) {

    // We want to create a variable to act as a unique master ID. This variable
    // fluctuates, and we add product quantities just to mix it up. This can be done
    // multiple ways.

    $m = $this->master + $quantity;

    // Just in case (for future customization), we want to check to see if the slot
    // already exists in the basket array.

    if($this->basket[$m]) {

        // Here, we want to loop through each item set, in case we want to add custom
        // code per item. The user may add five of the same item, but here we can loop
        // through each item for future customization.

        $count = 0;
        while($count < $quantity) {
            $this->quantity++;
            $this->master++;
            $count++;
        }

        // Here, we want to update the quantity of the item in the basket, since the
        // user can purchase more than 1 of the same item. This uses the function in
        // the APT_Product class.

        $this->basket[$m]->update($quantity);
    }
    else {

        // If the slot $m did not exist in the basket, we want to create it. First,
        // we want to check for additional args or attributes for this product. If
        // there are none, we cant to create a null value for $args.

        if(!is_array($args)) { $args = null; }

        // We want to update the entire shopping cart total quantity.

        $this->quantity = $this->quantity + $quantity;

        // Now, we want to update the master ID slot count. This method is just one
        // way to mix it up.

        $this->master = $this->master + $quantity;

        // Finally, we want to create the slot in the $basket array for this object as
        // an APT_Product object, passing the necessary arguments.

        $this->basket[$m] = new APT_Product($id, $quantity, $this->master, $args);
    }
}

What we want to do here is just add a product by creating an object from the APT_Product class. We pass off the ID of the wordpress post ID (your product post type), the quanitity of items you want to add, the master ID, and the additional arguments. The arguments can be things such as the item color, size, etc. These attributes can be passed through the $_POST variable, and should be passed as an array. Additional attributes can be custom text for a product, or virtually anything else you could think of.

Now that we have the ability to add product sets to our cart, we need the ability to update them in any way possible. That’s what the master key slot is for. Generally this key can be passed off as variables for jQuery/Javascript to pick up, and therefore ajax functions can be created to manipulate the cart as well, simply by tracking each product set by the unique master identifier. Let’s take a look at our update function for the cart. Oh, and keep in mind that we want to use this function to control our APT_Product object.

// We want to accept the master ID, and the quantity to update

function update($master, $quantity) {

    // Let's check to make sure we are not updating the quanitity to the same value.
    // We only want to update the quantity if the new quantity is different.

    if($quantity !== $this->basket[$master]->quantity) {

        // This updates the quantity of the actual product item.

        $this->quantity = $this->quantity - $this->basket[$master]->quantity;
        $this->quantity = $this->quantity + $quantity;

        // Now, we need to update the master quantity of the entire cart, to keep track
        // of the total.

        $this->basket[$master]->update($quantity);
    }
}

The last crucial function we need for the shopping cart is the ability to remove the entire item set from the cart without disturbing any other item sets.

// The only information we need is the master ID to remove

function remove($master) {

    // We need to temporarily store the quantity of the item set, so we know how much
    // to subtract from the entire shopping cart total.

    $tmp_qty = $this->basket[$master]->quantity;

    // Now to update the total quantity.

    $this->quantity = $this->quantity - $tmp_qty;

    // Finally, remove the slot and all of its contents from the basket array.

    unset($this->basket[$master]);
}

So now that we’ve covered the entire APT Cart class, let’s begin dissecting the second class: APT Product.

class APT_Product {
    public $id;
    public $quantity;
    public $attributes;
    public $master;
}

Just like we did with the first class, we need to set up variables that we will use to store data about the product. We have the $id variable, which will be the WordPress post ID of your custom product post type. We also have the $quantity to store the total number of products in this set, and we have an array of $attributes that are being stored for this product set. Also, we want to create and store the master slot number in the $master variable so we always have it accessible in case we ever need it. Also leaves room to expand and grow.

Let’s take a look at how we want to construct our APT_Product object:

// We want to accept the WordPress Post ID, quantity, master ID number, and our
// product attributes.

function __construct($id, $quantity=1, $master=null, $args=null) {

    // Let's check to see if there are any arguments/attributes to deal with.

    if(is_array($args)) {

        // Now we need an empty array to store our attributes. This will be our "final" array.
        // I included this in order to filter this process for any reason.

        $apt_attributes = array();

        // Let's loop through the attributes

        foreach($args as $key=>$value) {

            // Here is where we store the same key and values in $args. Right now this is
            // redundant, but this step is crucial and necessary if you need to filter this
            // process. This process can be removed. We are re-creating the $args array into
            // $apt_attributes

            $apt_attributes[$key] = $value;
        }
        $this->attributes = $apt_attributes;
    }

    // Let's store the quantity of this product set for future use, and we need to store the
    // WordPress post ID, and the master ID as well.

    $this->quantity = $quantity;
    $this->id = $id;
    $this->master = $master;
}

This last function in the APT_Product class is used to update the product quantity (in this example). This function can be modified to accept attribute changes as well, but it all depends on the complexity of your project.

function update($quantity=1) {
    $this->quantity = $quantity;
}

I am a huge fan of customization. I believe if you build something yourself, you can control it exactly how you want, and it turns out to be more efficient than the other methods. WordPress can be customized at almost any level, and therefore you can create simple meta boxes on the back end to allow for product manipulation. You can use custom fields to store prices and other data specific to your product. The method described in this article is simply the shopping cart integration. At the very end of the process, you have a $_SESSION[‘apt_cart’] variable that contains all of the shipping information and product information to be used at the final point of sale.

One method to use after this is to create a PayPal IPN script that processes your payments through PayPal. You can create a final order on your server as a custom post type “orders”, and then have that order ID be used when communicating to PayPal. Your final total is calculated by grabbing the final price from a custom field. This price can be sent off to PayPal using a Buy Now URL with the Order ID and total. To prevent against malicious attacks, you can compare the total from the Order’s Custom Price Field to the amount paid to PayPal. When you verify the PayPal payment and total, you can then update the order’s status.

There is so much that goes into E-Commerce, but to explain one method of payment is just that: one method. There are many other merchants such as Authorize.net, and they all have their own ways of accepting payments. I personally prefer creating the orders server-side, so we have all the information at our hands. Then, we can pass the orders off through whichever merchant we need. These two classes simply provide a way to keep track of custom post types that you have created as “products” or items to be added to a shopping cart.

Thank you for considering Absolute as your affordable SEO company. I know you have several options in SEO Services for your website placement and hope you let us earn your business. I promise to be part of your project and to treat it as if it were my own. After all, "IT IS". Though Absolute does reserve the right to decline your website project, we look forward to hearing from you.

Tom Bates | President | Google+