Wern Ancheta

Adventures in Web Development.

Getting Started With Shopify App Development

| Comments

In this article I’ll be showing you how to start developing apps for Shopify. But first of all what is Shopify?

Shopify is an online e-commerce platform, you can use Shopify to create online stores to sell goods and services.
The only difference between Shopify and other e-commerce solutions like Wordpress or Joomla is that you don’t have to install anything yourself. Every store is hosted by Shopify. But you can use a custom domain if you want.

As were going to create a Shopify App its also important that we understand what a Shopify app is:

Shopify apps are used for adding extra features and capabilities to Shopify.

If you’ve ever used a Content Management System like Wordpress or Drupal you might have noticed that the plugin or modules are uploaded into the site were Wordpress or Drupal is running.

But in Shopify you don’t need to upload anything. Shopify apps are basically hosted on a different server. So the creators of the App takes care of all the resources needed by the app to run.

Register as a Shopify Partner

The first thing that you need to do is to register a Shopify Partner Account. This will allow you to create Apps for Shopify.

register as a shopify partner

After you have filled up and successfully submitted the form go ahead and verify your email address.

Create an App

Once you’re done verifying you can now login to your Shopify partners account.

Once you’re logged in click on the Apps tab. This is where the apps that you have created using your account will be listed.

Click on the create app button to create a new app.

your apps

The form for creating a new app asks for some information regarding the app that you want to create. But the only one’s which are required is the Name of app and the Application Callback URL. As this is only a getting started tutorial were just going to fill up what’s required. The app name is simply a human readable name for the app. Make sure that it directly describes what the app does so you can easily make sense of what it does by just reading its name. The Application Callback URL is the URL where the merchant will be redirected after he installs your app. As we are only getting started we can actually put in the url in your local development server. So something like: http://localhost/shopify_testing/shopify_app.php

create app

Once the app is created the API Key and Shared Secret will be generated by Shopify. You can use this later on to authenticate requests to the Shopify API.

Create a Dev Shop

Now that you’re done creating an App we can now create a Dev Shop. A Dev Shop as the name suggests is a Shopify Shop used for testing the apps that you develop. Unlike real Shopify Shops a Dev Shop has no time restrictions and all the functionality available to a normal Shop is also available. The only difference is that a Dev Shop cannot accept payments. Although Shopify has provided a bogus payment gateway so developers can still test out the actual checkout process even when using a Dev Shop.

To create a Dev Shop, just click on the Dev Shops tab then click on the create new dev shop button. Then fill up the form for creating a new Dev Shop. Everything is required:

create dev shop

Once you’re done just click on the create dev shop button to finish creating the dev shop. After that you can now access your dev shop by accessing a url similar to the following:

1
https://shop-name.myshopify.com/admin

Dev Shop Settings

As were going to do some API calls using the app later on. Its useful to set some of the General Settings on your dev shop. I suggest supplying information for the following fields:

  • Store name
  • Homepage title
  • Account email
  • Customer email
  • Phone
  • Street
  • City
  • Postal/Zip Code
  • Country
  • Currency

You can also setup the checkout settings. Like I said earlier, a dev shop can only accept payments via the Bogus Gateway.

Bogus Gateway

When testing payment via bogus gateway the credit card number will always be 1 and the card security code is 111.

Installing the Dependencies

Now were ready to develop the app. To make things easier we will be using a library that will interact with the Shopify API.

First create a composer.json file and put the following contents:

1
2
3
4
5
6
{
    "minimum-stability": "dev",
    "require": {
        "sandeepshetty/shopify_api": "dev-master"
    }
}

If you haven’t already installed Composer, go ahead and install it by executing the following command from the terminal:

1
curl -s http://getcomposer.org/installer | php

Once Composer is installed execute the following command in the same directory where the composer.json file is. This will install all the Shopify API library along with all of its dependencies:

1
php composer.phar install

Once everything is installed by Composer you will see the following directories under the vendor directory:

1
2
3
-composer
-sandeepshetty
-autoload.php

Database

Were going to use the database for storing the general app data and store specific data.

App Settings

