'method_not_allowed']); exit; } $raw = file_get_contents('php://input') ?: ''; $req = json_decode($raw, true); if (!is_array($req)) { http_response_code(400); echo json_encode(['error' => 'invalid_json']); exit; } $heartbeat = $req['heartbeat'] ?? []; if (!is_array($heartbeat)) { $heartbeat = []; } $type = (string)($heartbeat['type'] ?? 'generic'); $srvEpoch = time(); $srvTz = date('O'); $resp = [ 'heartbeat' => [ 'type' => $type, 'server_date' => $srvEpoch, 'server_tz' => $srvTz, ], ]; if ($type === 'ntp') { $clientDate = (int)($heartbeat['date'] ?? 0); $clientTz = (string)($heartbeat['tz'] ?? ''); $resp['heartbeat']['client_date'] = $clientDate; $resp['heartbeat']['client_tz'] = $clientTz; $resp['heartbeat']['correction_seconds'] = $clientDate > 0 ? ($srvEpoch - $clientDate) : null; $resp['heartbeat']['enabled'] = true; } if ($type === 'ip') { $resp['heartbeat']['external_ip'] = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? ($_SERVER['REMOTE_ADDR'] ?? ''); } echo json_encode($resp, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);