[Mod] Sending Customized SMS Messages

Modules, Add-ons and custom code that's more than just a quick hack or Mod.
Post Reply
Griever
Posts: 5
Joined: Fri Jul 24, 2009 7:27 pm

[Mod] Sending Customized SMS Messages

Post by Griever »

Known Compatability: v5.0.3 I am going to assume this works in later versions (and possibly earlier) as well...

Purpose

I had always thought (and so have customers) that it would be nice to choose to get sms alerts based on actions outside of ordering. For example, my website has a lot of extended frontend features where the customer can do several things outside of making orders, such as registering particular items to their account and submitting them for maintenance. In this aspect, it would be very convenient for these customers (and admins) to receive a short and simple sms alert after a particular event takes place.

Installation & Explanation

I am going to use one of my customized files as an example, and will assume that you can follow along appropriately. If you have any difficulties understanding this, please feel free to let me know.

So let's take this example: A client registers an instrument onto their account via the frontend. In this particular setup, once a user registers their instrument, an SMS alert is sent to that user for confirmation. This isn't always the case, but on my website I actually setup a customized "hierarchy" for special users. Think of it as being an admin on the frontend where you manage a subset of users. This is a great way of tracking which of your own clients are working, and is an extremely marketable feature taboot. So anyway, this "super user" is generally the one recieving the message.

Let's take a look at the code for when a user sets up their instrument:
/includes/class/class.tracking.php
(function stripped down to only show relevant information...)

Code: Select all

private function SendRegisterNewEquipment() {
        // Trigger all active new order notification methods
        $this->_SendTrackingNotifications('instrumentation');

        header("Location: ".$GLOBALS['ShopPath']."/tracking.php?action=");
    }
Notice the "$this->_SendTrackingNotifications();" line. This is another function within the same file which does the magic... which is shown below:

Code: Select all

private function _SendTrackingNotifications($type) {
        // Firstly, are there any order notification methods that are enabled?
        $notifications = GetEnabledNotificationModules();

        if(is_array($notifications) && count($notifications) > 0) {
            foreach($notifications as $notifier) {
                // Instantiate the notification object by reference
                if(GetModuleById('notification', $notify_object, $notifier['object']->GetId())) {
                    // Set the required variables
                    $notify_object->SetOrderId(23);
                    $notify_object->SetOrderTotal(50000.00);
                    $notify_object->SetOrderNumItems(1);
                    $notify_object->SetOrderPaymentMethod('Credit Card');

                    $response = $notify_object->SendNotification($type);

                    if(isset($response['outcome']) && $response['outcome'] == "fail") {
                        $GLOBALS['ISC_CLASS_LOG']->LogSystemError(array('notification', $notify_object->_name), GetLang('NotificationOrderError'), $response['message']);
                    } else if(isset($response['outcome']) && $response['outcome'] == "success") {
                        $GLOBALS['ISC_CLASS_LOG']->LogSystemSuccess(array('notification', $notify_object->_name), GetLang('NotificationOrderSuccess'), $response['message']);
                    }
                }
            }
        }
    }
After setting some generic required variables to mend well with the notification.php file, the $type parameter is taken into consideration and used with the $notify_object's SendNotification() method. This will not work unless you have customized your SMS module file. To see what I have done with mine, take a look below.

/modules/notification/module.sms.php
Note: This is not the original file, nor is it the file in its entirety. I have just pasted the two functions which have been modified for this particular purpose.

Code: Select all

    /**
     * Build and format the message to be sent (extended)
     */
    private function BuildSmsMessage($type = '') {
        $firephp->info('inside '.__FUNCTION__);
        if($type == '') {
            $firephp->log('type = null');
            // We'll use the SMSMessageContents variable from the modules.ini language file
            $message = sprintf(GetLang('SMSMessageContents'), $this->_orderid, $GLOBALS['StoreName'], $this->_ordernumitems, FormatPrice($this->_ordertotal, false, true, false, GetDefaultCurrency()), $this->_orderpaymentmethod);
            return urlencode($message);
        } elseif($type == 'instrumentation') {
            $firephp->log('type = instrumentation');
            $message = sprintf(GetLang('SMSInstrumentationSetup'), $GLOBALS['StoreName'], '[instrument name]', '[serialnumber]');
            return urlencode($message);
        }
    }

    /**
     * Send the order notification SMS text message
     */
    public function SendNotification($type = '') {
        $firephp->info('inside '.__FUNCTION__);
        // Load up the variables for the SMS gateway
        $this->_username = $this->GetValue("username");
        $this->_password = $this->GetValue("password");
        $this->_cellnumber = $this->GetValue("cellnumber");

        if($type == '') {
            $this->_message = $this->BuildSmsMessage(); // send the standard SMS message
        } elseif($type == 'instrumentation') {
            $this->_message = $this->BuildSmsMessage('instrumentation');
        }

        $sms_url = sprintf("http://www.smsglobal.com.au/http-api.php?action=sendsms&user=%s&password=%s&from=%s&to=%s&clientcharset=UTF-8&text=%s", $this->_username, $this->_password, $this->_cellnumber, $this->_cellnumber, urlencode($this->_message));

        // Let's try to send the message
        $result = PostToRemoteFileAndGetResponse($sms_url);

        if(is_numeric(isc_strpos($result, "OK"))) {
            $result = array("outcome" => "success",
                "message" => sprintf(GetLang('SMSNotificationSentNumber'), $this->_cellnumber)
            );
        } else {
            // The message couldn't be sent. Do they have enough credit?
            $low_balance = false;
            $bal_url = sprintf("http://www.smsglobal.com.au/http-api.php?action=balancesms&user=%s&password=%s", $this->_username, $this->_password);
            $bal_result = PostToRemoteFileAndGetResponse($bal_url);

            // SMSGlobal returns the balance in the format: BALANCE: 0.0999999; USER: johndoe
            $bal_data = explode(";", $bal_result);

            if(is_array($bal_data) && count($bal_data) > 1) {
                $bal_data_1 = explode(":", $bal_data[0]);

                if(is_array($bal_data_1)) {
                    $balance = floor((int)trim($bal_data_1[1]));

                    if($balance == 0) {
                        $low_balance = true;
                    }
                }
            }

            if($low_balance) {
                $error_message = GetLang('SMSZeroBalance');
            } else {
                $error_message = $bal_result;
            }

            $result = array("outcome" => "fail",
                "message" => $error_message
            );
        }

        return $result;
    }
As you can see, I have essentially taken the original SMS building and SMS sending methods, and given them support to handle an accepted parameter. This is required because you have to take into consideration the other functions which will still be using this file for standard SMS alerts. As you can see in the BuildSMSMessage() function, I am doing a check for a type of 'instrumentation'. If that is found within the sent arguments, then it will generate a seperate message with seperate data, and pass that to be sent along, thus generating a whole new SMS alert.

These can be done on a CRON basis, or any setup really. A good thing to remember though is that this was a poor example for anybody planning on doing this with their own customers. Right now, if you look closely at the files, the username, password, and cell number are taken straight from the admin configuration. This brings up a problem; You can now only use a single phone number to recieve these alerts. I have written around this in my build, but that is another tutorial in itself. This article was basically to give you a proper footing into sending your own custom SMS messages.

Hopefully you learned something. Remember, feel free to complain if you couldn't understand my writing. I tend to go a little crazy when I write these things and forget to explain myself sometimes... :oops: But I'll try my best to clear things up if you need assistance.
Post Reply