1
2
3
4
5
6
7
8
CREATE TABLE IF NOT EXISTS `tbl_appsettings` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `api_key` varchar(300) DEFAULT NULL,
  `redirect_url` varchar(300) DEFAULT NULL,
  `permissions` text,
  `shared_secret` varchar(300) NOT NULL,
  PRIMARY KEY (`id`)
)
  • id – auto-increment primary key
  • api key – the API key that you got earlier when you created an app
  • redirect_url – the url where the merchant will be redirected after installing your app. This is also the url where the merchant will be redirected when he accesses your app from his store.
  • permissions – an array of permissions allowed in your app. These are specific data that your app has access to when a merchant installs your app into his Shop. Some examples are read orders and read products.
  • shared_secret – your apps shared secret. This identifies you as the app owner so only you as the app creator should have access to it.

Store Settings

1
2
3
4
5
6
CREATE TABLE IF NOT EXISTS `tbl_usersettings` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `access_token` text NOT NULL,
  `store_name` varchar(300) NOT NULL,
  PRIMARY KEY (`id`)
)
  • id – auto-increment primary key
  • access_token – the permanent access token associated with the store to be used when authenticating API requests. This is saved into the database so that there will be no need to generate the access token everytime the merchant uses the application.
  • store_name – the name of the store under the myshopify domain. For example: mystore.myshopify.com

Getting App Permissions

Now were ready to actually develop the app. Start by creating the file that you used earlier for the callback URL. In this case were simply going to call it shopify_app.php. Include the library that we downloaded earlier using Composer.

1
2
3
4
<?php
require 'vendor/autoload.php';
use sandeepshetty\shopify_api;
?>

Next check if the shop name is passed in the URL. When the app is accessed from the shop it will always have the shop name passed as an argument along with the callback URL that you specified in the app settings. We then use this shop name to query the database if the shop already exists.

If the shop already exists then we verify if the request is a valid request from Shopify. We can do that by calling the is_valid_request() method from the Shopify API library so were sure that not just anyone can access the app by directly inputting the URL and the required arguments.

If the request is valid we simply save the shopify signature and shop name to the session so it can be accessed on each subsequent request to the app. This will be used to determine if a user is currently logged in to the app.

This means that there’s no need to have a separate login feature for the app. As long as the merchant has properly gone through the process of accessing the app. That is by first

If the shop doesn’t exist in the database yet we simply get the specific permissions stored in the database, convert it to an array then supply it as an argument along with the shop name and api key to the permission_url() method. The permission_url() method generates the URL to the page which asks the merchant to give the app the permission to get specific data from the merchant’s store.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?php
session_start(); //start a session

$db = new Mysqli("localhost", "root", "", "shopify_app");

if($db->connect_errno){
  die('Connect Error: ' . $db->connect_errno);
}

$select_settings = $db->query("SELECT * FROM tbl_appsettings WHERE id = 1");
$app_settings = $select_settings->fetch_object();

if(!empty($_GET['shop'])){ //check if the shop name is passed in the URL
  $shop = $_GET['shop']; //shop-name.myshopify.com

  $select_store = $db->query("SELECT store_name FROM tbl_usersettings WHERE store_name = '$shop'"); //check if the store exists
  
  if($select_store->num_rows > 0){
      
      if(shopify_api\is_valid_request($_GET, $app_settings->shared_secret)){ //check if its a valid request from Shopify        
          $_SESSION['shopify_signature'] = $_GET['signature'];
          $_SESSION['shop'] = $shop;
          header('Location: http://localhost/shopify_testing/admin.php'); //redirect to the admin page
      }
      
  }else{     

      //convert the permissions to an array
      $permissions = json_decode($app_settings->permissions, true);

      //get the permission url
      $permission_url = shopify_api\permission_url(
          $_GET['shop'], $app_settings->api_key, $permissions
      );
      $permission_url .= '&redirect_uri=' . $app_settings->redirect_url;

      header('Location: ' . $permission_url); //redirect to the permission url
  }
}
?>

Once the merchant has granted the permission for your app to access specific data he will be redirected to the URL you specify as the value for the redirect_uri argument passed in the permission URL.

As you can see were getting the redirect URL from the database. This redirect URL shouldn’t necessarily be the same as the URL that you used for the callback URL in your app settings. This redirect URL has the responsibility of saving the shop’s details into the database. This is because the merchant will only be redirected to this URL the first time he installs your app.

