Sipgate() Class

I wanted a PHP class that used the Sipgate API for sending SMS (text) messages, and to enable click-to-dial (click2dial) on my desk phone, which uses Sipgate as its VoIP provider. I couldn't find one online, so I wrote one.

If you specify a country It runs phone numbers through a filter to add the correct international dialing code

Source code

class Sipgate
{
	var $username;
	var $password;
	var $sip_id;

	// Init.

		function Sipgate($username, $password, $sip_id = false)
		{
			$this->username = $username;
			$this->password = $password;
			$this->sip_id = $sip_id;
		}

	// System methods.

		// Request a list of the RPC methods offered by the server with each entry being the name of a method stored as string value.
		// Returns the response as an array.
		function list_methods()
		{
			return $this->_request('system.listMethods');
		}

		// Request a human readable description of the given method containing information about purpose and usage.
		// Returns the response as an array.
		function method_help($method)
		{
			return $this->_request('system.methodHelp', array('MethodName' => $method));
		}

		// Request the signature of the given RPC method. 
		// The server will return a list of signatures valid for the specified method. 
		// The signature is defined as the promised return value?s type followed by the types of any arguments. 
		// A method MAY be called in more than one way, which is what the purpose of defining signatures is meant to distinguish.
		// Returns the response as an array.
		function method_signature($method)
		{
			return $this->_request('system.methodSignature', array('MethodName' => $method));
		}

		// The system.serverInfo method provides specific information on the server software.
		// Returns the response as an array.
		function server_info()
		{
			return $this->_request('system.serverInfo');
		}

	// Samurai functions.

		// Request an account statement for a specified period.
		// Returns the full response as an array.
		function account_statement($time_from = 0, $time_to = false)
		{
			if (!$time_to) $time_to = time();

			$args = array('PeriodStart' => date('c', $time_from), 'PeriodEnd' => date('c', $time_to));
			return $this->_request('samurai.AccountStatementGet', $args);
		}

		// The client SHOULD identify itself to the server including version and vendor information to allow for better support in cases of problems.
		// Returns true on success or false on failure.
		function identify($client_vendor, $client_name, $client_version = '1.0')
		{
			$args = array('ClientName' => $client_name, 'ClientVersion' => $client_version, 'ClientVendor' => $client_vendor);
			return $this->_request('samurai.ClientIdentify', $args);
		}

		// Request the list of SIP URIs belonging to the user's account.
		// Returns array of SIP URIs on success, false on failure.
		function uris()
		{
			if ($response = $this->_request('samurai.OwnUriListGet')) return $response['OwnUriList'];
			else return false;
		}

		// Request the current balance of the users account in pence
		// Returns balance on success or false on failure (remember to === false in case of zero balance).
		function balance()
		{
			if ($response = $this->_request('samurai.BalanceGet')) return $response['CurrentBalance']['TotalIncludingVat']; // Round to pence.
			else return false;
		}

		// Click-to-dial.
		// $number must have no spaces and include an international calling code, but no IDD or NDD prefixes (0, 00, +, etc).
		// Returns SessionID on success, false on failure.
		function call($number, $time = false)
		{
			if (!$this->sip_id)
			{
				trigger_error('SIP-ID is required for click-to-dial.', E_USER_ERROR);
				return false;
			}

			$args = array('LocalUri' => 'sip:' . $this->sip_id . '@sipgate.co.uk', 'RemoteUri' => 'sip:' . $number . '@sipgate.net', 'TOS' => 'voice', 'Content' => '');
			if ($time) $args['Schedule'] = date('c', $time);

			if ($response = $this->_request('samurai.SessionInitiate', $args)) return $response['SessionID'];
			else return false;
		}

		// Hang up after a click-to-dial.
		// $session_id must be an open session.
		// Returns true on success, false on failure.
		function call_end($session_id)
		{
			$args = array('SessionID' => $session_id);

			if ($response = $this->_request('samurai.SessionClose', $args)) return true;
			else return false;
		}

		// Get status of a session.
		// $session_id must be a valid session.
		// Returns human-readable status on success, false on failure (or session not found, ie call ended).
		function call_status($session_id)
		{
			$args = array('SessionID' => $session_id);

			if ($response = $this->_request('samurai.SessionClose', $args)) return $response['SessionStatus'];
			else return false;
		}

