- Добавлен SSE endpoint (aiassist/ai_sse.php) для real-time получения ответов от n8n - Обновлен n8n_proxy.php: убран callback, добавлена передача Redis параметров в n8n - Обновлен ai-drawer-simple.js: переход с polling на SSE с fallback через Redis - Добавлен check_redis_response.php для прямого чтения из Redis кэша - Добавлена документация: N8N_REDIS_SETUP.md, N8N_REDIS_FIX.md, AI_DRAWER_REDIS_SSE.md - Поддержка plain text ответов от n8n (автоматическое определение формата) - Кэширование ответов в Redis для надежности (TTL 5 минут)
116 lines
3.9 KiB
PHP
116 lines
3.9 KiB
PHP
<?php
|
|
// aiassist/n8n_proxy.php
|
|
// Proxy между AI Drawer и n8n
|
|
// n8n обрабатывает запрос и публикует ответ напрямую в Redis
|
|
|
|
header('Content-Type: application/json');
|
|
header('Access-Control-Allow-Origin: *');
|
|
header('Access-Control-Allow-Methods: POST, OPTIONS');
|
|
header('Access-Control-Allow-Headers: Content-Type');
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
|
|
http_response_code(200);
|
|
exit();
|
|
}
|
|
|
|
error_reporting(E_ALL);
|
|
ini_set('display_errors', 1);
|
|
|
|
if (!function_exists('curl_init')) {
|
|
http_response_code(500);
|
|
echo json_encode(['error' => 'cURL not available']);
|
|
exit();
|
|
}
|
|
|
|
try {
|
|
$input = json_decode(file_get_contents('php://input'), true);
|
|
|
|
if (!$input) {
|
|
throw new Exception('Invalid JSON input');
|
|
}
|
|
|
|
$message = $input['message'] ?? '';
|
|
$context = $input['context'] ?? [];
|
|
$sessionId = $input['sessionId'] ?? 'crm-session-' . time();
|
|
|
|
// Генерируем уникальный task_id
|
|
$taskId = 'task-' . uniqid() . '-' . time();
|
|
|
|
error_log("N8N Proxy: New task {$taskId} for session {$sessionId}");
|
|
|
|
// Отправляем запрос в n8n
|
|
// n8n обработает и опубликует ответ напрямую в Redis: ai:response:{taskId}
|
|
$n8nWebhookUrl = 'https://n8n.clientright.pro/webhook/0b20bf1e-7cda-4dc8-899e-a7c3be4096c0';
|
|
|
|
$payload = [
|
|
'message' => $message,
|
|
'context' => $context,
|
|
'sessionId' => $sessionId,
|
|
'taskId' => $taskId,
|
|
'redisChannel' => "ai:response:{$taskId}", // Канал для публикации ответа
|
|
'redisHost' => 'crm.clientright.ru',
|
|
'redisPort' => 6379,
|
|
'redisPassword' => 'CRM_Redis_Pass_2025_Secure!',
|
|
'timestamp' => date('Y-m-d H:i:s'),
|
|
'source' => 'crm-client'
|
|
];
|
|
|
|
error_log("N8N Proxy: Sending to n8n - Task: {$taskId}, Redis channel: ai:response:{$taskId}");
|
|
|
|
$ch = curl_init();
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_URL => $n8nWebhookUrl,
|
|
CURLOPT_POST => true,
|
|
CURLOPT_POSTFIELDS => json_encode($payload),
|
|
CURLOPT_HTTPHEADER => [
|
|
'Content-Type: application/json',
|
|
'User-Agent: CRM-N8N-Integration/1.0'
|
|
],
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_TIMEOUT => 10,
|
|
CURLOPT_SSL_VERIFYPEER => true,
|
|
CURLOPT_FOLLOWLOCATION => true
|
|
]);
|
|
|
|
$response = curl_exec($ch);
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
$error = curl_error($ch);
|
|
curl_close($ch);
|
|
|
|
if ($error) {
|
|
error_log("N8N Proxy: cURL error for task {$taskId}: {$error}");
|
|
} else {
|
|
error_log("N8N Proxy: Task {$taskId} sent to n8n, HTTP code: {$httpCode}");
|
|
}
|
|
|
|
// Возвращаем task_id клиенту
|
|
// Клиент подпишется на SSE и получит ответ когда n8n опубликует в Redis
|
|
echo json_encode([
|
|
'success' => true,
|
|
'task_id' => $taskId,
|
|
'status' => 'accepted',
|
|
'message' => 'Запрос принят в обработку',
|
|
'redisChannel' => "ai:response:{$taskId}" // Для информации
|
|
]);
|
|
|
|
} catch (Exception $e) {
|
|
$errorMessage = "N8N Proxy Error: " . $e->getMessage();
|
|
error_log($errorMessage);
|
|
|
|
$logEntry = [
|
|
'timestamp' => date('Y-m-d H:i:s'),
|
|
'error' => $e->getMessage(),
|
|
'file' => $e->getFile(),
|
|
'line' => $e->getLine(),
|
|
'trace' => $e->getTraceAsString()
|
|
];
|
|
file_put_contents('/var/www/fastuser/data/www/crm.clientright.ru/logs/n8n_proxy_errors.log', json_encode($logEntry, JSON_UNESCAPED_UNICODE) . "\n", FILE_APPEND | LOCK_EX);
|
|
|
|
http_response_code(500);
|
|
echo json_encode([
|
|
'error' => $e->getMessage(),
|
|
'fallback' => true,
|
|
'timestamp' => date('Y-m-d H:i:s')
|
|
]);
|
|
}
|
|
?>
|