900) { return false; } // Generate the expected signature $expected_sig = hash_hmac('sha256', $device_id . $ts, $secret_key); // Secure comparison return hash_equals($expected_sig, $sig); } function jsonError($message, $code = 400) { http_response_code($code); echo json_encode(['status' => 'failure', 'message' => $message]); exit; } // ---------------------------------------------------------------------------- // API Request Routing // ---------------------------------------------------------------------------- $method = $_SERVER['REQUEST_METHOD']; $contentType = $_SERVER['CONTENT_TYPE'] ?? ''; // Check if request is API call from the Bot $isApiCall = false; $device_id = null; $ts = null; $sig = null; if ($method === 'GET' && isset($_GET['device_id'], $_GET['ts'], $_GET['sig'])) { $isApiCall = true; $device_id = $_GET['device_id']; $ts = intval($_GET['ts']); $sig = $_GET['sig']; } elseif ($method === 'POST') { // Check if JSON body has device credentials $rawInput = file_get_contents('php://input'); $input = json_decode($rawInput, true); if ($input && isset($input['device_id'], $input['ts'], $input['sig'])) { $isApiCall = true; $device_id = $input['device_id']; $ts = intval($input['ts']); $sig = $input['sig']; } } if ($isApiCall) { header('Content-Type: application/json; charset=UTF-8'); // Validate signature if (!validateSignature($device_id, $ts, $sig, SECRET_KEY)) { jsonError("Unauthorized device signature or expired timestamp. Device ID: $device_id, ts: $ts", 401); } if ($method === 'GET') { // Dequeue one task for this bot (FIFO) $tasks = json_decode(file_get_contents(TASKS_FILE), true); if (count($tasks) > 0) { $task = array_shift($tasks); file_put_contents(TASKS_FILE, json_encode($tasks, JSON_PRETTY_PRINT)); echo json_encode([ "status" => "success", "has_task" => true, "task" => $task ]); } else { echo json_encode([ "status" => "success", "has_task" => false ]); } exit; } elseif ($method === 'POST') { // Record Scrape result if (empty($input['task_id']) || empty($input['status'])) { jsonError("Missing required parameters in payload"); } $results = json_decode(file_get_contents(RESULTS_FILE), true); $newResult = [ 'task_id' => $input['task_id'], 'device_id' => $device_id, 'status' => $input['status'], // 'success' or 'failed' 'type' => $input['type'] ?? 'price_check', 'recorded_at' => date('Y-m-d H:i:s'), 'result_data' => $input['result_data'] ?? [] ]; array_unshift($results, $newResult); file_put_contents(RESULTS_FILE, json_encode($results, JSON_PRETTY_PRINT)); echo json_encode([ "status" => "success", "message" => "Result recorded successfully" ]); exit; } } // ---------------------------------------------------------------------------- // Admin Dashboard UI (Rendered on normal GET browser requests) // ---------------------------------------------------------------------------- // Handle Admin Actions $message = ''; $msgType = 'success'; if (isset($_POST['action'])) { if ($_POST['action'] === 'add_task') { $app = $_POST['app'] ?? ''; $start_loc = $_POST['start_location'] ?? ''; $end_loc = $_POST['end_location'] ?? ''; $start_lat = floatval($_POST['start_lat'] ?? 0.0); $start_lng = floatval($_POST['start_lng'] ?? 0.0); $end_lat = floatval($_POST['end_lat'] ?? 0.0); $end_lng = floatval($_POST['end_lng'] ?? 0.0); if ($app && $start_loc && $end_loc) { $tasks = json_decode(file_get_contents(TASKS_FILE), true); $taskId = "prc_" . uniqid(); $newTask = [ "task_id" => $taskId, "type" => "price_check", "app" => $app, "start_location" => $start_loc, "end_location" => $end_loc, "payload" => [ "start_lat" => $start_lat, "start_lng" => $start_lng, "end_lat" => $end_lat, "end_lng" => $end_lng ] ]; $tasks[] = $newTask; file_put_contents(TASKS_FILE, json_encode($tasks, JSON_PRETTY_PRINT)); $message = "Task successfully added and queued! Task ID: $taskId"; } else { $message = "Please fill in all required fields."; $msgType = 'error'; } } elseif ($_POST['action'] === 'clear_tasks') { file_put_contents(TASKS_FILE, json_encode([])); $message = "Task queue cleared successfully."; } elseif ($_POST['action'] === 'clear_results') { file_put_contents(RESULTS_FILE, json_encode([])); $message = "Scrape results history cleared successfully."; } } // Fetch stats and lists for display $currentTasks = json_decode(file_get_contents(TASKS_FILE), true); $scrapedResults = json_decode(file_get_contents(RESULTS_FILE), true); ?>
Standalone API Endpoint & Simulation Controller Panel
Route: →
Device:
Distance: km | Time: