You are here

sms_twilio.module in Twilio SMS Integration 7

Same filename and directory in other branches
  1. 6 sms_twilio.module
  2. 7.2 sms_twilio.module

Adds support for sending SMS messages using the Twilio gateway.

File

sms_twilio.module
View source
<?php

define('DEFAULT_TWILIO_API_VERSION', '2010-04-01');

/**
 * @file
 * Adds support for sending SMS messages using the Twilio gateway.
 */

/**
 * Implements hook_gateway_info().
 */
function sms_twilio_gateway_info() {
  return array(
    'twilio' => array(
      'name' => 'Twilio',
      'configure form' => 'sms_twilio_admin_form',
      'receive' => TRUE,
      'send' => 'sms_twilio_send',
      'send form' => 'sms_twilio_send_form',
    ),
  );
}

/**
 * Admin/settings form.
 */
function sms_twilio_admin_form($configuration) {
  $form['sms_twilio_api_sid'] = array(
    '#type' => 'textfield',
    '#title' => t('Account SID'),
    '#description' => t('Twilio Account SID - the 34 character string beginning with AC'),
    '#size' => 40,
    '#maxlength' => 255,
    '#default_value' => !empty($configuration['sms_twilio_api_sid']) ? $configuration['sms_twilio_api_sid'] : '',
  );
  $form['sms_twilio_api_auth_token'] = array(
    '#type' => 'textfield',
    '#title' => t('API ID'),
    '#description' => t('Twilio auth token - <a href="https://www.twilio.com/user/account">available on your dashboard</a>'),
    '#size' => 40,
    '#maxlength' => 255,
    '#default_value' => !empty($configuration['sms_twilio_api_auth_token']) ? $configuration['sms_twilio_api_auth_token'] : '',
  );
  $form['sms_twilio_number'] = array(
    '#type' => 'textfield',
    '#title' => t('Number'),
    '#description' => t('A <a href="https://www.twilio.com/user/account/phone-numbers" target="_new">phone number</a> from your Twilio account'),
    '#size' => 40,
    '#maxlength' => 255,
    '#default_value' => !empty($configuration['sms_twilio_number']) ? $configuration['sms_twilio_number'] : '',
  );
  $form['sms_twilio_path'] = array(
    '#type' => 'textfield',
    '#title' => t('Twilio library path'),
    '#description' => t('The path to the twilio library'),
    '#size' => 40,
    '#maxlength' => 255,
    '#default_value' => !empty($configuration['sms_twilio_path']) ? $configuration['sms_twilio_path'] : 'sites/all/libraries/twilio',
  );
  $form['sms_twilio_api'] = array(
    '#type' => 'radios',
    '#title' => t('Twilio API Version'),
    '#description' => t('The version of the above path to use for the Twilio API'),
    '#options' => array(
      '2008-08-01' => '2008-08-01',
      '2010-04-01' => '2010-04-01',
    ),
    '#default_value' => !empty($configuration['sms_twilio_api']) ? $configuration['sms_twilio_api'] : DEFAULT_TWILIO_API_VERSION,
  );
  return $form;
}

/**
 * Validates the submission of the configuration form.
 */
function sms_twilio_admin_form_validate($form, &$form_state) {
}

/**
 * Returns custom additions to be added to the send forms
 */
function sms_twilio_send_form() {
  $form['country'] = array(
    '#type' => 'select',
    '#title' => t('Country'),
    '#multiple' => FALSE,
    '#options' => sms_country_codes(),
    '#default_value' => -1,
  );
  return $form;
}

/**
 * Callback for sending messages.
 */
function sms_twilio_send($number, $message, $options) {
  $number = preg_replace("/[^0-9\\+]/", '', $number);
  $number = trim($number);
  $number = ltrim($number, '0');

  // Remove leading zeros
  if (isset($options['country'])) {
    $index = strpos($number, $options['country']);
    if ($index === FALSE || $index > 0) {
      $number = $options['country'] . $number;
    }
  }
  return sms_twilio_command('sendmsg', array(
    'number' => $number,
    'message' => $message,
  ), NULL, NULL);
}

/**
 * Executes a command using the Twilio API
 */
