doctorPhone = $doctorPhone; $this->patientPhone = $patientPhone; $this->warnTime = $warnTime; $this->hangTime = $hangTime; // Create a new Factory instance $factory = new Clue\React\Ami\Factory(); // Create a new Client instance and connect to the Asterisk server $factory->createClient('user:secret@localhost')->then(function (Clue\React\Ami\Client $client) { // Assign the client to the property $this->client = $client; // Create a new ActionSender instance $this->sender = new Clue\React\Ami\ActionSender($client); // Call the patient number $this->callPatient(); }); } // Define the callPatient method private function callPatient() { // Try to originate a call to the patient number using the ActionSender instance try { // Create an action with the parameters $action = new Clue\React\Ami\Protocol\Action([ 'Action' => 'Originate', 'Channel' => 'SIP/' . $this->patientPhone, 'Context' => 'default', 'Exten' => 's', 'Priority' => 1, 'CallerID' => 'SecureCall', 'Async' => true, 'Variable' => [ '__SECURECALL' => true, '__DOCTORPHONE' => $this->doctorPhone, '__WARNTIME' => $this->warnTime, '__HANGTIME' => $this->hangTime ] ]); // Send the action and get a promise for the response $promise = $this->sender->request($action); // Handle the response when it arrives $promise->then(function (Clue\React\Ami\Protocol\Response $response) { // Check if the call was answered if ($response->getFieldValue('Response') == 'Success' && ($response->getFieldValue('Reason') == '4' || strpos($response->getFieldValue('Message'), 'Originate successfully queued') !== false)) { // Get the patient channel from the response if ($response->hasField('Channel')) { // Use the Channel field if available (Asterisk 1.8+) $this->patientChannel = $response->getFieldValue('Channel'); } else { // Use the SIP channel name otherwise (Asterisk 1.6-) $this->patientChannel = 'SIP/' . $this->patientPhone . '-' . substr($response->getActionId(), -4); } // Call the doctor number $this->callDoctor(); } else { // Call an web api and send status $this->callWebApi('patient_not_answered'); } }); } catch (Exception $e) { // Handle any errors that may occur when sending the action echo 'Error: ' . $e->getMessage() . PHP_EOL; } } // Define the callDoctor method private function callDoctor() { // Try to originate a call to the doctor number using the ActionSender instance try { // Create an action with the parameters $action = new Clue\React\Ami\Protocol\Action([ 'Action' => 'Originate', 'Channel' => 'SIP/' . $this->doctorPhone, 'Context' => 'default', 'Exten' => 's', 'Priority' => 1, 'CallerID' => 'SecureCall', 'Async' => true, 'Variable' => [ '__SECURECALL' => true, '__PATIENTPHONE' => $this->patientPhone, '__WARNTIME' => $this->warnTime, '__HANGTIME' => $this->hangTime ] ]); // Send the action and get a promise for the response $promise = $this->sender->request($action); // Handle the response when it arrives $promise->then(function (Clue\React\Ami\Protocol\Response $response) { // Check if the call was answered if ($response->getFieldValue('Response') == 'Success' && ($response->getFieldValue('Reason') == '4' || strpos($response->getFieldValue('Message'), 'Originate successfully queued') !== false)) { // Get the doctor channel from the response if ($response->hasField('Channel')) { // Use the Channel field if available (Asterisk 1.8+) $this->doctorChannel = $response->getFieldValue('Channel'); } else { // Use the SIP channel name otherwise (Asterisk 1.6-) $this->doctorChannel = 'SIP/' . $this->doctorPhone . '-' . substr($response->getActionId(), -4); } // Bridge the patient and doctor channels $this->bridgeChannels(); } else { // Call an web api and send status $this->callWebApi('doctor_not_answered'); } }); } catch (Exception $e) { // Handle any errors that may occur when sending the action echo 'Error: ' . $e->getMessage() . PHP_EOL; } } // Define the bridgeChannels method private function bridgeChannels() { // Try to bridge the patient and doctor channels using the ActionSender instance try { // Create an action with the parameters $action = new Clue\React\Ami\Protocol\Action([ 'Action' => 'Bridge', 'Channel1' => $this->patientChannel, 'Channel2' => $this->doctorChannel, 'Tone' => true ]); // Send the action and get a promise for the response $promise = $this->sender->request($action); // Handle the response when it arrives $promise->then(function (Clue\React\Ami\Protocol\Response $response) { // Check if the channels were bridged successfully if ($response->getFieldValue('Response') == 'Success') { // Call an web api and send status $this->callWebApi('call_bridged'); } else { // Call an web api and send status $this->callWebApi('bridge_failed'); } }); } catch (Exception $e) { // Handle any errors that may occur when sending the action echo 'Error: ' . $e->getMessage() . PHP_EOL; } } // Define the callWebApi method private function callWebApi($status) { // TODO: Implement this method to call an external web api and send the status of the call echo "Call status: " . $status . PHP_EOL; } } // Create a new SecureCall instance with some parameters $secureCall = new SecureCall('1234567890', '0987654321', 60, 120);