OpenXE/classes/Modules/Sipgate/SipgateWebHook.php

331 lines
8.4 KiB
PHP
Raw Normal View History

2021-05-21 08:49:41 +02:00
<?php
namespace Xentral\Modules\Sipgate;
use DOMAttr;
use \DOMDocument;
use \DOMElement;
/**
* Class SipGateWebHook
*
* Manage incoming requests from sipgate web hook api. This class is only used in
* www/pages/callcenter.php in Callcenter::CallcenterCall in switch 'sipgate' to
* create the xml response.
*
* It also provides methods to hang up the call etc.
*
* @see https://developer.sipgate.io/push-api/api-reference
* @see https://github.com/sipgate/sipgate.io/blob/master/examples/php/
*
* @example new SipGateWebHook($_POST, 'http://localhost:8080');
*/
class SipgateWebHook
{
/** @var array $data The call date. By default $_POST */
private $data = [];
/** @var string $url Optional the callback url to listen for following events. */
private $url = '';
/**
* @param array $data The call data
* @param string The url used as web hook for 'onAnswer' & 'onHangup' events.
*/
public function __construct($data, $url = '')
{
$data = (array)$data;
$data['timestamp'] = time();
$data['date'] = date('Y-m-d H:i:s');
$this->data = $data;
if (is_string($url) && filter_var($url, FILTER_VALIDATE_URL)) {
$this->url = $url;
}
}
/**
* @param string $key
* @param string $fallback
*
* @return mixed|string
*/
public function getData($key, $fallback = '')
{
return array_key_exists($key, $this->data)
? $this->data[$key]
: $fallback;
}
/**
* Redirect the call and alter your caller id (call charges apply).
* Calls with direction=in can be redirected to up to 5 targets.
*
* @return void
*/
public function dial()
{
$config = [
// 'voicemail' => true,
'suppress' => true,
'numbers' => [
123,
456,
678,
],
];
/**
* @param DOMDocument $dom
* @param DOMElement $parent
*
* @return DOMElement|null
*/
$callback = static function ($dom, $parent) use ($config) {
if (isset($config['voicemail']) && $config['voicemail']) {
return $dom->createElement('Voicemail');
}
/*
* Suppress phone number
*/
if ((isset($config['suppress']) && $config['suppress']) ||
(isset($config['anonymous']) && $config['anonymous'])) {
$anonymous = $dom->createAttribute('anonymous');
$anonymous->value = 'true';
$parent->appendChild($anonymous);
}
if (isset($config['number']) && $config['number']) {
/*
* override 'numbers' with 'number'
*/
$config['numbers'] = $config['number'];
}
/*
* Redirect incoming call to (multiple) destination(s)
* Calls with direction=in can be redirected to up to 5 targets.
*/
if (isset($config['numbers']) && $config['numbers']) {
$numbers = (array)$config['numbers'];
$numbers = array_filter($numbers);
$numbers = array_slice($numbers, 0, 5);
foreach ($numbers as $number) {
$numberElement = $dom->createElement('Number', $number);
$parent->appendChild($numberElement);
}
}
return null;
};
$this->createXMLResponse('Dial', $callback);
}
/**
* Send call to voice mail
*
* <?xml version="1.0" encoding="UTF-8"?>
* <Response>
* <Dial>
* <Voicemail />
* </Dial>
* </Response>
*
* @return void
*/
public function voiceMail()
{
/**
* @param DOMDocument $dom
*
* @return DOMElement|null
*/
$callback = static function ($dom) {
return $dom->createElement('Voicemail');
};
$this->createXMLResponse('Dial', $callback);
}
/**
* Reject call signaling busy
*
* <?xml version="1.0" encoding="UTF-8"?>
* <Response>
* <Reject reason="busy" />
* </Response>
*
* @return void
*/
public function busy()
{
/**
* @param DOMDocument $dom
*
* @return DOMAttr
*/
$callback = static function ($dom) {
$hangupReason = $dom->createAttribute('reason');
$hangupReason->value = 'busy';
return $hangupReason;
};
$this->createXMLResponse('Reject', $callback);
}
/**
* Reject call
*
* <?xml version="1.0" encoding="UTF-8"?>
* <Response>
* <Reject />
* </Response>
*
* @return void
*/
public function reject()
{
$this->createXMLResponse('Reject');
}
/**
* Hang up calls
*
* <?xml version="1.0" encoding="UTF-8"?>
* <Response>
* <Hangup />
* </Response>
*
* @return void
*/
public function hangUp()
{
$this->createXMLResponse('Hangup');
}
/**
* Play a sound file
*
* @see: https://developer.sipgate.io/push-api/api-reference/#play
*
* Please note:
* Currently the sound file needs to be a mono 16bit PCM WAV file with a sampling rate of 8kHz.
* You can use conversion tools like the open source audio editor Audacity to convert any sound
* file to the correct format. Linux users might want to use mpg123 to convert the file:
* $ mpg123 --rate 8000 --mono -w output.wav input.mp3
*
* <?xml version="1.0" encoding="UTF-8"?>
* <Response>
* <Play>
* <Url>http://example.com/example.wav</Url>
* </Play>
* </Response>
*
* @param string $url
*
* @return void
*/
public function play($url)
{
/**
* @param DOMDocument $dom
*
* @return DOMElement
*/
$callback = static function ($dom) use ($url) {
return $dom->createElement('Url', $url);
};
$this->createXMLResponse('Play', $callback);
}
/**
* sets header to xml and displays output
*
* @return bool
*/
public function listenOnFollowingEvents()
{
if (headers_sent()) {
return false;
}
if (!$this->url) {
return false;
}
// createXMLResponse starts sending headers & display some content
$this->createXMLResponse(false);
return true;
}
/**
* Create XML like:
*
* <?xml version="1.0" encoding="UTF-8"?>
* <Response onAnswer="http://localhost" onHangup="http://localhost">
* <Reject reason="busy"/>
* </Response>
*
* @param string $childName
* @param callable $callback
*
* @return void
*/
private function createXMLResponse($childName, $callback = null)
{
$dom = new DOMDocument('1.0', 'UTF-8');
$response = $dom->createElement('Response');
/*
* On new call, set the onAnswer & onHangup flags
*/
if ($this->url && $this->data['event'] && $this->data['event'] === 'newCall') {
$url = $this->url;
/*
* If you set the onAnswer attribute sipgate.io will push an answer-event,
* when a call is answered by the other party.
*/
$response->setAttribute('onAnswer', $url);
/*
* If you set the onHangup attribute sipgate.io will push a hangup-event
* when the call ends.
*/
$response->setAttribute('onHangup', $url);
}
if (is_string($childName) && $childName) {
/*
* create the child defined in the $childName argument
*/
$child = $dom->createElement($childName);
/*
* If a callback is given, let's append it's response
* to the child.
*/
if ($callback !== null && is_callable($callback)) {
$element = $callback($dom, $child);
if ($element) {
$child->appendChild($element);
}
}
$response->appendChild($child);
}
$dom->appendChild($response);
header('Content-type: application/xml');
echo $dom->saveXML();
}
}