Initialer Laravel Commit für BetiX
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (8.4) (push) Has been cancelled
tests / ci (8.5) (push) Has been cancelled

This commit is contained in:
2026-04-04 18:01:50 +02:00
commit 0280278978
374 changed files with 65210 additions and 0 deletions

View File

@@ -0,0 +1,116 @@
<?php
namespace App\Services;
use Illuminate\Support\Facades\Http;
use RuntimeException;
class BetiXClient
{
private string $apiKey;
private string $baseUrl;
private float $timeout;
public function __construct()
{
$this->apiKey = (string) config('services.betix.key');
$this->baseUrl = rtrim((string) config('services.betix.url', 'https://originals.betix.io'), '/');
$this->timeout = (float) config('services.betix.timeout', 10.0);
}
// ── Public API methods ──────────────────────────────────────────────────
public function games(): array
{
return $this->request('GET', '/operator/games');
}
public function launch(array $payload): array
{
return $this->request('POST', '/operator/launch', $payload);
}
public function session(string $token): array
{
return $this->request('GET', "/operator/session/{$token}");
}
public function endSession(string $token): array
{
return $this->request('POST', "/operator/session/{$token}/end");
}
// ── HMAC signing ────────────────────────────────────────────────────────
/**
* Verify an inbound webhook from BetiX.
* Returns true if the X-Signature header matches the raw body.
*/
public function verifyWebhook(string $rawBody, string $signature): bool
{
$secret = (string) config('services.betix.webhook_secret');
$expected = hash_hmac('sha256', $rawBody, $secret);
return hash_equals($expected, $signature);
}
// ── HTTP transport ───────────────────────────────────────────────────────
private function request(string $method, string $path, array $data = []): array
{
$body = $data ? json_encode($data) : '';
$ts = (string) time();
$nonce = bin2hex(random_bytes(8));
$bodyHex = bin2hex($body);
$message = "{$ts}:{$nonce}:{$method}:{$path}:{$bodyHex}";
$sig = hash_hmac('sha256', $message, $this->apiKey);
$url = $this->baseUrl . $path;
\Illuminate\Support\Facades\Log::debug('[BetiXClient] request', [
'method' => $method,
'url' => $url,
'body' => $body ?: '{}',
'message' => $message,
]);
try {
$response = Http::withHeaders([
'X-API-Key' => $this->apiKey,
'X-Timestamp' => $ts,
'X-Nonce' => $nonce,
'X-Signature' => $sig,
'Accept' => 'application/json',
'Origin' => rtrim((string) config('app.url'), '/'),
])
->timeout($this->timeout)
->withBody($body ?: '{}', 'application/json')
->send($method, $url);
} catch (\Throwable $e) {
\Illuminate\Support\Facades\Log::error('[BetiXClient] connection failed', [
'url' => $url,
'error' => $e->getMessage(),
'exception' => get_class($e),
]);
throw new RuntimeException("BetiX unreachable: {$e->getMessage()}", 0, $e);
}
$json = $response->json() ?? [];
\Illuminate\Support\Facades\Log::debug('[BetiXClient] response', [
'status' => $response->status(),
'body' => $response->body(),
'json' => $json,
]);
if ($response->failed()) {
\Illuminate\Support\Facades\Log::error('[BetiXClient] API error', [
'status' => $response->status(),
'body' => $response->body(),
]);
throw new RuntimeException($json['error'] ?? "BetiX API error {$response->status()}");
}
return $json;
}
}