Create an OpenCart SMS Extension to Notify Store Owners of New Orders

May 10, 2019
Written by
Olawale Williams
Contributor
Opinions expressed by Twilio contributors are their own

Create an OpenCart SMS Extension to Notify Store Owners of New Orders.png

In this tutorial, we'll explore how to use the Twilio SMS API to create an OpenCart module that sends an SMS when a customer places an order, registers, or has their order history modified.

OpenCart is a free open source e-commerce platform for online merchants. It provides a professional and reliable foundation from which to build a successful online store. This foundation appeals to a wide variety of users; ranging from seasoned web developers looking for a user-friendly interface to use, to shop owners just launching their business online for the first time.

Tutorial Requirements

  • PHP development environment using lamp (for Linux users), xampp (for windows users) e.t.c.
  • Global installation of Composer
  • Twilio Account
  • OpenCart Installation

OpenCart requirement and Installation

OpenCart requirements and installation can be found in the OpenCart official documentation.

Understand the OpenCart folder structure

The OpenCart is one of the great examples of MVC framework as it provides separate folders for controller, model, view and language. In order to start creating your first OpenCart module, you must know the basic fundamentals of OpenCart. You can learn the basic fundamentals of OpenCart by visiting the OpenCart documentation. For creating a module in OpenCart, you have to follow a directory structure. You can learn about the directory structure here. So, in order to start module development in OpenCart, you have to create a file in the module folder of each controller, language, and view. You don’t need to create a model file in module development as your values of the module will be stored in a table named setting. The queries for saving the values in the setting table are written in the admin->model->setting->setting.php file.

Create a new OpenCart Twilio SMS custom module

Twilio Messaging API

The Twilio Messaging API makes it easy to send and receive SMS and MMS messages as well as query meta-data about text messages such as delivery status, associated media, and leverage tools like Copilot to manage your messages globally at scale. In this tutorial, we will only be using the SMS API for our OpenCart module. We will first learn the module development in OpenCart 3.2.0 (which at the time of writing is the latest).

First, we will create all the folders and files needed for this module using the given tree hierarchy below into a folder upload:

c:\users\willy\desktop\twilio\twilio-sms.ocmod

|
|   install.xml
|

\---upload
    +---admin
    |   +---controller
    |   |   \---extension
    |   |       \---module
    |   |               twilio_sms.php
    |   |
    |   +---language
    |   |   \---en-gb
    |   |       \---extension
    |   |           \---module
    |   |                   twilio_sms.php
    |   |
    |   \---view
    |       \---template
    |           \---extension
    |               \---module
    |                       twilio_sms.twig
    |
    \---catalog
        \---view
            \---theme
                \---default
                    \---template
                        \---mail
                                order_add_sms.twig
                                order_edit_sms.twig

Create an admin interface to store the Twilio SMS Account credentials

To create the admin interface to store the Twilio SMS account credential three (3) files will be modified:

upload/admin/controller/extension/module/twilio_sms.php controls the model, language and how to parse all the data to be used in the view file. In this file, you will also learn many other things about OpenCart such as how to load language, model, views and how to make their use of them in the view file. Add the following code to twilio_sms.php.

<?php
class ControllerExtensionModuleTwilioSms extends Controller {
        private $error = array();

