Cornerstore

This add-on is operated by Crispy Mountain GmbH

Powerful e-commerce backend for custom online shops

Cornerstore

Last Updated: 07 May 2015

Table of Contents

Cornerstore is a Heroku add-on for easy development of custom online shops. It provides a RESTful API, a unified checkout and a backend that can be used to manage products, orders and shop settings.

Cornerstore allows developers to build sophisticated online shops without reinventing the wheel, by leaving the front-end coding, technologies and tools to the developer. In contrast to other shop software, which uses template engines and runs the whole shop on the provider’s platform, Cornerstore supplies common resources like products, collections and orders only via API.

Provisioning the add-on

Our free developer plan has all necessary features to get started, but allows just 20 orders for testing purposes. It is advisable to upgrade to a bigger plan, as soon as the app goes into production. A list of all available plans can be found here

Cornerstore can be attached to a Heroku application via the CLI:

$ heroku addons:create cornerstore:developer
-----> Adding cornerstore to fattoria-croccante... done, v18 (developer)

Once Cornerstore has been added the Manager can be accessed via the app’s dashboard. Also the CORNERSTORE_URL environment variable is set which contains access credentials to the store.

Getting started

Cornerstore consists of 3 major pieces:

1. Cornerstore Manager

alt text

Cornerstore Manager can be used to add products, collections and images. To get an idea of its capabilities you should play around with it and enter some test data.

The manager can be accessed via the CLI:

$ heroku addons:open cornerstore
Opening cornerstore:supermarket for fattoria-croccante... done

or by visiting the Heroku Dashboard and selecting the application in question. Select Cornerstore from the Add-ons menu.

Once the shop is in production, access can be granted to merchants, so they can administer their orders and shop settings. They don’t need to access the Manager via Heroku, instead they can use https://<app-name>.cornerstore.io and login with their own user accounts.

2. RESTful API

Our RESTful API can be used to retrieve data from and upload data to the backend using common HTTP requests. Results will be presented in JSON.

Some common requests are presented in the upcoming sections, with a complete API documentation available here.

3. Unified checkout

A pain point for many developers is integration of payment providers (such as Paypal or Stripe), email delivery services and tax calculations. Cornerstore does all that out of the box.

By redirecting the customer to https://<app-name>.cornerstore.io/checkout/<checkout_id> our unified checkout page handles the order process, without the need to build anything custom beforehand.

Shipping and payment options can be configured in the Cornerstore Manager.

Sample Store: Fattoria Croccante

There’s a sample store implementation based on Ruby on Rails that can be cloned as a starting point for development:

$ git clone https://github.com/crispymtn/fattoria-croccante

Using Cornerstore with Ruby

Ruby applications will need to add the following entry into their Gemfile specifying the Cornerstore client library.

gem 'cornerstore', github: 'crispymtn/cornerstore-gem'

Update application dependencies with bundler.

$ bundle install

The following examples show some basic requests in Ruby. More detailed information on available resources and results can be found in our documentation.

# Retrieve a specific product by ID
product = Cornerstore::Product.find('sugo-al-basilico')
product.name           #=> "Sugo Al Basilico"
product.manufacturer   # => "Fattoria Croccante"

# Retrieve all collections
collections = Cornerstore::Collection.all
products = collections.first.child_collections.first.products

# Perform a product search
results = Cornerstore::Search.new(params[:keywords])

# Create a cart
cart = Cornerstore::Cart.create({
  cart_url: 'http://fattoria-croccante.herokuapp.com/cart',
  success_url: 'http://fattoria-croccante.herokuapp.com/cart/success',
  placed_email_callback_url: 'https://fattoria-croccante.herokuapp.com/emails/placed_notification'
})

# Connect the session to the cart (in Rails or Sinatra)
session[:cart_id] = cart.id

# Add line items based on a variant
variant = product.variants.first
variant.order_number           # => "FC-SUGO-01"
variant.price.decimal_amount   # => 4.5

line_item = cart.line_items.create_from_variant(variant)

# Add line item from scratch
line_item = cart.line_items.create({
  qty: 2,
  description: 'The best tagiatelle on the planet',
  order_number: 'TG3234',
  unit: '500g Bag',
  price: Price.new(1299, 'USD'),
  weight: 1.43
})

# Delete line items
cart.line_items.last.destroy

# Redirect the customer to the checkout (in Rails or Sinatra)
redirect_to cart.checkout_url, protocol: 'https'

Using Cornerstore with other languages

Cornerstore can be used with many languages including your favourite web framework by crafting the HTTP requests to the API yourself. All responses are in the JSON format. Parsing libraries are available for all modern languages and frameworks. The following examples show how the Cornerstore API could be accessed with PHP.

