diff --git a/upload_documents_to_crm.php b/upload_documents_to_crm.php index 43c07fb6..7538957f 100644 --- a/upload_documents_to_crm.php +++ b/upload_documents_to_crm.php @@ -293,13 +293,11 @@ function normalizeInputData($data) { return []; } -// Основная функция для создания документов -function createDocumentsInCRM($filesArray, $userName = 'api') { - global $adb, $current_user; +// Функция для получения сессии webservice с retry +function getWebserviceSession($userName, $maxRetries = 3) { + global $adb; - writeLog('🚀 Начинаем создание документов...'); - - // 1. Получаем access key пользователя + // Получаем access key пользователя $rs = $adb->pquery('SELECT id, accesskey FROM vtiger_users WHERE user_name=?', [$userName]); if (!$rs || $adb->num_rows($rs) == 0) { writeLog("❌ Пользователь $userName не найден"); @@ -308,53 +306,93 @@ function createDocumentsInCRM($filesArray, $userName = 'api') { $userId = $adb->query_result($rs, 0, 'id'); $accessKey = $adb->query_result($rs, 0, 'accesskey'); - // 2. Получаем challenge token + $endpointUrl = 'https://crm.clientright.ru/webservice.php'; + $ch = curl_init(); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + for ($attempt = 1; $attempt <= $maxRetries; $attempt++) { + writeLog("🔐 Попытка аутентификации #{$attempt}..."); + + // Добавляем случайную задержку для избежания race condition + if ($attempt > 1) { + $delay = rand(100, 500) * 1000; // 100-500ms в микросекундах + usleep($delay); + writeLog("⏱️ Задержка " . ($delay / 1000) . "ms перед попыткой #{$attempt}"); + } + + // getchallenge + curl_setopt($ch, CURLOPT_URL, $endpointUrl . '?operation=getchallenge&username=' . urlencode($userName)); + curl_setopt($ch, CURLOPT_POST, 0); + curl_setopt($ch, CURLOPT_HTTPGET, 1); + $resp = curl_exec($ch); + if ($resp === false) { + writeLog('❌ CURL error (challenge): ' . curl_error($ch)); + continue; + } + + $resp = ltrim($resp, "\xEF\xBB\xBF\x00\x09\x0A\x0D\x20"); + $challenge = json_decode($resp, true); + if (!$challenge || empty($challenge['result']['token'])) { + writeLog("❌ Invalid challenge response (attempt #{$attempt}): " . substr($resp, 0, 100)); + continue; + } + $token = $challenge['result']['token']; + + // login + $key = md5($token . $accessKey); + curl_setopt($ch, CURLOPT_URL, $endpointUrl); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, [ + 'operation' => 'login', + 'username' => $userName, + 'accessKey' => $key, + ]); + $resp = curl_exec($ch); + if ($resp === false) { + writeLog('❌ CURL error (login): ' . curl_error($ch)); + continue; + } + + $resp = ltrim($resp, "\xEF\xBB\xBF\x00\x09\x0A\x0D\x20"); + $login = json_decode($resp, true); + if (!$login || empty($login['result']['sessionName'])) { + writeLog("❌ Login failed (attempt #{$attempt}): " . substr($resp, 0, 100)); + continue; + } + + writeLog("✅ Аутентификация успешна с попытки #{$attempt}"); + return [ + 'sessionId' => $login['result']['sessionName'], + 'userId' => $userId, + 'curl' => $ch + ]; + } + + curl_close($ch); + return ['error' => 'Authentication failed after ' . $maxRetries . ' attempts']; +} + +// Основная функция для создания документов +function createDocumentsInCRM($filesArray, $userName = 'api') { + global $adb, $current_user; + + writeLog('🚀 Начинаем создание документов...'); + + // Получаем сессию с retry логикой + $session = getWebserviceSession($userName); + if (isset($session['error'])) { + return $session; + } + + $sessionId = $session['sessionId']; + $userId = $session['userId']; + $ch = $session['curl']; + $endpointUrl = 'https://crm.clientright.ru/webservice.php'; - // getchallenge - curl_setopt($ch, CURLOPT_URL, $endpointUrl . '?operation=getchallenge&username=' . urlencode($userName)); - $resp = curl_exec($ch); - if ($resp === false) { - writeLog('❌ CURL error: ' . curl_error($ch)); - return ['error' => 'Network error']; - } - - $resp = ltrim($resp, "\xEF\xBB\xBF\x00\x09\x0A\x0D\x20"); - $challenge = json_decode($resp, true); - if (!$challenge || empty($challenge['result']['token'])) { - writeLog('❌ Invalid challenge response: ' . substr($resp, 0, 100)); - return ['error' => 'Authentication failed']; - } - $token = $challenge['result']['token']; - - // 3. Логинимся - $key = md5($token . $accessKey); - curl_setopt($ch, CURLOPT_URL, $endpointUrl); - curl_setopt($ch, CURLOPT_POST, 1); - curl_setopt($ch, CURLOPT_POSTFIELDS, [ - 'operation' => 'login', - 'username' => $userName, - 'accessKey' => $key, - ]); - $resp = curl_exec($ch); - if ($resp === false) { - writeLog('❌ CURL error: ' . curl_error($ch)); - return ['error' => 'Network error']; - } - - $resp = ltrim($resp, "\xEF\xBB\xBF\x00\x09\x0A\x0D\x20"); - $login = json_decode($resp, true); - if (!$login || empty($login['result']['sessionName'])) { - writeLog('❌ Login failed: ' . substr($resp, 0, 100)); - return ['error' => 'Authentication failed']; - } - $sessionId = $login['result']['sessionName']; - // 4. Устанавливаем current_user для CRMEntity $current_user = new Users(); $current_user->retrieveCurrentUserInfoFromFile((int)$userId);