        public function index() {
                $this->load->language('extension/module/twilio_sms');

                $this->document->setTitle($this->language->get('heading_title'));

                $this->load->model('setting/setting');

                if (($this->request->server['REQUEST_METHOD'] == 'POST') && $this->validate()) {
                        $this->model_setting_setting->editSetting('module_twilio_sms', $this->request->post);

                        $this->session->data['success'] = $this->language->get('text_success');

                        $this->response->redirect($this->url->link('marketplace/extension', 'user_token=' . $this->session->data['user_token'] . '&type=module', true));
                }

                if (isset($this->error['warning'])) {
                        $data['error_warning'] = $this->error['warning'];
                } else {
                        $data['error_warning'] = '';
                }

                $data['breadcrumbs'] = array();

                $data['breadcrumbs'][] = array(
                        'text' => $this->language->get('text_home'),
                        'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token'], true)
                );

                $data['breadcrumbs'][] = array(
                        'text' => $this->language->get('text_extension'),
                        'href' => $this->url->link('marketplace/extension', 'user_token=' . $this->session->data['user_token'] . '&type=module', true)
                );

                $data['breadcrumbs'][] = array(
                        'text' => $this->language->get('heading_title'),
                        'href' => $this->url->link('extension/module/twilio_sms', 'user_token=' . $this->session->data['user_token'], true)
                );

                $data['action'] = $this->url->link('extension/module/twilio_sms', 'user_token=' . $this->session->data['user_token'], true);

                $data['cancel'] = $this->url->link('marketplace/extension', 'user_token=' . $this->session->data['user_token'] . '&type=module', true);

                if (isset($this->request->post['module_twilio_sms_sms_status'])) {
                        $data['module_twilio_sms_status'] = $this->request->post['module_twilio_sms_status'];
                } else {
                        $data['module_twilio_sms_status'] = $this->config->get('module_twilio_sms_status');
                }

                if (isset($this->request->post['module_twilio_sms_account_sid'])) {
                        $data['module_twilio_sms_account_sid'] = $this->request->post['module_twilio_sms_account_sid'];
                } else {
                        $data['module_twilio_sms_account_sid'] = $this->config->get('module_twilio_sms_account_sid');
                }

                if (isset($this->request->post['module_twilio_sms_account_auth_token'])) {
                        $data['module_twilio_sms_account_auth_token'] = $this->request->post['module_twilio_sms_account_auth_token'];
                } else {
                        $data['module_twilio_sms_account_auth_token'] = $this->config->get('module_twilio_sms_account_auth_token');
                }

                if (isset($this->request->post['module_twilio_sms_account_phone_number'])) {
                        $data['module_twilio_sms_account_phone_number'] = $this->request->post['module_twilio_sms_account_phone_number'];
                } else {
                        $data['module_twilio_sms_account_phone_number'] = $this->config->get('module_twilio_sms_account_phone_number');
                }

                $data['header'] = $this->load->controller('common/header');
                $data['column_left'] = $this->load->controller('common/column_left');
                $data['footer'] = $this->load->controller('common/footer');

                $this->response->setOutput($this->load->view('extension/module/twilio_sms', $data));
        }

        protected function validate() {
                if (!$this->user->hasPermission('modify', 'extension/module/twilio_sms')) {
                        $this->error['warning'] = $this->language->get('error_permission');
                }

                return !$this->error;
        }
}

upload/admin/language/en-gb/extension/module/twilio_sms.php will assign the languages to the indices of an array. Please keep in mind that $_ is the name of the array. Add the following code to this file.

<?php
// Heading
$_['heading_title']    = 'Twilio SMS';

// Text
$_['text_extension']   = 'Extensions';
$_['text_success']     = 'Success: You have modified Twilio SMS module!';
$_['text_edit']        = 'Edit Twilio SMS Module';

// Entry
$_['entry_status']     = 'Status';
$_['entry_twilio_account_sid']     = 'Twilio account SID';
$_['entry_twilio_account_auth_token']     = 'Twilio account Auth Token';
$_['entry_twilio_account_phone_number']     = 'Twilio Phone Number';
//$_['entry_twilio_sms_body']     = 'Message body';

// Help
$_['help_twilio_account_sid']         = 'Find your Twilio Account Sid at twilio.com/console or twilio account dashboard.';
$_['help_twilio_account_auth_token']  = 'Find your Twilio Account Auth Token at twilio.com/console or twilio account dashboard.';
$_['help_twilio_account_phone_number']     =  'Find your Twilio Account Phone Number at twilio.com/console or twilio account dashboard.';
//$_['help_twilio_sms_body']     =  'This is the body of the sms to be sent once an order is placed.';
// Error
$_['error_permission'] = 'Warning: You do not have permission to modify Twilio SMS module!';

