'ok']); } // Только POST if ($_SERVER['REQUEST_METHOD'] !== 'POST') { json_response(['success' => false, 'error' => 'Method not allowed'], 405); } log_message('=== START API REQUEST ==='); log_message('Host: ' . ($_SERVER['HTTP_HOST'] ?? 'not set')); log_message('SERVER_NAME: ' . ($_SERVER['SERVER_NAME'] ?? 'not set')); log_message('REQUEST_URI: ' . ($_SERVER['REQUEST_URI'] ?? 'not set')); // Проверяем, что запрос идёт на правильный домен $host = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'] ?? ''; if (!empty($host) && strpos($host, 'crm.clientright.ru') === false && strpos($host, 'aeroflot.clientright.ru') !== false) { log_message('⚠️ WARNING: Request came to wrong virtual host: ' . $host); // Не блокируем, но логируем для диагностики } // Получаем входные данные $input = file_get_contents('php://input'); log_message('Raw input: ' . substr($input, 0, 500)); $input = ltrim($input, "\xEF\xBB\xBF\x00\x09\x0A\x0D\x20"); $data = json_decode($input, true); if (json_last_error() !== JSON_ERROR_NONE) { log_message('❌ JSON Error: ' . json_last_error_msg()); json_response([ 'success' => false, 'error' => 'Invalid JSON: ' . json_last_error_msg() ], 400); } // Поддерживаем как массив, так и одиночный объект $documents_array = is_array($data) && isset($data[0]) ? $data : [$data]; log_message('Processing ' . count($documents_array) . ' document(s)'); // Обрабатываем каждый документ $processed_documents = []; $S3_HOST = 'https://s3.twcstorage.ru'; foreach ($documents_array as $idx => $doc) { $contact_id = $doc['contact_id'] ?? null; $project_id = $doc['project_id'] ?? null; $ticket_id = $doc['ticket_id'] ?? null; // Поддерживаем оба формата: file и file_url $file_path = $doc['file'] ?? $doc['file_url'] ?? null; if (!$file_path) { log_message("❌ Document #{$idx}: missing 'file' or 'file_url'"); continue; } // Строим полный S3 URL if (strpos($file_path, 'http') === 0) { $file_url = $file_path; } elseif (strpos($file_path, '/') === 0) { $file_url = $S3_HOST . $file_path; } else { $file_url = $S3_HOST . '/' . $file_path; } // Поддерживаем оба формата: filename и file_name $file_name = $doc['filename'] ?? $doc['file_name'] ?? null; if (!$file_name) { log_message("❌ Document #{$idx}: missing 'filename' or 'file_name'"); continue; } $file_type = $doc['file_type'] ?? 'Документ'; // Валидация обязательных полей if (!$contact_id || !$project_id) { log_message("❌ Document #{$idx}: missing contact_id or project_id"); continue; } log_message(" [{$idx}] {$file_name} (type: {$file_type})"); log_message(" Contact: {$contact_id}, Project: {$project_id}, Ticket: " . ($ticket_id ?: 'N/A')); log_message(" File URL: {$file_url}"); $processed_documents[] = [ 'url' => $file_url, 'file_name' => $file_name, 'description' => $file_type, 'projectid' => (int)$project_id, 'ticket_id' => $ticket_id ? (int)$ticket_id : null, 'contactid' => (int)$contact_id, 'pages' => 1 ]; } if (empty($processed_documents)) { log_message('❌ No valid documents to process'); json_response([ 'success' => false, 'error' => 'No valid documents to process' ], 400); } log_message('📤 Processing ' . count($processed_documents) . ' documents via upload_documents_to_crm.php'); // ✅ Вызываем upload_documents_to_crm.php напрямую через include (избегаем проблем с HTTP/Nginx) // Берем общие параметры из первого документа $first_doc = $processed_documents[0]; // Формируем данные в формате, который ожидает upload_documents_to_crm.php $upload_data = [ 'documents' => $processed_documents, 'projectid' => $first_doc['projectid'], 'ticket_id' => $first_doc['ticket_id'], 'user_id' => 1 ]; log_message('Payload: ' . substr(json_encode($upload_data, JSON_UNESCAPED_UNICODE), 0, 500)); // ✅ Вызываем upload_documents_to_crm.php напрямую через include (избегаем проблем с HTTP) // Загружаем функции из upload_documents_to_crm.php $upload_script_path = __DIR__ . '/upload_documents_to_crm.php'; // ✅ Перехватываем вывод (на случай, если скрипт что-то выводит) ob_start(); // ✅ Помечаем, что скрипт вызван из API — чтобы upload_documents_to_crm не выполнял тестовый GET-блок (который создавал лишний документ "Иск" по проекту 354918 при каждом запросе) define('UPLOAD_DOCUMENTS_CALLED_FROM_API', true); // ✅ Сохраняем оригинальный REQUEST_METHOD и устанавливаем GET, чтобы предотвратить выполнение основного POST-кода в upload_documents_to_crm $original_request_method = $_SERVER['REQUEST_METHOD'] ?? null; $_SERVER['REQUEST_METHOD'] = 'GET'; // ✅ Загружаем upload_documents_to_crm.php (только функции; тестовый GET-блок не выполнится из-за UPLOAD_DOCUMENTS_CALLED_FROM_API) try { require_once $upload_script_path; // ✅ Восстанавливаем оригинальный REQUEST_METHOD if ($original_request_method !== null) { $_SERVER['REQUEST_METHOD'] = $original_request_method; } } catch (Throwable $e) { ob_end_clean(); // ✅ Восстанавливаем оригинальный REQUEST_METHOD даже при ошибке if ($original_request_method !== null) { $_SERVER['REQUEST_METHOD'] = $original_request_method; } log_message('❌ Fatal error loading upload_documents_to_crm.php: ' . $e->getMessage() . ' in ' . $e->getFile() . ':' . $e->getLine()); json_response([ 'success' => false, 'error' => 'Failed to load upload script: ' . $e->getMessage() ], 500); } // ✅ Вызываем функцию normalizeInputData для преобразования данных $filesArray = normalizeInputData($upload_data); if (!is_array($filesArray) || empty($filesArray)) { ob_end_clean(); log_message('❌ Error: Failed to normalize input data. Type: ' . gettype($filesArray) . ', Empty: ' . (empty($filesArray) ? 'yes' : 'no')); json_response([ 'success' => false, 'error' => 'Failed to normalize input data' ], 400); } // ✅ Вызываем функцию createDocumentsInCRM напрямую log_message('🚀 Calling createDocumentsInCRM with ' . count($filesArray) . ' files'); $results = createDocumentsInCRM($filesArray); log_message('🔍 createDocumentsInCRM returned. Type: ' . gettype($results) . ', Is array: ' . (is_array($results) ? 'yes, count: ' . count($results) : 'no')); // ✅ Очищаем output buffer ob_end_clean(); // ✅ Проверяем результат if (isset($results['error'])) { log_message('❌ Error: ' . $results['error']); json_response([ 'success' => false, 'error' => 'Upload failed: ' . $results['error'] ], 500); } // ✅ Формируем ответ в формате, который ожидает api_attach_documents.php // ✅ Проверяем успешность if (is_array($results) && !empty($results)) { $results_array = $results; // Формируем ответ $processed_results = []; $errors = []; foreach ($results_array as $idx => $res) { $status = $res['status'] ?? 'unknown'; if ($status === 'success') { $crm_result = $res['crm_result'] ?? []; $processed_results[] = [ 'document_id' => $crm_result['document_id'] ?? null, 'document_numeric_id' => $crm_result['document_numeric_id'] ?? null, 'attached_to' => isset($res['ticket_id']) && $res['ticket_id'] ? 'ticket' : 'project', 'attached_to_id' => $res['ticket_id'] ?? $res['projectid'] ?? null, 'file_name' => $res['file_name'] ?? null, 'file_type' => $res['description'] ?? null, 's3_bucket' => $crm_result['s3_bucket'] ?? null, 's3_key' => $crm_result['s3_key'] ?? null, 'file_size' => $crm_result['file_size'] ?? null, 'message' => $crm_result['message'] ?? null ]; } else { $error_msg = $res['crm_result']['message'] ?? ($res['error'] ?? 'Unknown error'); $errors[] = [ 'file_name' => $res['file_name'] ?? 'Unknown', 'error' => $error_msg ]; } } json_response([ 'success' => true, 'total_processed' => count($results_array), 'successful' => count($processed_results), 'failed' => count($errors), 'results' => $processed_results, 'errors' => !empty($errors) ? $errors : null ]); } else { $error_msg = is_array($results) && isset($results['error']) ? $results['error'] : 'Upload failed'; log_message('❌ Upload failed: ' . (is_string($error_msg) ? $error_msg : json_encode($error_msg))); json_response([ 'success' => false, 'error' => is_string($error_msg) ? $error_msg : 'Upload failed' ], 500); }