Drupal 6 SMS Framework: Esendex PHP5 SOAP Gateway

Submitted by nigel on Wednesday 30th December 2009

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($sendxmlXSD_ANYXMLNULLNULLNULL);
            
$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($headerxmlXSD_ANYXMLNULLNULLNULL);
    
$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
blog terms
Drupal Drupal 6 PHP