function sms_twilio_command($command = 'auth', $data = array(), $config = NULL, $account = '') {
  if (!isset($config)) {
    $gateway = sms_gateways('gateway', 'twilio');
    $config = $gateway['configuration'];
  }

  // Twilio REST API version
  $ApiVersion = isset($config['sms_twilio_api']) && $config['sms_twilio_api'] ? $config['sms_twilio_api'] : DEFAULT_TWILIO_API_VERSION;

  // Set our AccountSid and AuthToken
  $AccountSid = $config['sms_twilio_api_sid'];
  $AuthToken = $config['sms_twilio_api_auth_token'];

  // Instantiate a new Twilio Rest Client
  switch ($ApiVersion) {
    case '2010-04-01':

      // Include the PHP TwilioRest library
      require_once DRUPAL_ROOT . '/' . $config['sms_twilio_path'] . '/Services/Twilio.php';
      $client = new Services_Twilio($AccountSid, $AuthToken);
      switch ($command) {
        case 'sendmsg':
          $response = $client->account->messages
            ->sendMessage($config['sms_twilio_number'], $data['number'], $data['message']);
          break;
      }
      break;
    case '2008-08-01':

      // Include the PHP TwilioRest library
      require_once DRUPAL_ROOT . '/' . $config['sms_twilio_path'] . '/twilio.php';
      $client = new TwilioRestClient($AccountSid, $AuthToken);
      switch ($command) {
        case 'sendmsg':
          $response = $client
            ->request("/{$ApiVersion}/Accounts/{$AccountSid}/SMS/Messages", "POST", array(
            "To" => $data['number'],
            "From" => $config['sms_twilio_number'],
            "Body" => $data['message'],
          ));
          break;
      }
      break;
    default:
      $result = array(
        'status' => FALSE,
        'message' => t('Invalid Twilio API: @api', array(
          '@api',
          $ApiVersion,
        )),
      );
      return $result;
  }
  watchdog('sms_twilio', print_r($response, TRUE));

  // Check for HTTP errors
  if ($response->IsError) {
    $result = array(
      'status' => FALSE,
      'message' => t('An error occured during the HTTP request: @error', array(
        '@error' => $response->ErrorMessage,
      )),
    );
  }
  else {
    $result = array(
      'status' => TRUE,
      'data' => t('Message sent to @number', array(
        '@number' => $data['number'],
      )),
    );
  }
  return $result;
}

/**
 * Implements hook_menu().
 *
 * Twilio will POST to this path when an SMS is received
 */
function sms_twilio_menu() {
  $items = array();
  $items['sms/twilio/incoming'] = array(
    'title' => 'Incoming Twilio SMS',
    'page callback' => 'sms_twilio_incoming',
    'access callback' => TRUE,
    'menu_name' => 'SMS',
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Informs the SMS Framework of the incoming SMS
 */
function sms_twilio_incoming() {
  global $base_url;
  if (isset($_REQUEST['From']) and isset($_REQUEST['To']) and isset($_REQUEST['FromCountry']) and isset($_REQUEST['FromCity']) and isset($_REQUEST['FromState']) and isset($_REQUEST['FromZip'])) {

    // Details on validating the Twilio signature: http://www.twilio.com/docs/security
    $gateway = sms_gateways('gateway', 'twilio');
    $config = $gateway['configuration'];
    $string_to_sign = $base_url . "/sms/twilio/incoming";
    ksort($_POST);
    foreach ($_POST as $key => $value) {
      $string_to_sign .= $key . $value;
    }
    $sig = base64_encode(hash_hmac("sha1", $string_to_sign, $config['sms_twilio_api_auth_token'], TRUE));
    $from = $_REQUEST['From'];
    $body = $_REQUEST['Body'];
    if (strcmp($_SERVER["HTTP_X_TWILIO_SIGNATURE"], $sig) != 0) {
      watchdog('sms_twilio', 'Incoming sms from @from has a bad Twilio signature - dropping!', array(
        '@from' => $from,
      ), WATCHDOG_WARNING);
    }
    else {

      // watchdog('sms_twilio', 'Handling incoming sms from '.$from.': '.$body);
      $opts = array();
      $opts['to'] = $_REQUEST['To'];
      $opts['fromcountry'] = $_REQUEST['FromCountry'];
      $opts['fromcity'] = $_REQUEST['FromCity'];
      $opts['fromstate'] = $_REQUEST['FromState'];
      $opts['fromzip'] = $_REQUEST['FromZip'];
      sms_incoming($from, $body, $opts);
    }
  }
}

Functions

Namesort descending Description
sms_twilio_admin_form Admin/settings form.
sms_twilio_admin_form_validate Validates the submission of the configuration form.
sms_twilio_command Executes a command using the Twilio API
sms_twilio_gateway_info Implements hook_gateway_info().
sms_twilio_incoming Informs the SMS Framework of the incoming SMS
sms_twilio_menu Implements hook_menu().
sms_twilio_send Callback for sending messages.
sms_twilio_send_form Returns custom additions to be added to the send forms

Constants