You will know that the merchant has already been redirected to this page when both a code and the shop name is passed as an argument to the URL. A permanent access token can then be generated by passing in the name of the shop, api key, shared secret and the temporary code generated by shopify to the oauth_access_token() method.

Then we save the shop details to the database and to the current session. Finally we redirect to the admin page.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
if(!empty($_GET['shop']) && !empty($_GET['code'])){

  $shop = $_GET['shop']; //shop name

  //get permanent access token
  $access_token = shopify_api\oauth_access_token(
      $_GET['shop'], $app_settings->api_key, $app_settings->shared_secret, $_GET['code']
  );

  //save the shop details to the database
  $db->query("
     INSERT INTO tbl_usersettings 
     SET access_token = '$access_token',
     store_name = '$shop'
 ");

  //save the signature and shop name to the current session
  $_SESSION['shopify_signature'] = $_GET['signature'];
  $_SESSION['shop'] = $shop;

  header('Location: http://localhost/shopify_testing/shopify_app.php/admin.php');
}
?>

Now that we’ve gone through the process of getting permissions for the app and written the code for it. It’s time for you to actually install the app to the dev shop that you created earlier. Apps are normally installed from the Shopify app store but we haven’t submitted our app to the Shopify app store yet. So what we’ll do is to go ahead and access the install URL for the app:

1
http://shop-name.myshopify.com/admin/api/auth?api_key=xyz

Be sure to replace shop-name with the actual name of the dev shop that you created earlier. And the value for the api_key to be the actual api key for your app.

That specific URL is where the merchants will be ultimately redirected to once they install your app from the Shopify app store so we don’t really need to submit our app to the app store yet. And Shopify won’t really approve the app unless its well done. It has to go through some sort of review process to make sure that its safe for shop owners(merchants) to install it.

Making API Requests

Now that were done with the authentication part we can now make requests to the API. Go ahead and create the admin.php file. That is where we make requests to the API to get some data about the shop were it is installed. But wait, we don’t have any data to fetch from the shop yet. For starters go ahead and create some products on the dev shop that you created earlier. Come back here after you’ve done that.

Products

Cool! Now you’ve added some products to your shop. We can now fetch some of those products by talking to the API. First you have to call the client method from the Shopify API library passing along the shop name, access token, api key and the shared secret. All of this data is already present in the database as long as the merchant has gone through the install process.

1
2
3
4
5
<?php
$shopify = shopify_api\client(
  $shop, $shop_data->access_token, $app_settings->api_key, $app_settings->shared_secret
);
?>

Once you’re done with that you can now use the $shopify variable to call methods from the API. Here were getting a list of products that are published in the shop:

1
2
3
<?php
$products = $shopify('GET', '/admin/products.json', array('published_status' => 'published'));
?>

The first argument that we specify above is the request method. It can either be GET or POST depending on what’s included in the documentation. Some methods require GET as the request method and some require POST. But the common pattern is that when you’re modifying or creating something the request method to use is POST, but when only retrieving specific data you use GET.

The second argument is the resource that you’re trying to access. In this case were accessing products.json which refers to the products in the shop.

The third argument is an array of arguments that you want to pass. There’s a bunch of arguments that you can pass with the products resource. In the above example we used the published_status and supplied published as its value. This is like saying to the API that we only want to get the products which are published. In shopify products can either be draft or published. Published means that its already viewable by customers in your shop. It means that the merchant is already displaying the product for sale. There’s also the product_type argument this allows you to limit the products returned for a specific product type only. For example you only want to return perishable goods.

Here’s a sample response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
Array
(
    [0] => Array
        (
            [body_html] => Crested shirt
            [created_at] => 2013-10-13T23:09:53-04:00
            [handle] => crested-shirt
            [id] => 164668989
            [product_type] => t-shirts
            [published_at] => 2013-10-13T23:09:13-04:00
            [published_scope] => global
            [template_suffix] => 
            [title] => Crested shirt
            [updated_at] => 2013-10-14T01:31:44-04:00
            [vendor] => zentopia
            [tags] => 
            [variants] => Array
                (
                    [0] => Array
                        (
                            [barcode] => 
                            [compare_at_price] => 
                            [created_at] => 2013-10-13T23:09:53-04:00
                            [fulfillment_service] => manual
                            [grams] => 234
                            [id] => 378254785
                            [inventory_management] => 
                            [inventory_policy] => deny
                            [option1] => Default Title
                            [option2] => 
                            [option3] => 
                            [position] => 1
                            [price] => 322.00
                            [product_id] => 164668989
                            [requires_shipping] => 1
                            [sku] => 
                            [taxable] => 1
                            [title] => Default Title
                            [updated_at] => 2013-10-13T23:09:53-04:00
                            [inventory_quantity] => 0
                        )

                )

            [options] => Array
                (
                    [0] => Array
                        (
                            [id] => 197676733
                            [name] => Title
                            [position] => 1
                            [product_id] => 164668989
                        )

                )

            [images] => Array
                (
                    [0] => Array
                        (
                            [created_at] => 2013-10-14T01:31:39-04:00
                            [id] => 330590691
                            [position] => 1
                            [product_id] => 164668989
                            [updated_at] => 2013-10-14T01:31:39-04:00
                            [src] => http://cdn.shopify.com/s/files/1/0279/0287/products/crest.jpg?305
                        )

                )

            [image] => Array
                (
                    [created_at] => 2013-10-14T01:31:39-04:00
                    [id] => 330590691
                    [position] => 1
                    [product_id] => 164668989
                    [updated_at] => 2013-10-14T01:31:39-04:00
                    [src] => http://cdn.shopify.com/s/files/1/0279/0287/products/crest.jpg?305
                )

        )
)

Note that you can also specify the fields that you want to return by using the fields as an argument and supply a comma-separated list of the fields that you want to return. Something like:

1
2
3
4
5
6
7
8
<?php
$arguments = array(
  'published_status' => 'published',
  'fields' => 'body_html,created_at,handle,id,title,image'
);

$products = $shopify('GET', '/admin/products.json', $arguments);
?>

The documentation for the products is available here. Go through it so you know what other methods you can call that involves the products in the shop.

Orders

You can also access information about orders using the API.

To get a list of orders:

1
2
3
4
5
6
7
8
9
<?php
$arguments = array(
  'limit' => '10', //default: 50
  'page' => '1', //default: 1
  'status' => 'open',

);
$orders = $shopify('GET', '/admin/orders.json', $arguments);
?>

Here’s a sample response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
Array
(
    [0] => Array
        (
            [buyer_accepts_marketing] => 1
            [cancel_reason] => 
            [cancelled_at] => 
            [cart_token] => ba56ddbaab418b79566316fe5e99e4e3
            [checkout_token] => 2b4ef76523c1bb6fc6e6825a97a4c992
            [closed_at] => 
            [confirmed] => 1
            [created_at] => 2013-10-17T00:13:59-04:00
            [currency] => PHP
            [email] => vbcanc@gmail.com
            [financial_status] => authorized
            [fulfillment_status] => 
            [gateway] => bogus
            [id] => 188680051
            [landing_site] => /
            [location_id] => 
            [name] => #1001
            [note] => 
            [number] => 1
            [reference] => 
            [referring_site] => 
            [source] => browser
            [subtotal_price] => 322.00
            [taxes_included] => 
            [test] => 1
            [token] => 35330c6d0bb04c0198ab94b04317e1af
            [total_discounts] => 0.00
            [total_line_items_price] => 322.00
            [total_price] => 342.00
            [total_price_usd] => 7.93
            [total_tax] => 0.00
            [total_weight] => 234
            [updated_at] => 2013-10-17T00:13:59-04:00
            [user_id] => 
            [browser_ip] => 180.191.38.211
            [landing_site_ref] => 
            [order_number] => 1001
            [discount_codes] => Array
                (
                )

            [note_attributes] => Array
                (
                )

            [processing_method] => direct
            [checkout_id] => 140790649
            [source_name] => web
            [line_items] => Array
                (
                    [0] => Array
                        (
                            [fulfillment_service] => manual
                            [fulfillment_status] => 
                            [grams] => 234
                            [id] => 328820335
                            [price] => 322.00
                            [product_id] => 164668989
                            [quantity] => 1
                            [requires_shipping] => 1
                            [sku] => 
                            [title] => Crested shirt
                            [variant_id] => 378254785
                            [variant_title] => 
                            [vendor] => zentopia
                            [name] => Crested shirt
                            [variant_inventory_management] => 
                            [properties] => Array
                                (
                                )

                            [product_exists] => 1
                        )

                )

            [shipping_lines] => Array
                (
                    [0] => Array
                        (
                            [code] => International Shipping
                            [price] => 20.00
                            [source] => shopify
                            [title] => International Shipping
                        )

                )

            [tax_lines] => Array
                (
                )

            [payment_details] => Array
                (
                    [avs_result_code] => 
                    [credit_card_bin] => 1
                    [cvv_result_code] => 
                    [credit_card_number] => XXXX-XXXX-XXXX-1
                    [credit_card_company] => Bogus
                )

            [billing_address] => Array
                (
                    [address1] => 86-92 & 103 Brighton Road Coulsdon Surrey
                    [address2] => 
                    [city] => Coulsdon
                    [company] => doble
                    [country] => United Kingdom
                    [first_name] => sfs
                    [last_name] => rew
                    [latitude] => 51.314819
                    [longitude] => -0.12435
                    [phone] => 3252325
                    [province] => Surrey
                    [zip] => CR5 2NG
                    [name] => sfs rew
                    [country_code] => GB
                    [province_code] => 
                )

            [shipping_address] => Array
                (
                    [address1] => 86-92 & 103 Brighton Road Coulsdon Surrey
                    [address2] => 
                    [city] => Coulsdon
                    [company] => doble
                    [country] => United Kingdom
                    [first_name] => sfs
                    [last_name] => rew
                    [latitude] => 51.314819
                    [longitude] => -0.12435
                    [phone] => 3252325
                    [province] => Surrey
                    [zip] => CR5 2NG
                    [name] => sfs rew
                    [country_code] => GB
                    [province_code] => 
                )

            [fulfillments] => Array
                (
                )

            [client_details] => Array
                (
                    [accept_language] => en-US,en;q=0.8
                    [browser_ip] => xxx.xxx.xx.xxx
                    [session_hash] => 4bb858f172df6367b05ab424f9c6bd0f778e711e9046c5a13833cc91bc33a237
                    [user_agent] => Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/28.0.1500.71 Chrome/28.0.1500.71 Safari/537.36
                )

            [customer] => Array
                (
                    [accepts_marketing] => 1
                    [created_at] => 2013-10-15T21:26:24-04:00
                    [email] => vbcanc@gmail.com
                    [first_name] => wef
                    [id] => 148878735
                    [last_name] => rew
                    [last_order_id] => 
                    [multipass_identifier] => 
                    [note] => 
                    [orders_count] => 0
                    [state] => disabled
                    [total_spent] => 0.00
                    [updated_at] => 2013-10-17T00:14:01-04:00
                    [verified_email] => 1
                    [tags] => 
                    [last_order_name] => 
                    [image_url] => //gravatar.com/avatar/aba221e4cb888289b95b7864d754c4ce?default=http%3A%2F%2Fcdn.shopify.com%2Fs%2Fimages%2Fadmin%2Fcustomers%2Fcustomers_avatar_england_londonbridge.png
                    [default_address] => Array
                        (
                            [address1] => 86-92 & 103 Brighton Road Coulsdon Surrey
                            [address2] => 
                            [city] => Coulsdon
                            [company] => doble
                            [country] => United Kingdom
                            [first_name] => sfs
                            [id] => 193735639
                            [last_name] => rew
                            [phone] => 3252325
                            [province] => Surrey
                            [zip] => CR5 2NG
                            [name] => sfs rew
                            [province_code] => 
                            [country_code] => GB
                            [country_name] => United Kingdom
                            [default] => 1
                        )

                )

        )

)

As you can see from the above response all information about a specific order is returned. The line items, payment details, billing address and customer information are all included in the default response. Information about the device (IP address, browser) were the order was made is also captured by Shopify.

Webhooks

The Shopify API also supports webhooks. In case you don’t know what a webhook is here’s a good definition from Wikipedia:

A Webhook, in web development, is a method of augmenting or altering the behavior of a web page, or web application, with custom callbacks. These callbacks may be maintained, modified, and managed by third-party users and developers who may not necessarily be affiliated with the originating website or application.

In simple terms a webhook is used to perform specific actions when a certain event happens. In Shopify there are a number of events which you can hook into to perform specific action:

Webhooks can be set from the dev shop or from the app. To set a webhook from the dev shop go to the admin page of your shop, click on the settings tab then click on notifications tab. Scroll down until you find the webhooks section. To create a new webhook just click on the create a webhook button. Then select the event in which you want to add a webhook then enter the complete URL of the page where you want to submit the data when the specific event happens.

Webhook

To add a webhook via the API simply make a POST request to the webhooks resource and passing in the topic and address. The topic is the actual event and the address is the URL which you want to submit the data returned from the specific event when it happens. Do note that we can’t use the local server URL for this. It must be a URL that’s actually accessible from the internet. In the example below were submitting the data to the address specified when a cart is created or updated.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
//when cart is created
$arguments = array(
  'topic' => 'cart/creation',
  'address' => 'http://somewhere.com/update_inventory.php'
);

$webhooks = $shopify('GET', '/admin/webhooks.json', $arguments);

//when cart is updated
$arguments = array(
  'topic' => 'cart/update',
  'address' => 'http://somewhere.com/update_inventory.php'
);

$webhooks = $shopify('GET', '/admin/webhooks.json', $arguments);
?>

Remember that every event where you can hook upon in the admin interface you can also create a hook on it using the API. You can read more about webhooks here.

If you want to check what specific data is being passed to the URL that you specify for a specific webhook you can use a service like request bin

Heres a sample request for when a cart is created. You can use the properties under the data property as a basis for the data that you’re going to access from the address that you specified in your webhook:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
{
  "url": "http://api.yourapihere.com/",
  "headers": {
    "Connection": "close",
    "X-Shopify-Topic": "carts/create",
    "Host": "api.yourapihere.com",
    "Accept-Encoding": "gzip, deflate, compress",
    "X-Shopify-Shop-Domain": "test-shop.myshopify.com",
    "User-Agent": "Ruby",
    "Content-Type": "application/json",
    "Content-Length": "281",
    "Accept": "*/*"
  },
  "args": {},
  "data": "{\"id\":\"carts:eeafa272cebfd4b22385bc4b645e762c\",\"token\":\"eeafa272cebfd4b22385bc4b645e762c\",\"line_items\":[{\"id\":null,\"title\":\"Example T-Shirt\",\"price\":\"19.99\",\"line_price\":\"59.97\",\"quantity\":3,\"sku\":\"example-shirt-s\",\"grams\":200,\"vendor\":\"Acme\",\"properties\":null,\"variant_id\":null}]}",
  "origin": "54.236.226.56",
  "form": {},
  "files": {},
  "json": {
    "id": "carts:eeafa272cebfd4b22385bc4b645e762c",
    "line_items": [
      {
        "id": null,
        "sku": "example-shirt-s",
        "variant_id": null,
        "quantity": 3,
        "vendor": "Acme",
        "grams": 200,
        "title": "Example T-Shirt",
        "properties": null,
        "price": "19.99",
        "line_price": "59.97"
      }
    ],
    "token": "eeafa272cebfd4b22385bc4b645e762c"
  }
}

The data that is passed to the address that you specified is an input stream. It’s not passed using the common GET or POST request method. You can use the fopen() method in PHP and pass in the php://input stream. Then pass in rb as the mode. rb means read-only in binary mode. Then we just loop through the input stream until we reach the end of the file. Inside the loop we also use the fread() method to read from the resource created when we called fopen() earlier. We also pass the maximum number of bytes to read which is 4096 (approximately 4Mb). Finally we close the resource and convert the webhook content to an array using the json_decode() method.

1
2
3
4
5
6
7
8
9
10
11
12
<?php
$webhook_content = '';
$webhook = fopen('php://input' , 'rb');
while(!feof($webhook)){ //loop through the input stream while the end of file is not reached
    $webhook_content .= fread($webhook, 4096); //append the content on the current iteration
}
fclose($webhook); //close the resource

$data = json_decode($webhook_content, true); //convert the json to array

//do whatever you want with the data
?>

Conclusion

That’s it! You’ve learned how to create a Shopify app. Creating a shopify app involves creating a Shopify partners account, a dev shop and an app. You’ve also learned that Shopify apps aren’t directly integrated into a shop, instead it is hosted somewhere else. Shopify apps are a nice way to extend the functionality that is already available to Shopify.

Resources

Comments