Drupal 6 SMS Framework: Esendex PHP5 SOAP Gateway

Drupal 6 SMS Framework enables the sending of SMS from a Drupal 6 website, through a suitable bureau service. The 'glue' between the SMS Framework module and the chosen SMS bureau is called a 'gateway'. Each bureau needs the development of a dedicated gateway, and currently there are few available. In reality, the only gateways for Drupal 6 are Clickatell and a generic email facility.

In the hope of encouraging others to have a go, I have developed another. My gateway connects to UK (amongst others) provider Esendex. Furthermore, I have opted to code in PHP5 and using the PHP5 built-in SOAP module. This means that should you be tempted to develop a SOAP gateway for another bureau, you can use my module as a starting point.

There are a couple of negatives. Firstly, the module only works with PHP5 and the built-in SOAP class. If you wish to extend this, there are plenty of tutorials on the Internet to guide you.

Currently, the module only allows a single send, although my intention is to develop my module further to allow for multi-recipient messages. In addition, there is no incoming message facility. This may toddle along in the fullness of time. Finally, it would be great to have a message status facility but this is a shortcoming of the Framework and as such I am reliant upon the Framework developers to include this.

Below is the code. If you have any comments, please register and add as appropriate.
sms_esendex.module

<?php
// Copyright <a href="http://www.badzilla.co.uk
//" title="www.badzilla.co.uk
//">www.badzilla.co.uk
//</a> Licence GPL. This program may be distributed as per the terms of GPL and all credits
// must be retained
//
// If you find this script useful, please consider a donation to help me fund my web presence
// and encourage me to develop more products to be placed under the terms of GPL
// To donate, go to <a href="http://www.badzilla.co.uk" title="http://www.badzilla.co.uk">http://www.badzilla.co.uk</a> and click on the donation button
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

/**
* @file
* Adds support for sending SMS messages using the Esendex gateway.
* Authored by badzilla.co.uk
* November/December 2009
*/

/**
* Implementation of hook_gateway_info().
*/
function sms_esendex_gateway_info() {
  return array(
   
'esendex' => array(
     
'name' => 'Esendex',
     
'configure form' => 'sms_esendex_admin_form',
     
'send' => 'sms_esendex_send',
    ),
  );
}



/**
* Callback for sending messages.
*/
function sms_esendex_send($number, $message, $options) {
   
    return
sms_esendex_command('sendmsg', array('number' => $number, 'message' => $message));
}



function
sms_esendex_admin_form($configuration) {

   
$form['sms_esendex_messagelimit'] = array(
       
'#type' => 'item',
       
'#title' => t('Message Limit'),
       
'#value' => sms_esendex_messagelimit(),
    );
 
   
$form['sms_esendex_account'] = array(
       
'#type' => 'textfield',
       
'#title' => t('Account'),
       
'#description' => t('Esendex Account.'),
       
'#size' => 40,
       
'#maxlength' => 255,
       
'#default_value' => $configuration['sms_esendex_account'],
    );

   
$form['sms_esendex_user'] = array(
       
'#type' => 'textfield',
       
'#title' => t('User'),
       
'#description' => t('The username of your Esendex account.'),
       
'#size' => 40,
       
'#maxlength' => 255,
       
'#default_value' => $configuration['sms_esendex_user'],
    );

   
$form['sms_esendex_password'] = array(
       
'#type' => 'textfield',
       
'#title' => t('Password'),
       
'#description' => t('The current password on your Esendex account.'),
       
'#size' => 30,
       
'#maxlength' => 64,
       
'#default_value' => $configuration['sms_esendex_password'],
    );
 
    return
$form;
}



/**
* Gets the current message limit
*/
function sms_esendex_messagelimit() {
   
   
$ret = sms_esendex_command('limit');
    return isset(
$ret['data']) ? $ret['data'] : t('N/A');
}




/**
* Validates the submission of the configuration form.
*/
function sms_esendex_admin_form_validate($form, &$form_state) {
   
   
$result = sms_esendex_command('state', array(), $form_state['values']);
 
    if (
$result['status'])
       
form_set_error('', '');

}



