; raspunde JSON: // {"status":"pending"} cat timp tokenul nu a sosit (intotdeauna HTTP 200, nu 404), // continutul fisierului de token (succes sau eroare ANAF) o SINGURA data, apoi il sterge. // Fara session_start() — evita serializarea pe lock-ul de sesiune PHP. header('Content-Type: application/json; charset=utf-8'); // Director tokenuri (acelasi ca in index.php) — protejat cu .htaccess $tokens_dir = __DIR__ . '/tokens'; if (!is_dir($tokens_dir)) { @mkdir($tokens_dir, 0700, true); } $tokens_htaccess = $tokens_dir . '/.htaccess'; if (!file_exists($tokens_htaccess)) { @file_put_contents($tokens_htaccess, "Require all denied\n"); } // Validare stricta format state: 64 caractere [A-Za-z0-9] (protectie path traversal) $state = isset($_POST['state']) ? (string)$_POST['state'] : ''; if (strlen($state) !== 64 || !preg_match('/^[A-Za-z0-9]+$/', $state)) { http_response_code(400); echo json_encode(['error' => 'invalid_state']); exit(); } // TTL: sterge fisierele de tokenuri (si .tmp orfane) mai vechi de 10 minute // (aliniat cu timeout-ul de polling din ROACONT) $now = time(); foreach (array_merge((array)glob($tokens_dir . '/*.json'), (array)glob($tokens_dir . '/*.tmp')) as $f) { if (($now - filemtime($f)) > 600) { @unlink($f); } } // Numele fisierului = SHA-256(state): secretul nu apare in listinguri de directoare $token_file = $tokens_dir . '/' . hash('sha256', $state) . '.json'; if (!file_exists($token_file)) { echo json_encode(['status' => 'pending']); exit(); } // Claim atomic prin rename: din doua cereri concurente una singura primeste tokenul, // cealalta "pending"; previne si citirea unui JSON partial (index.php scrie .tmp + rename) $claim_file = $tokens_dir . '/' . hash('sha256', $state) . '_claim_' . getmypid() . '.json'; if (!@rename($token_file, $claim_file)) { echo json_encode(['status' => 'pending']); exit(); } // Citire INAINTE de stergere; la esec nu stergem (TTL curata fisierul claim ramas) $content = file_get_contents($claim_file); if ($content === false || $content === '') { echo json_encode(['error' => 'read_error']); exit(); } @unlink($claim_file); // Continutul JSON exact cum a fost salvat de index.php (tokenuri sau eroare ANAF) echo $content;