pquery($query); if ($adb->num_rows($result) == 0) { $output = 'Проект не найден'; file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - Проект с id '.$projectid.' не найден'.PHP_EOL, FILE_APPEND); } else { $accountid = $adb->query_result($result, 0, 'accountid'); $acc1 = $adb->query_result($result, 0, 'acc1'); $acc2 = $adb->query_result($result, 0, 'acc2'); $userid = $adb->query_result($result, 0, 'userid'); $authdoc = getAuthDoc($accountid, $userid); // Поднимаем доверку на представителя Заявителя (он же ответственный по Проекту) if ($authdoc['result'] == 'NO') { $output = 'У Ответственного по Проекту '.$projectid. ' в Контрагенте '.$accountid.' нет доверенности от Заявителя'; AddComment($projectid, $output, 'comment'); } else { $price = $adb->query_result($result, 0, 'price'); $contactid = $adb->query_result($result, 0, 'contactid'); $jurisdiction = $adb->query_result($result, 0, 'jurisdiction'); // Подсудность if ($jurisdiction == 'По месту исполнения договора') { $address = $adb->query_result($result, 0, 'agrplace'); } else { if ($jurisdiction == 'По месту нахождения ответчика') { $address = $adb->query_result($result, 0, 'offaddress'); } else { $address = $adb->query_result($result, 0, 'mailingstreet'); } } file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - Будем подаваться '.$jurisdiction.'. Эту здесь: '.$address.PHP_EOL, FILE_APPEND); $court = getCourt($contactid, $address, $price); // Ищем суд по адресу и сумме цены иска if ($court['result'] <> 'YES') { $output = array('status' => 'ERROR', 'message' => $court['result']); AddComment($projectid, $court['result'], 'comment'); } else { $claim = getClaim($projectid, $processType); if ($claim['result'] == 'NO') { if ($processType == '201.01') { $output = 'В Проекте '.$projectid. 'отсутствует Исковое заявление'; } else { $output = 'В Проекте '.$projectid. 'отсутствует заявление на выдачу исполнительного листа'; } AddComment($projectid, $output, 'comment'); } else { $multipart = []; // Этот массив будем отдавать в вызове // Доверенность $authFilename = $authdoc['filename']; if (empty($authFilename) || filter_var($authFilename, FILTER_VALIDATE_URL)) { $authFilename = $authdoc['description'] . '.pdf'; } $multipart[] = [ 'name' => 'files', 'contents' => fopen($authdoc['filepath'], 'r'), 'path' => $authdoc['filepath'], 'filename' => $authFilename ]; file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - добавили в массив файл "'.$authFilename.'"'.PHP_EOL, FILE_APPEND); // Исковое $claimFilename = $claim['filename']; if (empty($claimFilename) || filter_var($claimFilename, FILTER_VALIDATE_URL)) { $claimFilename = $claim['description'] . '.pdf'; } $multipart[] = [ 'name' => 'files', 'contents' => fopen($claim['filepath'], 'r'), 'path' => $claim['filepath'], 'filename' => $claimFilename ]; file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - добавили в массив файл "'.$claimFilename.'"'.PHP_EOL, FILE_APPEND); $data = []; // А тут мы соберем огромный массив, который потом превратится в json для fillData $data['appealType'] = 2; // Подает Представитель // Декодируем HTML entities для всех текстовых полей $data['mySelfAdditionalData']['courtNoticesAddressIndex'] = $adb->query_result($result, 0, 'index_notice'); $data['mySelfAdditionalData']['courtNoticesAddress'] = html_entity_decode($adb->query_result($result, 0, 'addr_notice'), ENT_QUOTES | ENT_HTML5, 'UTF-8'); $data['mySelfAdditionalData']['email'] = $adb->query_result($result, 0, 'usermail'); $data['mySelfAdditionalData']['authorizationDocument']['fileIndex'] = 0; $data['mySelfAdditionalData']['authorizationDocument']['description'] = $authdoc['description']; $data['mySelfAdditionalData']['authorizationDocument']['pagesCount'] = $authdoc['pages']; $data['additionalForRepresentativeApplicants'][0]['dataType'] = 'entity'; $data['additionalForRepresentativeApplicants'][0]['entity']['name'] = html_entity_decode(htmlspecialchars_decode($adb->query_result($result, 0, 'accountname')), ENT_QUOTES | ENT_HTML5, 'UTF-8'); $data['additionalForRepresentativeApplicants'][0]['entity']['international'] = false; $data['additionalForRepresentativeApplicants'][0]['entity']['inn'] = $adb->query_result($result, 0, 'inn'); $data['additionalForRepresentativeApplicants'][0]['entity']['kpp'] = $adb->query_result($result, 0, 'kpp'); $data['additionalForRepresentativeApplicants'][0]['entity']['ogrnip'] = $adb->query_result($result, 0, 'ogrn'); $data['additionalForRepresentativeApplicants'][0]['entity']['proceduralStatus'] = '50710010'; $data['additionalForRepresentativeApplicants'][0]['entity']['legalIndex'] = $adb->query_result($result, 0, 'bill_code'); $data['additionalForRepresentativeApplicants'][0]['entity']['legalAddress'] = html_entity_decode($adb->query_result($result, 0, 'bill_city').', '.$adb->query_result($result, 0, 'bill_street'), ENT_QUOTES | ENT_HTML5, 'UTF-8'); $data['additionalForRepresentativeApplicants'][0]['entity']['isLegalAdressEqualToActualResidenceAddress'] = false; $data['additionalForRepresentativeApplicants'][0]['entity']['actualResidenceIndex'] = $adb->query_result($result, 0, 'ship_code'); $data['additionalForRepresentativeApplicants'][0]['entity']['actualResidenceAddress'] = html_entity_decode($adb->query_result($result, 0, 'ship_city').', '.$adb->query_result($result, 0, 'ship_street'), ENT_QUOTES | ENT_HTML5, 'UTF-8'); $data['additionalForRepresentativeApplicants'][0]['entity']['email'] = $adb->query_result($result, 0, 'email1'); $data['additionalForRepresentativeApplicants'][0]['entity']['phoneNumber'] = $adb->query_result($result, 0, 'phone'); $data['court']['region'] = $court['region']; $data['court']['judicialAuthority'] = $court['code']; $data['appealDocument']['fileIndex'] = 1; $data['appealDocument']['description'] = $claim['description']; $data['appealDocument']['pagesCount'] = $claim['pages']; if ($processType == '201.01') { // Если отправляем исковое, то подтягиваем все прочие Документы из Проекта $otherDocs = getOtherDocs($projectid, $accountid, $acc1, $acc2); if (count($otherDocs) > 0) { $fileIndexInMultipart = 2; // Начинаем с 2 (0 - доверенность, 1 - исковое) for ($i=0; $i 'files', 'contents' => fopen($otherDocs[$i]['filepath'], 'r'), 'filename' => $filename ]; file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - добавили в массив файл "'.$filename.'" (путь: '.$otherDocs[$i]['filepath'].')'.PHP_EOL, FILE_APPEND); } } } else { if ($processType == '217.01') { $data['caseNumber'] = $adb->query_result($result, 0, 'casenumber');; } } $data['tax']['type'] = '1'; $data['processType'] = $processType; $multipart[] = [ 'name' => 'certificate', 'contents' => fopen('storage/cert.pfx', 'r'), 'filename' => 'cert.pfx' ]; $multipart[] = [ 'name' => 'fillData', 'contents' => json_encode($data) ]; file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - fillData JSON: '.json_encode($data).PHP_EOL, FILE_APPEND); file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - additionalAppealDocuments count: '.count($data['additionalAppealDocuments']).PHP_EOL, FILE_APPEND); $cookies = GetCookies($version); if ($cookies != 'Не удалось получить куки') { // Формируем заголовок запроса // yft,fkjdj1 - это старый пин-код $headers = [ 'x-api-key' => GetKey($version), 'hidden-authorization-cookies' => htmlspecialchars_decode($cookies), 'hidden-certificate-pin' => '3365', 'custom' => 'Zx123456' ]; $url = GetUrl($version); //$url = 'https://webhook.nodul.ru/765/dev/eea1b30c-14db-4499-9fc2-4d13e394bae6'; //$url = 'https://eoj0ndhyykckfh.m.pipedream.net'; //$url = 'https://webhook.nodul.ru/13/dev/test-some-error'; // Отправляем запрос с повторами file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - отправляем multipart с '.count($multipart).' файлами'.PHP_EOL, FILE_APPEND); foreach($multipart as $idx => $part) { $filename = isset($part['filename']) ? $part['filename'] : 'НЕТ'; $hasContents = isset($part['contents']) ? 'ДА' : 'НЕТ'; file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - файл '.$idx.': name='.$part['name'].', filename='.$filename.', contents='.$hasContents.PHP_EOL, FILE_APPEND); } $output = SendRequest($url, $multipart, $headers, 1); //file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - вернулись в основной скрипт после отправки запроса'.PHP_EOL, FILE_APPEND); if ($version == 'Prod' and $output['status'] == 'OK') { // Сохраним в Проекте входящий номер, если он есть $number = $output['message']; file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - еще раз взяли номер в основном скрипте: '.$number.PHP_EOL, FILE_APPEND); if (!empty($number) and !is_null($number)) { file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - убедились, что он не пустой'.PHP_EOL, FILE_APPEND); if ($processType == '201.01') { $url = 'https://crm.clientright.ru/shorturl.php?id=65eeaa0f425672.54413377&workflow_id=31&record_id='.$projectid.'®='.$number; } else { $url = 'https://crm.clientright.ru/shorturl.php?id=66508afc2008a4.30213815&workflow_id=80&record_id='.$projectid.'®='.$number; } $ch = curl_init(); curl_setopt($ch, CURLOPT_POST, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_HEADER, 0); $out = curl_exec($ch); curl_close($ch); file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - получили ответ от WD: '.$out.PHP_EOL, FILE_APPEND); //$query = 'update vtiger_projectcf set cf_2204 = "'.$number.'" where projectid = '.$projectid; //$result = $adb->pquery($query); //file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - сохранили в Проект рег.номер входящего: '.$number.PHP_EOL, FILE_APPEND); } } //$output = json_encode($multipart); } } } } } // Очищаем временные файлы после отправки if (isset($authdoc) && isset($claim) && isset($otherDocs)) { $tempFiles = []; if (isset($authdoc['is_temp_file']) && $authdoc['is_temp_file']) { $tempFiles[] = $authdoc; } if (isset($claim['is_temp_file']) && $claim['is_temp_file']) { $tempFiles[] = $claim; } foreach ($otherDocs as $doc) { if (isset($doc['is_temp_file']) && $doc['is_temp_file']) { $tempFiles[] = $doc; } } cleanupTempFiles($tempFiles); } if (is_array($output)) { file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - отдаем ответ в первичный вызывающий скрипт : '.json_encode($output).PHP_EOL, FILE_APPEND); } else { file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - отдаем ответ в первичный вызывающий скрипт : '.$output.PHP_EOL, FILE_APPEND); } return $output; } /** * Очищает временные файлы после отправки */ function cleanupTempFiles($files) { foreach ($files as $file) { if (isset($file['is_temp_file']) && $file['is_temp_file'] === true && file_exists($file['filepath'])) { unlink($file['filepath']); file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - удален временный файл: '.$file['filepath'].PHP_EOL, FILE_APPEND); } } } /** * Получает временный файл из S3 для использования в multipart запросе */ function getTempFileFromS3($s3Url, $tempFilename) { try { // Оригинальный URL для логирования $originalUrl = $s3Url; file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - скачиваем файл из S3 (исходный URL): '.$originalUrl.PHP_EOL, FILE_APPEND); // 🔧 УЛУЧШЕННАЯ ОБРАБОТКА URL // ВАЖНО: Сначала экранируем # чтобы parse_url не воспринял его как fragment $s3Url = str_replace('#', '___HASH___', $s3Url); // Разбираем URL на части $urlParts = parse_url($s3Url); if ($urlParts === false || !isset($urlParts['scheme']) || !isset($urlParts['host'])) { file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - некорректный URL S3'.PHP_EOL, FILE_APPEND); return false; } // Правильно кодируем путь к файлу // Разбиваем путь на сегменты и кодируем каждый отдельно $path = isset($urlParts['path']) ? $urlParts['path'] : ''; $pathSegments = explode('/', $path); $encodedSegments = array_map(function($segment) { // Возвращаем # обратно перед кодированием $segment = str_replace('___HASH___', '#', $segment); // rawurlencode кодирует все спецсимволы, включая #, пробелы, кириллицу и т.д. return rawurlencode($segment); }, $pathSegments); $encodedPath = implode('/', $encodedSegments); // Собираем URL обратно $s3Url = $urlParts['scheme'] . '://' . $urlParts['host'] . $encodedPath; // Если URL был изменен, логируем исправленную версию if ($s3Url !== $originalUrl) { file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - URL правильно закодирован: '.$s3Url.PHP_EOL, FILE_APPEND); } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $s3Url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 30); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); $fileContent = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $curlError = curl_error($ch); curl_close($ch); if ($httpCode === 200 && $fileContent !== false && !empty($fileContent)) { $tempPath = sys_get_temp_dir() . '/' . $tempFilename; file_put_contents($tempPath, $fileContent); file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - файл сохранен во временную папку: '.$tempPath.' (размер: '.strlen($fileContent).' байт)'.PHP_EOL, FILE_APPEND); return $tempPath; } else { file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - ошибка скачивания файла из S3, HTTP код: '.$httpCode.', CURL error: '.$curlError.PHP_EOL, FILE_APPEND); return false; } } catch (Exception $e) { file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - исключение при скачивании из S3: '.$e->getMessage().PHP_EOL, FILE_APPEND); return false; } } function getAuthDoc($accountid, $userid) { global $adb; $output = []; // Сначала пытаемся найти локальный файл (оригинальная логика) $query = 'select n.title, ncf.cf_1953 as pages, case when a.storedname is not null then concat(a.`path`, a.attachmentsid, "_", a.storedname) else concat(a.`path`, a.attachmentsid, "_", a.name) end as filepath, case when a.storedname is not null then concat(a.attachmentsid, "_", a.storedname) else concat(a.attachmentsid, "_", a.name) end as filename, a.`type`, n.filename as s3_filename, n.s3_bucket, n.s3_key, n.filelocationtype from vtiger_senotesrel r left join vtiger_notes n on n.notesid = r.notesid left join vtiger_crmentity e on e.crmid = r.notesid left join vtiger_notescf ncf on ncf.notesid = r.notesid left join vtiger_seattachmentsrel r2 on r2.crmid = r.notesid left join vtiger_attachments a on a.attachmentsid = r2.attachmentsid where e.smownerid = ? and r.crmid = ? and e.deleted = 0 and n.filename like "%подтверждающий_полномочия%"'; $result = $adb->pquery($query, array($userid, $accountid)); if ($adb->num_rows($result) == 0) { $output['result'] = 'NO'; file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - доверенность с подстрокой "подтверждающий_полномочия" в Контрагенте '.$accountid.' не найдена'.PHP_EOL, FILE_APPEND); } else { $output['result'] = 'YES'; $output['description'] = $adb->query_result($result, 0, 'title'); if (!is_numeric(substr($output['description'], 0, 1))) { $output['description'] = '0_'.$output['description']; } $output['description'] = str_replace(' ', '_', $output['description']); // Проверяем тип размещения файла $filelocationtype = $adb->query_result($result, 0, 'filelocationtype'); $s3_filename = $adb->query_result($result, 0, 's3_filename'); $s3_bucket = $adb->query_result($result, 0, 's3_bucket'); $s3_key = $adb->query_result($result, 0, 's3_key'); if ($filelocationtype == 'E' && !empty($s3_bucket) && !empty($s3_key)) { // Файл в S3 - скачиваем во временную папку file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - доверенность найдена в S3, bucket: '.$s3_bucket.', key: '.$s3_key.PHP_EOL, FILE_APPEND); $s3Url = $s3_filename; // filename содержит полный S3 URL $tempFilename = 'auth_doc_' . time() . '.pdf'; $tempPath = getTempFileFromS3($s3Url, $tempFilename); if ($tempPath) { $output['filepath'] = $tempPath; $output['is_temp_file'] = true; // Флаг для последующей очистки file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - S3 файл доверенности успешно скачан во временную папку'.PHP_EOL, FILE_APPEND); } else { $output['result'] = 'NO'; file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - не удалось скачать доверенность из S3'.PHP_EOL, FILE_APPEND); return $output; } } else { // Локальный файл (оригинальная логика) $output['filepath'] = $adb->query_result($result, 0, 'filepath'); $output['is_temp_file'] = false; file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - доверенность найдена как локальный файл'.PHP_EOL, FILE_APPEND); } $output['filename'] = $adb->query_result($result, 0, 'title').'.pdf'; if (!is_numeric(substr($output['filename'], 0, 1))) { $output['filename'] = '0_'.$output['filename']; } $output['filename'] = str_replace(' ', '_', $output['filename']); $output['type'] = $adb->query_result($result, 0, 'type'); $output['pages'] = $adb->query_result($result, 0, 'pages'); if (empty($output['pages']) or $output['pages'] == 0) { $output['pages'] = getPDFPageCount($output['filepath']); } file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - Нашли доверенность в Контрагенте '.$accountid.PHP_EOL, FILE_APPEND); } return $output; } function getClaim($projectid, $processType) { global $adb; $output = []; $query = 'select n.title, ncf.cf_1953 as pages, case when a.storedname is not null then concat(a.`path`, a.attachmentsid, "_", a.storedname) else concat(a.`path`, a.attachmentsid, "_", a.name) end as filepath, case when a.storedname is not null then concat(a.attachmentsid, "_", a.storedname) else concat(a.attachmentsid, "_", a.name) end as filename, a.`type`, n.filename as s3_filename, n.s3_bucket, n.s3_key, n.filelocationtype from vtiger_senotesrel r left join vtiger_notes n on n.notesid = r.notesid left join vtiger_crmentity e on e.crmid = r.notesid left join vtiger_notescf ncf on ncf.notesid = r.notesid left join vtiger_seattachmentsrel r2 on r2.crmid = r.notesid left join vtiger_attachments a on a.attachmentsid = r2.attachmentsid where r.crmid = ? and e.deleted = 0 and '; if ($processType == '201.01') { // Ищем исковые заявления по нескольким критериям $query .= '(n.filename like "%Исковое_заявление%" OR n.title like "%Исковое_заявление%" OR n.title like "%исковое%" OR n.filename like "%исковое%")'; } else { $query .= 'n.filename like "%7777777%"'; // Так у нас кодируется признак заявления на выдачу исполнительного листа } $result = $adb->pquery($query, array($projectid)); if ($adb->num_rows($result) == 0) { $output['result'] = 'NO'; if ($processType == '201.01') { file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - Исковое заявление с подстрокой "Исковое_заявление" в Проекте '.$projectid.' не найдено'.PHP_EOL, FILE_APPEND); } else { file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - Заявление на выдачу исполнительного листа с подстрокой "7777777" в Проекте '.$projectid.' не найдено'.PHP_EOL, FILE_APPEND); } } else { $output['result'] = 'YES'; $output['description'] = $adb->query_result($result, 0, 'title'); if (!is_numeric(substr($output['description'], 0, 1))) { $output['description'] = '0_'.$output['description']; } $output['description'] = str_replace(' ', '_', $output['description']); // Проверяем тип размещения файла $filelocationtype = $adb->query_result($result, 0, 'filelocationtype'); $s3_filename = $adb->query_result($result, 0, 's3_filename'); $s3_bucket = $adb->query_result($result, 0, 's3_bucket'); $s3_key = $adb->query_result($result, 0, 's3_key'); if ($filelocationtype == 'E' && !empty($s3_bucket) && !empty($s3_key)) { // Файл в S3 - скачиваем во временную папку if ($processType == '201.01') { file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - исковое заявление найдено в S3, bucket: '.$s3_bucket.', key: '.$s3_key.PHP_EOL, FILE_APPEND); } else { file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - заявление на выдачу исполнительного листа найдено в S3, bucket: '.$s3_bucket.', key: '.$s3_key.PHP_EOL, FILE_APPEND); } $s3Url = $s3_filename; // filename содержит полный S3 URL $tempFilename = 'claim_doc_' . time() . '.pdf'; $tempPath = getTempFileFromS3($s3Url, $tempFilename); if ($tempPath) { $output['filepath'] = $tempPath; $output['is_temp_file'] = true; // Флаг для последующей очистки if ($processType == '201.01') { file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - S3 файл искового заявления успешно скачан во временную папку'.PHP_EOL, FILE_APPEND); } else { file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - S3 файл заявления на выдачу исполнительного листа успешно скачан во временную папку'.PHP_EOL, FILE_APPEND); } } else { $output['result'] = 'NO'; if ($processType == '201.01') { file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - не удалось скачать исковое заявление из S3'.PHP_EOL, FILE_APPEND); } else { file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - не удалось скачать заявление на выдачу исполнительного листа из S3'.PHP_EOL, FILE_APPEND); } return $output; } } else { // Локальный файл (оригинальная логика) $output['filepath'] = $adb->query_result($result, 0, 'filepath'); $output['is_temp_file'] = false; if ($processType == '201.01') { file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - исковое заявление найдено как локальный файл'.PHP_EOL, FILE_APPEND); } else { file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - заявление на выдачу исполнительного листа найдено как локальный файл'.PHP_EOL, FILE_APPEND); } } $output['filename'] = $adb->query_result($result, 0, 'title').'.pdf'; if (!is_numeric(substr($output['filename'], 0, 1))) { $output['filename'] = '0_'.$output['filename']; } $output['filename'] = str_replace(' ', '_', $output['filename']); $output['type'] = $adb->query_result($result, 0, 'type'); $output['pages'] = $adb->query_result($result, 0, 'pages'); if (empty($output['pages']) or $output['pages'] == 0) { $output['pages'] = getPDFPageCount($output['filepath']); } if ($processType == '201.01') { file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - Нашли исковое заявление в Проекте '.$projectid.PHP_EOL, FILE_APPEND); } else { file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - Нашли заявление на выдачу исполнительного листа в Проекте '.$projectid.PHP_EOL, FILE_APPEND); } } return $output; } function getOtherDocs($projectid, $accountid, $acc1, $acc2) { global $adb; $output = []; //$i = 0; // Сначала вытащим доки из Проекта, но только те, которые лежат в папке "Суд" $query = 'select n.title, ncf.cf_1953 as pages, case when n.filelocationtype = "E" and n.s3_bucket is not null and n.s3_key is not null then concat("https://s3.twcstorage.ru/", n.s3_bucket, "/", n.s3_key) else case when a.storedname is not null then concat(a.`path`, a.attachmentsid, "_", a.storedname) else concat(a.`path`, a.attachmentsid, "_", a.name) end end as filepath, case when n.filelocationtype = "E" and n.s3_bucket is not null and n.s3_key is not null then concat(n.title, ".pdf") else case when a.storedname is not null then concat(a.attachmentsid, "_", a.storedname) else concat(a.attachmentsid, "_", a.name) end end as filename, case when n.filelocationtype = "E" and n.s3_bucket is not null and n.s3_key is not null then "application/pdf" else a.`type` end as filetype, n.filelocationtype, n.s3_bucket, n.s3_key from vtiger_senotesrel r left join vtiger_notes n on n.notesid = r.notesid left join vtiger_crmentity e on e.crmid = r.notesid left join vtiger_notescf ncf on ncf.notesid = r.notesid left join vtiger_seattachmentsrel r2 on r2.crmid = r.notesid left join vtiger_attachments a on a.attachmentsid = r2.attachmentsid where r.crmid = ? and e.deleted = 0 and n.filename not like "%Исковое_заявление%" and n.folderid = 3 and ( (n.filelocationtype = "E" and n.s3_bucket is not null and n.s3_key is not null) or (a.`type` = "application/pdf" or a.`type` = "application/octet-stream") )'; $result = $adb->pquery($query, array($projectid)); if ($adb->num_rows($result) > 0) { file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - найдено документов в проекте '.$projectid.': '.$adb->num_rows($result).PHP_EOL, FILE_APPEND); for ($i=0; $i<$adb->num_rows($result); $i++) { $output[$i]['description'] = $adb->query_result($result, $i, 'title'); if (!is_numeric(substr($output[$i]['description'], 0, 1))) { $output[$i]['description'] = $i.'_'.$output[$i]['description']; } $output[$i]['description'] = str_replace(' ', '_', $output[$i]['description']); $output[$i]['filepath'] = $adb->query_result($result, $i, 'filepath'); $output[$i]['filename'] = $adb->query_result($result, $i, 'filename'); if (!is_numeric(substr($output[$i]['filename'], 0, 1))) { $output[$i]['filename'] = $i.'_'.$output[$i]['filename']; } $output[$i]['filename'] = str_replace(' ', '_', $output[$i]['filename']); $output[$i]['type'] = $adb->query_result($result, $i, 'filetype'); $output[$i]['pages'] = $adb->query_result($result, $i, 'pages'); $output[$i]['filelocationtype'] = $adb->query_result($result, $i, 'filelocationtype'); $output[$i]['s3_bucket'] = $adb->query_result($result, $i, 's3_bucket'); $output[$i]['s3_key'] = $adb->query_result($result, $i, 's3_key'); if (empty($output[$i]['pages']) or $output[$i]['pages'] == 0) { $output[$i]['pages'] = getPDFPageCount($output[$i]['filepath']); } file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - файл из проекта: '.$output[$i]['filename'].' (location: '.$output[$i]['filelocationtype'].')'.PHP_EOL, FILE_APPEND); //echo $i.' - '.$output[$i]['filename'].'
'; } } // А теперь из Контрагентов (трех), но только те, которые лежат в папке "Суд" $query = 'select n.title, ncf.cf_1953 as pages, case when n.filelocationtype = "E" and n.s3_bucket is not null and n.s3_key is not null then concat("https://s3.twcstorage.ru/", n.s3_bucket, "/", n.s3_key) else case when a.storedname is not null then concat(a.`path`, a.attachmentsid, "_", a.storedname) else concat(a.`path`, a.attachmentsid, "_", a.name) end end as filepath, case when n.filelocationtype = "E" and n.s3_bucket is not null and n.s3_key is not null then concat(n.title, ".pdf") else case when a.storedname is not null then concat(a.attachmentsid, "_", a.storedname) else concat(a.attachmentsid, "_", a.name) end end as filename, case when n.filelocationtype = "E" and n.s3_bucket is not null and n.s3_key is not null then "application/pdf" else a.`type` end as filetype, n.filelocationtype, n.s3_bucket, n.s3_key from vtiger_senotesrel r left join vtiger_notes n on n.notesid = r.notesid left join vtiger_crmentity e on e.crmid = r.notesid left join vtiger_notescf ncf on ncf.notesid = r.notesid left join vtiger_seattachmentsrel r2 on r2.crmid = r.notesid left join vtiger_attachments a on a.attachmentsid = r2.attachmentsid where r.crmid in (?, ?, ?) and e.deleted = 0 and n.folderid = 3 and ( (n.filelocationtype = "E" and n.s3_bucket is not null and n.s3_key is not null) or (a.`type` = "application/pdf" or a.`type` = "application/octet-stream") )'; $result = $adb->pquery($query, array($accountid, $acc1, $acc2)); if ($adb->num_rows($result) > 0) { file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - найдено документов в контрагентах ('.$accountid.', '.$acc1.', '.$acc2.'): '.$adb->num_rows($result).PHP_EOL, FILE_APPEND); for ($j=0; $j<$adb->num_rows($result); $j++) { $output[$i]['description'] = $adb->query_result($result, $j, 'title'); if (!is_numeric(substr($output[$i]['description'], 0, 1))) { $output[$i]['description'] = $i.'_'.$output[$i]['description']; } $output[$i]['description'] = str_replace(' ', '_', $output[$i]['description']); $output[$i]['filepath'] = $adb->query_result($result, $j, 'filepath'); $output[$i]['filename'] = $adb->query_result($result, $j, 'filename'); $output[$i]['type'] = $adb->query_result($result, $j, 'filetype'); $output[$i]['pages'] = $adb->query_result($result, $j, 'pages'); $output[$i]['filelocationtype'] = $adb->query_result($result, $j, 'filelocationtype'); $output[$i]['s3_bucket'] = $adb->query_result($result, $j, 's3_bucket'); $output[$i]['s3_key'] = $adb->query_result($result, $j, 's3_key'); if (!is_numeric(substr($output[$i]['filename'], 0, 1))) { $output[$i]['filename'] = $i.'_'.$output[$i]['filename']; } $output[$i]['filename'] = str_replace(' ', '_', $output[$i]['filename']); if (empty($output[$i]['pages']) or $output[$i]['pages'] == 0) { $output[$i]['pages'] = getPDFPageCount($output[$i]['filepath']); } file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - файл из контрагента: '.$output[$i]['filename'].' (location: '.$output[$i]['filelocationtype'].')'.PHP_EOL, FILE_APPEND); $i++; } } return $output; } function getCourt($contactid, $address, $price) { $output = []; $output['result'] = 'YES'; if (empty($address) and (empty($contactid) or $contactid < 1)) { $output['result'] = 'Не указаны исходные данные'; file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - не указан адрес для поиска суда'.PHP_EOL, FILE_APPEND); } else { if (empty($address) and $contactid > 0) { $query = 'select a.mailingstreet from vtiger_contactaddress a left join vtiger_crmentity e on e.crmid = a.contactaddressid where e.deleted = 0 and a.contactaddressid = '.$contactid; $result = $adb->pquery($query); if ($adb->num_rows($result) == 0) { $output['result'] = 'Контакт не найден'; } else { $address = $adb->query_result($result, 0, 'mailingstreet'); } } // Декодируем HTML entities в адресе (—,   и т.д.) $address = html_entity_decode($address, ENT_QUOTES | ENT_HTML5, 'UTF-8'); } if ($output['result'] == 'YES') { file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - начинаем поиск суда для адреса '.$address.PHP_EOL, FILE_APPEND); $host = "https://api.xn----7sbarabva2auedgdkhac2adbeqt1tna3e.xn--p1ai/api"; // адрес сервера api $token = "y4kNd3Li2NDxyOgaG37ZDuGTWg5CfF2A2dERwbFUjas"; // указать полученный токен // запрос по адресу $url = $host."?token=".$token."&address=".urlencode($address); // запрос по координатам //$coords = "49.099524 55.794340"; // координаты точки, разделитель - пробел //$url = $host . "?token=" . $token . "&coords=" . urlencode($coords); $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($curl); curl_close($curl); $court = json_decode($response, true); if ($price > 100000) { // Если цена иска - от 100 тысяч, то нам будем нужен федеральный суд $need = 'court_fs'; file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - сумма иска более 100к - нужен федеральный суд'.PHP_EOL, FILE_APPEND); } else { // А если меньше, то мировой $need = 'court_ms'; file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - сумма иска менее 100к - нужен мировой суд'.PHP_EOL, FILE_APPEND); } if (isset($court['request'][$need])) { $output['code'] = $court['request'][$need]['code']; $output['region'] = substr($output['code'], 0, 2); // Первые две цифры кода суда - это регион $output['name'] = $court['request'][$need]['title']; $output['site'] = $court['request'][$need]['site']; $output['phone'] = $court['request'][$need]['tel']; $output['email'] = $court['request'][$need]['email']; $output['address'] = $court['request'][$need]['address']; file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - и он найден в бесплатной версии API. Код суда: '.$output['code'].PHP_EOL, FILE_APPEND); } else { // В бесплатной версии поиска подсудности нужного суда не нашлось - придется лезть в платный сервис file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - но в бесплатной версии API его нет - полезем в платную'.PHP_EOL, FILE_APPEND); $apikey = GetKey('Prod'); $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => 'https://api-yc.explorer.debex.ru/production/jurisdiction', CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS =>'{ "address": "'.addslashes($address).'", "get_fssp_geo": 1 }', CURLOPT_HTTPHEADER => array( 'x-api-key: '.$apikey, 'Content-Type: application/json' ), )); $response = curl_exec($curl); curl_close($curl); $court = json_decode($response, true); if ($price > 100000) { // Если цена иска - от 100 тысяч, то нам будем нужен федеральный суд $need = 'higher_court'; } else { // А если меньше, то мировой $need = 'court'; } if (isset($court['result'][$need])) { $output['code'] = $court['result'][$need]['code']; $output['region'] = substr($output['code'], 0, 2); // Первые две цифры кода суда - это регион $output['name'] = $court['result'][$need]['court_name']; $output['site'] = $court['result'][$need]['website']; $output['phone'] = $court['result'][$need]['phone_normalized'][0]['phone']; $output['email'] = $court['result'][$need]['email']; $output['address'] = $court['result'][$need]['address']; file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - а тут мы его и нашли: '.$output['code'].PHP_EOL, FILE_APPEND); } else { // Нужный суд не нашелся ни в платном, ни в бесплатном сервисе - не можем продолжать $output['result'] = 'Суд для адреса '.$address.' не найден'; file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - но его и в платном API тоже нет'.PHP_EOL, FILE_APPEND); } } } return $output; } function GetCookies($version) { //$version = 'Dev'; if ($version == 'Dev') { file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - поднимаем тестовые куки для версии Dev'.PHP_EOL, FILE_APPEND); $curl = curl_init(); $apiKey = GetKey('Dev'); curl_setopt_array($curl, array( CURLOPT_URL => 'https://api-yc.explorer.debex.ru/dev/sudrf-auth', CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_HTTPHEADER => array( 'x-api-key: '.$apiKey ), )); $response = curl_exec($curl); curl_close($curl); } else { $response = 'No'; if (file_exists('cookies.txt')) { file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - Найден файл со старыми куками'.PHP_EOL, FILE_APPEND); $created = filemtime('cookies.txt'); // Дата создания файла (получения и сохранения cookies) $now = time(); $diff = $now - $created; if ($diff < 10800) { // Если старый файл создан более 3 часов назад $response = file_get_contents('cookies.txt'); file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - создан менее 3 часов назад - берем куки из него'.PHP_EOL, FILE_APPEND); } else { file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - создан более 3 часов назад - будем получать новые'.PHP_EOL, FILE_APPEND); } } if ($response == 'No') { // Будем получать новые $url = "https://api-yc.explorer.debex.ru/production/sudrf-auth-chatbot"; $ch = curl_init($url); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'x-api-key: ' . GetKey('Prod'), 'hidden-bot-phone-number: +79262306381' ]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, []); file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - отправляем запрос с СМС-подтверждением'.PHP_EOL, FILE_APPEND); $response = curl_exec($ch); curl_close($ch); // И сохраним их на будущее if (strpos($response, "error") !== false) { $response = 'Не удалось получить куки'; file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - в ответ получили ошибку. Куков нет.'.PHP_EOL, FILE_APPEND); } else { file_put_contents('cookies.txt', $response); file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - ответ получен, новые куки сохранены в файле cookies.txt'.PHP_EOL, FILE_APPEND); } } } return $response; } function GetUrl($version) { /* if ($version == 'Dev') { $url = 'https://explorer-proxy.debex.ru/api/dev/sudrf'; } elseif ($version == 'Stage') { $url = 'https://explorer-proxy.debex.ru/api/stage/sudrf'; } elseif ($version == 'Prod') { $url = 'https://explorer-proxy.debex.ru/api/production/sudrf'; } */ if ($version == 'Dev') { $url = 'https://explorer-proxy.debex.ru/api/v3/dev/sudrf'; } elseif ($version == 'Stage') { $url = 'https://explorer-proxy.debex.ru/api/v3/stage/sudrf'; } elseif ($version == 'Prod') { $url = 'https://explorer-proxy.debex.ru/api/v3/production/sudrf'; } return $url; } function GetKey($version) { if ($version == 'Dev') { $key = 'sandboxklientpravdjknkjsdndsd8y789!'; } else { $key = 'productionklientpravkjnkjnhkhj87y!'; } return $key; } function SendRequest ($url, $multipart, $headers, $count) { if ($count < 6) { $client = new Client(); file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - непосредственно отправляем запрос. Попытка №'.$count.PHP_EOL, FILE_APPEND); try { $response = $client->request('POST', $url, [ 'headers' => $headers, 'multipart' => $multipart ]); $statusCode = $response->getStatusCode(); if ($statusCode >= 200 && $statusCode < 300) { // Успешный ответ //$output = $response->getBody()->getContents(); $output = $response->getBody(); } else { // Ошибка $output = "Ошибка HTTP: " . $statusCode . " - " . $response->getReasonPhrase(); } // Выводим ответ //$output = $response->getBody(); file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - получили ответ на запрос: '.$output.PHP_EOL, FILE_APPEND); // Вытаскиваем номер входящего $arrResponse = json_decode($output, true); $number = $arrResponse['data']['appealNumber']; file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - вытащили рег.номер: '.$number.PHP_EOL, FILE_APPEND); $output = array('status' => 'OK', 'message' => $number); } catch (Exception $ex) { // Обрабатываем исключение, например, выводим сообщение об ошибке $output = $ex->getMessage(); file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - получили ошибку при выполнении запроса: '.$output.PHP_EOL, FILE_APPEND); // 🔍 УЛУЧШЕНИЕ: Извлекаем тело ответа для детальной диагностики if ($ex instanceof \GuzzleHttp\Exception\RequestException && $ex->hasResponse()) { $response = $ex->getResponse(); $statusCode = $response->getStatusCode(); $responseBody = (string) $response->getBody(); file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - HTTP статус код: '.$statusCode.PHP_EOL, FILE_APPEND); file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - Тело ответа от сервера: '.$responseBody.PHP_EOL, FILE_APPEND); // Если это JSON, попробуем распарсить для читаемости $jsonData = json_decode($responseBody, true); if (json_last_error() === JSON_ERROR_NONE && !empty($jsonData)) { file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - Детали ошибки (JSON): '.print_r($jsonData, true).PHP_EOL, FILE_APPEND); } } else { file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - Тело ответа недоступно (возможно, проблема с соединением)'.PHP_EOL, FILE_APPEND); } $RetryFlag = false; // Флаг перезапуска $retry = array("500", "403", "417"); // Массив ошибок, при которых будем пробовать еще раз foreach ($retry as $errorcode) { if (strpos($output, $errorcode) !== false) { // В строке с ответом с ошибкой есть код, при котором будем пробовать еще раз $RetryFlag = true; break; } } if ($RetryFlag) { // Отключены повторы - сразу возвращаем ошибку $output = array('status' => 'ERROR', 'message' => 'Ошибка при отправке запроса'); } else { $output = array('status' => 'ERROR', 'message' => 'Похоже на ошибку в составе данных - перезапускать не будем'); } } } else { $output = array('status' => 'ERROR', 'message' => 'Отправка не удалась'); } return $output; } ?>