		// Send a text message to a phone number.
		// $country must be a two-letter ISO code.
		// $number must have no spaces and include an international calling code, but no IDD or NDD prefixes (0, 00, +, etc).
		//  It can also be an array of numbers to send the text to multiple phones.
		// Returns true on success, false on failure.
		function text($number, $message, $time = false)
		{
			if (is_array($number))
			{
				$args = array('RemoteUri' => array(), 'TOS' => 'text', 'Content' => $message);

				foreach ($number as $t_number) $args['RemoteUri'][] = 'sip:' . $t_number . '@sipgate.net';

				if ($time) $args['Schedule'] = date('c', $time);

				if ($response = $this->_request('samurai.SessionInitiateMulti', $args)) return true;
				else return false;
			}
			else
			{
				$args = array('RemoteUri' => 'sip:' . $number . '@sipgate.net', 'TOS' => 'text', 'Content' => $message);
				if ($time) $args['Schedule'] = date('c', $time);

				if ($response = $this->_request('samurai.SessionInitiate', $args)) return true;
				else return false;
			}
		}

	// Private functions.

		// Do a request and throw an error on failure.
		// Returns true on success and false on failure.
		private function _request($method, $args = array())
		{
			$url = 'https://' . $this->username . ':' . $this->password . '@samurai.sipgate.net/RPC2';

			$request = xmlrpc_encode_request($method, $args);
			$context = stream_context_create(array('http' => array(
				'method' => 'POST',
				'header' => 'Content-Type: text/xml',
				'content' => $request
			)));

			$file = file_get_contents($url, false, $context);
			$response = xmlrpc_decode($file);

			if ($response['StatusCode'] == 200) return ($response);
			else
			{
				if ($response['faultCode']) trigger_error($response['faultCode'] . ': ' . $response['faultString'], E_USER_ERROR);
				elseif ($response['StatusCode']) trigger_error($response['faultString'], E_USER_ERROR);
				else trigger_error('Sipgate error.', 'Unknown error in Sipgate response.', E_USER_ERROR);
				return false;
			}
		}
}

Examples

Click-to-dial

Start a call on your desk phone.

$username = 'username'; // Your Sipgate username.
$password = 'password'; // Your Sipgate password.
$sip_id = '1234567'; // SIP-ID of your desk phone.
$sg = new Sipgate($username, $password, $sip_id);

$phone = '441234567890' // Phone number you want to dial formatted for Sipgate.

$sg->call($phone); // Dial the number.

Sending an SMS

Send an SMS via Sipgate. A SIP-ID is not required for sending SMS messages.

$username = 'username'; // Your Sipgate username.
$password = 'password'; // Your Sipgate password.
$sg = new Sipgate($username, $password);

$phone = '441234567890' // Phone number you want to dial formatted for Sipgate.

$message = 'Hi, this is just a test message!';

$sg->text($phone, $message); // Send the text.

Format phone numbers

I like to run phone numbers through this function to remove the spaces and format them for Sipgate.

If you specify a country, the function uses my Countries dataset PHP array to strip national dialing prefixes (eg '0') and add the correct international dialing code (eg '44' or '48') to phone numbers.

// Format the phone number for Sipgate.
function sipgate_format_phone($number, $country = false)
{
	$number = preg_replace('/[^0-9+]/', '', (substr($number, 0, 20))); // Remove everything except letters and plusses.
	if (empty($number)) return false;

	if (!$country) return $number; // No country - fingers crossed!
	if (substr($number, 0, 1) == '+') return substr($number, 1); // Already an international number - just trim the plus and don't add any prefixes.

	// Load international dialing rules.
	if ($country == 'GB') $rules = array('dial' => '44', 'idd' => '00', 'ndd' => '0');
	else
	{
		include('list_dialing.php');
		if (!$rules = $GLOBALS['dialing'][$country]) return $number; // Invalid ISO code - we can't fix it :'(
	}

	if (strlen($rules['ndd']) > 0 && substr($number, 0, strlen($rules['ndd'])) == $rules['ndd']) return $rules['dial'] . substr($number, strlen($rules['ndd'])); // Trim off the national prefix if it's there.
	else return $rules['dial'] . $number; // If it's not, return the international prefix.
}

Example

$phone = '01234 567 890';
$phone = sipgate_format_phone($phone, 'GB'); // UK number.
echo $phone; // Outputs 441234567890

$phone = '01234 56 78 90';
$phone = sipgate_format_phone($phone, 'DE'); // German number.
echo $phone; // Outputs 491234567890