function
sms_esendex_command($command = 'state', $data = array(), $config = NULL) {

   
$gateway = sms_gateways('gateway', 'esendex');

    if (
$config == NULL)
       
$config = $gateway['configuration'];

    switch(
$command) {
        case
'state':
        case
'limit':
           
$endpoint = 'https://www.esendex.com/secure/messenger/soap/AccountService.asmx?wsdl';
           
$soapaction = 'com.esendex.ems.soapinterface/GetAccountState';
           
$args = array(new SoapParam('', 'com:GetAccountState'));
           
$fname = 'GetAccountState';
            break;

        case
'sendmsg':
           
$endpoint = 'https://www.esendex.com/secure/messenger/soap/SendService.asmx?wsdl';
           
$soapaction = 'com.esendex.ems.soapinterface/SendMessage';

           
$sendxml = '<com:SendMessage>';
           
$sendxml .= '<com:recipient>' . $data['number'] . '</com:recipient>';
           
$sendxml .= '<com:body>' . $data['message'] . '</com:body>';
           
$sendxml .= '<com:type>Text</com:type>';
           
$sendxml .= '</com:SendMessage>';

           
$sendbody = new SoapVar($sendxml, XSD_ANYXML, NULL, NULL, NULL);
           
$args = array("ItemXml" => $sendbody);
           
           
$fname = 'SendMessage';
            break;

    }

   
// override the __doRequest to hack the ns1 namespace prefix which seems to stuff up the esendex server
    // for some reason their ASP.NET server demands a namespace prefix of 'com'
   
if (!class_exists(MSSoapClient)) {
            class
MSSoapClient extends SoapClient {

            function
__doRequest($request, $location, $action, $version) {
               
               
$request = str_replace('ns1', 'com', $request);

               
// parent call - note that a snapshot of $request is held in a buffer so
                // subsequent dump using __getLastRequest *WILL NOT* reflect the changes effected
                // here. This is a known feature.
                // See PHP manual php.net/manual/en/soapclient.dorequest.php
               
return parent::__doRequest($request, $location, $action, $version);

            }
        }
    }

   
// PHP5 built-in SOAP client
   
$param = array('location' => $endpoint,
                  
'uri'      => 'com.esendex.ems.soapinterface',
                  
'style'    => SOAP_DOCUMENT,
                  
'use'      => SOAP_LITERAL,
                  
'trace'    => 1);

   
$soap = new MSSoapClient(NULL, $param);

   
$options = array('location'   => $endpoint,
                    
'uri'        => 'com.esendex.ems.soapinterface',
                    
'soapaction' => $soapaction);

   
$headerxml = '<com:MessengerHeader>';
   
$headerxml .= '<com:Username>' . $config['sms_esendex_user'] . '</com:Username>';
   
$headerxml .= '<com:Password>' . $config['sms_esendex_password'] . '</com:Password>';
   
$headerxml .= '<com:Account>' . $config['sms_esendex_account'] . '</com:Account>';
   
$headerxml .= '</com:MessengerHeader>';

   
$headerbody = new SoapVar($headerxml, XSD_ANYXML, NULL, NULL, NULL);
   
$header = new SOAPHeader('com.esendex.ems.soapinterface', 'MessengerHeader', $headerbody);

   
// attempt the soap call; if error then log the messages and return
   
try {
       
$result = $soap->__soapCall($fname, $args, $options, $header);
    } catch (
SoapFault $soapFault) {
       
watchdog('sms', 'Esendex Request Headers: %s', array('%s' => $soap->__getLastRequestHeaders()));
       
watchdog('sms', 'Esendex Request: %s', array('%s' => $soap->__getLastRequest()));
       
watchdog('sms', 'Esendex Error Response: %s', array('%s' => $soapFault));
        if (!isset(
$soapFault->faultcode))
           
drupal_set_message(t('Esendex Error: Refer to System Report for Stack Trace'), 'error');
        else
           
drupal_set_message(t('Esendex Error @errno: @errstr',
                                  array(
'@errno' => $soapFault->detail->ErrorCode,
                                       
'@errstr' => $soapFault->detail->ErrorMessage)), 'error');

        return array(
'status' => true, 'data' => NULL);
    }

   
// no error so everything ok. Extract the returning data we need
    // uncomment below for debugging
    // watchdog('sms', 'Esendex Result: @res', array('@res' => print_r($result, TRUE)));
   
switch($command) {
        case
'state':
        case
'limit':
           
$retdata = $result->MessageLimit;
            break;

        case
'sendmsg':
           
// do nothing
           
$retdata = '';
            break;
    }   


    return array(
'status' => false, 'data' => $retdata);
}
?>

sms_esendex.info
;
name = "Esendex"
description = "Allows the SMS Framework to use Esendex as a gateway."
package = SMS Framework
dependencies[] = sms
core = 6.x


AttachmentSize
esendex-0.1.1.tar.gz2.7 KB