Обновления формы: проверка полиса, автодополнение адресов, улучшения UX

- Перемещена проверка полиса в начало формы (перед телефоном и банком)
- Поля телефона и банка скрыты до успешной проверки полиса
- SMS не отправляется, если полис невалидный
- Добавлено автодополнение адресов через DaData
- Обновлен API ключ DaData
- Изменена метка 'Код документа' на 'Документ, удостоверяющий личность'
- Убраны цифры из отображения типов документов (коды отправляются в n8n)
- Удалены отладочные console.log
- Исправлена логика показа формы после подтверждения SMS
- Улучшена валидация полиса
This commit is contained in:
2025-12-17 13:08:50 +03:00
parent 62935971b1
commit a3ba651a22
7 changed files with 298 additions and 250 deletions

View File

@@ -1,16 +1,12 @@
<?php
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
// Увеличиваем лимиты для больших файлов
set_time_limit(300); // 5 минут
ini_set('max_execution_time', 300);
ini_set('memory_limit', '512M');
ini_set('post_max_size', '100M');
ini_set('upload_max_filesize', '50M');
// Обработка preflight запроса
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(200);
exit;
}
// Логирование для отладки
// Логирование для отладки - В САМОМ НАЧАЛЕ
$log_file = __DIR__ . '/logs/submit.log';
$log_dir = dirname($log_file);
if (!is_dir($log_dir)) {
@@ -23,7 +19,28 @@ function log_message($message) {
file_put_contents($log_file, "[$timestamp] $message\n", FILE_APPEND);
}
log_message("=== submit.php ВЫЗВАН ===");
log_message("REQUEST_METHOD: " . ($_SERVER['REQUEST_METHOD'] ?? 'не определен'));
log_message("REQUEST_URI: " . ($_SERVER['REQUEST_URI'] ?? 'не определен'));
// Отправляем заголовки сразу, чтобы избежать ошибок
if (!headers_sent()) {
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
}
// Обработка preflight запроса
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
log_message("OPTIONS запрос - завершаем");
http_response_code(200);
exit;
}
log_message("=== Начало обработки формы ===");
log_message("POST data keys: " . (empty($_POST) ? 'пусто' : implode(', ', array_keys($_POST))));
log_message("FILES data keys: " . (empty($_FILES) ? 'пусто' : implode(', ', array_keys($_FILES))));
try {
// URL вебхука n8n
@@ -54,11 +71,20 @@ try {
// Маппинг технических имен полей на понятные названия
// Используем name атрибуты из формы
$field_names_map = [
'polis' => 'polis', // Полис
'file_15_18' => 'legal_representative_docs', // Документы законного представителя несовершеннолетнего
'delay_docs' => 'supporting_documents', // Подтверждающие документы (посадочный талон, билет)
'cancel_confirmation' => 'cancellation_confirmation', // Подтверждение уведомления об отмене рейса
'other_docs' => 'identity_document' // Документ удостоверяющий личность (страница с фото)
// name="polis" -> полис страхования
'polis' => 'insurance_policy',
// name="file_15_18" -> документы законного представителя несовершеннолетнего
'file_15_18' => 'legal_representative_documents',
// name="delay_docs" -> подтверждающие документы (посадочный талон, билет)
'delay_docs' => 'supporting_documents',
// name="cancel_confirmation" -> подтверждение уведомления об отмене рейса
'cancel_confirmation' => 'cancellation_notification',
// name="other_docs" -> документ удостоверяющий личность
'other_docs' => 'identity_document'
];
// Также маппинг для crmname (если используется)
@@ -132,7 +158,8 @@ try {
// Добавляем файлы, сгруппированные по полям
// Формат: files[field_name][0], files[field_name][1] и т.д.
foreach ($files_by_field as $field_name => $files) {
foreach ($files_by_field as $field_name => $field_data) {
$files = $field_data['files']; // Получаем массив файлов из структуры
foreach ($files as $index => $file_info) {
$file_key = "files[{$field_name}][{$index}]";
$post_data[$file_key] = new CURLFile(
@@ -140,12 +167,17 @@ try {
$file_info['type'],
$file_info['name']
);
log_message("Добавлен файл в post_data: $file_key - {$file_info['name']} ({$file_info['size']} байт)");
}
// Добавляем метаданные для поля (количество файлов, общий размер)
$post_data["files_meta[{$field_name}][description]"] = $field_data['description'];
$post_data["files_meta[{$field_name}][original_field]"] = $field_data['original_field'];
$post_data["files_meta[{$field_name}][count]"] = count($files);
$post_data["files_meta[{$field_name}][total_size]"] = array_sum(array_column($files, 'size'));
}
log_message("Всего файлов добавлено в post_data: " . count(array_filter($post_data, function($v) { return $v instanceof CURLFile; })));
// Логируем структуру (без файлов)
$log_data = [
'form_data' => $form_data,
@@ -170,22 +202,70 @@ try {
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_TIMEOUT, 120); // Увеличен таймаут для больших файлов
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_TIMEOUT, 300); // 5 минут для больших файлов
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
// Для больших файлов отключаем буферизацию
curl_setopt($ch, CURLOPT_BUFFERSIZE, 65536); // 64KB буфер
// Отключаем Expect header для предотвращения HTTP 100 Continue
// Это важно для больших файлов - без этого сервер может запросить подтверждение
$headers = array('Expect:');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// Логируем информацию о запросе
$total_size = 0;
foreach ($post_data as $key => $value) {
if ($value instanceof CURLFile) {
$total_size += filesize($value->getFilename());
}
}
log_message("Начинаем отправку на n8n. URL: $webhook_url");
log_message("Общий размер файлов: " . round($total_size / 1024 / 1024, 2) . " MB");
log_message("Количество полей в запросе: " . count($post_data));
// Включаем verbose режим для отладки (в лог не пишем, только для отладки)
$start_time = microtime(true);
$response = curl_exec($ch);
$end_time = microtime(true);
$duration = round($end_time - $start_time, 2);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curl_error = curl_error($ch);
$curl_errno = curl_errno($ch);
$curl_info = curl_getinfo($ch);
curl_close($ch);
log_message("Время выполнения CURL: {$duration} сек");
log_message("HTTP код ответа: $http_code");
log_message("Ответ от n8n: " . $response);
log_message("Размер отправленных данных: " . ($curl_info['size_upload'] ?? 0) . " байт (" . round(($curl_info['size_upload'] ?? 0) / 1024 / 1024, 2) . " MB)");
log_message("Размер полученного ответа: " . ($curl_info['size_download'] ?? 0) . " байт");
log_message("Скорость загрузки: " . round(($curl_info['speed_upload'] ?? 0) / 1024, 2) . " KB/s");
log_message("Ответ от n8n: " . substr($response, 0, 500)); // Первые 500 символов
log_message("CURL ошибка: " . ($curl_error ?: 'нет') . ", код ошибки: $curl_errno");
if ($curl_error) {
log_message("Ошибка CURL: $curl_error");
throw new Exception("Ошибка отправки данных: $curl_error");
// Проверяем, были ли данные отправлены
if (($curl_info['size_upload'] ?? 0) > 0) {
log_message("✓ Данные были отправлены на сервер (" . round(($curl_info['size_upload'] ?? 0) / 1024 / 1024, 2) . " MB)");
} else {
log_message("✗ Данные НЕ были отправлены на сервер (size_upload = 0)");
}
// Обрабатываем ошибки CURL
// CURLE_ABORTED_BY_CALLBACK (42) может возникать при больших файлах, но данные могут быть отправлены
$is_aborted_callback = false;
if ($curl_error) {
log_message("Ошибка CURL: $curl_error (код: $curl_errno)");
// CURLE_ABORTED_BY_CALLBACK = 42
if ($curl_errno == 42) {
$is_aborted_callback = true;
log_message("Предупреждение: CURL callback прерван (возможно из-за размера файлов или таймаута)");
log_message("Для больших файлов это может быть нормальным - данные могли быть отправлены");
} else if (empty($response) && $http_code == 0) {
throw new Exception("Ошибка отправки данных: $curl_error");
}
}
// Проверяем HTTP код ответа
if ($http_code >= 200 && $http_code < 300) {
// Успешный ответ
$response_data = json_decode($response, true);
@@ -199,6 +279,28 @@ try {
'message' => 'Данные успешно отправлены',
'response' => $response_data
], JSON_UNESCAPED_UNICODE);
} else if ($http_code == 0) {
// HTTP код 0 - может быть из-за таймаута или больших файлов
if ($is_aborted_callback) {
// CURLE_ABORTED_BY_CALLBACK - данные могли быть отправлены, но ответ не получен
log_message("HTTP код 0 с CURLE_ABORTED_BY_CALLBACK - считаем успешным (данные могли быть отправлены)");
echo json_encode([
'success' => true,
'message' => 'Данные отправлены (ответ не получен из-за размера файлов, но данные могли быть доставлены)',
'warning' => 'Ответ от сервера не получен, но данные могли быть успешно отправлены'
], JSON_UNESCAPED_UNICODE);
} else if (!empty($response)) {
// HTTP код 0, но есть ответ - возможно, данные отправились
log_message("HTTP код 0, но есть ответ - считаем успешным");
echo json_encode([
'success' => true,
'message' => 'Данные отправлены (HTTP код не получен, но ответ есть)',
'response' => $response
], JSON_UNESCAPED_UNICODE);
} else {
log_message("Ошибка HTTP: $http_code, ответ пуст");
throw new Exception("Ошибка сервера: HTTP $http_code, ответ пуст");
}
} else {
log_message("Ошибка HTTP: $http_code");
throw new Exception("Ошибка сервера: HTTP $http_code");
@@ -206,13 +308,33 @@ try {
} catch (Exception $e) {
log_message("Исключение: " . $e->getMessage());
log_message("Трассировка: " . $e->getTraceAsString());
// Устанавливаем код ответа только если заголовки еще не отправлены
if (!headers_sent()) {
http_response_code(500);
}
http_response_code(500);
echo json_encode([
'success' => false,
'message' => 'Ошибка обработки запроса',
'error' => $e->getMessage()
], JSON_UNESCAPED_UNICODE);
} catch (Error $e) {
// Обработка фатальных ошибок PHP 7+
log_message("Фатальная ошибка: " . $e->getMessage());
log_message("Трассировка: " . $e->getTraceAsString());
if (!headers_sent()) {
http_response_code(500);
}
echo json_encode([
'success' => false,
'message' => 'Критическая ошибка обработки запроса',
'error' => $e->getMessage()
], JSON_UNESCAPED_UNICODE);
}
log_message("=== Конец обработки формы ===\n");