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,112 @@
<?php
namespace App\Http\Controllers;
use App\Models\OperatorCasino;
use App\Models\OperatorSession;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
class OperatorController extends Controller
{
// Supported game slugs
private const VALID_GAMES = ['dice', 'crash', 'mines', 'plinko'];
/**
* GET /operator/games
*
* Returns the full game catalog with thumbnail URLs and launch paths.
*/
public function games(Request $request)
{
$baseUrl = rtrim((string) config('games.game_base_url', config('app.url')), '/');
$games = collect(config('games.catalog', []))->map(fn ($g) => array_merge($g, [
'thumbnail_url' => "{$baseUrl}/assets/games/{$g['slug']}.png",
'launch_path' => "/{$g['slug']}",
]));
return response()->json(['games' => $games]);
}
/**
* POST /operator/launch
*
* Creates a new operator game session and returns the launch URL.
*/
public function launch(Request $request)
{
/** @var OperatorCasino $casino */
$casino = $request->attributes->get('operator_casino');
$data = $request->validate([
'player_id' => ['required', 'string', 'max:255'],
'balance' => ['required', 'numeric', 'min:0'],
'currency' => ['required', 'string', 'size:3'],
'game' => ['required', 'string', 'in:' . implode(',', self::VALID_GAMES)],
// license_key is consumed by middleware; allow it in the body without failing validation
'license_key' => ['sometimes', 'string'],
]);
// Generate server seed for provably-fair and store it encrypted
$serverSeed = bin2hex(random_bytes(32));
$serverSeedHash = hash('sha256', $serverSeed);
$token = (string) Str::uuid();
$expiresAt = now()->addHours(4);
OperatorSession::create([
'session_token' => $token,
'operator_casino_id' => $casino->id,
'player_id' => $data['player_id'],
'game_slug' => $data['game'],
'currency' => strtoupper($data['currency']),
'start_balance' => $data['balance'],
'current_balance' => $data['balance'],
'server_seed' => encrypt($serverSeed),
'server_seed_hash' => $serverSeedHash,
'status' => 'active',
'expires_at' => $expiresAt,
]);
$baseUrl = rtrim((string) config('games.game_base_url', config('app.url')), '/');
$launchUrl = "{$baseUrl}/{$data['game']}?session={$token}";
return response()->json([
'session_token' => $token,
'launch_url' => $launchUrl,
'server_seed_hash' => $serverSeedHash,
'expires_at' => $expiresAt->toIso8601String(),
]);
}
/**
* GET /operator/session/{token}
*
* Returns the current state of a session including the final balance delta.
* The casino should call this after the player's session ends.
*/
public function session(Request $request, string $token)
{
/** @var OperatorCasino $casino */
$casino = $request->attributes->get('operator_casino');
$session = OperatorSession::where('session_token', $token)
->where('operator_casino_id', $casino->id)
->firstOrFail();
$session->expireIfNeeded();
return response()->json([
'session_token' => $session->session_token,
'player_id' => $session->player_id,
'game' => $session->game_slug,
'currency' => $session->currency,
'start_balance' => (float) $session->start_balance,
'current_balance' => (float) $session->current_balance,
'balance_delta' => round((float) $session->current_balance - (float) $session->start_balance, 4),
'status' => $session->status,
'expires_at' => $session->expires_at->toIso8601String(),
]);
}
}