<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.innovaphone.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Treitinger</id>
	<title>innovaphone wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.innovaphone.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Treitinger"/>
	<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Special:Contributions/Treitinger"/>
	<updated>2026-05-11T16:12:38Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.42.3</generator>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Howto:SOAP_API_PHP5_Sample_Code&amp;diff=39559</id>
		<title>Howto:SOAP API PHP5 Sample Code</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Howto:SOAP_API_PHP5_Sample_Code&amp;diff=39559"/>
		<updated>2015-11-09T14:24:37Z</updated>

		<summary type="html">&lt;p&gt;Treitinger: /* The innovaphone PBX API wrapper class */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Applies To==&lt;br /&gt;
This information applies to&lt;br /&gt;
&lt;br /&gt;
* V9 innovaphone PBX platform&lt;br /&gt;
* web server running PHP 5&lt;br /&gt;
&lt;br /&gt;
innovaphone PBX web services can be used from PHP easily.  Here is how&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- web service, soap service, soapservice, webservice, php, soap api, soapapi --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==More Information==&lt;br /&gt;
===Configuration===&lt;br /&gt;
You will need php with the SoapClient class available.&lt;br /&gt;
&lt;br /&gt;
The innovaphone PBX wsdl file is required.  See [[Reference8:SOAP API]] for information how to obtain this file.  &lt;br /&gt;
To access older WSDL versions, you will need to change the WSDL URL setting (in &amp;lt;code&amp;gt;const ___wsdl&amp;lt;/code&amp;gt;) and adapt to the required number of version booleans in the call to &amp;lt;code&amp;gt;Initialize()&amp;lt;/code&amp;gt; in the pbx wrapper class.&lt;br /&gt;
&lt;br /&gt;
If you have access to the internet, you can try out the sample code given below right away.  Of course you may also adapt the sample script configuration and try with your own innovaphone PBX.&lt;br /&gt;
&lt;br /&gt;
===Running the Sample Code===&lt;br /&gt;
To demonstrate SOAP usage with PHP, a simple script is presented that will allow you to initiate a call using a web page.&lt;br /&gt;
&lt;br /&gt;
The following class &#039;&#039;&#039;innoPBX&#039;&#039;&#039; is used to wrap the (somewhat clumsy) PHP SOAP access mechanism:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// innovaphone PBX SOAP API PHP wrapper class&lt;br /&gt;
//&lt;br /&gt;
&lt;br /&gt;
class innoPBX extends SOAPClient {&lt;br /&gt;
&lt;br /&gt;
    protected $___key; 		// the session key&lt;br /&gt;
    protected $___session; 	// the session id&lt;br /&gt;
&lt;br /&gt;
    protected $___options = array(&lt;br /&gt;
				// default SOAPClient::__construct options used by the class&lt;br /&gt;
	&amp;quot;connection_timeout&amp;quot; =&amp;gt; 10,&lt;br /&gt;
	&amp;quot;exceptions&amp;quot; =&amp;gt; true,&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
    const ___wsdl = &#039;http://www.innovaphone.com/wsdl/pbx900.wsdl&#039;;&lt;br /&gt;
&lt;br /&gt;
    // class constructor&lt;br /&gt;
    public function __construct(&lt;br /&gt;
	$server, 	// the PBX IP&lt;br /&gt;
	$httpu,		// the HTTP user id (e.g. &amp;quot;admin&amp;quot;)&lt;br /&gt;
	$httpp,		// the HTTP password (e.g. &amp;quot;ip800&amp;quot;)&lt;br /&gt;
	$user = null,		// the PBX user CN to work with &lt;br /&gt;
	$options = null,&lt;br /&gt;
			// extra or overriding options for SOAPClient::__construct&lt;br /&gt;
	$wsdl = null    // the wsdl file location&lt;br /&gt;
    ) {	&lt;br /&gt;
	$wsdl = ($wsdl === null) ? self::___wsdl : $wsdl;&lt;br /&gt;
	$usedoptions = array(			// forced options&lt;br /&gt;
	    &#039;login&#039; =&amp;gt; $httpu,&lt;br /&gt;
	    &#039;password&#039; =&amp;gt; $httpp,&lt;br /&gt;
	    &#039;location&#039; =&amp;gt; &amp;quot;http://$server/PBX0/user.soap&amp;quot;,&lt;br /&gt;
			);&lt;br /&gt;
	if (is_array($options)) $usedoptions += $options;	&lt;br /&gt;
						// merge in user options&lt;br /&gt;
	$usedoptions += $this-&amp;gt;___options;	// merged in class global options&lt;br /&gt;
&lt;br /&gt;
	// construct parent class&lt;br /&gt;
	parent::__construct($wsdl, $usedoptions);&lt;br /&gt;
&lt;br /&gt;
	// get the connection (using and activating v9 wsdl)&lt;br /&gt;
	$init = $this-&amp;gt;Initialize($user, &amp;quot;PHP SOAP Wrapper&amp;quot;, true, true, true, true, true);&lt;br /&gt;
	$this-&amp;gt;___key = $init[&#039;key&#039;];&lt;br /&gt;
	$this-&amp;gt;___session = $init[&#039;return&#039;];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function key() { return $this-&amp;gt;___key; }&lt;br /&gt;
    public function session() { return $this-&amp;gt;___session; }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Save this code into a file named &#039;&#039;&#039;innopbx.class.php&#039;&#039;&#039; on your web server.  This class is of course not required to use PHP SOAP with the innovaphone PBX API.  However, it comes handy and should be generic enough to be useful in most cases.&lt;br /&gt;
&lt;br /&gt;
The SOAP client uses the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// get the innoPBX wrapper class&lt;br /&gt;
require_once(&#039;innopbx.class.php&#039;);&lt;br /&gt;
&lt;br /&gt;
// dummy classes to map SOAP results to (really would love to use namespaces here...)&lt;br /&gt;
// you can add methods and variables to these classes as needed&lt;br /&gt;
class innoUserInfo { };&lt;br /&gt;
class innoCallInfo { };&lt;br /&gt;
class innoAnyInfo { };&lt;br /&gt;
class innoGroup { };&lt;br /&gt;
class innoNo { };&lt;br /&gt;
class innoInfo { };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// config, adapt to your need&lt;br /&gt;
// this data below will work with innovaphones demo PBX.  Just register 2 phones as user-3 and user-4 and hve fun!&lt;br /&gt;
$server = &amp;quot;145.253.157.200&amp;quot;;&lt;br /&gt;
$user = &amp;quot;SOAP&amp;quot;;&lt;br /&gt;
$httpu = &amp;quot;demo&amp;quot;;&lt;br /&gt;
$httpp = &amp;quot;demo&amp;quot;;&lt;br /&gt;
$caller = &amp;quot;PBX User Four&amp;quot;;&lt;br /&gt;
$destination = &amp;quot;130&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
print &amp;quot;&amp;lt;pre&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// create connector to PBX&lt;br /&gt;
// class mapping is optional&lt;br /&gt;
$inno = new innoPBX($server, $httpu, $httpp, $user,&lt;br /&gt;
	    array(&#039;classmap&#039; =&amp;gt; array(&amp;quot;UserInfo&amp;quot; =&amp;gt; &amp;quot;innoUserInfo&amp;quot;, &lt;br /&gt;
				&amp;quot;CallInfo&amp;quot; =&amp;gt; &amp;quot;innoCallInfo&amp;quot;,&lt;br /&gt;
				&amp;quot;AnyInfo&amp;quot; =&amp;gt; &amp;quot;innoAnyInfo&amp;quot;,&lt;br /&gt;
				&amp;quot;Group&amp;quot; =&amp;gt; &amp;quot;innoGroup&amp;quot;,&lt;br /&gt;
				&amp;quot;No&amp;quot; =&amp;gt; &amp;quot;innoNo&amp;quot;,&lt;br /&gt;
				&amp;quot;Info&amp;quot; =&amp;gt; &amp;quot;innoInfo&amp;quot;,&lt;br /&gt;
			    )));&lt;br /&gt;
if ($inno-&amp;gt;key() == 0) die(&amp;quot;failed to login to PBX&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// show all methods supported by this object&lt;br /&gt;
print &amp;quot;All the functions provided by class innoPBX:\n&amp;quot;;&lt;br /&gt;
print_r($inno-&amp;gt;__getFunctions());&lt;br /&gt;
print &amp;quot;\n\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// get version info&lt;br /&gt;
$v = $inno-&amp;gt;Version();&lt;br /&gt;
&lt;br /&gt;
// show both types of infos list&lt;br /&gt;
function showInfos(&amp;amp;$poll, $head, $cn = &amp;quot;&amp;quot;, $user = &amp;quot;&amp;quot;, $call = &amp;quot;&amp;quot;) {&lt;br /&gt;
    print $head . &amp;quot;\n&amp;quot;;&lt;br /&gt;
    if ($cn !== null) {&lt;br /&gt;
	print count($poll-&amp;gt;user) . &amp;quot; UserInfos\n&amp;quot;;&lt;br /&gt;
	foreach($poll-&amp;gt;user as $ui) {&lt;br /&gt;
	    if (($cn === &amp;quot;&amp;quot;) || ($cn == $ui-&amp;gt;cn)) {&lt;br /&gt;
		print &amp;quot;     {$ui-&amp;gt;cn} ({$ui-&amp;gt;h323} #{$ui-&amp;gt;e164}) state {$ui-&amp;gt;state}\n&amp;quot;;&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
    if ($call !== null) {&lt;br /&gt;
	print count($poll-&amp;gt;call) . &amp;quot; CallInfos\n&amp;quot;;&lt;br /&gt;
	foreach($poll-&amp;gt;call as $ci) {&lt;br /&gt;
	    if ((($user === &amp;quot;&amp;quot;) || ($user == $ci-&amp;gt;user)) &amp;amp;&amp;amp;&lt;br /&gt;
		(($call === &amp;quot;&amp;quot;) || ($call == $ci-&amp;gt;call))) {&lt;br /&gt;
		    print &amp;quot;    {$ci-&amp;gt;user}/{$ci-&amp;gt;call} {$ci-&amp;gt;No[1]-&amp;gt;h323} #{$ci-&amp;gt;No[1]-&amp;gt;e164} (remote {$ci-&amp;gt;No[0]-&amp;gt;h323} #{$ci-&amp;gt;No[0]-&amp;gt;e164}) msg {$ci-&amp;gt;msg}\n&amp;quot;;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// retrieve the full user list.  Foreach object in the PBX, one userinfo is posted, terminated by an empty one&lt;br /&gt;
// You cannot assume that you will receive this list within a certain number of Poll results, so please iterate&lt;br /&gt;
print &amp;quot;Retrieving User list for &amp;quot;; foreach ($v as $name =&amp;gt; $value) print &amp;quot;\n  $name=$value &amp;quot;; print &amp;quot;...\n\n&amp;quot;;&lt;br /&gt;
$seen = false;&lt;br /&gt;
$i = 1;&lt;br /&gt;
while (!$seen) {&lt;br /&gt;
    $p = $inno-&amp;gt;Poll($inno-&amp;gt;session());&lt;br /&gt;
    showInfos($p, &amp;quot;Poll() result #$i&amp;quot;, &amp;quot;&amp;quot;, null, null); $i++;&lt;br /&gt;
    if ($p-&amp;gt;user[count($p-&amp;gt;user)-1]-&amp;gt;cn == &amp;quot;&amp;quot;) {&lt;br /&gt;
	// we have seen all entries&lt;br /&gt;
	print &amp;quot; --- END OF LIST ---\n\n&amp;quot;;&lt;br /&gt;
	$seen = true;&lt;br /&gt;
	break;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// create a call on behalf of some user&lt;br /&gt;
// first we need a user handle&lt;br /&gt;
print &amp;quot;\nObtaining a user handle for $caller...&amp;quot;;&lt;br /&gt;
$uhandle = $inno-&amp;gt;UserInitialize($inno-&amp;gt;session(), $caller);&lt;br /&gt;
print &amp;quot; $uhandle\n&amp;quot;;&lt;br /&gt;
if ($uhandle == 0) {&lt;br /&gt;
    die(&amp;quot;cant get user handle for $caller&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// then we create a call&lt;br /&gt;
print &amp;quot;Creating call from $caller to $destination...&amp;quot;;&lt;br /&gt;
$call = $inno-&amp;gt;UserCall($uhandle, null, $destination, null, 0, array());&lt;br /&gt;
print &amp;quot; $call\n&amp;quot;;&lt;br /&gt;
if ($call == 0) {&lt;br /&gt;
    die(&amp;quot;cant call on behalf of user $caller ($uhandle)&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// get call state(s) until call disappears&lt;br /&gt;
// note: you must at least poll for one call info related to this call, if you end&lt;br /&gt;
// the session right after UserCall, the call will not succeed!&lt;br /&gt;
$done = false;&lt;br /&gt;
while (!$done) {&lt;br /&gt;
    ob_flush();   // this is just to see the progress on the call states&lt;br /&gt;
    $p = $inno-&amp;gt;Poll($inno-&amp;gt;session());&lt;br /&gt;
    showInfos($p, &amp;quot;Call States #$i for #{$call}&amp;quot;, $caller, $uhandle, $call); $i++;&lt;br /&gt;
    // see if there was a del event (there is ALWAYS a del event)&lt;br /&gt;
    // we could as well look for an event with active = false&lt;br /&gt;
    foreach ($p-&amp;gt;call as $ci) {&lt;br /&gt;
	if (($ci-&amp;gt;user == $uhandle) &amp;amp;&amp;amp; &lt;br /&gt;
	    ($ci-&amp;gt;call == $call) &amp;amp;&amp;amp;&lt;br /&gt;
	    ($ci-&amp;gt;msg == &amp;quot;del&amp;quot;)) {&lt;br /&gt;
		print &amp;quot;\nCall terminated!\n&amp;quot;;&lt;br /&gt;
		$done = true;&lt;br /&gt;
	    }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// terminate the session&lt;br /&gt;
$e = $inno-&amp;gt;End($inno-&amp;gt;session());&lt;br /&gt;
&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Save this into a file named &#039;&#039;&#039;innopbx.sample.php&#039;&#039;&#039; in the same directory of your web server.&lt;br /&gt;
To run the code, you need to examine and possibly adapt the configuration parameters in &#039;&#039;&#039;innopbx.sample.php&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// config, adapt to your need&lt;br /&gt;
// this data below will work with innovaphones demo PBX.  Just register 2 phones as user-3 and user-4 and hve fun!&lt;br /&gt;
$server = &amp;quot;145.253.157.200&amp;quot;;&lt;br /&gt;
$user = &amp;quot;SOAP&amp;quot;;&lt;br /&gt;
$httpu = &amp;quot;demo&amp;quot;;&lt;br /&gt;
$httpp = &amp;quot;demo&amp;quot;;&lt;br /&gt;
$caller = &amp;quot;PBX User Four&amp;quot;;&lt;br /&gt;
$destination = &amp;quot;130&amp;quot;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This configuration will work right away with our publicly available [http://145.253.157.200 demo PBX].  You simply need to register 2 phones with the &#039;&#039;&#039;user-3&#039;&#039;&#039; and &#039;&#039;&#039;user-4&#039;&#039;&#039; users.&lt;br /&gt;
&lt;br /&gt;
Of course you can also use your own PBX.  Set the configuration parameters as follow:&lt;br /&gt;
{|&lt;br /&gt;
|$server || IP address of your innovaphone PBX&lt;br /&gt;
|-&lt;br /&gt;
| $user || CN (aka &#039;&#039;Long name&#039;&#039;) of a PBX user that is active group member of a group where all others are (active or passive) members of&lt;br /&gt;
|-&lt;br /&gt;
| $httpu || the admin account of the box running the innovaphone PBX (e.g.&#039;&#039;&#039;admin&#039;&#039;&#039;)&lt;br /&gt;
|-&lt;br /&gt;
| $httpp || the admin password of this box (e.g. &#039;&#039;&#039;ip&#039;&#039;xxx&#039;&#039;&#039;&#039;&#039;)&lt;br /&gt;
|-&lt;br /&gt;
| $caller || CN (aka &#039;&#039;Long name&#039;&#039;) of a PBX user you will have the script make a call for&lt;br /&gt;
|-&lt;br /&gt;
| $destination || the number to be called&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the configuration parameters are set, you can point your browser to &#039;&#039;&#039;http:&#039;&#039;&#039;&amp;lt;nowiki&amp;gt;//&amp;lt;/nowiki&amp;gt;&#039;&#039;your-web-server-ip&#039;&#039;/&#039;&#039;path-to-folder&#039;&#039;/&#039;&#039;&#039;innopbx.sample.php&#039;&#039;&#039; which should create a call on &#039;&#039;&#039;$callers&#039;&#039;&#039; phone.&lt;br /&gt;
&lt;br /&gt;
Please note that you need internet access to retrieve the wsdl from innovaphone&#039;s web site.&lt;br /&gt;
&lt;br /&gt;
===How the code works===&lt;br /&gt;
====The innovaphone PBX API wrapper class====&lt;br /&gt;
&lt;br /&gt;
This class is derived from (&#039;&#039;extends&#039;&#039; in PHP speak) the standard SOAPClient class.   It basically simplifies the use of the standard class and performs the required call to &#039;&#039;&#039;Initialize&#039;&#039;&#039; within its constructor.&lt;br /&gt;
&lt;br /&gt;
The constructor takes the following arguments:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function __construct($server, $httpu, $httpp, $user, $options = null, $wsdl = null);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|$server, $httpu, $httpp, $user || see table above&lt;br /&gt;
|-&lt;br /&gt;
| $options &lt;br /&gt;
| an optional array of further options to SOAPClient::__construct.  Normally not required.  See [http://www.php.net/manual/en/soapclient.soapclient.php the PHP SOAPClient class documentation] for details.&lt;br /&gt;
|-&lt;br /&gt;
| $wsdl&lt;br /&gt;
| the optional URI of the pbx wsdl file.  Please note that you should use &#039;&#039;&#039;pbx501.wsdl&#039;&#039;&#039; instead of &#039;&#039;&#039;pbx.wsdl&#039;&#039;&#039;, as this is the more recent version of the wsdl.  By default, the wsdl is received from the innovaphone web and (subject to PHP configuration options) cached in PHP&#039;s wsdl cache.  If you intend to supply it locally, use a &#039;&#039;&#039;file://&#039;&#039;&#039; URI.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Calls to PBX API functions defined in the wsdl can be done directly through an instance of &#039;&#039;&#039;class innoPBX&#039;&#039;&#039;.  These member functions - which are neither defined in &#039;&#039;&#039;class innoPBX&#039;&#039;&#039; nor in &#039;&#039;&#039;class SOAPClient&#039;&#039;&#039; - are created automagically by reading the wsdl:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$v = $inno-&amp;gt;Version();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To see the functions available and their PHP signatures, you may call&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$inno = new innoPBX(...);&lt;br /&gt;
print_r($inno-&amp;gt;$inno-&amp;gt;__getFunctions());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Many PBX SOAP API functions required either the &#039;&#039;session-key&#039;&#039; or &#039;&#039;session-handle&#039;&#039;.   These are available from the class instance for convenience:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$p = $inno-&amp;gt;Poll($inno-&amp;gt;session());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== How to use the innovaphone PBX API wrapper class with SSL ====&lt;br /&gt;
In order to make a secure connection to the PBX, you have to change the &#039;&#039;&#039;inno.class.php&#039;&#039;&#039; as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&#039;location&#039; =&amp;gt; &amp;quot;https://$server/PBX0/user.soap&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note&#039;&#039;: in &#039;&#039;&#039;PHP 5.6&#039;&#039;&#039; all encrypted client streams now &#039;&#039;&#039;enable peer verification by default&#039;&#039;&#039;. By default, this will use OpenSSL&#039;s default CA bundle to verify the peer certificate.&lt;br /&gt;
See: [http://php.net/manual/en/soapclient.getfunctions.php OpenSSL changes in PHP 5.6.x]&lt;br /&gt;
&lt;br /&gt;
To disable peer verification for the soap connection, you have to pass this as an option to the constructor:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$context = stream_context_create(array(&lt;br /&gt;
 &#039;ssl&#039; =&amp;gt; array(&lt;br /&gt;
  &#039;verify_peer&#039; =&amp;gt; false,&lt;br /&gt;
  &#039;verify_peer_name&#039; =&amp;gt; false,&lt;br /&gt;
  &#039;allow_self_signed&#039; =&amp;gt; false&lt;br /&gt;
 )&lt;br /&gt;
));&lt;br /&gt;
&lt;br /&gt;
$options = array(&#039;stream_context&#039; =&amp;gt; $context); &lt;br /&gt;
&lt;br /&gt;
$inno = new innoPBX($server, $httpu, $httpp, $user, $options, $wsdl); &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More information on stream_context_create and ssl options:&lt;br /&gt;
[http://php.net/stream_context_create stream_context_create] and&lt;br /&gt;
[http://php.net/manual/en/context.ssl.php SSL context options]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====How PHP maps SOAP parameters to method parameters and results====&lt;br /&gt;
The mapping of parameters is pretty straight forward.  Arguments passed in to a SOAP method are passed as a value parameters to the class methods.  The thing to understand is that return values are always passed as return values, never as &#039;&#039;by-reference&#039;&#039; method arguments.&lt;br /&gt;
&lt;br /&gt;
If a SOAP method returns a single item, then it is returned by the function directly with appropriate type:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
int UserInitialize(int $session, string $user);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The single return value from the &#039;&#039;&#039;UserInitialize&#039;&#039;&#039; SOAP method is returned as &#039;&#039;&#039;int&#039;&#039;&#039; by the &#039;&#039;&#039;UserInitialize&#039;&#039;&#039; &#039;&#039;&#039;innoPBX&#039;&#039;&#039;-method.&lt;br /&gt;
&lt;br /&gt;
If the SOAP methods returns multiple items, then the corresponding class method will return an array:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
array Initialize(string $user, string $appl);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
will return an array such as&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
array(&lt;br /&gt;
    [&#039;return&#039;] =&amp;gt; value&lt;br /&gt;
    [&#039;key&#039;] =&amp;gt; value&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
In the method signature printed out by &#039;&#039;&#039;__getFunctions()&#039;&#039;&#039; this looks like&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
list(int $return, int $key) Initialize(string $user, string $appl)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====The sample class user====&lt;br /&gt;
This section will discuss the sample code.  It is not a decent description of the PBX SOAP API.  For this, see the related articles.&lt;br /&gt;
&lt;br /&gt;
A new &#039;&#039;&#039;innoPBX&#039;&#039;&#039; class instance object &#039;&#039;&#039;$inno&#039;&#039;&#039; is created using the values from the configuration variables discussed above.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$inno = new innoPBX($server, $httpu, $httpp, $user,&lt;br /&gt;
	    array(&#039;classmap&#039; =&amp;gt; array(&amp;quot;UserInfo&amp;quot; =&amp;gt; &amp;quot;innoUserInfo&amp;quot;, &lt;br /&gt;
				&amp;quot;CallInfo&amp;quot; =&amp;gt; &amp;quot;innoCallInfo&amp;quot;,&lt;br /&gt;
				&amp;quot;AnyInfo&amp;quot; =&amp;gt; &amp;quot;innoAnyInfo&amp;quot;,&lt;br /&gt;
				&amp;quot;Group&amp;quot; =&amp;gt; &amp;quot;innoGroup&amp;quot;,&lt;br /&gt;
				&amp;quot;No&amp;quot; =&amp;gt; &amp;quot;innoNo&amp;quot;,&lt;br /&gt;
				&amp;quot;Info&amp;quot; =&amp;gt; &amp;quot;innoInfo&amp;quot;,&lt;br /&gt;
			    )));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The option fifth argument will add a &#039;&#039;&#039;classmap&#039;&#039;&#039; entry to the options passed to &#039;&#039;&#039;SOAPClient::__construct&#039;&#039;&#039;.  If this is done, the SOAP class will use your defined classes when returning values to the caller.  Otherwise, structured return values will be indexed arrays (using the element names as array indexes).    This is neat, but not required for the class to function.&lt;br /&gt;
&lt;br /&gt;
When &#039;&#039;&#039;Initialize&#039;&#039;&#039; (which is done implicitly in the &#039;&#039;&#039;innoPBX&#039;&#039;&#039; constructor) was successfull, one &#039;&#039;&#039;UserInfo&#039;&#039;&#039; class object per PBX object is posted to the caller.  This list is terminated by an empty entry (more precisely, an entry with an empty &#039;&#039;&#039;cn&#039;&#039;&#039; member).&lt;br /&gt;
&lt;br /&gt;
The &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
while (!$seen) {&lt;br /&gt;
    $p = $inno-&amp;gt;Poll($inno-&amp;gt;session());&lt;br /&gt;
    ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
loop will retrieve and show all these entries.  &lt;br /&gt;
&lt;br /&gt;
To be able to perform calls, a user session must be opened by&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$uhandle = $inno-&amp;gt;UserInitialize($inno-&amp;gt;session(), $caller);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;$uhandle&#039;&#039;&#039; retrieved will identify the user to be worked with on subsequent calls.&lt;br /&gt;
&lt;br /&gt;
A call on behalf of &#039;&#039;&#039;$caller&#039;&#039;&#039; is then initiated:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$call = $inno-&amp;gt;UserCall($uhandle, null, $destination, null, 0, array());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When &#039;&#039;&#039;UserCall&#039;&#039;&#039; returns a non-zero call handle, the call is initiated and can be monitored by examining &#039;&#039;&#039;CallInfo&#039;&#039;&#039; events returned by subsequent &#039;&#039;&#039;Poll()&#039;&#039;&#039; calls:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
while (!$done) {&lt;br /&gt;
    $p = $inno-&amp;gt;Poll($inno-&amp;gt;session());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
this will retrieve events from the PBX &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
	if (($ci-&amp;gt;user == $uhandle) &amp;amp;&amp;amp; &lt;br /&gt;
	    ($ci-&amp;gt;call == $call) &amp;amp;&amp;amp;&lt;br /&gt;
	    ($ci-&amp;gt;msg == &amp;quot;del&amp;quot;)) {&lt;br /&gt;
		print &amp;quot;\nCall terminated!\n&amp;quot;;&lt;br /&gt;
		$done = true;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
until a &#039;&#039;&#039;del&#039;&#039;&#039; event is seen for the call previously created by UserCall.  Please note that any number of call events may occur, e.g. because someone else called $caller.  You cannot assume that all events retrieved are related to the call you created.  Also, any number of &#039;&#039;&#039;UserInfo&#039;&#039;&#039; events may be retrieved.&lt;br /&gt;
&lt;br /&gt;
Please note that there is no need to consume all of the events related to the call for it to work.  However, you must not terminate the session before the call is actually proceeding.  If you do so, strange things will happen.  To be sure the call proceeds, it is ok to wait for &#039;&#039;just any&#039;&#039; &#039;&#039;&#039;CallInfo&#039;&#039;&#039; event related to the call. You can then safely terminate your session and exit the web page.&lt;br /&gt;
&lt;br /&gt;
==More Sample Code==&lt;br /&gt;
Much more elaborate SOAP sample code is available for download from [http://download.innovaphone.com/ice/wiki-src/#soapphp5 the samples section] on http://download.innovaphone.com.&lt;br /&gt;
&lt;br /&gt;
This code shows how to deal with call control on master/slave scenarios as well as how to perform PBX configuration updates or PBX object creation using the [[Howto:Using the SOAP Admin Function|SOAP Admin function]].  Currently, there are the following sample functions available:&lt;br /&gt;
&lt;br /&gt;
* create a SOAP session to the master PBX&lt;br /&gt;
* create a user session on a device&lt;br /&gt;
* initiate a call via SOAP and terminate it once connected&lt;br /&gt;
* List all available SOAP functions&lt;br /&gt;
* Show an object&#039;s configuration using the Admin() function&lt;br /&gt;
* Modify a user object using the Admin() function&lt;br /&gt;
* Clone a PBX object using the Admin() function&lt;br /&gt;
* Add call forwarding using Admin() function&lt;br /&gt;
* Delete call forwarding using Admin() function&lt;br /&gt;
* Get the PBX key&lt;br /&gt;
* Generate an encrypted PBX user password&lt;br /&gt;
* Set a new password for user&lt;br /&gt;
* Get the password of a PBX object in clear&lt;br /&gt;
&lt;br /&gt;
Although this code is written in PHP5, it is also good reading if you do not intend to use PHP as it exemplifies the principles of using SOAP and the SOAP Admin() function.&lt;br /&gt;
&lt;br /&gt;
==Download ==&lt;br /&gt;
*[http://download.innovaphone.com/ice/wiki-src#soapphp5 http://download.innovaphone.com/ice/wiki-src#soapphp5] - download the complete file package of scripts and files described in this article.&lt;br /&gt;
&lt;br /&gt;
==Related Articles==&lt;br /&gt;
* [[Reference:SOAP API]]&lt;br /&gt;
* [[Reference7:SOAP API]]&lt;br /&gt;
* [[Reference8:SOAP API]]&lt;br /&gt;
* [[Reference9:Concept SOAP API]]&lt;br /&gt;
* [[Reference10:Concept SOAP API]]&lt;br /&gt;
&lt;br /&gt;
* [[Howto:Using the SOAP Admin Function]]&lt;br /&gt;
&lt;br /&gt;
[http://wiki.innovaphone.com/index.php?search=soap+sample&amp;amp;go=Go Search all SOAP sample code in the wiki]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--*[[Main_Page|wiki-innovaphone]]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Sample|{{PAGENAME}}]]&lt;/div&gt;</summary>
		<author><name>Treitinger</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Howto:SOAP_API_PHP5_Sample_Code&amp;diff=39558</id>
		<title>Howto:SOAP API PHP5 Sample Code</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Howto:SOAP_API_PHP5_Sample_Code&amp;diff=39558"/>
		<updated>2015-11-09T11:53:30Z</updated>

		<summary type="html">&lt;p&gt;Treitinger: /* How the code works */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Applies To==&lt;br /&gt;
This information applies to&lt;br /&gt;
&lt;br /&gt;
* V9 innovaphone PBX platform&lt;br /&gt;
* web server running PHP 5&lt;br /&gt;
&lt;br /&gt;
innovaphone PBX web services can be used from PHP easily.  Here is how&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- web service, soap service, soapservice, webservice, php, soap api, soapapi --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==More Information==&lt;br /&gt;
===Configuration===&lt;br /&gt;
You will need php with the SoapClient class available.&lt;br /&gt;
&lt;br /&gt;
The innovaphone PBX wsdl file is required.  See [[Reference8:SOAP API]] for information how to obtain this file.  &lt;br /&gt;
To access older WSDL versions, you will need to change the WSDL URL setting (in &amp;lt;code&amp;gt;const ___wsdl&amp;lt;/code&amp;gt;) and adapt to the required number of version booleans in the call to &amp;lt;code&amp;gt;Initialize()&amp;lt;/code&amp;gt; in the pbx wrapper class.&lt;br /&gt;
&lt;br /&gt;
If you have access to the internet, you can try out the sample code given below right away.  Of course you may also adapt the sample script configuration and try with your own innovaphone PBX.&lt;br /&gt;
&lt;br /&gt;
===Running the Sample Code===&lt;br /&gt;
To demonstrate SOAP usage with PHP, a simple script is presented that will allow you to initiate a call using a web page.&lt;br /&gt;
&lt;br /&gt;
The following class &#039;&#039;&#039;innoPBX&#039;&#039;&#039; is used to wrap the (somewhat clumsy) PHP SOAP access mechanism:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// innovaphone PBX SOAP API PHP wrapper class&lt;br /&gt;
//&lt;br /&gt;
&lt;br /&gt;
class innoPBX extends SOAPClient {&lt;br /&gt;
&lt;br /&gt;
    protected $___key; 		// the session key&lt;br /&gt;
    protected $___session; 	// the session id&lt;br /&gt;
&lt;br /&gt;
    protected $___options = array(&lt;br /&gt;
				// default SOAPClient::__construct options used by the class&lt;br /&gt;
	&amp;quot;connection_timeout&amp;quot; =&amp;gt; 10,&lt;br /&gt;
	&amp;quot;exceptions&amp;quot; =&amp;gt; true,&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
    const ___wsdl = &#039;http://www.innovaphone.com/wsdl/pbx900.wsdl&#039;;&lt;br /&gt;
&lt;br /&gt;
    // class constructor&lt;br /&gt;
    public function __construct(&lt;br /&gt;
	$server, 	// the PBX IP&lt;br /&gt;
	$httpu,		// the HTTP user id (e.g. &amp;quot;admin&amp;quot;)&lt;br /&gt;
	$httpp,		// the HTTP password (e.g. &amp;quot;ip800&amp;quot;)&lt;br /&gt;
	$user = null,		// the PBX user CN to work with &lt;br /&gt;
	$options = null,&lt;br /&gt;
			// extra or overriding options for SOAPClient::__construct&lt;br /&gt;
	$wsdl = null    // the wsdl file location&lt;br /&gt;
    ) {	&lt;br /&gt;
	$wsdl = ($wsdl === null) ? self::___wsdl : $wsdl;&lt;br /&gt;
	$usedoptions = array(			// forced options&lt;br /&gt;
	    &#039;login&#039; =&amp;gt; $httpu,&lt;br /&gt;
	    &#039;password&#039; =&amp;gt; $httpp,&lt;br /&gt;
	    &#039;location&#039; =&amp;gt; &amp;quot;http://$server/PBX0/user.soap&amp;quot;,&lt;br /&gt;
			);&lt;br /&gt;
	if (is_array($options)) $usedoptions += $options;	&lt;br /&gt;
						// merge in user options&lt;br /&gt;
	$usedoptions += $this-&amp;gt;___options;	// merged in class global options&lt;br /&gt;
&lt;br /&gt;
	// construct parent class&lt;br /&gt;
	parent::__construct($wsdl, $usedoptions);&lt;br /&gt;
&lt;br /&gt;
	// get the connection (using and activating v9 wsdl)&lt;br /&gt;
	$init = $this-&amp;gt;Initialize($user, &amp;quot;PHP SOAP Wrapper&amp;quot;, true, true, true, true, true);&lt;br /&gt;
	$this-&amp;gt;___key = $init[&#039;key&#039;];&lt;br /&gt;
	$this-&amp;gt;___session = $init[&#039;return&#039;];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function key() { return $this-&amp;gt;___key; }&lt;br /&gt;
    public function session() { return $this-&amp;gt;___session; }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Save this code into a file named &#039;&#039;&#039;innopbx.class.php&#039;&#039;&#039; on your web server.  This class is of course not required to use PHP SOAP with the innovaphone PBX API.  However, it comes handy and should be generic enough to be useful in most cases.&lt;br /&gt;
&lt;br /&gt;
The SOAP client uses the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// get the innoPBX wrapper class&lt;br /&gt;
require_once(&#039;innopbx.class.php&#039;);&lt;br /&gt;
&lt;br /&gt;
// dummy classes to map SOAP results to (really would love to use namespaces here...)&lt;br /&gt;
// you can add methods and variables to these classes as needed&lt;br /&gt;
class innoUserInfo { };&lt;br /&gt;
class innoCallInfo { };&lt;br /&gt;
class innoAnyInfo { };&lt;br /&gt;
class innoGroup { };&lt;br /&gt;
class innoNo { };&lt;br /&gt;
class innoInfo { };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// config, adapt to your need&lt;br /&gt;
// this data below will work with innovaphones demo PBX.  Just register 2 phones as user-3 and user-4 and hve fun!&lt;br /&gt;
$server = &amp;quot;145.253.157.200&amp;quot;;&lt;br /&gt;
$user = &amp;quot;SOAP&amp;quot;;&lt;br /&gt;
$httpu = &amp;quot;demo&amp;quot;;&lt;br /&gt;
$httpp = &amp;quot;demo&amp;quot;;&lt;br /&gt;
$caller = &amp;quot;PBX User Four&amp;quot;;&lt;br /&gt;
$destination = &amp;quot;130&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
print &amp;quot;&amp;lt;pre&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// create connector to PBX&lt;br /&gt;
// class mapping is optional&lt;br /&gt;
$inno = new innoPBX($server, $httpu, $httpp, $user,&lt;br /&gt;
	    array(&#039;classmap&#039; =&amp;gt; array(&amp;quot;UserInfo&amp;quot; =&amp;gt; &amp;quot;innoUserInfo&amp;quot;, &lt;br /&gt;
				&amp;quot;CallInfo&amp;quot; =&amp;gt; &amp;quot;innoCallInfo&amp;quot;,&lt;br /&gt;
				&amp;quot;AnyInfo&amp;quot; =&amp;gt; &amp;quot;innoAnyInfo&amp;quot;,&lt;br /&gt;
				&amp;quot;Group&amp;quot; =&amp;gt; &amp;quot;innoGroup&amp;quot;,&lt;br /&gt;
				&amp;quot;No&amp;quot; =&amp;gt; &amp;quot;innoNo&amp;quot;,&lt;br /&gt;
				&amp;quot;Info&amp;quot; =&amp;gt; &amp;quot;innoInfo&amp;quot;,&lt;br /&gt;
			    )));&lt;br /&gt;
if ($inno-&amp;gt;key() == 0) die(&amp;quot;failed to login to PBX&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// show all methods supported by this object&lt;br /&gt;
print &amp;quot;All the functions provided by class innoPBX:\n&amp;quot;;&lt;br /&gt;
print_r($inno-&amp;gt;__getFunctions());&lt;br /&gt;
print &amp;quot;\n\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// get version info&lt;br /&gt;
$v = $inno-&amp;gt;Version();&lt;br /&gt;
&lt;br /&gt;
// show both types of infos list&lt;br /&gt;
function showInfos(&amp;amp;$poll, $head, $cn = &amp;quot;&amp;quot;, $user = &amp;quot;&amp;quot;, $call = &amp;quot;&amp;quot;) {&lt;br /&gt;
    print $head . &amp;quot;\n&amp;quot;;&lt;br /&gt;
    if ($cn !== null) {&lt;br /&gt;
	print count($poll-&amp;gt;user) . &amp;quot; UserInfos\n&amp;quot;;&lt;br /&gt;
	foreach($poll-&amp;gt;user as $ui) {&lt;br /&gt;
	    if (($cn === &amp;quot;&amp;quot;) || ($cn == $ui-&amp;gt;cn)) {&lt;br /&gt;
		print &amp;quot;     {$ui-&amp;gt;cn} ({$ui-&amp;gt;h323} #{$ui-&amp;gt;e164}) state {$ui-&amp;gt;state}\n&amp;quot;;&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
    if ($call !== null) {&lt;br /&gt;
	print count($poll-&amp;gt;call) . &amp;quot; CallInfos\n&amp;quot;;&lt;br /&gt;
	foreach($poll-&amp;gt;call as $ci) {&lt;br /&gt;
	    if ((($user === &amp;quot;&amp;quot;) || ($user == $ci-&amp;gt;user)) &amp;amp;&amp;amp;&lt;br /&gt;
		(($call === &amp;quot;&amp;quot;) || ($call == $ci-&amp;gt;call))) {&lt;br /&gt;
		    print &amp;quot;    {$ci-&amp;gt;user}/{$ci-&amp;gt;call} {$ci-&amp;gt;No[1]-&amp;gt;h323} #{$ci-&amp;gt;No[1]-&amp;gt;e164} (remote {$ci-&amp;gt;No[0]-&amp;gt;h323} #{$ci-&amp;gt;No[0]-&amp;gt;e164}) msg {$ci-&amp;gt;msg}\n&amp;quot;;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// retrieve the full user list.  Foreach object in the PBX, one userinfo is posted, terminated by an empty one&lt;br /&gt;
// You cannot assume that you will receive this list within a certain number of Poll results, so please iterate&lt;br /&gt;
print &amp;quot;Retrieving User list for &amp;quot;; foreach ($v as $name =&amp;gt; $value) print &amp;quot;\n  $name=$value &amp;quot;; print &amp;quot;...\n\n&amp;quot;;&lt;br /&gt;
$seen = false;&lt;br /&gt;
$i = 1;&lt;br /&gt;
while (!$seen) {&lt;br /&gt;
    $p = $inno-&amp;gt;Poll($inno-&amp;gt;session());&lt;br /&gt;
    showInfos($p, &amp;quot;Poll() result #$i&amp;quot;, &amp;quot;&amp;quot;, null, null); $i++;&lt;br /&gt;
    if ($p-&amp;gt;user[count($p-&amp;gt;user)-1]-&amp;gt;cn == &amp;quot;&amp;quot;) {&lt;br /&gt;
	// we have seen all entries&lt;br /&gt;
	print &amp;quot; --- END OF LIST ---\n\n&amp;quot;;&lt;br /&gt;
	$seen = true;&lt;br /&gt;
	break;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// create a call on behalf of some user&lt;br /&gt;
// first we need a user handle&lt;br /&gt;
print &amp;quot;\nObtaining a user handle for $caller...&amp;quot;;&lt;br /&gt;
$uhandle = $inno-&amp;gt;UserInitialize($inno-&amp;gt;session(), $caller);&lt;br /&gt;
print &amp;quot; $uhandle\n&amp;quot;;&lt;br /&gt;
if ($uhandle == 0) {&lt;br /&gt;
    die(&amp;quot;cant get user handle for $caller&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// then we create a call&lt;br /&gt;
print &amp;quot;Creating call from $caller to $destination...&amp;quot;;&lt;br /&gt;
$call = $inno-&amp;gt;UserCall($uhandle, null, $destination, null, 0, array());&lt;br /&gt;
print &amp;quot; $call\n&amp;quot;;&lt;br /&gt;
if ($call == 0) {&lt;br /&gt;
    die(&amp;quot;cant call on behalf of user $caller ($uhandle)&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// get call state(s) until call disappears&lt;br /&gt;
// note: you must at least poll for one call info related to this call, if you end&lt;br /&gt;
// the session right after UserCall, the call will not succeed!&lt;br /&gt;
$done = false;&lt;br /&gt;
while (!$done) {&lt;br /&gt;
    ob_flush();   // this is just to see the progress on the call states&lt;br /&gt;
    $p = $inno-&amp;gt;Poll($inno-&amp;gt;session());&lt;br /&gt;
    showInfos($p, &amp;quot;Call States #$i for #{$call}&amp;quot;, $caller, $uhandle, $call); $i++;&lt;br /&gt;
    // see if there was a del event (there is ALWAYS a del event)&lt;br /&gt;
    // we could as well look for an event with active = false&lt;br /&gt;
    foreach ($p-&amp;gt;call as $ci) {&lt;br /&gt;
	if (($ci-&amp;gt;user == $uhandle) &amp;amp;&amp;amp; &lt;br /&gt;
	    ($ci-&amp;gt;call == $call) &amp;amp;&amp;amp;&lt;br /&gt;
	    ($ci-&amp;gt;msg == &amp;quot;del&amp;quot;)) {&lt;br /&gt;
		print &amp;quot;\nCall terminated!\n&amp;quot;;&lt;br /&gt;
		$done = true;&lt;br /&gt;
	    }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// terminate the session&lt;br /&gt;
$e = $inno-&amp;gt;End($inno-&amp;gt;session());&lt;br /&gt;
&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Save this into a file named &#039;&#039;&#039;innopbx.sample.php&#039;&#039;&#039; in the same directory of your web server.&lt;br /&gt;
To run the code, you need to examine and possibly adapt the configuration parameters in &#039;&#039;&#039;innopbx.sample.php&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// config, adapt to your need&lt;br /&gt;
// this data below will work with innovaphones demo PBX.  Just register 2 phones as user-3 and user-4 and hve fun!&lt;br /&gt;
$server = &amp;quot;145.253.157.200&amp;quot;;&lt;br /&gt;
$user = &amp;quot;SOAP&amp;quot;;&lt;br /&gt;
$httpu = &amp;quot;demo&amp;quot;;&lt;br /&gt;
$httpp = &amp;quot;demo&amp;quot;;&lt;br /&gt;
$caller = &amp;quot;PBX User Four&amp;quot;;&lt;br /&gt;
$destination = &amp;quot;130&amp;quot;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This configuration will work right away with our publicly available [http://145.253.157.200 demo PBX].  You simply need to register 2 phones with the &#039;&#039;&#039;user-3&#039;&#039;&#039; and &#039;&#039;&#039;user-4&#039;&#039;&#039; users.&lt;br /&gt;
&lt;br /&gt;
Of course you can also use your own PBX.  Set the configuration parameters as follow:&lt;br /&gt;
{|&lt;br /&gt;
|$server || IP address of your innovaphone PBX&lt;br /&gt;
|-&lt;br /&gt;
| $user || CN (aka &#039;&#039;Long name&#039;&#039;) of a PBX user that is active group member of a group where all others are (active or passive) members of&lt;br /&gt;
|-&lt;br /&gt;
| $httpu || the admin account of the box running the innovaphone PBX (e.g.&#039;&#039;&#039;admin&#039;&#039;&#039;)&lt;br /&gt;
|-&lt;br /&gt;
| $httpp || the admin password of this box (e.g. &#039;&#039;&#039;ip&#039;&#039;xxx&#039;&#039;&#039;&#039;&#039;)&lt;br /&gt;
|-&lt;br /&gt;
| $caller || CN (aka &#039;&#039;Long name&#039;&#039;) of a PBX user you will have the script make a call for&lt;br /&gt;
|-&lt;br /&gt;
| $destination || the number to be called&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the configuration parameters are set, you can point your browser to &#039;&#039;&#039;http:&#039;&#039;&#039;&amp;lt;nowiki&amp;gt;//&amp;lt;/nowiki&amp;gt;&#039;&#039;your-web-server-ip&#039;&#039;/&#039;&#039;path-to-folder&#039;&#039;/&#039;&#039;&#039;innopbx.sample.php&#039;&#039;&#039; which should create a call on &#039;&#039;&#039;$callers&#039;&#039;&#039; phone.&lt;br /&gt;
&lt;br /&gt;
Please note that you need internet access to retrieve the wsdl from innovaphone&#039;s web site.&lt;br /&gt;
&lt;br /&gt;
===How the code works===&lt;br /&gt;
====The innovaphone PBX API wrapper class====&lt;br /&gt;
&lt;br /&gt;
This class is derived from (&#039;&#039;extends&#039;&#039; in PHP speak) the standard SOAPClient class.   It basically simplifies the use of the standard class and performs the required call to &#039;&#039;&#039;Initialize&#039;&#039;&#039; within its constructor.&lt;br /&gt;
&lt;br /&gt;
The constructor takes the following arguments:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function __construct($server, $httpu, $httpp, $user, $options = null, $wsdl = null);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|$server, $httpu, $httpp, $user || see table above&lt;br /&gt;
|-&lt;br /&gt;
| $options &lt;br /&gt;
| an optional array of further options to SOAPClient::__construct.  Normally not required.  See [http://php.net/manual/en/soapclient.construct.php the PHP SOAPClient class documentation] for details.&lt;br /&gt;
|-&lt;br /&gt;
| $wsdl&lt;br /&gt;
| the optional URI of the pbx wsdl file.  Please note that you should use &#039;&#039;&#039;pbx501.wsdl&#039;&#039;&#039; instead of &#039;&#039;&#039;pbx.wsdl&#039;&#039;&#039;, as this is the more recent version of the wsdl.  By default, the wsdl is received from the innovaphone web and (subject to PHP configuration options) cached in PHP&#039;s wsdl cache.  If you intend to supply it locally, use a &#039;&#039;&#039;file://&#039;&#039;&#039; URI.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Calls to PBX API functions defined in the wsdl can be done directly through an instance of &#039;&#039;&#039;class innoPBX&#039;&#039;&#039;.  These member functions - which are neither defined in &#039;&#039;&#039;class innoPBX&#039;&#039;&#039; nor in &#039;&#039;&#039;class SOAPClient&#039;&#039;&#039; - are created automagically by reading the wsdl:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$v = $inno-&amp;gt;Version();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To see the functions available and their PHP signatures, you may call&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$inno = new innoPBX(...);&lt;br /&gt;
print_r($inno-&amp;gt;$inno-&amp;gt;__getFunctions());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Many PBX SOAP API functions required either the &#039;&#039;session-key&#039;&#039; or &#039;&#039;session-handle&#039;&#039;.   These are available from the class instance for convenience:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$p = $inno-&amp;gt;Poll($inno-&amp;gt;session());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== How to use the innovaphone PBX API wrapper class with SSL ====&lt;br /&gt;
In order to make a secure connection to the PBX, you have to change the &#039;&#039;&#039;inno.class.php&#039;&#039;&#039; as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&#039;location&#039; =&amp;gt; &amp;quot;https://$server/PBX0/user.soap&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note&#039;&#039;: in &#039;&#039;&#039;PHP 5.6&#039;&#039;&#039; all encrypted client streams now &#039;&#039;&#039;enable peer verification by default&#039;&#039;&#039;. By default, this will use OpenSSL&#039;s default CA bundle to verify the peer certificate.&lt;br /&gt;
See: [http://php.net/manual/en/soapclient.getfunctions.php OpenSSL changes in PHP 5.6.x]&lt;br /&gt;
&lt;br /&gt;
To disable peer verification for the soap connection, you have to pass this as an option to the constructor:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$context = stream_context_create(array(&lt;br /&gt;
 &#039;ssl&#039; =&amp;gt; array(&lt;br /&gt;
  &#039;verify_peer&#039; =&amp;gt; false,&lt;br /&gt;
  &#039;verify_peer_name&#039; =&amp;gt; false,&lt;br /&gt;
  &#039;allow_self_signed&#039; =&amp;gt; false&lt;br /&gt;
 )&lt;br /&gt;
));&lt;br /&gt;
&lt;br /&gt;
$options = array(&#039;stream_context&#039; =&amp;gt; $context); &lt;br /&gt;
&lt;br /&gt;
$inno = new innoPBX($server, $httpu, $httpp, $user, $options, $wsdl); &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More information on stream_context_create and ssl options:&lt;br /&gt;
[http://php.net/stream_context_create stream_context_create] and&lt;br /&gt;
[http://php.net/manual/en/context.ssl.php SSL context options]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====How PHP maps SOAP parameters to method parameters and results====&lt;br /&gt;
The mapping of parameters is pretty straight forward.  Arguments passed in to a SOAP method are passed as a value parameters to the class methods.  The thing to understand is that return values are always passed as return values, never as &#039;&#039;by-reference&#039;&#039; method arguments.&lt;br /&gt;
&lt;br /&gt;
If a SOAP method returns a single item, then it is returned by the function directly with appropriate type:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
int UserInitialize(int $session, string $user);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The single return value from the &#039;&#039;&#039;UserInitialize&#039;&#039;&#039; SOAP method is returned as &#039;&#039;&#039;int&#039;&#039;&#039; by the &#039;&#039;&#039;UserInitialize&#039;&#039;&#039; &#039;&#039;&#039;innoPBX&#039;&#039;&#039;-method.&lt;br /&gt;
&lt;br /&gt;
If the SOAP methods returns multiple items, then the corresponding class method will return an array:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
array Initialize(string $user, string $appl);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
will return an array such as&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
array(&lt;br /&gt;
    [&#039;return&#039;] =&amp;gt; value&lt;br /&gt;
    [&#039;key&#039;] =&amp;gt; value&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
In the method signature printed out by &#039;&#039;&#039;__getFunctions()&#039;&#039;&#039; this looks like&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
list(int $return, int $key) Initialize(string $user, string $appl)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====The sample class user====&lt;br /&gt;
This section will discuss the sample code.  It is not a decent description of the PBX SOAP API.  For this, see the related articles.&lt;br /&gt;
&lt;br /&gt;
A new &#039;&#039;&#039;innoPBX&#039;&#039;&#039; class instance object &#039;&#039;&#039;$inno&#039;&#039;&#039; is created using the values from the configuration variables discussed above.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$inno = new innoPBX($server, $httpu, $httpp, $user,&lt;br /&gt;
	    array(&#039;classmap&#039; =&amp;gt; array(&amp;quot;UserInfo&amp;quot; =&amp;gt; &amp;quot;innoUserInfo&amp;quot;, &lt;br /&gt;
				&amp;quot;CallInfo&amp;quot; =&amp;gt; &amp;quot;innoCallInfo&amp;quot;,&lt;br /&gt;
				&amp;quot;AnyInfo&amp;quot; =&amp;gt; &amp;quot;innoAnyInfo&amp;quot;,&lt;br /&gt;
				&amp;quot;Group&amp;quot; =&amp;gt; &amp;quot;innoGroup&amp;quot;,&lt;br /&gt;
				&amp;quot;No&amp;quot; =&amp;gt; &amp;quot;innoNo&amp;quot;,&lt;br /&gt;
				&amp;quot;Info&amp;quot; =&amp;gt; &amp;quot;innoInfo&amp;quot;,&lt;br /&gt;
			    )));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The option fifth argument will add a &#039;&#039;&#039;classmap&#039;&#039;&#039; entry to the options passed to &#039;&#039;&#039;SOAPClient::__construct&#039;&#039;&#039;.  If this is done, the SOAP class will use your defined classes when returning values to the caller.  Otherwise, structured return values will be indexed arrays (using the element names as array indexes).    This is neat, but not required for the class to function.&lt;br /&gt;
&lt;br /&gt;
When &#039;&#039;&#039;Initialize&#039;&#039;&#039; (which is done implicitly in the &#039;&#039;&#039;innoPBX&#039;&#039;&#039; constructor) was successfull, one &#039;&#039;&#039;UserInfo&#039;&#039;&#039; class object per PBX object is posted to the caller.  This list is terminated by an empty entry (more precisely, an entry with an empty &#039;&#039;&#039;cn&#039;&#039;&#039; member).&lt;br /&gt;
&lt;br /&gt;
The &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
while (!$seen) {&lt;br /&gt;
    $p = $inno-&amp;gt;Poll($inno-&amp;gt;session());&lt;br /&gt;
    ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
loop will retrieve and show all these entries.  &lt;br /&gt;
&lt;br /&gt;
To be able to perform calls, a user session must be opened by&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$uhandle = $inno-&amp;gt;UserInitialize($inno-&amp;gt;session(), $caller);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;$uhandle&#039;&#039;&#039; retrieved will identify the user to be worked with on subsequent calls.&lt;br /&gt;
&lt;br /&gt;
A call on behalf of &#039;&#039;&#039;$caller&#039;&#039;&#039; is then initiated:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$call = $inno-&amp;gt;UserCall($uhandle, null, $destination, null, 0, array());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When &#039;&#039;&#039;UserCall&#039;&#039;&#039; returns a non-zero call handle, the call is initiated and can be monitored by examining &#039;&#039;&#039;CallInfo&#039;&#039;&#039; events returned by subsequent &#039;&#039;&#039;Poll()&#039;&#039;&#039; calls:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
while (!$done) {&lt;br /&gt;
    $p = $inno-&amp;gt;Poll($inno-&amp;gt;session());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
this will retrieve events from the PBX &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
	if (($ci-&amp;gt;user == $uhandle) &amp;amp;&amp;amp; &lt;br /&gt;
	    ($ci-&amp;gt;call == $call) &amp;amp;&amp;amp;&lt;br /&gt;
	    ($ci-&amp;gt;msg == &amp;quot;del&amp;quot;)) {&lt;br /&gt;
		print &amp;quot;\nCall terminated!\n&amp;quot;;&lt;br /&gt;
		$done = true;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
until a &#039;&#039;&#039;del&#039;&#039;&#039; event is seen for the call previously created by UserCall.  Please note that any number of call events may occur, e.g. because someone else called $caller.  You cannot assume that all events retrieved are related to the call you created.  Also, any number of &#039;&#039;&#039;UserInfo&#039;&#039;&#039; events may be retrieved.&lt;br /&gt;
&lt;br /&gt;
Please note that there is no need to consume all of the events related to the call for it to work.  However, you must not terminate the session before the call is actually proceeding.  If you do so, strange things will happen.  To be sure the call proceeds, it is ok to wait for &#039;&#039;just any&#039;&#039; &#039;&#039;&#039;CallInfo&#039;&#039;&#039; event related to the call. You can then safely terminate your session and exit the web page.&lt;br /&gt;
&lt;br /&gt;
==More Sample Code==&lt;br /&gt;
Much more elaborate SOAP sample code is available for download from [http://download.innovaphone.com/ice/wiki-src/#soapphp5 the samples section] on http://download.innovaphone.com.&lt;br /&gt;
&lt;br /&gt;
This code shows how to deal with call control on master/slave scenarios as well as how to perform PBX configuration updates or PBX object creation using the [[Howto:Using the SOAP Admin Function|SOAP Admin function]].  Currently, there are the following sample functions available:&lt;br /&gt;
&lt;br /&gt;
* create a SOAP session to the master PBX&lt;br /&gt;
* create a user session on a device&lt;br /&gt;
* initiate a call via SOAP and terminate it once connected&lt;br /&gt;
* List all available SOAP functions&lt;br /&gt;
* Show an object&#039;s configuration using the Admin() function&lt;br /&gt;
* Modify a user object using the Admin() function&lt;br /&gt;
* Clone a PBX object using the Admin() function&lt;br /&gt;
* Add call forwarding using Admin() function&lt;br /&gt;
* Delete call forwarding using Admin() function&lt;br /&gt;
* Get the PBX key&lt;br /&gt;
* Generate an encrypted PBX user password&lt;br /&gt;
* Set a new password for user&lt;br /&gt;
* Get the password of a PBX object in clear&lt;br /&gt;
&lt;br /&gt;
Although this code is written in PHP5, it is also good reading if you do not intend to use PHP as it exemplifies the principles of using SOAP and the SOAP Admin() function.&lt;br /&gt;
&lt;br /&gt;
==Download ==&lt;br /&gt;
*[http://download.innovaphone.com/ice/wiki-src#soapphp5 http://download.innovaphone.com/ice/wiki-src#soapphp5] - download the complete file package of scripts and files described in this article.&lt;br /&gt;
&lt;br /&gt;
==Related Articles==&lt;br /&gt;
* [[Reference:SOAP API]]&lt;br /&gt;
* [[Reference7:SOAP API]]&lt;br /&gt;
* [[Reference8:SOAP API]]&lt;br /&gt;
* [[Reference9:Concept SOAP API]]&lt;br /&gt;
* [[Reference10:Concept SOAP API]]&lt;br /&gt;
&lt;br /&gt;
* [[Howto:Using the SOAP Admin Function]]&lt;br /&gt;
&lt;br /&gt;
[http://wiki.innovaphone.com/index.php?search=soap+sample&amp;amp;go=Go Search all SOAP sample code in the wiki]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--*[[Main_Page|wiki-innovaphone]]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Sample|{{PAGENAME}}]]&lt;/div&gt;</summary>
		<author><name>Treitinger</name></author>
	</entry>
	<entry>
		<id>https://wiki.innovaphone.com/index.php?title=Howto:SOAP_API_PHP5_Sample_Code&amp;diff=39557</id>
		<title>Howto:SOAP API PHP5 Sample Code</title>
		<link rel="alternate" type="text/html" href="https://wiki.innovaphone.com/index.php?title=Howto:SOAP_API_PHP5_Sample_Code&amp;diff=39557"/>
		<updated>2015-11-09T11:33:58Z</updated>

		<summary type="html">&lt;p&gt;Treitinger: /* The innovaphone PBX API wrapper class */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Applies To==&lt;br /&gt;
This information applies to&lt;br /&gt;
&lt;br /&gt;
* V9 innovaphone PBX platform&lt;br /&gt;
* web server running PHP 5&lt;br /&gt;
&lt;br /&gt;
innovaphone PBX web services can be used from PHP easily.  Here is how&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- web service, soap service, soapservice, webservice, php, soap api, soapapi --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==More Information==&lt;br /&gt;
===Configuration===&lt;br /&gt;
You will need php with the SoapClient class available.&lt;br /&gt;
&lt;br /&gt;
The innovaphone PBX wsdl file is required.  See [[Reference8:SOAP API]] for information how to obtain this file.  &lt;br /&gt;
To access older WSDL versions, you will need to change the WSDL URL setting (in &amp;lt;code&amp;gt;const ___wsdl&amp;lt;/code&amp;gt;) and adapt to the required number of version booleans in the call to &amp;lt;code&amp;gt;Initialize()&amp;lt;/code&amp;gt; in the pbx wrapper class.&lt;br /&gt;
&lt;br /&gt;
If you have access to the internet, you can try out the sample code given below right away.  Of course you may also adapt the sample script configuration and try with your own innovaphone PBX.&lt;br /&gt;
&lt;br /&gt;
===Running the Sample Code===&lt;br /&gt;
To demonstrate SOAP usage with PHP, a simple script is presented that will allow you to initiate a call using a web page.&lt;br /&gt;
&lt;br /&gt;
The following class &#039;&#039;&#039;innoPBX&#039;&#039;&#039; is used to wrap the (somewhat clumsy) PHP SOAP access mechanism:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// innovaphone PBX SOAP API PHP wrapper class&lt;br /&gt;
//&lt;br /&gt;
&lt;br /&gt;
class innoPBX extends SOAPClient {&lt;br /&gt;
&lt;br /&gt;
    protected $___key; 		// the session key&lt;br /&gt;
    protected $___session; 	// the session id&lt;br /&gt;
&lt;br /&gt;
    protected $___options = array(&lt;br /&gt;
				// default SOAPClient::__construct options used by the class&lt;br /&gt;
	&amp;quot;connection_timeout&amp;quot; =&amp;gt; 10,&lt;br /&gt;
	&amp;quot;exceptions&amp;quot; =&amp;gt; true,&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
    const ___wsdl = &#039;http://www.innovaphone.com/wsdl/pbx900.wsdl&#039;;&lt;br /&gt;
&lt;br /&gt;
    // class constructor&lt;br /&gt;
    public function __construct(&lt;br /&gt;
	$server, 	// the PBX IP&lt;br /&gt;
	$httpu,		// the HTTP user id (e.g. &amp;quot;admin&amp;quot;)&lt;br /&gt;
	$httpp,		// the HTTP password (e.g. &amp;quot;ip800&amp;quot;)&lt;br /&gt;
	$user = null,		// the PBX user CN to work with &lt;br /&gt;
	$options = null,&lt;br /&gt;
			// extra or overriding options for SOAPClient::__construct&lt;br /&gt;
	$wsdl = null    // the wsdl file location&lt;br /&gt;
    ) {	&lt;br /&gt;
	$wsdl = ($wsdl === null) ? self::___wsdl : $wsdl;&lt;br /&gt;
	$usedoptions = array(			// forced options&lt;br /&gt;
	    &#039;login&#039; =&amp;gt; $httpu,&lt;br /&gt;
	    &#039;password&#039; =&amp;gt; $httpp,&lt;br /&gt;
	    &#039;location&#039; =&amp;gt; &amp;quot;http://$server/PBX0/user.soap&amp;quot;,&lt;br /&gt;
			);&lt;br /&gt;
	if (is_array($options)) $usedoptions += $options;	&lt;br /&gt;
						// merge in user options&lt;br /&gt;
	$usedoptions += $this-&amp;gt;___options;	// merged in class global options&lt;br /&gt;
&lt;br /&gt;
	// construct parent class&lt;br /&gt;
	parent::__construct($wsdl, $usedoptions);&lt;br /&gt;
&lt;br /&gt;
	// get the connection (using and activating v9 wsdl)&lt;br /&gt;
	$init = $this-&amp;gt;Initialize($user, &amp;quot;PHP SOAP Wrapper&amp;quot;, true, true, true, true, true);&lt;br /&gt;
	$this-&amp;gt;___key = $init[&#039;key&#039;];&lt;br /&gt;
	$this-&amp;gt;___session = $init[&#039;return&#039;];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function key() { return $this-&amp;gt;___key; }&lt;br /&gt;
    public function session() { return $this-&amp;gt;___session; }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Save this code into a file named &#039;&#039;&#039;innopbx.class.php&#039;&#039;&#039; on your web server.  This class is of course not required to use PHP SOAP with the innovaphone PBX API.  However, it comes handy and should be generic enough to be useful in most cases.&lt;br /&gt;
&lt;br /&gt;
The SOAP client uses the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// get the innoPBX wrapper class&lt;br /&gt;
require_once(&#039;innopbx.class.php&#039;);&lt;br /&gt;
&lt;br /&gt;
// dummy classes to map SOAP results to (really would love to use namespaces here...)&lt;br /&gt;
// you can add methods and variables to these classes as needed&lt;br /&gt;
class innoUserInfo { };&lt;br /&gt;
class innoCallInfo { };&lt;br /&gt;
class innoAnyInfo { };&lt;br /&gt;
class innoGroup { };&lt;br /&gt;
class innoNo { };&lt;br /&gt;
class innoInfo { };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// config, adapt to your need&lt;br /&gt;
// this data below will work with innovaphones demo PBX.  Just register 2 phones as user-3 and user-4 and hve fun!&lt;br /&gt;
$server = &amp;quot;145.253.157.200&amp;quot;;&lt;br /&gt;
$user = &amp;quot;SOAP&amp;quot;;&lt;br /&gt;
$httpu = &amp;quot;demo&amp;quot;;&lt;br /&gt;
$httpp = &amp;quot;demo&amp;quot;;&lt;br /&gt;
$caller = &amp;quot;PBX User Four&amp;quot;;&lt;br /&gt;
$destination = &amp;quot;130&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
print &amp;quot;&amp;lt;pre&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// create connector to PBX&lt;br /&gt;
// class mapping is optional&lt;br /&gt;
$inno = new innoPBX($server, $httpu, $httpp, $user,&lt;br /&gt;
	    array(&#039;classmap&#039; =&amp;gt; array(&amp;quot;UserInfo&amp;quot; =&amp;gt; &amp;quot;innoUserInfo&amp;quot;, &lt;br /&gt;
				&amp;quot;CallInfo&amp;quot; =&amp;gt; &amp;quot;innoCallInfo&amp;quot;,&lt;br /&gt;
				&amp;quot;AnyInfo&amp;quot; =&amp;gt; &amp;quot;innoAnyInfo&amp;quot;,&lt;br /&gt;
				&amp;quot;Group&amp;quot; =&amp;gt; &amp;quot;innoGroup&amp;quot;,&lt;br /&gt;
				&amp;quot;No&amp;quot; =&amp;gt; &amp;quot;innoNo&amp;quot;,&lt;br /&gt;
				&amp;quot;Info&amp;quot; =&amp;gt; &amp;quot;innoInfo&amp;quot;,&lt;br /&gt;
			    )));&lt;br /&gt;
if ($inno-&amp;gt;key() == 0) die(&amp;quot;failed to login to PBX&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// show all methods supported by this object&lt;br /&gt;
print &amp;quot;All the functions provided by class innoPBX:\n&amp;quot;;&lt;br /&gt;
print_r($inno-&amp;gt;__getFunctions());&lt;br /&gt;
print &amp;quot;\n\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// get version info&lt;br /&gt;
$v = $inno-&amp;gt;Version();&lt;br /&gt;
&lt;br /&gt;
// show both types of infos list&lt;br /&gt;
function showInfos(&amp;amp;$poll, $head, $cn = &amp;quot;&amp;quot;, $user = &amp;quot;&amp;quot;, $call = &amp;quot;&amp;quot;) {&lt;br /&gt;
    print $head . &amp;quot;\n&amp;quot;;&lt;br /&gt;
    if ($cn !== null) {&lt;br /&gt;
	print count($poll-&amp;gt;user) . &amp;quot; UserInfos\n&amp;quot;;&lt;br /&gt;
	foreach($poll-&amp;gt;user as $ui) {&lt;br /&gt;
	    if (($cn === &amp;quot;&amp;quot;) || ($cn == $ui-&amp;gt;cn)) {&lt;br /&gt;
		print &amp;quot;     {$ui-&amp;gt;cn} ({$ui-&amp;gt;h323} #{$ui-&amp;gt;e164}) state {$ui-&amp;gt;state}\n&amp;quot;;&lt;br /&gt;
	    }&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
    if ($call !== null) {&lt;br /&gt;
	print count($poll-&amp;gt;call) . &amp;quot; CallInfos\n&amp;quot;;&lt;br /&gt;
	foreach($poll-&amp;gt;call as $ci) {&lt;br /&gt;
	    if ((($user === &amp;quot;&amp;quot;) || ($user == $ci-&amp;gt;user)) &amp;amp;&amp;amp;&lt;br /&gt;
		(($call === &amp;quot;&amp;quot;) || ($call == $ci-&amp;gt;call))) {&lt;br /&gt;
		    print &amp;quot;    {$ci-&amp;gt;user}/{$ci-&amp;gt;call} {$ci-&amp;gt;No[1]-&amp;gt;h323} #{$ci-&amp;gt;No[1]-&amp;gt;e164} (remote {$ci-&amp;gt;No[0]-&amp;gt;h323} #{$ci-&amp;gt;No[0]-&amp;gt;e164}) msg {$ci-&amp;gt;msg}\n&amp;quot;;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// retrieve the full user list.  Foreach object in the PBX, one userinfo is posted, terminated by an empty one&lt;br /&gt;
// You cannot assume that you will receive this list within a certain number of Poll results, so please iterate&lt;br /&gt;
print &amp;quot;Retrieving User list for &amp;quot;; foreach ($v as $name =&amp;gt; $value) print &amp;quot;\n  $name=$value &amp;quot;; print &amp;quot;...\n\n&amp;quot;;&lt;br /&gt;
$seen = false;&lt;br /&gt;
$i = 1;&lt;br /&gt;
while (!$seen) {&lt;br /&gt;
    $p = $inno-&amp;gt;Poll($inno-&amp;gt;session());&lt;br /&gt;
    showInfos($p, &amp;quot;Poll() result #$i&amp;quot;, &amp;quot;&amp;quot;, null, null); $i++;&lt;br /&gt;
    if ($p-&amp;gt;user[count($p-&amp;gt;user)-1]-&amp;gt;cn == &amp;quot;&amp;quot;) {&lt;br /&gt;
	// we have seen all entries&lt;br /&gt;
	print &amp;quot; --- END OF LIST ---\n\n&amp;quot;;&lt;br /&gt;
	$seen = true;&lt;br /&gt;
	break;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// create a call on behalf of some user&lt;br /&gt;
// first we need a user handle&lt;br /&gt;
print &amp;quot;\nObtaining a user handle for $caller...&amp;quot;;&lt;br /&gt;
$uhandle = $inno-&amp;gt;UserInitialize($inno-&amp;gt;session(), $caller);&lt;br /&gt;
print &amp;quot; $uhandle\n&amp;quot;;&lt;br /&gt;
if ($uhandle == 0) {&lt;br /&gt;
    die(&amp;quot;cant get user handle for $caller&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// then we create a call&lt;br /&gt;
print &amp;quot;Creating call from $caller to $destination...&amp;quot;;&lt;br /&gt;
$call = $inno-&amp;gt;UserCall($uhandle, null, $destination, null, 0, array());&lt;br /&gt;
print &amp;quot; $call\n&amp;quot;;&lt;br /&gt;
if ($call == 0) {&lt;br /&gt;
    die(&amp;quot;cant call on behalf of user $caller ($uhandle)&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// get call state(s) until call disappears&lt;br /&gt;
// note: you must at least poll for one call info related to this call, if you end&lt;br /&gt;
// the session right after UserCall, the call will not succeed!&lt;br /&gt;
$done = false;&lt;br /&gt;
while (!$done) {&lt;br /&gt;
    ob_flush();   // this is just to see the progress on the call states&lt;br /&gt;
    $p = $inno-&amp;gt;Poll($inno-&amp;gt;session());&lt;br /&gt;
    showInfos($p, &amp;quot;Call States #$i for #{$call}&amp;quot;, $caller, $uhandle, $call); $i++;&lt;br /&gt;
    // see if there was a del event (there is ALWAYS a del event)&lt;br /&gt;
    // we could as well look for an event with active = false&lt;br /&gt;
    foreach ($p-&amp;gt;call as $ci) {&lt;br /&gt;
	if (($ci-&amp;gt;user == $uhandle) &amp;amp;&amp;amp; &lt;br /&gt;
	    ($ci-&amp;gt;call == $call) &amp;amp;&amp;amp;&lt;br /&gt;
	    ($ci-&amp;gt;msg == &amp;quot;del&amp;quot;)) {&lt;br /&gt;
		print &amp;quot;\nCall terminated!\n&amp;quot;;&lt;br /&gt;
		$done = true;&lt;br /&gt;
	    }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// terminate the session&lt;br /&gt;
$e = $inno-&amp;gt;End($inno-&amp;gt;session());&lt;br /&gt;
&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Save this into a file named &#039;&#039;&#039;innopbx.sample.php&#039;&#039;&#039; in the same directory of your web server.&lt;br /&gt;
To run the code, you need to examine and possibly adapt the configuration parameters in &#039;&#039;&#039;innopbx.sample.php&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// config, adapt to your need&lt;br /&gt;
// this data below will work with innovaphones demo PBX.  Just register 2 phones as user-3 and user-4 and hve fun!&lt;br /&gt;
$server = &amp;quot;145.253.157.200&amp;quot;;&lt;br /&gt;
$user = &amp;quot;SOAP&amp;quot;;&lt;br /&gt;
$httpu = &amp;quot;demo&amp;quot;;&lt;br /&gt;
$httpp = &amp;quot;demo&amp;quot;;&lt;br /&gt;
$caller = &amp;quot;PBX User Four&amp;quot;;&lt;br /&gt;
$destination = &amp;quot;130&amp;quot;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This configuration will work right away with our publicly available [http://145.253.157.200 demo PBX].  You simply need to register 2 phones with the &#039;&#039;&#039;user-3&#039;&#039;&#039; and &#039;&#039;&#039;user-4&#039;&#039;&#039; users.&lt;br /&gt;
&lt;br /&gt;
Of course you can also use your own PBX.  Set the configuration parameters as follow:&lt;br /&gt;
{|&lt;br /&gt;
|$server || IP address of your innovaphone PBX&lt;br /&gt;
|-&lt;br /&gt;
| $user || CN (aka &#039;&#039;Long name&#039;&#039;) of a PBX user that is active group member of a group where all others are (active or passive) members of&lt;br /&gt;
|-&lt;br /&gt;
| $httpu || the admin account of the box running the innovaphone PBX (e.g.&#039;&#039;&#039;admin&#039;&#039;&#039;)&lt;br /&gt;
|-&lt;br /&gt;
| $httpp || the admin password of this box (e.g. &#039;&#039;&#039;ip&#039;&#039;xxx&#039;&#039;&#039;&#039;&#039;)&lt;br /&gt;
|-&lt;br /&gt;
| $caller || CN (aka &#039;&#039;Long name&#039;&#039;) of a PBX user you will have the script make a call for&lt;br /&gt;
|-&lt;br /&gt;
| $destination || the number to be called&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When the configuration parameters are set, you can point your browser to &#039;&#039;&#039;http:&#039;&#039;&#039;&amp;lt;nowiki&amp;gt;//&amp;lt;/nowiki&amp;gt;&#039;&#039;your-web-server-ip&#039;&#039;/&#039;&#039;path-to-folder&#039;&#039;/&#039;&#039;&#039;innopbx.sample.php&#039;&#039;&#039; which should create a call on &#039;&#039;&#039;$callers&#039;&#039;&#039; phone.&lt;br /&gt;
&lt;br /&gt;
Please note that you need internet access to retrieve the wsdl from innovaphone&#039;s web site.&lt;br /&gt;
&lt;br /&gt;
===How the code works===&lt;br /&gt;
====The innovaphone PBX API wrapper class====&lt;br /&gt;
&lt;br /&gt;
This class is derived from (&#039;&#039;extends&#039;&#039; in PHP speak) the standard SOAPClient class.   It basically simplifies the use of the standard class and performs the required call to &#039;&#039;&#039;Initialize&#039;&#039;&#039; within its constructor.&lt;br /&gt;
&lt;br /&gt;
The constructor takes the following arguments:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function __construct($server, $httpu, $httpp, $user, $options = null, $wsdl = null);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|$server, $httpu, $httpp, $user || see table above&lt;br /&gt;
|-&lt;br /&gt;
| $options &lt;br /&gt;
| an optional array of further options to SOAPClient::__construct.  Normally not required.  See [http://php.net/manual/en/soapclient.construct.php the PHP SOAPClient class documentation] for details.&lt;br /&gt;
|-&lt;br /&gt;
| $wsdl&lt;br /&gt;
| the optional URI of the pbx wsdl file.  Please note that you should use &#039;&#039;&#039;pbx501.wsdl&#039;&#039;&#039; instead of &#039;&#039;&#039;pbx.wsdl&#039;&#039;&#039;, as this is the more recent version of the wsdl.  By default, the wsdl is received from the innovaphone web and (subject to PHP configuration options) cached in PHP&#039;s wsdl cache.  If you intend to supply it locally, use a &#039;&#039;&#039;file://&#039;&#039;&#039; URI.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Calls to PBX API functions defined in the wsdl can be done directly through an instance of &#039;&#039;&#039;class innoPBX&#039;&#039;&#039;.  These member functions - which are neither defined in &#039;&#039;&#039;class innoPBX&#039;&#039;&#039; nor in &#039;&#039;&#039;class SOAPClient&#039;&#039;&#039; - are created automagically by reading the wsdl:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$v = $inno-&amp;gt;Version();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To see the functions available and their PHP signatures, you may call&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$inno = new innoPBX(...);&lt;br /&gt;
print_r($inno-&amp;gt;$inno-&amp;gt;__getFunctions());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Many PBX SOAP API functions required either the &#039;&#039;session-key&#039;&#039; or &#039;&#039;session-handle&#039;&#039;.   These are available from the class instance for convenience:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$p = $inno-&amp;gt;Poll($inno-&amp;gt;session());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====How PHP maps SOAP parameters to method parameters and results====&lt;br /&gt;
The mapping of parameters is pretty straight forward.  Arguments passed in to a SOAP method are passed as a value parameters to the class methods.  The thing to understand is that return values are always passed as return values, never as &#039;&#039;by-reference&#039;&#039; method arguments.&lt;br /&gt;
&lt;br /&gt;
If a SOAP method returns a single item, then it is returned by the function directly with appropriate type:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
int UserInitialize(int $session, string $user);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The single return value from the &#039;&#039;&#039;UserInitialize&#039;&#039;&#039; SOAP method is returned as &#039;&#039;&#039;int&#039;&#039;&#039; by the &#039;&#039;&#039;UserInitialize&#039;&#039;&#039; &#039;&#039;&#039;innoPBX&#039;&#039;&#039;-method.&lt;br /&gt;
&lt;br /&gt;
If the SOAP methods returns multiple items, then the corresponding class method will return an array:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
array Initialize(string $user, string $appl);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
will return an array such as&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
array(&lt;br /&gt;
    [&#039;return&#039;] =&amp;gt; value&lt;br /&gt;
    [&#039;key&#039;] =&amp;gt; value&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
In the method signature printed out by &#039;&#039;&#039;__getFunctions()&#039;&#039;&#039; this looks like&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
list(int $return, int $key) Initialize(string $user, string $appl)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====The sample class user====&lt;br /&gt;
This section will discuss the sample code.  It is not a decent description of the PBX SOAP API.  For this, see the related articles.&lt;br /&gt;
&lt;br /&gt;
A new &#039;&#039;&#039;innoPBX&#039;&#039;&#039; class instance object &#039;&#039;&#039;$inno&#039;&#039;&#039; is created using the values from the configuration variables discussed above.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$inno = new innoPBX($server, $httpu, $httpp, $user,&lt;br /&gt;
	    array(&#039;classmap&#039; =&amp;gt; array(&amp;quot;UserInfo&amp;quot; =&amp;gt; &amp;quot;innoUserInfo&amp;quot;, &lt;br /&gt;
				&amp;quot;CallInfo&amp;quot; =&amp;gt; &amp;quot;innoCallInfo&amp;quot;,&lt;br /&gt;
				&amp;quot;AnyInfo&amp;quot; =&amp;gt; &amp;quot;innoAnyInfo&amp;quot;,&lt;br /&gt;
				&amp;quot;Group&amp;quot; =&amp;gt; &amp;quot;innoGroup&amp;quot;,&lt;br /&gt;
				&amp;quot;No&amp;quot; =&amp;gt; &amp;quot;innoNo&amp;quot;,&lt;br /&gt;
				&amp;quot;Info&amp;quot; =&amp;gt; &amp;quot;innoInfo&amp;quot;,&lt;br /&gt;
			    )));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The option fifth argument will add a &#039;&#039;&#039;classmap&#039;&#039;&#039; entry to the options passed to &#039;&#039;&#039;SOAPClient::__construct&#039;&#039;&#039;.  If this is done, the SOAP class will use your defined classes when returning values to the caller.  Otherwise, structured return values will be indexed arrays (using the element names as array indexes).    This is neat, but not required for the class to function.&lt;br /&gt;
&lt;br /&gt;
When &#039;&#039;&#039;Initialize&#039;&#039;&#039; (which is done implicitly in the &#039;&#039;&#039;innoPBX&#039;&#039;&#039; constructor) was successfull, one &#039;&#039;&#039;UserInfo&#039;&#039;&#039; class object per PBX object is posted to the caller.  This list is terminated by an empty entry (more precisely, an entry with an empty &#039;&#039;&#039;cn&#039;&#039;&#039; member).&lt;br /&gt;
&lt;br /&gt;
The &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
while (!$seen) {&lt;br /&gt;
    $p = $inno-&amp;gt;Poll($inno-&amp;gt;session());&lt;br /&gt;
    ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
loop will retrieve and show all these entries.  &lt;br /&gt;
&lt;br /&gt;
To be able to perform calls, a user session must be opened by&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$uhandle = $inno-&amp;gt;UserInitialize($inno-&amp;gt;session(), $caller);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;$uhandle&#039;&#039;&#039; retrieved will identify the user to be worked with on subsequent calls.&lt;br /&gt;
&lt;br /&gt;
A call on behalf of &#039;&#039;&#039;$caller&#039;&#039;&#039; is then initiated:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$call = $inno-&amp;gt;UserCall($uhandle, null, $destination, null, 0, array());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When &#039;&#039;&#039;UserCall&#039;&#039;&#039; returns a non-zero call handle, the call is initiated and can be monitored by examining &#039;&#039;&#039;CallInfo&#039;&#039;&#039; events returned by subsequent &#039;&#039;&#039;Poll()&#039;&#039;&#039; calls:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
while (!$done) {&lt;br /&gt;
    $p = $inno-&amp;gt;Poll($inno-&amp;gt;session());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
this will retrieve events from the PBX &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
	if (($ci-&amp;gt;user == $uhandle) &amp;amp;&amp;amp; &lt;br /&gt;
	    ($ci-&amp;gt;call == $call) &amp;amp;&amp;amp;&lt;br /&gt;
	    ($ci-&amp;gt;msg == &amp;quot;del&amp;quot;)) {&lt;br /&gt;
		print &amp;quot;\nCall terminated!\n&amp;quot;;&lt;br /&gt;
		$done = true;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
until a &#039;&#039;&#039;del&#039;&#039;&#039; event is seen for the call previously created by UserCall.  Please note that any number of call events may occur, e.g. because someone else called $caller.  You cannot assume that all events retrieved are related to the call you created.  Also, any number of &#039;&#039;&#039;UserInfo&#039;&#039;&#039; events may be retrieved.&lt;br /&gt;
&lt;br /&gt;
Please note that there is no need to consume all of the events related to the call for it to work.  However, you must not terminate the session before the call is actually proceeding.  If you do so, strange things will happen.  To be sure the call proceeds, it is ok to wait for &#039;&#039;just any&#039;&#039; &#039;&#039;&#039;CallInfo&#039;&#039;&#039; event related to the call. You can then safely terminate your session and exit the web page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==More Sample Code==&lt;br /&gt;
Much more elaborate SOAP sample code is available for download from [http://download.innovaphone.com/ice/wiki-src/#soapphp5 the samples section] on http://download.innovaphone.com.&lt;br /&gt;
&lt;br /&gt;
This code shows how to deal with call control on master/slave scenarios as well as how to perform PBX configuration updates or PBX object creation using the [[Howto:Using the SOAP Admin Function|SOAP Admin function]].  Currently, there are the following sample functions available:&lt;br /&gt;
&lt;br /&gt;
* create a SOAP session to the master PBX&lt;br /&gt;
* create a user session on a device&lt;br /&gt;
* initiate a call via SOAP and terminate it once connected&lt;br /&gt;
* List all available SOAP functions&lt;br /&gt;
* Show an object&#039;s configuration using the Admin() function&lt;br /&gt;
* Modify a user object using the Admin() function&lt;br /&gt;
* Clone a PBX object using the Admin() function&lt;br /&gt;
* Add call forwarding using Admin() function&lt;br /&gt;
* Delete call forwarding using Admin() function&lt;br /&gt;
* Get the PBX key&lt;br /&gt;
* Generate an encrypted PBX user password&lt;br /&gt;
* Set a new password for user&lt;br /&gt;
* Get the password of a PBX object in clear&lt;br /&gt;
&lt;br /&gt;
Although this code is written in PHP5, it is also good reading if you do not intend to use PHP as it exemplifies the principles of using SOAP and the SOAP Admin() function.&lt;br /&gt;
&lt;br /&gt;
==Download ==&lt;br /&gt;
*[http://download.innovaphone.com/ice/wiki-src#soapphp5 http://download.innovaphone.com/ice/wiki-src#soapphp5] - download the complete file package of scripts and files described in this article.&lt;br /&gt;
&lt;br /&gt;
==Related Articles==&lt;br /&gt;
* [[Reference:SOAP API]]&lt;br /&gt;
* [[Reference7:SOAP API]]&lt;br /&gt;
* [[Reference8:SOAP API]]&lt;br /&gt;
* [[Reference9:Concept SOAP API]]&lt;br /&gt;
* [[Reference10:Concept SOAP API]]&lt;br /&gt;
&lt;br /&gt;
* [[Howto:Using the SOAP Admin Function]]&lt;br /&gt;
&lt;br /&gt;
[http://wiki.innovaphone.com/index.php?search=soap+sample&amp;amp;go=Go Search all SOAP sample code in the wiki]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--*[[Main_Page|wiki-innovaphone]]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Sample|{{PAGENAME}}]]&lt;/div&gt;</summary>
		<author><name>Treitinger</name></author>
	</entry>
</feed>