You are here

sms_twilio.module in Twilio SMS Integration 7.2

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

Adds support for sending SMS messages using the Twilio gateway.

File

sms_twilio.module
View source
<?php

use Twilio\Rest\Client;
use Twilio\Security\RequestValidator;

/**
 * @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',
    ),
  );
}
function sms_twilio_init() {
}

/**
 * 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 / Message Service ID'),
    '#description' => t('A <a href="https://www.twilio.com/user/account/phone-numbers" target="_new">phone number</a> from your Twilio account. You may also use a <a href="https://www.twilio.com/console/sms/services" target="_new">Message Service SID</a> for Copilot.'),
    '#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',
  );
  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'];
  }

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

  // Include the PHP TwilioRest library
  require_once DRUPAL_ROOT . '/' . $config['sms_twilio_path'] . '/autoload.php';

  // Instantiate a new Twilio Rest Client
  $client = new Client($AccountSid, $AuthToken);
  switch ($command) {
    case 'sendmsg':
      $payload = array(
        'body' => $data['message'],
      );
      if (strlen($config['sms_twilio_number']) == 34 && substr($config['sms_twilio_number'], 0, 2) == 'MG') {
        $payload['messagingServiceSid'] = $config['sms_twilio_number'];
      }
      else {
        $payload['from'] = $config['sms_twilio_number'];
      }
      $response = $client->messages
        ->create($data['number'], $payload);
      break;
  }
  watchdog('sms_twilio', print_r($response, TRUE));

  // Check for HTTP errors
  if ($response->errorCode != '') {
    $result = array(
      'status' => FALSE,
      'message' => t('An error occurred during the HTTP request: @error_code: @error.  Please see <a href="@twilio_url">the Twilio docs</a> for more information', array(
        '@error_code' => $response->errorCode,
        '@error' => $response->errorMessage,
        '@twilio_url' => 'https://www.twilio.com/docs/api/rest/message#error-values',
      )),
    );
    watchdog('sms_twilio', $result['message']);
  }
  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() {
  if (sms_twilio_validate_incoming_request_parameters()) {
    if (sms_twilio_validate_incoming()) {
      watchdog('sms_twilio', 'Handling incoming sms from ' . check_plain($_REQUEST['From']) . ': ' . check_plain($_REQUEST['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(check_plain($_REQUEST['From']), check_plain($_REQUEST['Body']), $opts);
    }
    else {
      watchdog('sms_twilio', 'Incoming sms from @from has a bad Twilio signature - dropping!', array(
        '@from' => check_plain($_REQUEST['From']),
      ), WATCHDOG_WARNING);
    }
  }
  else {
    watchdog('sms_twilio', 'Invalid parameters received.');
  }
}

/**
 * Validate incoming messages using Twilio SDK security methods
 *
 * @see http://www.twilio.com/docs/security
 *
 * @todo Need better way to test, as a service such as ngrok won't work without
 * specifying in $url.  Perhaps allow a configurable debugging setup which
 * accepts an alternative URL.
 */
function sms_twilio_validate_incoming() {
  global $base_url;
  $url = $base_url . $_SERVER['REQUEST_URI'];
  $gateway = sms_gateways('gateway', 'twilio');
  $config = $gateway['configuration'];
  if (!class_exists('RequestValidator')) {
    require_once DRUPAL_ROOT . '/' . $config['sms_twilio_path'] . '/autoload.php';
  }
  $signature = $_SERVER["HTTP_X_TWILIO_SIGNATURE"];
  $token = $config['sms_twilio_api_auth_token'];
  $validator = new RequestValidator($token);
  return $validator
    ->validate($signature, $url, $_REQUEST);
}

/**
 * Validate incoming request has necessary parameters
 */
function sms_twilio_validate_incoming_request_parameters() {
  return isset($_REQUEST['From']) && isset($_REQUEST['To']) && isset($_REQUEST['FromCountry']) && isset($_REQUEST['FromCity']) && isset($_REQUEST['FromState']) && isset($_REQUEST['FromZip']);
}

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_init
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
sms_twilio_validate_incoming Validate incoming messages using Twilio SDK security methods
sms_twilio_validate_incoming_request_parameters Validate incoming request has necessary parameters