<?
// We use this for recurring queries
function CallAPI($method, $url, $data = false)
{
  $curl = curl_init();

  // Authentication
  $cs_url = getenv('CORNERSTORE_URL');
  curl_setopt($curl, CURLOPT_HTTPHEADER, array("Authorization: Token " . parse_url($cs_url, PHP_URL_PASS)));

  // Set the right method
  curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);

  // If there is data attach it
  if ($data) {
    curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));
  }

  curl_setopt($curl, CURLOPT_URL, $url);
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);

  printf("Calling %s \n", $url);
  $json = curl_exec($curl);
  curl_close($curl);
  $response = json_decode($json);
  return $response;
}

// Getting a product
$product = CallAPI("GET", "https://fattoria-croccante.cornerstore.io/api/v1/products/spaghetti");
printf("Product name: %s \n", $product->name); // Spaghetti

// Create a cart
$cart_params = array(
  "cart[cart_url]" => "http://fattoria-croccante.herokuapp.com/cart",
  "cart[success_redirect_url]" => "http://fattoria-croccante.herokuapp.com/cart/success",
  "cart[placed_email_callback_url]" => "https://fattoria-croccante.herokuapp.com/emails/placed_notification"
);

$cart = CallAPI("POST", "https://fattoria-croccante.cornerstore.io/api/v1/carts", $cart_params);
printf("Cart ID: %s \n", $cart->_id); // The cart's object ID

// Add a line item based on a variant
$line_item_params = array(
  "line_item[qty]" => 5,
  "product_id" => $product->_id,
  "variant_id" => $product->variants[0]->_id
);

$line_item = CallAPI("POST", "https://fattoria-croccante.cornerstore.io/api/v1/carts/" . $cart->reference . "/line_items/derive", $line_item_params);
printf("Line item description: %s \n", $line_item->description); // Spaghetti

// Change the qty of the line item
$line_item_params = array("line_item[qty]" => 1);
CallAPI("PUT", "https://fattoria-croccante.cornerstore.io/api/v1/carts/" . $cart->reference . "/line_items/" . $line_item->_id, $line_item_params);
$cart = CallAPI("GET", "https://fattoria-croccante.cornerstore.io/api/v1/carts/" . $cart->reference);
printf("Amount of first line item: $%.2f \n", $cart->line_items[0]->price->amount); // 1

// Remove the line item again
CallAPI("DELETE", "https://fattoria-croccante.cornerstore.io/api/v1/carts/" . $cart->reference . "/line_items/" . $line_item->_id);
$cart = CallAPI("GET", "https://fattoria-croccante.cornerstore.io/api/v1/carts/" . $cart->reference);
printf("Number of line items: %d \n", count($cart->line_items)); // 0

?>

Local environment setup

After provisioning the add-on it’s necessary to locally replicate the config vars so your development environment can operate against the service.

You can use heroku config for displaying Cornerstore’s environment variables:

$ heroku config | grep CORNERSTORE
CORNERSTORE_URL      => https://token:ifuf83jnuivSF990uSSF9f9f0e@fattoria-croccante.cornerstore.io

Use Foreman to configure, run and manage process types specified in your app’s Procfile. Foreman reads configuration variables from an .env file. Use the following command to add the Cornerstore values retrieved from heroku config to .env.

$ heroku config -s | grep CORNERSTORE >> .env
$ more .env

If you use Ruby with the Cornerstore gem, you can also use a configuration yml file or Rails' secrets.yml to configure Cornerstore locally for development. Please refer to the gem’s documentation for further information about this.

Credentials and other sensitive configuration values should not be committed to a publicly available source-control. In Git exclude the .env file with: echo .env >> .gitignore.

Migrating between plans

Bigger plans allow more products, images, user accounts and certain features. No further configuration is needed to upgrade a plan. There will be no downtime and data migration is not necessary.

Unless plan limits are exceeded, which would prevent a downgrade, it is possible to switch back and forth between plans at any time.

Use the heroku addons:upgrade command to migrate to a new plan.

$ heroku addons:upgrade cornerstore:supermarket
-----> Upgrading cornerstore:supermarket to fattoria-croccante... done, v2 ($125/mo)
       Your plan has been updated to: cornerstore:supermarket

A list of all plans available can be found here.

Removing the add-on

Cornerstore can be removed via the CLI.

This will immediately and permanently erase all associated data and cannot be undone!

$ heroku addons:destroy cornerstore
-----> Removing cornerstore from fattoria-croccante... done, v3 (supermarket)

Support

All Cornerstore support and runtime issues should be submitted via one of the Heroku Support channels. Any non-support related issues or product feedback is always welcome via E-Mail or Twitter.

Additional resources

Find out more about Cornerstore and all the things, we can’t cover here: