Build a Mobile App to Sell Products with Drupal
Once we have built the mobile application, customers who have downloaded and installed the mobile app onto their Android or iOS (iPhone, iPad) device will be able to purchase the product as an In-App Purchase.
For this example website and mobile app, we're going to sell bottles of beer. *Cough* - Please don't actually sell beer without first getting permission from your local Big Brother.
The main 3 sets of tools we will utilize are:
- Drupal
- The website will be powered by Drupal 7
- Drupal Commerce
- The online store will be powered by the Commerce module for Drupal
- DrupalGap
This tutorial was inspired by this Session from DrupalCon Austin 2014. If you're new to any of these tools mentioned above, please watch the video for an introduction. Otherwise, let's get started!
1. Download and Install Drupal 7
2. Download and Install the Commerce Module for Drupal
If you're new to Drupal Commerce, I'd recommend checking out Commerce KickStart for a nice introduction. Otherwise, the Commerce module comes packed with many sub modules. To get started, we'll want to make sure the following modules are enabled on our Drupal site:
- Cart
- Checkout
- Commerce
- Commerce UI
- Customer
- Customer UI
- Line Item
- Line Item UI
- Order
- Order UI
- Payment
- Payment UI
- Price
- Product
- Product Pricing
- Product Pricing UI
- Product Reference
- Product UI
Woah, that was a lot of modules. Pretty much enable them all except for the Tax modules, and don't tell the King about it.
2a. Give users permission to go through the Checkout process
- On the Drupal site, go to: admin/people/permissions
- Next to the "Access checkout" permission, check the box for Anonymous and Authenticated users
- Click the "Save permissions" button
3. Add a Product Type
Go to:
admin/commerce/products/types/add
With the following info:
- Name: Beer
- Description: Mmmm, beer.
Then click the "Save and add fields" button.
4. Add a "Size" Field to the Product type
As a bare minimum, we want our customers to be able to choose the size of their beer. So let's add a new field on our Product type to accommodate this:
admin/commerce/products/types/beer/fields
Under the "Add new field" section, enter the following info:
- Label: Size
- Field type: List (text)
- Widget: Select list
Then click the "Save" button. Next up, in our "Allowed values list" for the field, let's copy/paste these values:
Pint 12 oz 22 oz 40 oz
Then click the "Save" button. Next, specify these values:
- Label: Size
- Required field: Check the box
- Default value: Pint
- Enable this field to function as an attribute field on Add to Cart forms: Check this box
- Number of values: 1
Then click the "Save settings" button.
5. Add some Products
We're now ready to add some products to sell. In Drupal, go to:
admin/commerce/products/add/beer
Then enter the following values:
- Product SKU: bells-oberon-12-oz
- Title: Bells Oberon 12 oz
- Price: $4.00
- Size: 12 oz
Click the "Save and add another" button, then enter the following values:
- Product SKU: bells-oberon-pint
- Title: Bells Oberon Pint
- Price: $5.00
- Size: Pint
As you can see we've now created 2 products which allow us to sell a Bells Oberon beer in either a 12 oz or pint size.
Repeat this procedure as many times as you want to build your beer catalog. After a while, we'll have a list of beer like so:
For now, prohibition is tough on the Internet so we only have 5 products to sell, within 3 types of beer.
- Bells Oberon
- Shorts Brew Soft Parade
- Sierra Nevada Torpedo Extra IPA
6. Add a Content Type to Display the Products
In Drupal, go to:
admin/structure/types/add
Enter Beer as the Name, then click the "Save and add fields" button.
6a. Add a Field to Reference the Products
Then under the "Add new field" section, enter the following info:
- Label: Beer Products
- Field type: Product reference
- Widget: Check boxes/radio buttons
Then click the "Save" button, then click the "Save field settings" button. Next, specify these values:
- Label: Beer Products
- Required field: Check the box
- Products types that can be referenced: Beer
- Default value: Pint
- Number of values: Unlimited
Then click the "Save settings" button.
6b. Add an Image Field to Show a Picture
If you're not already there, navigate to this page in Drupal:
admin/structure/types/manage/beer/fields
Under the "Add new field" section, enter the following info:
- Label: Photo
- Field type: Image
- Widget: Image
Then click the "Save" button, then click the "Save field settings" button. Next, specify these values:
- Label: Photo
- Required field: Check the box
Leave all the other settings as the default values provided, then click the "Save settings" button.
7. Create Content to Display Products
Now that we have some beer products created, we need to create some beer content to reference the beer products. This allows the "Add to cart" functionality to work within Drupal Commerce. On your Drupal site, go to:
node/add/beer
Enter these values:
- Title: Bells Oberon
- Beer Products:
- bells-oberon-12-oz: Check this box
- bells-oberon-pint: Check this box
- Photo: Upload a picture to use
Click the "Save" button, then repeat that process for the other two types of beer, using these values:
- Title: Sierra Nevada Torpedo Extra IPA
- Beer Products:
- sierra-nevada-torpedo-extra-ipa-12-oz: Check this box
- sierra-nevada-torpedo-extra-ipa-22-oz: Check this box
- Photo: Upload a picture to use
Then one more time with:
- Title: Shorts Brew Soft Parade
- Beer Products:
- shorts-brew-soft-parade-12: Check this box
- Photo: Upload a picture to use
8. Create a Page to Display the Product Content
We'll use Views to make a page to display our Beer content, in Drupal go to:
admin/structure/views/add
Enter these values:
- View name: Beers
- Show: Content
- of type: Beer
- sorted by: Title
Next check the "Create a page" box and enter these values (note, the zero used below means display all items):
- Page title: Beers
- Path: beers
- Display format: Table
- Items to display: 0
Then check the "Create a menu link" checkbox and enter these values:
- Menu: Main menu
- Link text: Beers
Then click the "Continue & edit" button.
8a. Display an Image with the Product Listing Page
Now, in the "Fields" section, follow these steps:
- Click the "Add" button
- Enter this keyword in the Search box: photo
- Check the box next to "Content: Photo"
- Click the "Add and configure fields" button
- Uncheck the "Create a label" box
- On the "Image style" select list, choose "Thumbnail (100 x 100)"
- On the "Link image to" select list, choose "Content"
- Click the "Apply" button
- In the "Fields" section, click the down arrow then click the "Rearrange" button
- Grab the handle next to the Photo field, and drag it above the Title field
- Click the "Apply" button
Finally, we can click the "Save" button on our View, then click the "Home" button to go home. We should now see a "Beers" button in our main menu, let's click it to look at our fine selection:
9. Enable a Payment Method
For this tutorial, we'll be using Stripe to accept a demonstration payment.
- Signup (or login) with Stripe
- Download and enable the Commerce Stripe module
- pay close attention to the README with this module to install it properly
- Go to: admin/commerce/config/payment-methods
- Click "enable" on the disabled Stripe payment method rule
- Click "edit" next to the enabled Stripe payment method rule
- Click "edit" next to the Stripe action
- In a separate window, login to Stripe website
- Go to: Your Account -> Account Settings -> API Keys
- Copy the Secret and Publishable test keys from Stripe
- Paste them back into the corresponding text fields in the "Payment Settings" section back on the Drupal site
- Click "Save"
- Flush all of Drupal's caches
10. E-commerce... done!
That's it, we've built a fully functional e-commerce website with Drupal Commerce to sell beer. Customers can now browse the beer on our website, add it to their cart, and complete the checkout process.
Let's now move on to building the mobile application...
11. Enable DrupalGap, Commerce DrupalGap and Commerce DrupalGap Stripe modules in Drupal
Since we'll be using DrupalGap to build the mobile application, let's download and enable the modules we'll need on our Drupal site:
- https://drupal.org/project/drupalgap
- https://drupal.org/project/commerce_drupalgap
- https://drupal.org/project/commerce_drupalgap_stripe
Refer to each module's README file for important installation instructions about their dependencies and setup configurations.
VERY IMPORTANT: At this time of writing this, the Commerce Services module (a dependancy of Commerce DrupalGap) isn't evolved enough to handle permissions properly. So for this to work properly we have to enable certain permissions for anonymous and authenticated users that we wouldn't normally grant, or we have to use user #1 to bypass the permissions. See this issue for more details: https://www.drupal.org/node/1943426
12. Set up the DrupalGap Mobile Application Development Kit
If you're new to DrupalGap, follow the Hello World guide to get started. For this example, we'll be developing the mobile app in Google Chrome using the Ripple plugin. Once everything is up and running, our app should look similar to the screen shot here.13. Enable the Address Field, Commerce and Commerce DrupalGap Stripe modules for DrupalGap
Just like Drupal, DrupalGap has contributed modules. We'll need to download and these two modules to our app's modules directory within DrupalGap:
- http://drupalgap.org/project/addressfield
- http://drupalgap.org/project/commerce
- http://drupalgap.org/project/commerce_drupalgap_stripe
Then enable the modules in our settings.js file, for example:
Drupal.modules.contrib['addressfield'] = { minified: true }; Drupal.modules.contrib['commerce'] = { minified: true }; Drupal.modules.contrib['commerce_drupalgap_stripe'] = {};
14. Create a Custom DrupalGap Module to Customize the App
Again, just like Drupal, DrupalGap allows us to create our own modules to handle customization. Let's create a custom module in DrupalGap, so its JavaScript file lives here:
www/app/modules/custom/my_module/my_module.js
Then enable the module from within the settings.js file:
Drupal.modules.contrib['my_module'] = {};
15. Create a JSON Page URL in Drupal to Retrieve the Beer List
Let the fun begin... first we need to access our beer list via JSON, so we need to setup a URL that will return JSON to us, in Drupal go to:
admin/structure/views/view/beers/edit
- Click +Add in the Display section
- Click Page
- Change the Display name to JSON
- Change the Format to JSON Data Document, on This page (override), then click the Apply (this display) button
- Uncheck the Views API mode checkbox, then click the Apply (this display) button
- Under Page Settings, change the Path to beers.json
- Under Fields, change the Label on both fields, so the first character in the label is lower case, on this display only
- Next to Fields, click the Add button
- Enter nid into the Search box
- Check the box next to Content: Nid and then press the Apply (this display) button
- Change the Label to nid and then press the Apply (this display) button
Now if we preview our results, we should see something like this:
{ "nodes" : [ { "node" : { "photo" : { "src": "http://localhost/drupal-7/sites/default/files/styles/thumbnail/public/sierranevada_torpedoextraipa12oz_0.jpg?itok=8sCnt0hP" }, "title" : "Sierra Nevada Torpedo Extra IPA", "nid" : "293" } }, { "node" : { "photo" : { "src": "http://localhost/drupal-7/sites/default/files/styles/thumbnail/public/soft-parade-1.jpg?itok=UWiqK1fL" }, "title" : "Shorts Brew Soft Parade", "nid" : "294" } }, { "node" : { "photo" : { "src": "http://localhost/drupal-7/sites/default/files/styles/thumbnail/public/bells-oberon-12_0.jpg?itok=Phb_X8bE" }, "title" : "Bells Oberon", "nid" : "292" } } ], "view" : { "name" : "beers", "display" : "page_1", "path" : "admin/structure/views/nojs/preview/beers/page_1", "root" : "nodes", "child" : "node", "pages" : null, "page" : null, "count" : 3, "limit" : null } }
Click the "Save" button to save the View. We're now ready to consume our beer as JSON, be sure to eat some food before consuming beer, and after I suppose.
16. Create a Page in the App to Display the Beer List
Since we created a custom module in DrupalGap earlier, we can use the my_module.js file to create a custom page using hook_menu(), like so:
/** * Implements hook_menu(). */ function my_module_menu() { try { var items = {}; items['beer-list'] = { title: 'Beer List', page_callback: 'my_module_beer_list_page' }; return items; } catch (error) { console.log('my_module_menu - ' + error); } } function my_module_beer_list_page() { try { var content = {}; content['my_beer_list'] = { theme: 'view', format: 'ul', path: 'beers.json', row_callback: 'my_module_beer_list_page_row', empty_callback: 'my_module_beer_list_page_empty' }; return content; } catch (error) { console.log('my_module_beer_list_page - ' + error); } } function my_module_beer_list_page_row(view, row) { try { var image = theme('image', { path: row.photo.src }); var title = '<h2>' + row.title + '</h2>'; var html = l(image + title, 'node/' + row.nid); return html; } catch (error) { console.log('my_module_beer_list_page_row - ' + error); } } function my_module_beer_list_page_empty(view) { try { return "Sorry, we are out of beer."; } catch (error) { console.log('my_module_beer_list_page_empty - ' + error); } }
Then if we set this newly created page as our App's front page in the settings.js file:
// App Front Page drupalgap.settings.front = 'beer-list';
We'll be able to see our beer list!
17. Let's Go Shopping for Beer!
Since DrupalGap comes with the ability to view nodes, and we chose to render our beer list with each item as a clickable link to its node page (e.g. node/123), we can click on an item in our beer list to view it. Since it is 9:30 AM at the time of writing this paragraph, I won't actually drink a beer, but if I had to choose, I'd click on the Oberon for now.Now that we're viewing the beer node, we can see that our "Add to Cart" form and picture of the beer were automatically rendered for us, neat-o. If we were to scroll down in the app, we could see the whole picture, but you get the idea. Since its early, let's select a 12 0z instead of a pint, and click the add to cart button.
Then we can proceed through the checkout process, which is similar to most e-commerce workflows:
18. All Done!
Now if we were to look in the admin order section in Drupal:
admin/commerce/orders
We would see our new order sitting there with a status of pending:
Pretty cool huh? Not bad. I hope you enjoyed this tutorial, and are inspired to try some of these technologies to build your own mobile application to sell your Drupal Commerce products. Thanks and happy coding!
Comments
Brian MacKinney (not verified)
Tue, 07/01/2014 - 13:28
Permalink
Great post! This type of full
Great post! This type of full site build tutorials is something I think the community needs more of. Have you considered posting this in the recipes section of d.o docs? https://www.drupal.org/documentation/site-recipes
tyler
Tue, 07/01/2014 - 15:28
Permalink
Thank you Brian. I wasn't
Thank you Brian. I wasn't aware of the Site Recipes section until now, thanks. If it wouldn't be in bad taste, I'd consider adding a "Blog post" section that page to start collecting external blog posts that match a Site Recipe. I'm not sure if the recipe guide is meant for internal pages only.
Jason (not verified)
Fri, 08/15/2014 - 14:51
Permalink
Hi Tyler,
Hi Tyler,
Thank you for this greaat tutorial.
I 've run through this and I'm getting the list. However, when I click a list item and go to the node page for the selection, the node title shows up, the node comments show up (if they are on) but no image, no options widgets, add to cart etc. appear. They are showing in the web app.
Any advice would be greatly appreciated.
Thank you again!
tyler
Sat, 08/16/2014 - 09:26
Permalink
Thanks for the kind words
Thanks for the kind words Jason.
Take a look at the commerce_cart_add_to_cart_form() function in commerce.js, there is a big bug listed next to the @TODO comment.
You'll most likely need to change the line below that to use the machine name of your product reference field on your content type that displays your products.
Try changing that to match your field's machine name. It would be great if you could figure out how to fix that line of code so it works for everyone, but I haven't been able to locate the field's machine name dynamically, so I just typed it in manually for now.
Also be sure to check out the DrupalGap display mode: http://www.drupalgap.org/node/184
Jason (not verified)
Mon, 08/18/2014 - 19:08
Permalink
Greetings!I set the problem I
Greetings!
I set the problem I describe above aside to test the Stripe payment method. I had been getting an error in mobile, so I went to confirm that the Drupal was processing cards properly. Nope.
I was getting this error:
Obviously, mobile won't work if web is not working. I discovered that the problem is with the deprecated event handler in jquery. I have Jquery Update Module installed and I had the current version set to 1.10. When I set that to 1.8 because the event handler live() was removed in 1.9 (http://api.jquery.com/live/) Stripe payments via Drupal worked well.
One down! Now, go back and try my payment via Ripple for mobile. No such luck. This is throwing this error in console:
I'm thinking there's validity to the notion that the jquery version on web must match jquery version on mobile?
I'll go to work resolving that. First by using jquery-1.8.x to test it. I'll post my results.
Now to my original question. The problem that I had was that the Display Settings for DrupalGap on the content type were not correct. I got the cart to display on my mobile app once I discovered that the content type display settings for DrupalGap needed to be adjusted and made sure to add the block code to the content region in settings.js
commerce_cart: {
pages: {
mode: 'exclude',
value: ['cart', 'checkout/*', 'checkout/shipping/*']
}
}
However, the cart showed up only because I was logged in as a user that had added items to the cart in the web app. The mobile app "Add To Cart" is not working.
Notice here that I did: console.log('We get the selector as ' + selector);
I think that the problem here may also be jquery related. When I had jquery update module set to 1.10, the result of that console.log =
We get selector as:
#node_8 select._commerce_cart_attribute
Now with jquery update module set to 1.8.x the output of that console.log =
We get selector as:
[object HTMLDivElement]
So, I'm wondering if this is a byproduct of the jquery version mismatch? In any event, this function is failing.
I think this is the function you were referencing. The comment you mentioned @TODO was not present? My machine name for the product here is
function _commerce_product_display_get_current_product_id() {
try {
// Iterate over each attribute on the page, pull out the field_name and
// value, and set them aside, so they can later be used to determine which
// product is currently selected.
var selector = '#' + drupalgap_get_page_id() + ' select._commerce_cart_attribute';
//var selector = node_8;
console.log('We get the selector as ' + selector);
var attributes = { };
$(selector).each(function(index, object) {
var field_name = $(object).attr('field_name')
var value = $(object).val();
attributes[field_name] = value;
});
Very sorry for the long post, however it might help others encountering the same problem.
Thanks again, Tyler!
tyler
Mon, 08/18/2014 - 21:22
Permalink
Thanks for the thorough
Thanks for the thorough report. It'd be better to post any issues, one at a time, in the Commerce DrupalGap issue queue(s):
I've had luck using the version of jQ and jQM that are packaged with DrupalGap. Also, I don't typically use jQuery update on the Drupal site.
Jason (not verified)
Mon, 08/18/2014 - 21:17
Permalink
Here is a patch that will
Here is a patch that will resolve the problem is found here. https://www.drupal.org/node/2247523
I'm not certain how this will affect the communication with Drupalgap.
Thanks!
Frederic (not verified)
Wed, 08/27/2014 - 16:28
Permalink
Hello Tyler, Thanks for your
Hello Tyler, Thanks for your great tutorial. I have a little problem. All my commerce fields don't appear on the mobile app. You can access the app via the url: http://e-gap.model225.com/mobile-application/ Please, could you help me ? Thanks.
tyler
Thu, 08/28/2014 - 07:28
Permalink
Hi Frederic,Thank you.Take a
Hi Frederic,
Thank you.
Take a look at your JavaScript Console in Chrome, it says:
This means you haven't set up the Commerce Services and/or Commerce DrupalGap modules properly on your Drupal site.
Be sure to closely follow the README:
https://github.com/signalpoint/commerce
Then make sure you're display settings are properly set:
http://www.drupalgap.org/node/184
Lee (not verified)
Thu, 01/01/2015 - 20:21
Permalink
Helllo Tyler,
Helllo Tyler,
I'm having the same problem as Frederic, the product-display/$node.json is returning a 404 error. On my product display (admin/commerce/products/types/product/display), there is no option for DrupalGap, but in the custom display settings, I can enable Node: DrupalGap. Could this be the problem?
Thanks,
-Lee
tyler
Thu, 01/01/2015 - 21:44
Permalink
The "manage display" is for
The "manage display" is for the content type that references your products. The product reference field on that content type should be set to "add to cart form". You don't need to worry about the display settings on the product type.
Lee (not verified)
Fri, 01/02/2015 - 16:18
Permalink
Tyler,
Tyler,
Ahh.. got it. Thank you for the clairification. I still can't figure out why my product-display/$node.json is returning a 404. Is there anything I can do to debug?
Thanks,
-Lee
tyler
Fri, 01/02/2015 - 16:21
Permalink
What's the URL that 404's? Go
What's the URL that 404's? Go to admin -> structure -> services, then edit the resources for drupalgap, and make sure the product display resource is enabled, then flush all of your caches. Stop by #drupal-drupalgap on IRC to chat.
Bruno Montibeller (not verified)
Fri, 11/07/2014 - 11:57
Permalink
Hi, I tried this tutorial and
Hi, I tried this tutorial and everything worked pretty fine, but, my app couldn't "send" to my drupal site the customer's Billing Information, I made a lot of tests to discover that neither your tutorial makes it work ( as I can see, your orders page can't show the customer's name).
Is this feature not working or am I doing something wrong?
tyler
Fri, 11/07/2014 - 12:00
Permalink
That feature hasn't been
That feature hasn't been implemented yet, the billing information form is only used for the Stripe payment gateway and isn't tied to the Order itself. Please consider contributing to the solution(s), thanks!
augustynen (not verified)
Thu, 12/04/2014 - 04:45
Permalink
I can't find settings.js ?
I can't find settings.js ?
Is it inside a module?
tyler
Thu, 12/04/2014 - 10:07
Permalink
The settings.js file doesn't
The settings.js file doesn't exist by default, you need to save a copy of default.settings.js as settings.js inside the "app" directory, for example: https://github.com/signalpoint/DrupalGap/tree/7.x-1.x/app
rogeer (not verified)
Sat, 12/13/2014 - 11:44
Permalink
Hi Tyler, I tried your
Hi Tyler, I tried your DrupalGap module and this tutorial - it's very cool.
I did everything, all is good, but path to product image in product node page is bad.
Error in Chrome console:
http://localhost/drupal_test_drpgpnew/mobile-application/localhost/drupa... Failed to load resource: the server responded with a status of 404 (Not Found)
Right path to image is localhost/drupal_test_drpgpnew/sites/default/files/2014-03-22%2017.41.03.jpg
Can you help me please?
Thank you very much.
Roger
(from Czech republic)
tyler
Mon, 12/15/2014 - 10:09
Permalink
Make sure your site_path in
Make sure your site_path in the settings.js file is set to:
Other than that I'm not quite sure. So it'd be best to file a bug report: https://github.com/signalpoint/commerce
rogeer (not verified)
Tue, 12/16/2014 - 16:45
Permalink
Thank you Tyler for your
Thank you Tyler for your answer, my site_path was set only to 'localhost/drupal....', now it works fine with http://localhost...
Thank you again. Roger
rogeer (not verified)
Mon, 12/29/2014 - 16:19
Permalink
Hello Tyler,
Hello Tyler,
please can you tell me, how can I set up other payment method?
I mean for example cash payment when I deliver goods - In mobile app customer just select payment method (cash payment), go through and complete order.
Thank you.
tyler
Mon, 12/29/2014 - 16:31
Permalink
First you need to decide on
First you need to decide on what module to use on your Drupal site to handle the cash payment. Then that same module will have to be built for DrupalGap.
Nithin Kolekar (not verified)
Mon, 01/05/2015 - 11:27
Permalink
Is this tutorial enough for
Is this tutorial enough for simple app for site admins for content approval? ( commerce/payment functionality doesn't required).
tyler
Mon, 01/05/2015 - 11:32
Permalink
Hi Nithin, DrupalGap can
Hi Nithin, DrupalGap can definitely be used to make a simple admin content approval app. This tutorial may not be the best starting point, but it has some valid related ideas in it. Checkout the Getting Started Guide for DrupalGap, it should have everything you need to build the app you describe.
augustynen (not verified)
Tue, 01/20/2015 - 05:50
Permalink
Hallo,
Hallo,
Thank you verry much for the tutorial.But I don't quit get it.
I get the title Beer List, but I can't see any of the products.
Howerver I have a menu of the lefttop were I can clink on content en can select create content while users don't have permission to do that.
Sow I went wrong somewere.
The other problem is the config.xml.
I placed the example config.xml in het root but I still get this error in ripple.
Can you help ?
tyler
Tue, 01/20/2015 - 09:50
Permalink
Don't worry about the config
Don't worry about the config.xml file in Chrome+Ripple, it isn't needed, and you can just ignore any errors about it.
augustynen (not verified)
Tue, 01/20/2015 - 09:12
Permalink
OKé,
OKé,
I have it working 50/50.
For some reasen I't only displays the product variantion but not the information dependend on the variaten type.
In my example I would like to sell furniture.
The image changes with the type of wood you choose just like the product code and the price.
How do I get that working?
I'm working in windows 7 with phonegap / google chrome ripple emulator
I'm working with drupal 7
It's not my first website, but the first time I use e-commerce and drupalgap.
I've watch the video and followed the tutorial.
tyler
Tue, 01/20/2015 - 09:52
Permalink
You'll most likely have to
You'll most likely have to dig into the code that powers the Commerce module for DrupalGap (commerce.js). It was built for demonstration purposes, and to my knowledge hasn't been used in a production environment yet, so it needs some improvements to accommodate a wider range of Commerce set ups.