upload/admin/view/template/extension/module/twilio_sms.twig contains the view portion of the admin module graphical user interface where the Twilio SMS account details such as your Twilio Account SID, Account Auth Token, phone number and also the status of the module will be inputted, saved, and edited. In this module you can install/uninstall and also enable or disable the module from the admin view section. Add the following code to the file.

{{ header }}{{ column_left }}
<div id="content">
  <div class="page-header">
    <div class="container-fluid">
      <div class="pull-right">
        <button type="submit" form="form-module" data-toggle="tooltip" title="{{ button_save }}" class="btn btn-primary"><i class="fa fa-save"></i></button>
        <a href="{{ cancel }}" data-toggle="tooltip" title="{{ button_cancel }}" class="btn btn-default"><i class="fa fa-reply"></i></a></div>
      <h1>{{ heading_title }}</h1>
      <ul class="breadcrumb">
        {% for breadcrumb in breadcrumbs %}
        <li><a href="{{ breadcrumb.href }}">{{ breadcrumb.text }}</a></li>
        {% endfor %}
      </ul>
    </div>
  </div>
  <div class="container-fluid">
    {% if error_warning %}
    <div class="alert alert-danger alert-dismissible"><i class="fa fa-exclamation-circle"></i> {{ error_warning }}
      <button type="button" class="close" data-dismiss="alert">&times;</button>
    </div>
    {% endif %}
    <div class="panel panel-default">
      <div class="panel-heading">
        <h3 class="panel-title"><i class="fa fa-pencil"></i> {{ text_edit }}</h3>
      </div>
      <div class="panel-body">
        <form action="{{ action }}" method="post" enctype="multipart/form-data" id="form-module" class="form-horizontal">
          <div class="form-group">
            <label class="col-sm-2 control-label" for="input-status">{{ entry_status }}</label>
            <div class="col-sm-10">
              <select name="module_twilio_sms_status" id="input-status" class="form-control">
                {% if module_twilio_sms_status %}
                <option value="1" selected="selected">{{ text_enabled }}</option>
                <option value="0">{{ text_disabled }}</option>
                {% else %}
                <option value="1">{{ text_enabled }}</option>
                <option value="0" selected="selected">{{ text_disabled }}</option>
                {% endif %}
              </select>
            </div>
          </div>
          <div class="form-group">
            <label class="col-sm-2 control-label" for="input-twilio-account-sid"><span data-toggle="tooltip" title="{{ help_twilio_account_sid }}">{{ entry_twilio_account_sid }}</span></label>
            <div class="col-sm-10">
              <input type="text" name="module_twilio_sms_account_sid" value="{{ module_twilio_sms_account_sid }}" placeholder="{{ entry_twilio_account_sid }}" id="input-bnpl-limit" class="form-control" />
            </div>
          </div>
          <div class="form-group">
            <label class="col-sm-2 control-label" for="input-twilio-account-auth-token"><span data-toggle="tooltip" title="{{ help_twilio_account_auth_token }}">{{ entry_twilio_account_auth_token }}</span></label>
            <div class="col-sm-10">
              <input type="text" name="module_twilio_sms_account_auth_token" value="{{ module_twilio_sms_account_auth_token }}" placeholder="{{ entry_twilio_account_auth_token }}" id="input-twilio-account-auth-token" class="form-control" />
            </div>
          </div>
          <div class="form-group">
            <label class="col-sm-2 control-label" for="input-twilio-account-phone-number"><span data-toggle="tooltip" title="{{ help_twilio_account_phone_number }}">{{ entry_twilio_account_phone_number }}</span></label>
            <div class="col-sm-10">
              <input type="text" name="module_twilio_sms_account_phone_number" value="{{ module_twilio_sms_account_phone_number }}" placeholder="{{ entry_twilio_account_phone_number }}" id="input-twilio-account-phone-number" class="form-control" />
            </div>
          </div>
          {# <div class="form-group">
            <label class="col-sm-2 control-label" for="input-bnpl-limit"><span data-toggle="tooltip" title="{{ help_twilio_account_sid }}">{{ entry_twilio_account_sid }}</span></label>
            <div class="col-sm-10">
              <input type="text" name="payment_pay_later_twilio_account_sid" value="{{ payment_pay_later_twilio_account_sid }}" placeholder="{{ entry_twilio_account_sid }}" id="input-bnpl-limit" class="form-control" />
            </div>
          </div> #}
        </form>
      </div>
    </div>
  </div>
</div>
{{ footer }}

NOTE: The view file is written using PHP twig templating engine as this is what is supported by the OpenCart version used in this tutorial.

Setup Twilio SMS

Create SMS template files

The purpose of creating this template is to replace the built-in email template that will not fit in the SMS screen and contain unnecessary fields not needed for SMS. These are custom SMS template view files we will be using to send SMS for orders placed by customers and when the status of an order changes.

NOTE: OpenCart already has some templates for sending email. Some of these templates will also be used for sending SMS since they fit in well while two of the templates will be written our self. The files below are the templates we will be writing.

Create the following files with the specified code.

upload/catalog/view/theme/default/template/mail/order_add_sms.twig

{{ text_greeting }}

{{ text_order_id }} {{ order_id }}
{{ text_date_added }} {{ date_added }}

{{ text_order_status }}

{{ order_status }}

{% if link %}
{{ text_link }}

{{ link }}
{% endif %}

{{ text_thanks }}
{{ store }}
{{ text_order_id }} {{ order_id }}
{{ text_date_added }} {{ date_added }}

{{ text_order_status }}

{{ order_status }}

{% if link %}
{{ text_link }}

{{ link }}
{% endif %}
{% if comment %}

{{ text_comment }}

{{ comment }}
{% endif %}

{{ text_thanks }}
{{ store }}

Include Twilio PHP SDK to OpenCart using Composer

To include Twilio’s PHP SDK in OpenCart we will be using composer for the installation. Run the command below in the root directory of your OpenCart project where the composer.json is located.

$ composer require twilio/sdk

After it has finished installing, go to \OpenCart_cart\upload\system\storage\vendor to confirm the Twilio SDK installed properly by ensuring that the vendor folder contains a twilio folder like what we have below.

C:UserswillyDesktoptwilio writing filesvendor_dir.png

Understand how ocmod and OpenCart core modification system works

OpenCart Modification System

Modification System is one of the default functionalities of OpenCart allowing you to edit system functionality without directly editing core files. This feature works with creating an XML file. You can read further here for better understanding.

Implement an actions to send SMS to the customer using ocmod to modify OpenCart core

This section of this tutorial includes the virtual modification of OpenCart files with the respective functions to send, import Twilio SMS code, and taking care of users who registered their phone number with the country code and local number without the country code this way the module will be able to validate phone number before sending messages to the number.

Create a file named install.xml in the root of the module and fill it with the content of the file below or just download the file to your system at twilio-sms.ocmod->upload->install.xml.md

NOTE: The naming is very important in ocmod as this is what is going to be used for making this module installable from the open cart admin. To understand how creating a module in OpenCart works, look into the link in the previous step of this tutorial.

Now we should have something like this:

c:\users\willy\desktop\twilio\twilio-sms.ocmod
|
|   install.xml
|
\---upload
    +---admin
    |   +---controller
    |   |   \---extension
    |   |       \---module
    |   |               twilio_sms.php
    |   |
    |   +---language
    |   |   \---en-gb
    |   |       \---extension
    |   |           \---module
    |   |                   twilio_sms.php
    |   |
    |   \---view
    |       \---template
    |           \---extension
    |               \---module
    |                       twilio_sms.twig
    |
    \---catalog
        \---view
            \---theme
                \---default
                    \---template
                        \---mail
                                order_add_sms.twig
                                order_edit_sms.twig

Package Your Code Into an Installable Module

To make this module installable, zip the module (including the upload folder and the install.xml file together) and name it anything you want. In my case, I named mine twilio-SMS.ocmod.zip.

NOTE: Make sure the zip file name has an extension of ocmod.zip to avoid error when installing it from the admin end.

We should have something like this:

c:\users\willy\desktop\twilio\twilio-sms.ocmod
|
|   install.xml
|   twilio-SMS.ocmod.zip
|
\---upload
    +---admin
    |   +---controller
    |   |   \---extension
    |   |       \---module
    |   |               twilio_sms.php
    |   |
    |   +---language
    |   |   \---en-gb
    |   |       \---extension
    |   |           \---module
    |   |                   twilio_sms.php
    |   |
    |   \---view
    |       \---template
    |           \---extension
    |               \---module
    |                       twilio_sms.twig
    |
    \---catalog
        \---view
            \---theme
                \---default
                    \---template
                        \---mail
                                order_add_sms.twig
                                order_edit_sms.twig

NOTE: To install this module from the OpenCart instance admin, all you need is the zip file (twilio-sms.ocmod.zip).

This module is written to work with Nigeria phone recipient number. To make this work with your country open the file install.xml in the root of the SMS module and change all occurrence of +234 to your own country code then zip the module again, then you can install and it will work with your country.

Remember to enter a verified phone number if you are using a trial account, otherwise enter any number you’d like to receive the notifications from.

Testing

To test, open up your website on the browser and navigate to the admin area (website/admin).

  • From the Admin interface, install the module we just created and refresh the modification for our changes to take place
  • From the Admin interface, fill in your Twilio account credentials
  • From the customer shopping interface,
    • make an order and confirm an SMS is sent
    • register a customer and confirm an SMS is sent
    • approve a customer and confirm an SMS is sent
    • reject a customer and confirm an SMS is sent
    • modify the order history and confirm an SMS is sent

Testing Result

I have carried out  my own testing and the results are below:

SMS result

G:twilio writing filesarticuleScreenshot_20190216-170409.png

G:twilio writing filesarticule2.png

G:twilio writing filesarticule0.png

G:twilio writing filesarticule3.png


Potential Issues

SMS region permission:

Unable to create record: Permission to send an SMS has not been enabled for the region indicated by the 'To' number.

Text message error

Solution:

What you need to do is go to your Twilio console, to the Geographic permissions (https://www.twilio.com/console/SMS/settings/geo-permissions) for SMS section and ensure you have the permission checked for sending to the country number you bought or the one you chose for your trial account. For me, mine is "US".

Permission error page:

Get permission error page when the Twilio credential module page is opened.

permission denied error

Solution:

Goto System->Users->User Groups in the admin to grant access and modify permission to the user group as shown below.

modify permissions

Conclusion

Now that you have completed this tutorial, you know how to:

  • Create a custom open cart module
  • Include the Twilio SDK in a new OpenCart module
  • Add Twilio’s Programmable SMS to your OpenCart Store

Congratulations! You have just set up an OpenCart SMS module that sends corresponding SMS notification using Twilio programmable SMS API. Twilio programmable SMS API can be used for a lot more than we just did. You could work on building a customer service chatbot that not only alerts customers but also receives customer replies via text messages to address customers complaints, and also provides a timely response and leverage tools like Copilot to manage your messages globally at scale. I look forward to hearing about your projects.

The complete code can be found on Github.

NOTE: To use the code directly from my GitHub repo, you have to run the composer command (composer require twilio/sdk ) in the root folder of your OpenCart installation where the composer.json for Twilio object to be available globally within the OpenCart installation and also don’t forget to verify your phone number for your trial account.

 

You can reach me via:

Email: olawalewilliams9438@gmail.com
Twitter: @sirwilly94
Github: williams9438