Add GatewayAPI module with configuration, routing, and core logic

Introduced a new GatewayAPI module to handle SMS messaging integration. This includes interfaces, core classes for API interaction, configuration management, and routing for config retrieval and update. Added necessary initializations in `index.php` to integrate the module seamlessly.
This commit is contained in:
Jepp9350
2025-04-10 10:51:32 +02:00
parent 9025f381df
commit 849f1cc53e
11 changed files with 487 additions and 0 deletions
+169
View File
@@ -0,0 +1,169 @@
<?php
namespace classes;
use Exception;
use gatewayapi\gatewayapi_c;
use interfaces\gatewayapi_i;
require_once WD . '/modules/gatewayapi/gatewayapi_c.php';
class gatewayapi implements gatewayapi_i
{
/**
* Configuration of the gatewayapi module
* @var gatewayapi_c $config
*/
public gatewayapi_c $config;
/**
* API URL
* @var string
*/
private string $api_url = 'https://gatewayapi.com';
public function __construct()
{
$this->config = new gatewayapi_c();
}
/**
* @inheritDoc
*/
public function send(array $to, string $message): bool
{
$this->requireEnabled();
$data = [
"recipients" => array_map(function ($recipient) {
return [
'msisdn' => $recipient,
];
}, $to),
'message' => $message,
'sender' => $this->config->sender->getVariableValue(),
];
$headers = [
'Authorization: ' . $this->config->api_key->getVariableValue(),
'Content-Type: application/json'
];
try {
self::sendRequest(
'/rest/mtsms',
'POST',
$data,
);
} catch (Exception $exception) {
throw new Exception('Failed to send SMS: ' . $exception->getMessage());
}
return true;
}
/**
* @inheritDoc
*/
public function requireEnabled(): void
{
if (!$this->isEnabled()) {
throw new Exception('GatewayAPI is not enabled');
}
}
/**
* @inheritDoc
* @throws Exception If the enabled property is not set
*/
public function isEnabled(): bool
{
try {
return $this->config->enabled->isTrue();
} catch (Exception $exception) {
return false;
}
}
/**
* @inheritDoc
* @throws Exception If the module is not enabled
* @throws Exception If the API key is not set
* @throws Exception If the sender is not set
* @throws Exception If the API URL is not set
* @throws Exception If the request fails
* @throws Exception If the response is not valid JSON
*/
public function sendRequest(string $url, string $method, array $data = [], array $headers = []): array
{
self::requireEnabled();
$json_encode = json_encode($data);
if ($json_encode === false) {
throw new Exception('Failed to encode data to JSON: ' . json_last_error_msg());
}
if (empty($url) || empty($method)) {
throw new Exception('URL and method are required');
}
// Add the token to the headers
return self::curlRequest(
$url,
$method,
$json_encode,
[
...$headers,
...self::getDefaultRequestHeaders(),
]
);
}
/**
* @param string $endpoint The URL endpoint to send the request to (e.g. /rest/mtsms)
* @param string $method The HTTP method to use (GET, POST, PUT, DELETE)
* @param string $json_encode The JSON-encoded data to send
* @param array $headers The headers to send with the request
* @param bool $allow_fail If true, the response will be returned even if the HTTP code is not 200, otherwise an exception will be thrown
* @throws Exception If the request fails
* @throws Exception If the response is not valid JSON
*/
private function curlRequest(string $endpoint, string $method, string $json_encode, array $headers, bool $allow_fail = false): array
{
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => $this->api_url . $endpoint,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_POSTFIELDS => $json_encode,
CURLOPT_HTTPHEADER => $headers
]);
$response = curl_exec($curl);
$http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
if ($http_code !== 200 && !$allow_fail) {
throw new Exception('Request failed with HTTP code ' . $http_code . ': ' . $response);
}
if (empty($response)) {
throw new Exception('Empty response from API');
}
$response = json_decode($response, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new Exception('Failed to decode JSON response: ' . json_last_error_msg());
}
if (!is_array($response)) {
throw new Exception('Invalid response format: ' . gettype($response));
}
// Check if the response is an array
return $response;
}
/**
* @inheritDoc
*/
public function getDefaultRequestHeaders(): array
{
return [
'Authorization: Token ' . $this->config->api_token->getVariableValue(),
'Content-Type: application/json',
];
}
}
+1
View File
@@ -64,6 +64,7 @@ require_once 'classes/stripe.php';
require_once 'classes/form.php';
require_once 'classes/pdf_generator.php';
require_once 'classes/fxratesapi.php';
require_once 'classes/gatewayapi.php';
/**
* Modules
@@ -0,0 +1,44 @@
<?php
namespace interfaces;
use Exception;
interface gatewayapi_i
{
/**
* Check if the module is enabled
* @return bool True if the module is enabled, false otherwise
*/
public function isEnabled(): bool;
/**
* Require the module to be enabled
* @throws Exception If the module is not enabled
*/
public function requireEnabled(): void;
/**
* Send a message
* @param array{string} $to The recipient(s) of the message
* @param string $message The message to be sent
* @return bool True if the message was sent, false otherwise
* @throws Exception If the module is not enabled
* @throws Exception If the message could not be sent
*/
public function send(array $to, string $message): bool;
/**
* Send request to the API
* @param string $url The URL to send the request to
* @param string $method The HTTP method to use (GET, POST, PUT, DELETE)
* @param array $data The data to send with the request
*/
public function sendRequest(string $url, string $method, array $data = []): array;
/**
* Get the default request headers
* @return array The default request headers
*/
public function getDefaultRequestHeaders(): array;
}
@@ -0,0 +1,29 @@
<?php
namespace gatewayapi\config;
use Exception;
use traits\module_config_variable;
class gatewayapi_api_key_c
{
use module_config_variable;
/**
* @throws Exception
*/
public function __construct()
{
self::setupConfigVariable(
'GatewayAPI',
'api_key',
'string',
false,
null,
'The API key for the GatewayAPI service',
'mlsn.7dd13651...',
true,
''
);
}
}
@@ -0,0 +1,29 @@
<?php
namespace gatewayapi\config;
use Exception;
use traits\module_config_variable;
class gatewayapi_api_secret_c
{
use module_config_variable;
/**
* @throws Exception
*/
public function __construct()
{
self::setupConfigVariable(
'GatewayAPI',
'api_secret',
'string',
true,
null,
'The secret for the GatewayAPI module',
'secret123',
true,
''
);
}
}
@@ -0,0 +1,29 @@
<?php
namespace gatewayapi\config;
use Exception;
use traits\module_config_variable;
class gatewayapi_api_token_c
{
use module_config_variable;
/**
* @throws Exception
*/
public function __construct()
{
self::setupConfigVariable(
'GatewayAPI',
'api_token',
'string',
true,
null,
'The token for the GatewayAPI module',
'tokensecret123',
true,
''
);
}
}
@@ -0,0 +1,29 @@
<?php
namespace gatewayapi\config;
use Exception;
use traits\module_config_variable;
class gatewayapi_enabled_c
{
use module_config_variable;
/**
* @throws Exception
*/
public function __construct()
{
self::setupConfigVariable(
'GatewayAPI',
'enabled',
'bool',
true,
null,
'Whether the GatewayAPI module is enabled or not',
'1',
false,
'false'
);
}
}
@@ -0,0 +1,29 @@
<?php
namespace gatewayapi\config;
use Exception;
use traits\module_config_variable;
class gatewayapi_sender_c
{
use module_config_variable;
/**
* @throws Exception
*/
public function __construct()
{
self::setupConfigVariable(
'GatewayAPI',
'sender',
'string',
true,
null,
'The sender name to use for the GatewayAPI',
'Virksomhedsnavn',
false,
'Virksomhedsnavn',
);
}
}
@@ -0,0 +1,69 @@
<?php
namespace gatewayapi;
$GatewayAPI_path = __DIR__;
$GatewayAPI_config_path = $GatewayAPI_path . '/config';
/** Universal */
require_once $GatewayAPI_path . '/config/gatewayapi_enabled_c.php';
require_once $GatewayAPI_path . '/config/gatewayapi_api_key_c.php';
require_once $GatewayAPI_path . '/config/gatewayapi_api_secret_c.php';
require_once $GatewayAPI_path . '/config/gatewayapi_sender_c.php';
require_once $GatewayAPI_path . '/config/gatewayapi_api_token_c.php';
use gatewayapi\config\gatewayapi_api_key_c;
use gatewayapi\config\gatewayapi_api_secret_c;
use gatewayapi\config\gatewayapi_api_token_c;
use gatewayapi\config\gatewayapi_enabled_c;
use gatewayapi\config\gatewayapi_sender_c;
use traits\module_config_t;
class gatewayapi_c
{
use module_config_t;
/**
* The status of the module
* @var gatewayapi_enabled_c
*/
public gatewayapi_enabled_c $enabled;
/**
* The API key for the module
* @var gatewayapi_api_key_c
*/
public gatewayapi_api_key_c $api_key;
/**
* The API secret for the module
* @var gatewayapi_api_secret_c
*/
public gatewayapi_api_secret_c $api_secret;
/**
* The sender for the module
* @var gatewayapi_sender_c
*/
public gatewayapi_sender_c $sender;
/**
* The API token for the module
* @var gatewayapi_api_token_c
*/
public gatewayapi_api_token_c $api_token;
public function __construct()
{
$this->setupConfig('GatewayAPI');
$this->allowUpdate([
gatewayapi_enabled_c::class,
gatewayapi_api_key_c::class,
gatewayapi_api_secret_c::class,
gatewayapi_sender_c::class,
gatewayapi_api_token_c::class,
]);
$this->enabled = new gatewayapi_enabled_c();
$this->api_key = new gatewayapi_api_key_c();
$this->api_secret = new gatewayapi_api_secret_c();
$this->sender = new gatewayapi_sender_c();
$this->api_token = new gatewayapi_api_token_c();
}
}
@@ -333,5 +333,43 @@ class moduleConfigRoute
'fxratesapi_config' => 'Update fxratesapi config'
]
);
/** GatewayAPI config > GET */
$this->get('/gatewayapi/config', function () {
global $response;
$this->requirePermission('gatewayapi_config');
$user = (new authentication())->get_user();
if ($user) {
(new logs_o())->add('gatewayapi_config', 'global', 1, $user->id, 'GATEWAYAPI_CONFIG', 'Successfully fetched gatewayapi config');
$response->success(
(new \classes\gatewayapi())->config->getConfigRequest()
);
} else {
(new logs_o())->add('gatewayapi_config', 'global', 1, 0, 'GATEWAYAPI_CONFIG', 'No user found, or invalid session');
$response->error('Invalid session', 400);
}
},
[
'gatewayapi_config' => 'Get gatewayapi config'
]
);
/** GatewayAPI config > POST */
$this->post('/gatewayapi/config', function () {
global $response;
$this->requirePermission('gatewayapi_config');
$user = (new authentication())->get_user();
if ($user) {
(new logs_o())->add('gatewayapi_config', 'global', 1, $user->id, 'GATEWAYAPI_CONFIG', 'Successfully updated gatewayapi config');
$response->success(
(new \classes\gatewayapi())->config->postConfigRequest()
);
} else {
(new logs_o())->add('gatewayapi_config', 'global', 1, 0, 'GATEWAYAPI_CONFIG', 'No user found, or invalid session');
$response->error('Invalid session', 400);
}
},
[
'gatewayapi_config' => 'Update gatewayapi config'
]
);
}
}
@@ -0,0 +1,21 @@
<?php
namespace routes;
use classes\response;
use classes\router;
use traits\route_t;
class moduleGatewayAPIRoute
{
use route_t;
public function run(): void
{
global /** @var response $response */
/** @var router $router */
$router, $response;
}
}