Files
crm.clientright.ru/include/utils/Debexpert-guzzle-n8n.php
Fedor 01c4fe80b5 chore: snapshot current working tree changes
Save all currently accumulated repository changes as a backup snapshot for Gitea so no local work is lost.
2026-03-26 14:19:01 +03:00

1243 lines
64 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/*********************************************************************************
* Набор методов для работы с ej.sudrf.ru через сервис debex.ru
* All Rights Reserved.
* Contributor(s): Илья Руденко itsaturn@yandex.ru
********************************************************************************/
require_once 'include/utils/utils.php';
require_once 'include/Webservices/Revise.php';
require_once 'modules/Users/Users.php';
require_once 'includes/Loader.php';
require_once 'vendor/autoload.php';
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\MultipartStream;
use GuzzleHttp\Exception\RequestException;
vimport ('includes.runtime.Globals');
vimport ('includes.runtime.BaseModel');
vimport ('includes.runtime.LanguageHandler');
function Send2Court($projectid, $processType, $version) {
if ($processType == '201.01') {
file_put_contents('logs/send2court.log', PHP_EOL.date('Y-m-d H:i:s').' - Запущена процедура отправки искового по Проекту '.$projectid.' в режиме '.$version.PHP_EOL, FILE_APPEND);
} else {
file_put_contents('logs/send2court.log', PHP_EOL.date('Y-m-d H:i:s').' - Запущена процедура отправки заявления на выдачу исполнительного листа по Проекту '.$projectid.' в режиме '.$version.PHP_EOL, FILE_APPEND);
}
global $adb;
$query = 'select u.index_notice, u.addr_notice, u.id as userid, a.accountid, a.accountname, a.inn, a.kpp, la.bill_code, la.bill_city, la.bill_street, ra.ship_code, ra.ship_city, ra.ship_street, a.phone, a.email1, pcf.cf_1511 as price, ca.mailingstreet, acf.cf_1951 as ogrn, u.email1 as usermail, pcf.cf_2274 as acc1, pcf.cf_2276 as acc2, pcf.cf_2292 as jurisdiction, pcf.cf_2294 as agrplace, oa.bill_street as offaddress, p.linktoaccountscontacts as contactid, pcf.cf_1507 as casenumber
from vtiger_project p
left join vtiger_projectcf pcf on pcf.projectid = p.projectid
left join vtiger_contactdetails cd on cd.contactid = p.linktoaccountscontacts
left join vtiger_contactaddress ca on ca.contactaddressid = p.linktoaccountscontacts
left join vtiger_account a on a.accountid = pcf.cf_1994
left join vtiger_accountscf acf on acf.accountid = pcf.cf_1994
left join vtiger_accountbillads la on la.accountaddressid = pcf.cf_1994
left join vtiger_accountshipads ra on ra.accountaddressid = pcf.cf_1994
left join vtiger_accountbillads oa on oa.accountaddressid = pcf.cf_2274
left join vtiger_crmentity e on e.crmid = p.projectid
left join vtiger_users u on u.id = e.smownerid
where e.deleted = 0 and p.projectid = '.$projectid;
$result = $adb->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<count($otherDocs); $i++) {
$newdoc = array();
$newdoc['fileIndex'] = $fileIndexInMultipart;
$newdoc['description'] = $otherDocs[$i]['description'];
$newdoc['pagesCount'] = $otherDocs[$i]['pages'];
// Проверяем является ли файл S3 файлом
if ($otherDocs[$i]['filelocationtype'] == 'E' && !empty($otherDocs[$i]['s3_bucket']) && !empty($otherDocs[$i]['s3_key'])) {
// Файл в S3 - скачиваем во временную папку
$s3Url = $otherDocs[$i]['filepath'];
$tempFilename = 'other_doc_' . $i . '_' . time() . '.pdf';
$tempPath = getTempFileFromS3($s3Url, $tempFilename);
if ($tempPath !== false) {
$otherDocs[$i]['filepath'] = $tempPath;
$otherDocs[$i]['is_temp_file'] = true;
file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - S3 файл скачан во временную папку: '.$tempPath.PHP_EOL, FILE_APPEND);
} else {
file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - ошибка скачивания S3 файла: '.$s3Url.PHP_EOL, FILE_APPEND);
continue; // Пропускаем этот файл
}
}
// Добавляем в JSON только если файл будет в multipart
$data['additionalAppealDocuments'][] = $newdoc;
$fileIndexInMultipart++;
// Проверяем и исправляем filename если нужно
$filename = $otherDocs[$i]['filename'];
if (empty($filename) || filter_var($filename, FILTER_VALIDATE_URL)) {
// Если filename пустой или это URL, используем title + .pdf
$filename = $otherDocs[$i]['description'] . '.pdf';
}
$multipart[] = [
'name' => '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'
];
$fillDataJson = json_encode($data);
$multipart[] = [
'name' => 'fillData',
'contents' => $fillDataJson
];
file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - fillData JSON: '.$fillDataJson.PHP_EOL, FILE_APPEND);
$payloadLogEntry = json_encode(
[
'ts' => date('c'),
'projectid' => $projectid,
'processType' => $processType,
'version' => $version,
'fillData' => $data
],
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
);
file_put_contents('logs/send2court_payload.jsonl', $payloadLogEntry.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.'&reg='.$number;
} else {
$url = 'https://crm.clientright.ru/shorturl.php?id=66508afc2008a4.30213815&workflow_id=80&record_id='.$projectid.'&reg='.$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'].'<br>';
}
}
// А теперь из Контрагентов (трех), но только те, которые лежат в папке "Суд"
$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) {
global $adb;
$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 в адресе (&mdash;, &nbsp; и т.д.)
$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 {
// Путь к cookies.txt в корне проекта (не зависит от CWD при вызове из веба/крона)
$cookieFile = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR . 'cookies.txt';
$response = 'No';
if (file_exists($cookieFile)) {
file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - Найден файл со старыми куками'.PHP_EOL, FILE_APPEND);
$created = filemtime($cookieFile);
$now = time();
$diff = $now - $created;
if ($diff < 10800) {
$response = file_get_contents($cookieFile);
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 {
if (file_put_contents($cookieFile, $response) === false) {
file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - ОШИБКА: не удалось записать куки в '.$cookieFile.' (проверьте права: веб-пользователь должен иметь запись)'.PHP_EOL, FILE_APPEND);
} else {
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,
'expect' => false // Отключаем Expect: 100-continue для совместимости с API
]);
$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();
$detailForCaller = $output;
file_put_contents('logs/send2court.log', date('Y-m-d H:i:s').' - получили ошибку при выполнении запроса: '.$output.PHP_EOL, FILE_APPEND);
// 🔍 УЛУЧШЕНИЕ: Извлекаем тело ответа для детальной диагностики и для возврата вызывающему (n8n)
if ($ex instanceof \GuzzleHttp\Exception\RequestException && $ex->hasResponse()) {
$response = $ex->getResponse();
$statusCode = $response->getStatusCode();
$responseBody = (string) $response->getBody();
$detailForCaller = $statusCode . ' ' . $response->getReasonPhrase() . ' — ' . (strlen($responseBody) > 600 ? substr($responseBody, 0, 600) . '...' : $responseBody);
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) {
// Отключены повторы — возвращаем реальный ответ Debex, чтобы видеть в n8n
$output = array('status' => 'ERROR', 'message' => 'Ошибка при отправке запроса: ' . $detailForCaller);
} else {
$output = array('status' => 'ERROR', 'message' => 'Похоже на ошибку в составе данных - перезапускать не будем. ' . $detailForCaller);
}
}
} else {
$output = array('status' => 'ERROR', 'message' => 'Отправка не удалась');
}
return $output;
}
/**
* Метаданные доверенности без скачивания файла (для n8n payload API).
* Возвращает url (S3) или path (локальный), description, pages (int), filename.
*/
function getAuthDocInfo($accountid, $userid) {
global $adb;
$out = ['result' => 'NO'];
$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 n.filename else null end as s3_url,
case when n.filelocationtype != "E" or n.s3_bucket is null or n.s3_key is null
then case when a.storedname is not null then concat(a.`path`, a.attachmentsid, "_", a.storedname) else concat(a.`path`, a.attachmentsid, "_", a.name) end
else null end as filepath
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) return $out;
$out['result'] = 'YES';
$out['description'] = $adb->query_result($result, 0, 'title');
if (!is_numeric(substr($out['description'], 0, 1))) $out['description'] = '0_' . $out['description'];
$out['description'] = str_replace(' ', '_', $out['description']);
$out['filename'] = $out['description'] . '.pdf';
$p = $adb->query_result($result, 0, 'pages');
$out['pages'] = (int)(is_numeric($p) ? $p : 0);
$s3 = $adb->query_result($result, 0, 's3_url');
$path = $adb->query_result($result, 0, 'filepath');
if (!empty($s3)) $out['url'] = $s3;
elseif (!empty($path)) $out['path'] = $path;
else return ['result' => 'NO'];
return $out;
}
/**
* Метаданные искового/заявления без скачивания (для n8n payload API).
*/
function getClaimInfo($projectid, $processType) {
global $adb;
$out = ['result' => 'NO'];
$q = '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 n.filename else null end as s3_url,
case when n.filelocationtype != "E" or n.s3_bucket is null or n.s3_key is null
then case when a.storedname is not null then concat(a.`path`, a.attachmentsid, "_", a.storedname) else concat(a.`path`, a.attachmentsid, "_", a.name) end else null end as filepath
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 ';
$q .= ($processType == '201.01') ? '(n.filename like "%Исковоеаявление%" OR n.title like "%Исковоеаявление%" OR n.title like "%исковое%" OR n.filename like "%исковое%")' : 'n.filename like "%7777777%"';
$result = $adb->pquery($q, array($projectid));
if ($adb->num_rows($result) == 0) return $out;
$out['result'] = 'YES';
$out['description'] = $adb->query_result($result, 0, 'title');
if (!is_numeric(substr($out['description'], 0, 1))) $out['description'] = '0_' . $out['description'];
$out['description'] = str_replace(' ', '_', $out['description']);
$out['filename'] = $out['description'] . '.pdf';
$p = $adb->query_result($result, 0, 'pages');
$out['pages'] = (int)(is_numeric($p) ? $p : 0);
$s3 = $adb->query_result($result, 0, 's3_url');
$path = $adb->query_result($result, 0, 'filepath');
if (!empty($s3)) $out['url'] = $s3;
elseif (!empty($path)) $out['path'] = $path;
else return ['result' => 'NO'];
return $out;
}
/**
* Нормализация телефона для ГАС: +7XXXXXXXXXX
*/
function normalizePhoneForGAS($phone) {
if (empty($phone)) return $phone;
$digits = preg_replace('/\D/', '', $phone);
if (strlen($digits) == 10 && $digits[0] == '9') return '+7' . $digits;
if (strlen($digits) == 11 && $digits[0] == '8') return '+7' . substr($digits, 1);
if (strlen($digits) == 11 && $digits[0] == '7') return '+' . $digits;
return $phone;
}
/**
* Собирает payload для отправки в Debex (fillData + список файлов). Для n8n.
* Возвращает ['fillData' => ..., 'files' => [...], 'version' => ..., 'processType' => ..., 'certificatePath' => ...] или ['error' => '...'].
*/
function GetSend2CourtPayload($projectid, $processType, $version) {
global $adb;
$query = 'select u.index_notice, u.addr_notice, u.id as userid, a.accountid, a.accountname, a.inn, a.kpp, la.bill_code, la.bill_city, la.bill_street, ra.ship_code, ra.ship_city, ra.ship_street, a.phone, a.email1, pcf.cf_1511 as price, ca.mailingstreet, acf.cf_1951 as ogrn, u.email1 as usermail, pcf.cf_2274 as acc1, pcf.cf_2276 as acc2, pcf.cf_2292 as jurisdiction, pcf.cf_2294 as agrplace, oa.bill_street as offaddress, p.linktoaccountscontacts as contactid, pcf.cf_1507 as casenumber
from vtiger_project p
left join vtiger_projectcf pcf on pcf.projectid = p.projectid
left join vtiger_contactaddress ca on ca.contactaddressid = p.linktoaccountscontacts
left join vtiger_account a on a.accountid = pcf.cf_1994
left join vtiger_accountscf acf on acf.accountid = pcf.cf_1994
left join vtiger_accountbillads la on la.accountaddressid = pcf.cf_1994
left join vtiger_accountshipads ra on ra.accountaddressid = pcf.cf_1994
left join vtiger_accountbillads oa on oa.accountaddressid = pcf.cf_2274
left join vtiger_crmentity e on e.crmid = p.projectid
left join vtiger_users u on u.id = e.smownerid
where e.deleted = 0 and p.projectid = ' . (int)$projectid;
$result = $adb->pquery($query);
if ($adb->num_rows($result) == 0) return ['error' => 'Проект не найден'];
$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 = getAuthDocInfo($accountid, $userid);
if ($authdoc['result'] !== 'YES') return ['error' => 'Нет доверенности у ответственного по проекту в контрагенте'];
$price = (float) $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');
elseif ($jurisdiction == 'По месту нахождения ответчика') $address = $adb->query_result($result, 0, 'offaddress');
else $address = $adb->query_result($result, 0, 'mailingstreet');
$address = html_entity_decode($address, ENT_QUOTES | ENT_HTML5, 'UTF-8');
$court = getCourt($contactid, $address, $price);
if ($court['result'] !== 'YES') return ['error' => $court['result']];
$claim = getClaimInfo($projectid, $processType);
if ($claim['result'] !== 'YES') return ['error' => ($processType == '201.01') ? 'Отсутствует исковое заявление' : 'Отсутствует заявление на выдачу исполнительного листа'];
$files = [];
$files[] = ['part' => 'files', 'filename' => $authdoc['filename'], 'fileIndex' => 0] + (isset($authdoc['url']) ? ['url' => $authdoc['url']] : ['path' => $authdoc['path']]);
$files[] = ['part' => 'files', 'filename' => $claim['filename'], 'fileIndex' => 1] + (isset($claim['url']) ? ['url' => $claim['url']] : ['path' => $claim['path']]);
$data = [];
$data['appealType'] = 2;
$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'] = (int) $authdoc['pages'];
$kpp = trim($adb->query_result($result, 0, 'kpp'));
$ogrn = trim($adb->query_result($result, 0, 'ogrn'));
$entity = [
'name' => html_entity_decode(htmlspecialchars_decode($adb->query_result($result, 0, 'accountname')), ENT_QUOTES | ENT_HTML5, 'UTF-8'),
'international' => false,
'inn' => $adb->query_result($result, 0, 'inn'),
'kpp' => $adb->query_result($result, 0, 'kpp'),
'proceduralStatus' => '50710010',
'legalIndex' => $adb->query_result($result, 0, 'bill_code'),
'legalAddress' => html_entity_decode($adb->query_result($result, 0, 'bill_city').', '.$adb->query_result($result, 0, 'bill_street'), ENT_QUOTES | ENT_HTML5, 'UTF-8'),
'isLegalAdressEqualToActualResidenceAddress' => false,
'actualResidenceIndex' => $adb->query_result($result, 0, 'ship_code'),
'actualResidenceAddress' => html_entity_decode($adb->query_result($result, 0, 'ship_city').', '.$adb->query_result($result, 0, 'ship_street'), ENT_QUOTES | ENT_HTML5, 'UTF-8'),
'email' => $adb->query_result($result, 0, 'email1'),
'phoneNumber' => normalizePhoneForGAS($adb->query_result($result, 0, 'phone')),
];
if (!empty($kpp)) $entity['ogrn'] = $ogrn;
else $entity['ogrnip'] = $ogrn;
$data['additionalForRepresentativeApplicants'][0] = ['dataType' => 'entity', 'entity' => $entity];
$data['court']['region'] = $court['region'];
$data['court']['judicialAuthority'] = $court['code'];
$data['appealDocument']['fileIndex'] = 1;
$data['appealDocument']['description'] = $claim['description'];
$data['appealDocument']['pagesCount'] = (int) $claim['pages'];
$data['tax']['type'] = '1';
$data['processType'] = $processType;
$fileIndexInMultipart = 2;
if ($processType == '201.01') {
$otherDocs = getOtherDocs($projectid, $accountid, $acc1, $acc2);
$data['additionalAppealDocuments'] = [];
foreach ($otherDocs as $i => $doc) {
$pages = isset($doc['pages']) ? (int)(is_numeric($doc['pages']) ? $doc['pages'] : 0) : 0;
$data['additionalAppealDocuments'][] = ['fileIndex' => $fileIndexInMultipart, 'description' => $doc['description'], 'pagesCount' => $pages];
$fn = isset($doc['filename']) && !empty($doc['filename']) && !filter_var($doc['filename'], FILTER_VALIDATE_URL) ? $doc['filename'] : $doc['description'] . '.pdf';
$entry = ['part' => 'files', 'filename' => $fn, 'fileIndex' => $fileIndexInMultipart];
if (!empty($doc['filelocationtype']) && $doc['filelocationtype'] == 'E' && !empty($doc['filepath'])) $entry['url'] = $doc['filepath'];
else $entry['path'] = $doc['filepath'];
$files[] = $entry;
$fileIndexInMultipart++;
}
} else {
$data['additionalAppealDocuments'] = [];
if ($processType == '217.01') $data['caseNumber'] = $adb->query_result($result, 0, 'casenumber');
}
$certPath = __DIR__ . '/../../storage/cert.pfx';
if (!is_file($certPath)) $certPath = 'storage/cert.pfx';
$files[] = ['part' => 'certificate', 'filename' => 'cert.pfx', 'path' => $certPath];
return [
'fillData' => $data,
'files' => $files,
'version' => $version,
'processType' => $processType,
'projectid' => $projectid,
'certificatePath' => $certPath,
];
}
?>