Add Bird API integration with voice call and flash call support
- Implement Bird API client (`bird.php`) for handling HTTP requests to Bird services. - Add routes for voice and flash call management (`birdVoiceFlashCallsRoute.php`, `birdNumbersRoute.php`). - Introduce test cases for voice calls, flash calls, and numbers (`VoiceCallsApiTest.php`, `NumbersAndFlashCallsApiTest.php`). - Include configuration management classes and APIs for enabling the Bird module and managing API keys (`bird_c.php`). - Provide OpenAPI specifications for flash call endpoints (`bird-flash-calls.md`).
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
<?php
|
||||
|
||||
namespace classes;
|
||||
|
||||
require_once WD . '/modules/bird/bird_c.php';
|
||||
|
||||
use bird\bird_c;
|
||||
use Exception;
|
||||
|
||||
class bird
|
||||
{
|
||||
/**
|
||||
* Configuration of the Bird module
|
||||
* @var bird_c|object
|
||||
*/
|
||||
public $config;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->config = new bird_c();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure module is enabled
|
||||
* @throws Exception
|
||||
*/
|
||||
function requireModuleEnabled(): void
|
||||
{
|
||||
if (!$this->config->enabled->isTrue()) {
|
||||
throw new Exception('The bird module is not enabled');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure API key is present
|
||||
* @throws Exception
|
||||
*/
|
||||
function requireValidApiKey(): void
|
||||
{
|
||||
$k = $this->config->api_key->getVariableValue();
|
||||
if ($k === null || $k === '') {
|
||||
throw new Exception('Invalid API key defined in the config (bird_api_key_c)');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure base URL is defined
|
||||
* @throws Exception
|
||||
*/
|
||||
function requireValidServerURL(): void
|
||||
{
|
||||
$u = $this->config->server_url->getVariableValue();
|
||||
if ($u === null || $u === '') {
|
||||
throw new Exception('Invalid server URL defined in the config (bird_server_url_c)');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a request to Bird API
|
||||
* @param string $endpoint e.g. "/v1/devices"
|
||||
* @param array $data request body
|
||||
* @param string $method HTTP method (currently only POST supported)
|
||||
* @return object|array|null
|
||||
* @throws Exception
|
||||
*/
|
||||
function sendRequest(string $endpoint, array $data = [], string $method = 'POST'): object|array|null
|
||||
{
|
||||
$this->requireModuleEnabled();
|
||||
$this->requireValidApiKey();
|
||||
$this->requireValidServerURL();
|
||||
return match (strtoupper($method)) {
|
||||
'POST' => $this->sendPostRequest($endpoint, $data),
|
||||
'GET' => $this->sendGetRequest($endpoint, $data),
|
||||
default => throw new Exception('Invalid request method'),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Send POST request
|
||||
* @param string $endpoint
|
||||
* @param array $data
|
||||
* @return array|object|null
|
||||
* @throws Exception
|
||||
*/
|
||||
function sendPostRequest(string $endpoint, array $data): array|object|null
|
||||
{
|
||||
$this->requireModuleEnabled();
|
||||
$this->requireValidApiKey();
|
||||
$this->requireValidServerURL();
|
||||
|
||||
$url = rtrim($this->config->server_url->getVariableValue(), '/') . $endpoint;
|
||||
$headers = [
|
||||
'Content-Type: application/json',
|
||||
'Authorization: Bearer ' . $this->config->api_key->getVariableValue(),
|
||||
];
|
||||
$body = json_encode($data);
|
||||
|
||||
$result = $this->doHttpRequest('POST', $url, $headers, $body);
|
||||
$status = (int)($result['status_code'] ?? 0);
|
||||
$response = $result['body'] ?? '';
|
||||
if ($status >= 400) {
|
||||
throw new Exception('Bird API request failed with status ' . $status);
|
||||
}
|
||||
if ($response === '' || $response === false || $response === null) {
|
||||
return null;
|
||||
}
|
||||
$decoded = json_decode($response);
|
||||
return $decoded ?? $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Low-level HTTP transport (curl). Tests can override this to stub network.
|
||||
* @param string $method
|
||||
* @param string $url
|
||||
* @param array $headers
|
||||
* @param string $body
|
||||
* @return array{status_code:int, body:string|false}
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function doHttpRequest(string $method, string $url, array $headers, string $body = ''): array
|
||||
{
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
$upper = strtoupper($method);
|
||||
if ($upper === 'POST') {
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
|
||||
} else {
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $upper);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
$resp = curl_exec($ch);
|
||||
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
if (curl_errno($ch)) {
|
||||
$err = curl_error($ch);
|
||||
curl_close($ch);
|
||||
throw new Exception('cURL error: ' . $err);
|
||||
}
|
||||
curl_close($ch);
|
||||
return [
|
||||
'status_code' => (int)$code,
|
||||
'body' => $resp,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Send GET request
|
||||
* @param string $endpoint
|
||||
* @param array $query
|
||||
* @return array|object|null
|
||||
* @throws Exception
|
||||
*/
|
||||
function sendGetRequest(string $endpoint, array $query = []): array|object|null
|
||||
{
|
||||
$this->requireModuleEnabled();
|
||||
$this->requireValidApiKey();
|
||||
$this->requireValidServerURL();
|
||||
|
||||
$base = rtrim($this->config->server_url->getVariableValue(), '/');
|
||||
$url = $base . $endpoint;
|
||||
if (!empty($query)) {
|
||||
$qs = http_build_query($query);
|
||||
$url .= (str_contains($url, '?') ? '&' : '?') . $qs;
|
||||
}
|
||||
$headers = [
|
||||
'Content-Type: application/json',
|
||||
'Authorization: Bearer ' . $this->config->api_key->getVariableValue(),
|
||||
];
|
||||
$result = $this->doHttpRequest('GET', $url, $headers);
|
||||
$status = (int)($result['status_code'] ?? 0);
|
||||
$response = $result['body'] ?? '';
|
||||
if ($status >= 400) {
|
||||
throw new Exception('Bird API request failed with status ' . $status);
|
||||
}
|
||||
if ($response === '' || $response === false || $response === null) {
|
||||
return null;
|
||||
}
|
||||
$decoded = json_decode($response);
|
||||
return $decoded ?? $response;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user