'avito', 2 => 'cian', 3 => 'yandex', 4 => 'domclick', ]; public function __construct($db = null, $debug = false) { if ($debug == true) { $this->debug = true; error_reporting(E_ALL | E_STRICT); ini_set('display_errors', 1); } if (isset($_SESSION['id'])) { if (isset($user)) { $this->_user = $user; } else { $user_id = intval($_SESSION['id']); $user = new User; $user->get($user_id); $this->_user = $user; } } else { $this->_user = null; } if (!is_null($this->_user)) $this->_agency_id = User::getUserAgencyID($this->_user->id); if (!is_null($db)) { $this->_db = $db; } else { $pdo = new MysqlPdo(hst, ndb, user, pass); $pdo->query("SET NAMES 'utf8'"); $this->_db = $pdo; } $this->_is_cli = isset($_SESSION); } private function _request($url, $options = null, $test = false) { $this->_curl_attempts++; if ($this->debug) $this->logs[] = 'Попытка запроса: ' . $this->_curl_attempts . ' по URL: ' . $url; $headers = []; $ch = curl_init($url); curl_setopt($ch, CURLOPT_CERTINFO, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); // запретить проверку сертификата удаленного сервера curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0"); curl_setopt($ch, CURLOPT_REFERER, "https://joywork.ru/"); curl_setopt($ch, CURLOPT_HEADER, 0); // При установке этого параметра в 1 результат будет включать полученные заголовки. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // При установке этого параметра в ненулевое значение CURL будет возвращать результат, а не выводить его. curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); //при получении HTTP заголовка "Location: " будет происходить перенаправление на указанный этим заголовком URL curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); curl_setopt($ch, CURLOPT_TIMEOUT, 20); curl_setopt($ch, CURLOPT_VERBOSE, 1); if (!is_null($options)) { if (isset($options['auth']) && isset($options['token'])) { if ($options['auth'] == 'bearer') { $headers[] = "Authorization: Bearer " . $options['token']; } else if ($options['auth'] == 'oauth') { $headers[] = "Authorization: OAuth " . $options['token']; } else if ($options['auth'] == 'token') { $headers[] = "Authorization: Token " . $options['token']; } } if (isset($options['method'])) { if ($options['method'] == 'post') { curl_setopt($ch, CURLOPT_POST, 1); } } else { curl_setopt($ch, CURLOPT_POST, 0); } if (isset($options['data'])) { curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($options['data'])); } if (isset($options['type'])) { if ($options['type'] == 'json') { $headers[] = "Accept: application/json"; $headers[] = "Content-Type: application/json"; } else if ($options['type'] == 'xml') { $headers[] = "Accept: application/xml"; $headers[] = "Content-Type: application/xml"; } } if (isset($options['headers']) && is_array($options['headers'])) { $headers = array_merge($headers, $options['headers']); } } if (!empty($headers)) { curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); } $content = curl_exec($ch); if (isset($_GET['dev'])) echo "
" . var_export(curl_getinfo($ch), true) . "
"; if ($test) { $error = curl_error($ch); // var_dump($error); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); // var_dump(curl_getinfo($ch)); return [ 'success' => ((int)$code === 200) ]; } curl_close($ch); if ((is_null($content) || $content == false) && !$test && $this->_curl_attempts < 3) { return $this->_request($url, $options, $test); } else { $this->_curl_attempts = 0; } return $content; } private function _getAuthToken($service = null, $client_id = null, $secret_key = null) { if (is_null($service)) $this->errors[] = 'Не указана площадка для получения токена авторизации API'; if (is_null($client_id) && strtolower($service) == 'avito') $this->errors[] = 'Не указан `client_id` для получения токена авторизации API'; if (is_null($secret_key)) $this->errors[] = 'Не указан `secret_key` для получения токена авторизации API'; if (is_null($service) || (is_null($client_id) && strtolower($service) == 'avito') || is_null($secret_key)) return false; $token = null; switch (strtolower($service)) { case 'avito' : if (isset($_SESSION[$this->_session_key]['avito'])) { $stored = $_SESSION[$this->_session_key]['avito']; if (time() <= intval($stored['expires'])) { $token = $stored['token']; } } if (is_null($token) || $this->_is_cli) { //var_dump($this->_tokens); if (isset($this->_tokens['avito']) && !is_null($this->_tokens['avito'])) { $stored = $this->_tokens['avito']; if (time() <= intval($stored['expires'])) { $token = $stored['token']; } } // var_dump($this->_api_id); if(empty($token) && $this->_api_id > 0){ $sql = "SELECT * FROM users_api WHERE id = {$this->_api_id}"; echo $sql; $q = $this->_db->query($sql); $api = $this->_db->fetch_assoc($q); if(isset($api['token']) && !empty($api['token'])){ if (time() <= intval($api['expires_in'])) { $token = $api['token']; } } } if (is_null($token)) { $url = "https://api.avito.ru/token/?grant_type=client_credentials&client_id=$client_id&client_secret=$secret_key"; $response = $this->_request($url, ['type' => 'json', 'method' => 'post']); if ($this->debug) $this->logs["https://api.avito.ru/token/?grant_type=client_credentials&client_id=$client_id&client_secret=$secret_key"] = $response; $data = json_decode($response, true); $token = $data['access_token']; if($this->_api_id > 0){ $expires = intval($data['expires_in']) + time(); $sql_in = "UPDATE users_api set token='{$token}', expires_in='{$expires}' WHERE id = {$this->_api_id}"; $this->_db->query($sql_in); } if ($this->_is_cli) { $this->_tokens['avito'] = [ 'expires' => intval($data['expires_in']) + time(), 'type' => strtolower($data['token_type']), 'token' => $token, ]; return $token; } else { if ($token) { $_SESSION[$this->_session_key]['avito'] = [ 'expires' => intval($data['expires_in']) + time(), 'type' => strtolower($data['token_type']), 'token' => $token, ]; } } } } break; case 'cian' : $token = $secret_key; break; case 'yandex' : $token = $secret_key; break; case 'domclick' : $token = $secret_key; break; } return $token; } private function _getObjectsIds($service = null, $agency_id = null) { $sql = "SELECT `objects`.`id`, `objects`.`nazv` FROM `objects` AS `objects` WHERE `objects`.`archive` <> 1 AND `objects`.`use_in_advert` > 0"; switch (strtolower($service)) { case 'avito' : $sql .= " AND `objects`.`add_to_avito_feed` > 0"; break; case 'cian' : $sql .= " AND `objects`.`add_to_cian_feed` > 0"; break; case 'yandex' : $sql .= " AND `objects`.`add_to_bn_feed` > 0"; break; case 'domclick' : $sql .= " AND `objects`.`add_to_domclick_feed` > 0"; break; } $sql .= " AND `objects`.`id_add_user` IN ( SELECT `id` FROM `users` WHERE `id` = $agency_id OR `id_manager` = $agency_id OR `id_manager` IN ( SELECT `id` FROM `users` WHERE `id_manager` = $agency_id ) OR `id_manager` IN ( SELECT `id` FROM `users` WHERE `id_manager` IN ( SELECT `id` FROM `users` WHERE `id_manager` = $agency_id ) ) )"; $rez = $this->_db->query($sql); $obj_ids = []; while ($object = $this->_db->fetch_assoc($rez)) { $obj_id = $object['id']; $obj_ids[$obj_id] = $object['nazv']; } return $obj_ids; } private static function _getServiceList() { return self::$_serviceList; } public static function getServiceName($service_id = null) { $serviceList = self::_getServiceList(); return $serviceList[$service_id]; } public static function getServiceByName($service = null) { return array_search($service, self::_getServiceList()); } public static function cleanUpStats($service = null, $object_id = null, $agency_id = null) { if (is_null($agency_id)) $agency_id = User::getUserAgencyID(); $service_id = self::getServiceByName($service); if (!is_null($service_id) && !is_null($object_id) && !is_null($agency_id)) { $sql = "DELETE FROM `ads_stats` WHERE `service_id` = '$service_id' AND `object_id` = '$object_id' AND `agency_id` = '$agency_id'"; return mysql_query($sql); } return false; } private function _getAvitoReportsIds($ext_user_id, $client_id, $secret_key, $page = 1) { $reportIds = []; if ($page > 1) $url = "https://api.avito.ru/autoload/v1/accounts/$ext_user_id/reports/?page=".intval($page); else $url = "https://api.avito.ru/autoload/v1/accounts/$ext_user_id/reports/"; $options = [ 'auth' => 'bearer', 'token' => $this->_getAuthToken('avito', $client_id, $secret_key), 'type' => 'json' ]; if ($response = $this->_request($url, $options)) $this->logs[] = "Успешное обращение к серверу API Авито."; else $this->logs[] = "Произошла ошибка обращения к серверу API Авито."; if ($this->debug) $this->logs[$url] = $response; $results = null; try { $results = json_decode($response, true); $this->logs[] = $results; if (is_array($results)) { // собираем ИД последних рапортов за сутки по выгрузке и индексации фидов $r_count = 0; foreach ($results['reports'] as $report) { if (!is_null($report['finished_at']) && $report['export_success'] == true) { //if (strtotime($report['finished_at']) >= strtotime('-7 days')) { $r_count++; $reportIds[] = $report['id']; //} } } $this->logs[] = "Обработано " . $r_count . " рапортов о выгрузке от Avito"; $pages = intval($results['meta']['pages']); $page = intval($results['meta']['page']); $per_page = intval($results['meta']['per_page']); $this->logs[] = "Текущая страница (оффсет): " . $page . " (" . ($page*$per_page) . ")"; if ($pages > $page) { $page++; $reportIds = array_merge($reportIds, $this->_getAvitoReportsIds($ext_user_id, $client_id, $secret_key, $page)); } } } catch (\Exception $exception) { $this->logs[] = $exception; } return $reportIds; } public function getStats($service_id = null, $period = null, $client_id = null, $secret_key = null, $ext_user_id = null, $object_id = null, $is_manual = false, $agency_id = null, $offset = 0) { ini_set('memory_limit', '256M'); $this->errors = []; $this->_api_attempts++; if (!$is_manual) echo "
_api_attempts " .var_export($this->_api_attempts, true). "
"; $service = $this->getServiceName($service_id); if (is_null($service)) $this->errors[] = 'Не указана площадка для получения статистики'; if (is_null($client_id) && (strtolower($service) == 'avito' || strtolower($service) == 'domclick')) $this->errors[] = 'Не указан `client_id` для получения статистики'; if (is_null($secret_key)) $this->errors[] = 'Не указан `secret_key` для получения статистики'; if (is_null($ext_user_id) && strtolower($service) == 'avito') $this->errors[] = 'Не указан `ext_user_id` обязательный для API Avito'; if (is_null($service) || (is_null($client_id) && (strtolower($service) == 'avito' || strtolower($service) == 'domclick')) || is_null($secret_key)) return false; if (is_array($period)) { $date_from = $period['date_from']; $date_to = $period['date_to']; } else { $date_to = date('Y-m-d'); switch (strtolower($period)) { case 'hour' : $date_from = date('Y-m-d', strtotime('-1 hour')); break; case 'day' : $date_from = date('Y-m-d', strtotime('-1 day')); break; case 'week' : $date_from = date('Y-m-d', strtotime('-1 week')); break; case 'month' : $date_from = date('Y-m-d', strtotime('-1 month')); break; default : $date_from = date('Y-m-d', strtotime('-1 week')); break; } } $output = []; $reports = []; if (is_null($agency_id)) $agency_id = $this->_agency_id; switch (strtolower($service)) { case 'avito' : // собираем ИД последних рапортов по выгрузке и индексации фидов $reportIds = $this->_getAvitoReportsIds($ext_user_id, $client_id, $secret_key, 1, 1); // Инвертируем список рапортов, будем шагать от старого к новому //$reportIds = array_reverse($reportIds); if (!$is_manual) { echo "
Всего обработано рапортов о выгрузке: " .count($reportIds). "
"; echo "
Рапорты о выгрузке: " . var_export($reportIds, true) . "
"; } if (count($reportIds)) { $ads = []; $objs = []; $adsIds = []; $service = $this->getServiceName($service_id); $obj_ids = $this->_getObjectsIds($service, $agency_id); if (!$is_manual) { echo "
Всего выгружается объектов: " . count($obj_ids) . "
"; echo "
Выгружаемые объекты: " . var_export($obj_ids, true) . "
"; } // обработка каждого рапорта и сбор ИД объявлений/объектов $report_num = 0; foreach ($reportIds as $reportId) { if (!$is_manual) echo "
Обработка рапорта №: " . $reportId . "
"; $report_status = false; if (!is_null($reportId)) { $url = "https://api.avito.ru/autoload/v1/accounts/$ext_user_id/reports/$reportId/"; $options = [ 'auth' => 'bearer', 'token' => $this->_getAuthToken('avito', $client_id, $secret_key), 'type' => 'json' ]; if ($response = $this->_request($url, $options)) $this->logs[date('Y-m-d H:i:s')][] = "Успешное обращение к серверу API Авито."; else $this->logs[date('Y-m-d H:i:s')][] = "Произошла ошибка обращения к серверу API Авито."; if ($this->debug) $this->logs["https://api.avito.ru/autoload/v1/accounts/$ext_user_id/reports/$reportId/"] = $response; $results = null; try { $results = json_decode($response, true); if (is_array($results)) { if (!$is_manual) echo "
В рапорте № " . $reportId . " объвлений: ". count($results['report']['ads']) ."
"; $added_count = 0; foreach ($results['report']['ads'] as $offer) { //if (isset($offer['avito_id']) && isset($offer['ad_id'])) { //if ($offer['statuses']['avito']) { $ads_id = intval($offer['avito_id']); $obj_id = intval($offer['ad_id']); //if (array_key_exists($obj_id, array_keys($obj_ids))) { // только существующие и рекламируемые объекты JW if (!array_key_exists($obj_id, $ads)) { $ads[$obj_id] = array_merge($offer, ['object_id' => $obj_id]); $adsIds[] = $ads_id; $objs[$ads_id] = $obj_id; $added_count++; if (!$is_manual) echo "
 - получен ИД объекта № " . $obj_id . ", ИД объвления на Авито: " . $ads_id . "
"; } if (!isset($offer['avito_id']) && !$is_manual) echo "
- для объекта $obj_id не присвоен ИД объвления на авито
"; if (!isset($offer['ad_id']) && !$is_manual) echo "
- не присвоен ИД объекта для объявления $ads_id на авито
"; //} //} //} } $report_status = true; if (!$is_manual) echo "
 По рапорту № " . $reportId . " обработано всего ИД объвлений: ". $added_count ."
"; } } catch (\Exception $exception) { $this->logs[date('Y-m-d H:i:s')][] = $exception; } } if (!$is_manual) echo "
Статус обработки рапорта №: " . $reportId . " - завершено ". ($report_status) ? 'успешно' : 'с ошибкой' ."
"; sleep(5); $report_num++; if ($report_num > 5) // (!) обрабатывает только 3 последних рапорта break; } $not_stored_obj = array_diff(array_keys($obj_ids), array_values($objs)); if ($this->debug) $this->logs[date('Y-m-d H:i:s')][] = "Объекты, по которым не удалось получить статистику: " . implode(', ', $not_stored_obj); if (!$is_manual) { echo "
Всего объявлений получено: " . count($ads) . "
"; echo "
Объявления: " . var_export($ads, true) . "
"; echo "
Объекты, по которым не удалось получить статистику: " . implode(', ', $not_stored_obj) . "
"; } $adsIds = array_filter($adsIds, function($value) { return ($value !== null && $value !== false && $value !== 0); }); if (count($ads) > 0 && count($adsIds) > 0) { if (is_null($offset) || !is_numeric($offset)) $offset = 0; if (!$is_manual) echo "
Собираем статистику для объявлений:  " .var_export($adsIds, true). "
"; $itemsIds = array_slice($adsIds, $offset, 200); if (count($itemsIds)) { $_offset = 0; $_total = count($ads); if ($_total > $_offset && $offset !== $_offset) { $_offset += 200; $offset = $_offset; } else { $offset = null; } $this->logs["count(itemsIds)"][] = count($itemsIds); $this->logs["itemsIds"][] = $itemsIds; $this->logs["total"][] = $_total; $this->logs["offset"][] = $offset; if ($this->debug) $this->logs["avito->total"][] = $_total; if ($this->debug) $this->logs["avito->offset"][] = $offset; if (!$is_manual) { echo "
total " . $_total . "
"; echo "
offset " . $offset . "
"; } // обработка ошибок и сбор мета-данных по каждому объявлению foreach ($ads as $offer) { $obj_id = $offer['object_id']; if (count($offer['messages']) > 0) { foreach ($offer['messages'] as $message) { //if ($message['type'] == 'error' || $message['type'] == 'warning') { if ($message['type'] == 'error') { if (!is_null($message['description'])) { $reports[$obj_id]['errors'][] = $message['description']; } if (!$is_manual) echo "
 - ошибка размещения у объекта $obj_id: " .$message['description']. "
"; } } // Запись в сфинкс флага об ошибке размещения try { if (!is_null($this->_db_sphinx)) { if (count($reports[$obj_id]['errors']) > 0) $this->_db_sphinx->query("UPDATE objects SET ads_error = 1 WHERE id = $obj_id"); else $this->_db_sphinx->query("UPDATE objects SET ads_error = 0 WHERE id = $obj_id"); } } catch (\Exception $exception) { $this->errors[] = $exception; } } if ($offer['statuses']['general']['value'] == 'success' || $offer['statuses']['avito']['value'] == 'active') $reports[$obj_id]['success'] = true; else $reports[$obj_id]['success'] = false; if (isset($offer['url'])) $reports[$obj_id]['url'] = $offer['url']; else $reports[$obj_id]['url'] = null; } // Запрос и сбор статистики по просмотрам $url = "https://api.avito.ru/stats/v1/accounts/$ext_user_id/items"; $options = [ 'auth' => 'bearer', 'token' => $this->_getAuthToken('avito', $client_id, $secret_key), 'method' => 'post', 'type' => 'json', 'data' => [ 'dateFrom' => $date_from, 'dateTo' => $date_to, 'fields' => [ 'uniqViews', 'uniqContacts', 'uniqFavorites' ], 'itemIds' => array_values($itemsIds) ] ]; if (!$is_manual) echo "
Собираем статистику лишь для объявлений:  " .var_export($itemsIds, true). "
"; $response = $this->_request($url, $options); if ($this->debug) $this->logs["https://api.avito.ru/stats/v1/accounts/$ext_user_id/items"] = $response; if (!$is_manual) echo "
response " .var_export($response, true). "
"; try { if ($results = json_decode($response, true)) { if (isset($results['result']['items'])) { foreach ($results['result']['items'] as $item) { //$this->logs[date('Y-m-d H:i:s')][] = $results['result']['items']; $ad_id = $item['itemId']; if ($obj_id = $objs[$ad_id]) { foreach ($item['stats'] as $stats) { $reports[$obj_id]['views'] += intval($stats['uniqViews']); $reports[$obj_id]['contacts'] += intval($stats['uniqContacts']); $reports[$obj_id]['favorites'] += intval($stats['uniqFavorites']); } } } } } else { $this->logs[date('Y-m-d H:i:s')][] = "Ошибка разбора ответа от API Авито."; } } catch (\Exception $exception) { $this->logs[date('Y-m-d H:i:s')][] = $exception; } sleep(5); // запрос и сбор статистики по звонкам $url = "https://api.avito.ru/core/v1/accounts/$ext_user_id/calls/stats/"; $options = [ 'auth' => 'bearer', 'token' => $this->_getAuthToken('avito', $client_id, $secret_key), 'method' => 'post', 'type' => 'json', 'data' => [ 'dateFrom' => $date_from, 'dateTo' => $date_to, 'itemIds' => array_values($itemsIds) ] ]; $response = $this->_request($url, $options); if ($this->debug) $this->logs["https://api.avito.ru/core/v1/accounts/$ext_user_id/calls/stats/"] = $response; try { if ($results = json_decode($response, true)) { if (isset($results['result']['items'])) { $this->logs = []; foreach ($results['result']['items'] as $item) { //$this->logs[date('Y-m-d H:i:s')][] = $results['result']['items']; $ad_id = $item['itemId']; if ($obj_id = $objs[$ad_id]) { foreach ($item['days'] as $stats) { $reports[$obj_id]['calls'] += intval($stats['calls']); } } } $this->logs[date('Y-m-d H:i:s')][] = $ads; } } else { $this->logs[date('Y-m-d H:i:s')][] = "Ошибка разбора ответа от API Авито."; } } catch (\Exception $exception) { $this->logs[date('Y-m-d H:i:s')][] = $exception; } if (!$is_manual) echo "
reports " .var_export($reports, true). "
"; if (!is_null($object_id) && in_array($object_id, $objs)) { $output = $reports[$object_id]; } sleep(5); } } /*if (count($not_stored_obj) > 0) { }*/ } break; case 'cian' : $url = "https://public-api.cian.ru/v1/get-order"; $options = [ 'auth' => 'bearer', 'token' => $this->_getAuthToken('cian', null, $secret_key), 'type' => 'json' ]; if ($response = $this->_request($url, $options)) $this->logs[] = "Успешное обращение к серверу API ЦИАН."; else $this->logs[] = "Произошла ошибка обращения к серверу API ЦИАН."; if ($this->debug) $this->logs["https://public-api.cian.ru/v1/get-order"] = $response; $results = null; try { $results = json_decode($response, true); } catch (\Exception $exception) { $this->logs[] = $exception; } if (is_array($results)) { $stored_ids = []; foreach ($results['result']['offers'] as $offer) { $ad_id = $offer['offerId']; $offer_id = $offer['offerId']; $url = "https://public-api.cian.ru/v1/get-views-statistics-by-days?offerId=$ad_id&dateFrom=$date_from&dateTo=$date_to"; $options = [ 'auth' => 'bearer', 'token' => $this->_getAuthToken('cian', null, $secret_key), 'type' => 'json' ]; $response = $this->_request($url, $options); if ($this->debug) $this->logs["https://public-api.cian.ru/v1/get-views-statistics-by-days?offerId=$ad_id&dateFrom=$date_from&dateTo=$date_to"] = $response; try { $results2 = json_decode($response, true); $report = []; $report['errors'] = []; if (isset($offer['result']['message'])) { $report['errors'] = [$offer['result']['message']]; } if (count($offer['errors']) > 0) $report['errors'] = array_merge($report['errors'], $offer['errors']); //if (count($offer['warnings']) > 0) // $report['errors'] = array_merge($report['errors'], $offer['warnings']); if ($offer['status'] == "Published") { $report['success'] = true; } else { switch ($offer['status']) { case "Blocked" : $report['errors'][] = "Объявление снято с публикации по причине применения санкции."; break; case "Deactivated" : $report['errors'][] = "Объявление было деактивировано (было скрыто)."; break; case "Deleted" : $report['errors'][] = "Объявление было удалёно."; break; case "Draft" : $report['errors'][] = "Объявление является черновиком."; break; case "Moderate" : $report['errors'][] = "Объявление требует модерации."; break; case "Refused" : $report['errors'][] = "Объявление было отклонено модератором."; break; case "RemovedByModerator" : $report['errors'][] = "Объявление было удалено модератором."; break; case "Sold" : $report['errors'][] = "Объявление не активно (объект продан/сдан)."; break; } $report['success'] = false; } if (isset($offer['url'])) $report['url'] = $offer['url']; else $report['url'] = null; if (isset($results2['result']['viewsByDays'])) { foreach ($results2['result']['viewsByDays'] as $stats) { if (isset($stats['views'])) $report['views'] += intval($stats['views']); } } else { $this->logs[] = "Ошибка разбора ответа от API ЦИАН."; } $report['calls'] = null; $report['favorites'] = null; if (isset($results2['result']['phoneShowsByDays'])) { foreach ($results2['result']['phoneShowsByDays'] as $stats) { if (isset($stats['phoneShows'])) $report['contacts'] += intval($stats['phoneShows']); } } else { $this->logs[] = "Ошибка разбора ответа от API ЦИАН."; } $ad_id = $offer['externalId']; $stored_ids[$offer_id] = $ad_id; $reports[$ad_id] = $report; // Запись в сфинкс флага об ошибке размещения try { if (!is_null($this->_db_sphinx)) { if (count($reports[$ad_id]['errors']) > 0) $this->_db_sphinx->query("UPDATE objects SET ads_error = 1 WHERE id = $ad_id"); else $this->_db_sphinx->query("UPDATE objects SET ads_error = 0 WHERE id = $ad_id"); } } catch (\Exception $exception) { $this->errors[] = $exception; } if (!is_null($object_id) && $object_id == $ad_id) { $output = $reports[$ad_id]; } } catch (\Exception $exception) { $this->logs[] = $exception; } } //... $part = 0; $limit = 0; $ads_query = []; $ads_ids_query = ''; foreach ($results['result']['offers'] as $offer) { if (!empty($ads_ids_query)) $ads_ids_query .= "&offersIds=" . $offer['offerId']; else $ads_ids_query .= "?offersIds=" . $offer['offerId']; $ads_query[$part] = "https://public-api.cian.ru/v1/get-views-statistics" . $ads_ids_query; if ($limit > 9) { $ads_ids_query = ''; $limit = 0; $part++; } else { $limit++; } } if (isset($_GET['dev'])) { var_export($ads_query); } if (!empty($ads_query)) { foreach ($ads_query as $url) { $options = [ 'auth' => 'bearer', 'token' => $this->_getAuthToken('cian', null, $secret_key), 'type' => 'json' ]; $response = $this->_request($url, $options); if ($this->debug) $this->logs[$url] = $response; try { $offer = json_decode($response, true); if (isset($offer['result']['statistics'])) { $add_report = []; $add_report['contacts'] = null; $add_report['views'] = null; $statistics = $offer['result']['statistics']; foreach ($statistics as $offer_stats) { if (isset($_GET['dev'])) { var_export($offer_stats); } $add_report['contacts'] = intval($offer_stats['phoneShows']); $add_report['views'] = intval($offer_stats['totalViews']); $offer_id = $offer_stats['offerId']; $ad_id = $stored_ids[$offer_id]; if (isset($_GET['dev'])) { var_export($reports[$ad_id]); var_export($add_report); } //if (isset($reports[$ad_id])) { $reports[$ad_id] = array_merge($reports[$ad_id], [ 'contacts' => !is_null($add_report['contacts']) ? $add_report['contacts'] : $reports[$ad_id]['contacts'], 'views' => !is_null($add_report['views']) ? $add_report['views'] : $reports[$ad_id]['views'] ]); if (!is_null($object_id) && $object_id == $ad_id) { $output = $reports[$ad_id]; } //} } } } catch (\Exception $exception) { $this->logs[] = $exception; } sleep(2); } } } break; case 'yandex' : $url = "https://api.realty.yandex.net/2.0/crm/feeds"; $options = [ 'auth' => 'oauth', 'token' => $this->_getAuthToken('yandex', null, $secret_key), 'method' => 'get', 'type' => 'json', 'headers' => [ 'X-Authorization: Vertis crm-dff153a8ef1a90d3bff5ee378dee416606cf8915' ], ]; if ($response = $this->_request($url, $options)) $this->logs[] = "Успешное обращение к серверу API Яндекс.Недвижимость."; else $this->logs[] = "Произошла ошибка обращения к серверу API Яндекс.Недвижимость."; if ($this->debug) $this->logs["https://api.realty.yandex.net/2.0/crm/feeds"] = $response; $results = null; try { $results = json_decode($response, true); } catch (\Exception $exception) { $this->logs[] = $exception; } if (is_array($results)) { if (isset($results['feeds'])) { $feed_uid = null; foreach ($results['feeds'] as $feed) { if ($feed['url'] == "https://joywork.ru/bn_ya_feeds/$agency_id.xml") { if ($feed['status'] == "ACCEPTED" || $feed['status'] == "ACCEPTED_WITH_REMARKS") $feed_uid = $feed['id']; /*if ($feed['status'] == "ACCEPTED_WITH_REMARKS") $reports['errors'] = ["XML-фид содержащий объект обработан с замечаниями публикации."];*/ } } if (!is_null($feed_uid)) { if ($offset) $url = "https://api.realty.yandex.net/2.0/crm/offers?offset=".$offset; else $url = "https://api.realty.yandex.net/2.0/crm/offers"; $options = [ 'auth' => 'oauth', 'token' => $this->_getAuthToken('yandex', null, $secret_key), 'method' => 'get', 'type' => 'json', 'headers' => [ 'X-Authorization: Vertis crm-dff153a8ef1a90d3bff5ee378dee416606cf8915' ], ]; $response = $this->_request($url, $options); if ($this->debug) $this->logs["https://api.realty.yandex.net/2.0/crm/offers"] = $response; try { $results2 = json_decode($response, true); $_offset = 0; $_total = $results2['listing']['slicing']['total']; if (isset($results2['listing']['slicing']['range']['to'])) $_offset = intval($results2['listing']['slicing']['range']['to']); elseif (isset($results2['listing']['slicing']['fragment']['offset'])) $_offset = intval($results2['listing']['slicing']['fragment']['offset']) + 100; if ($_total > $_offset && $offset !== $_offset) $offset = $_offset; else $offset = null; if ($this->debug) $this->logs["yandex->offset"][] = $offset; $this->logs['yandex->offers'] = $results2; if (isset($results2['listing']['snippets'])) { foreach ($results2['listing']['snippets'] as $value) { $offer = $value['offer']; if ($feed_uid == $offer['feedId']) { $report = []; $ad_id = $offer['id']; $url = "https://api.realty.yandex.net/2.0/crm/offer/$ad_id/stats?startTime=$date_from&endTime=$date_to"; $options = [ 'auth' => 'oauth', 'token' => $this->_getAuthToken('yandex', null, $secret_key), 'method' => 'get', 'type' => 'json', 'headers' => [ 'X-Authorization: Vertis crm-dff153a8ef1a90d3bff5ee378dee416606cf8915' ], ]; $response = $this->_request($url, $options); if ($this->debug) $this->logs["https://api.realty.yandex.net/2.0/crm/offer/$ad_id/stats?startTime=$date_from&endTime=$date_to"] = $response; try { $report['success'] = (empty($offer['state'])) ? true : false; /*if (count($offer['state']['errors']) > 0) $report['errors'] = array_merge($reports['errors'], $offer['state']['errors']['type']);*/ if (count($offer['state']['errors']) > 0) { foreach ($offer['state']['errors'] as $error) { switch ($error['type']) { case 'AD_ON_PHOTO' : $report['errors'][] = "На фотографиях размещена рекламная информация."; break; case 'AGENT_PHONE_NOT_SET' : $report['errors'][] = "Телефон агента или продавца не указан или указан в неправильном формате."; break; case 'BAD_PHOTO' : $report['errors'][] = "В объявлении используются неинформативные фотографии."; break; case 'BAN_OFFERS_WITHOUT_CADASTRAL_NUMBER' : $report['errors'][] = "Пропущено обязательное поле."; break; case 'BANNED_AGENCY' : $report['errors'][] = "Объявления этого агентства имеют низкий уровень достоверности."; break; case 'CHECK_ALREADY_BOOKED' : $report['errors'][] = "При проверке выяснилось, что объект находится под залогом."; break; case 'CHECK_INCORRECT_WATERMARK' : $report['errors'][] = "В объявлении используются фотографии, на которых есть посторонние изображения."; break; case 'CHECK_OFFER_IS_AD' : $report['errors'][] = "Проверка модератором: объявление носит рекламный характер."; break; case 'CHECK_OFFER_SOLD_OUT' : $report['errors'][] = "Проверка модератором: объект из объявления продан."; break; case 'CHECK_STOPWORD' : $report['errors'][] = "В описании объявления или в имени автора используются нецензурные выражения или реклама."; break; case 'CHECK_UNAVAILABLE' : $report['errors'][] = "До продавца невозможно дозвониться."; break; case 'CHECK_UNKNOWN_OBJECT' : $report['errors'][] = "Контактное лицо, указанное в объявлении, не владеет информацией об объекте."; break; case 'CHECK_UNKNOWN_REASON' : $report['errors'][] = "Объявление заблокировано по жалобе пользователя."; break; case 'CHECK_WRONG_ADDRESS' : $report['errors'][] = "Проверка модератором: указан неверный адрес объекта."; break; case 'CHECK_WRONG_DATA' : $report['errors'][] = "Проверка модератором: несоответствие параметров в объявлении."; break; case 'CHECK_WRONG_PHOTO' : $report['errors'][] = "Объявление содержит фотографии низкого качества или фотографии, не относящиеся к объекту."; break; case 'CHECK_WRONG_PRICE' : $report['errors'][] = "Проверка модератором: в объявлении указана неверная цена."; break; case 'CLONE' : $report['errors'][] = "У вас уже есть такое объявление."; break; case 'COORDINATES_NOT_FOUND' : $report['errors'][] = "Географические координаты объекта вычислены неправильно."; break; case 'COMMERCIAL_IN_LIVING' : $report['errors'][] = "Тип объекта не соответствует разделу сервиса."; break; case 'COMPLAINT_FROM_OWNER' : $report['errors'][] = "Информация о собственнике скрыта или объявление размещено без согласия собственника."; break; case 'CONTACT_IN_DESCRIPTION' : $report['errors'][] = "Контакты в описании."; break; case 'CREATION_DATE_NOT_SET' : $report['errors'][] = "Дата создания объявления не указана или указана в неподходящем формате."; break; case 'DAMAGED_PHOTO' : $report['errors'][] = "В объявлении используются маленькие фотографии или фотографии низкого качества."; break; case 'HOTEL' : $report['errors'][] = "Яндекс.Недвижимость не размещает объявления об аренде номеров в гостиницах и хостелах."; break; case 'HOUSE_IN_APARTMENT' : $report['errors'][] = "Тип объекта не соответствует разделу сервиса."; break; case 'HOUSE_IN_LOT' : $report['errors'][] = "Тип объекта не соответствует разделу сервиса."; break; case 'ILLEGAL_SELL_FOR_LEGAL_ADDRESS' : $report['errors'][] = "В объявлении о продаже коммерческого объекта указана категория «legal address» (юридический адрес)."; break; case 'INACTIVE_CAMPAIGN' : $report['errors'][] = "Рекламная кампания неактивна."; break; case 'INTERNAL_ID_NOT_SET' : $report['errors'][] = "Не указан идентификатор объявления."; break; case 'INVALID_COMMERCIAL_TYPES' : $report['errors'][] = "Не указана категория коммерческого объекта."; break; case 'INVALID_COMMISSION' : $report['errors'][] = "Неправильно указан размер комиссии."; break; case 'INVALID_ELECTRIC_CAPACITY' : $report['errors'][] = "Неправильно указана выделенная электрическая мощность."; break; case 'INVALID_FULL_OPTION_SALE' : $report['errors'][] = "Нельзя размещать переуступку на минимальном тарифе."; break; case 'INVALID_GARAGE_TYPE' : $report['errors'][] = "Не указан тип гаража."; break; case 'INVALID_PALLET_PRICE' : $report['errors'][] = "Неправильно указана стоимость палето-места."; break; case 'INVALID_PARKING_GUEST_PLACES' : $report['errors'][] = "Неправильно указано количество гостевых парковочных мест."; break; case 'INVALID_PARKING_PLACE_PRICE' : $report['errors'][] = "Неправильно указана стоимость парковочного места."; break; case 'INVALID_PARKING_PLACES' : $report['errors'][] = "Неправильно указано количество предоставляемых парковочных мест."; break; case 'INVALID_PHONE_LINES' : $report['errors'][] = "Неправильно указано количество телефонных линий."; break; case 'INVALID_PRICE' : $report['errors'][] = "Недостоверная цена."; break; case 'INVALID_PRIMARY_SALE' : $report['errors'][] = "Объявления «от застройщика» могут быть размещены только авторизованными партнерами."; break; case 'INVALID_SECURITY_PAYMENT' : $report['errors'][] = "Неправильно указан размер обеспечительного платежа."; break; case 'INVALID_USE_OF_OPEN_PLAN' : $report['errors'][] = "Значение «свободная планировка» используется только для объявлений о продаже квартир и коммерческой недвижимости."; break; case 'INVALID_USE_OF_STUDIO' : $report['errors'][] = "Значение «студия» используется только для объявлений о продаже квартир."; break; case 'LIVING_SPACE_IS_TOO_HIGH' : $report['errors'][] = "Неправильно указана жилая площадь."; break; case 'LOCATION_NOT_FOUND' : $report['errors'][] = "Неизвестно местоположение объекта."; break; case 'LOT_AREA_NOT_SET' : $report['errors'][] = "Не указана площадь участка."; break; case 'LOT_HAS_AREA_AND_LOT_AREA' : $report['errors'][] = "В объявлении о продаже участка без дома площадь участка передана в теге area."; break; case 'LOT_RENT' : $report['errors'][] = "Яндекс.Недвижимость не размещает объявления об аренде участков."; break; case 'LOW_ACTUALITY' : $report['errors'][] = "Объявление не соответствуют требованиям Яндекс.Недвижимости."; break; case 'NEW_IN_OLD' : $report['errors'][] = "Тип объекта не соответствует разделу сервиса."; break; case 'NO_IMAGES' : $report['errors'][] = "Отсутствуют фотографии объекта."; break; case 'NO_INFO' : $report['errors'][] = "Объект закрыт для просмотра или не существует."; break; case 'NO_PLACEMENT' : $report['errors'][] = "Необходимо оплатить размещение объявлений."; break; case 'NO_PLAN_PHOTO' : $report['errors'][] = "В объявлении о продаже квартиры в новостройке нет изображения планировки."; break; case 'NO_ROOMS_IN_APARTMENT' : $report['errors'][] = "Не указано количество комнат в квартире."; break; case 'NO_ROOMS_OFFERED_FOR_ROOMS' : $report['errors'][] = "В объявлении о продаже или аренде комнат не указано количество комнат, участвующих в сделке, и общее количество комнат."; break; case 'NO_SHOW' : $report['errors'][] = "Объект закрыт для просмотра."; break; case 'NOT_REALTY' : $report['errors'][] = "Объявление содержит информацию о продаже товаров или услуг."; break; case 'OFFER_TOO_OLD' : $report['errors'][] = "Слишком старое объявление."; break; case 'OLD_PHOTO' : $report['errors'][] = "В объявлении используются старые фотографии."; break; case 'PARTIALLY_ADDRESS' : $report['errors'][] = "Неполный адрес или неточная метка на карте."; break; case 'PEOPLE_ON_PHOTO' : $report['errors'][] = "На снимках есть люди или посторонние предметы."; break; case 'PHONE_NOT_EXIST' : $report['errors'][] = "Указан неверный или недействительный телефон."; break; case 'PHONE_UNAVAILABLE' : $report['errors'][] = "Указан неверный или недействительный телефон."; break; case 'PHOTO_STEAL' : $report['errors'][] = "Недостоверные или чужие фотографии."; break; case 'REGISTRATION' : $report['errors'][] = "Объявление содержит информацию об услугах."; break; case 'RENT_IN_SELL' : $report['errors'][] = "Тип сделки не соответствует разделу сервиса."; break; case 'PRICE_ERROR' : $report['errors'][] = "Недостоверная цена."; break; case 'PRICE_NOT_SET' : $report['errors'][] = "Не указана цена объекта."; break; case 'PRICE_PERIOD_NOT_SET_FOR_RENT' : $report['errors'][] = "Срок аренды указан в неподходящем формате."; break; case 'PRICE_PERIOD_SET_FOR_SELL' : $report['errors'][] = "В объявлении о продаже объекта указан период для расчета стоимости аренды."; break; case 'PRICE_PERIOD_UNKNOWN' : $report['errors'][] = "Неправильно указан период для расчета стоимости аренды."; break; case 'PRICE_UNIT_UNKNOWN' : $report['errors'][] = "Неизвестная единица измерения площади."; break; case 'ROOM_IN_APARTMENT' : $report['errors'][] = "Тип объекта не соответствует разделу сервиса."; break; case 'ROOMS_OFFERED_GREATER_OR_EQUAL_THAN_ROOMS' : $report['errors'][] = "Количество комнат в квартире, предлагаемых для аренды или покупки, превышает общее количество комнат в квартире."; break; case 'ROOMS_SPACE_NOT_MATCH_ROOMS_COUNT' : $report['errors'][] = "Количество переданных значений площади комнат не соответствует количеству комнат."; break; case 'SERVICE_SUGGEST' : $report['errors'][] = "В объявлении предлагаются услуги или другие объекты."; break; case 'SITE_OFFER_BASE_FIELD_NOT_SET' : $report['errors'][] = "Отсутствуют поля, обязательные для новостроек."; break; case 'STRANGE_DISTANCE_FOR_MANUAL_POINT' : $report['errors'][] = "Указанные координаты не соответствуют действительности."; break; case 'SUSPICIOUS_OFFER_AGE' : $report['errors'][] = "Объявление не соответствует требованиям к срокам размещения."; break; case 'TEXT_IN_PHOTO' : $report['errors'][] = "В объявлении используются фотографии, на которых есть посторонние изображения."; break; case 'TOO_BIG_LOT_AREA' : $report['errors'][] = "Объекты площадью более 1 гектара считаются участками коммерческого назначения."; break; case 'UNKNOWN_CATEGORY' : $report['errors'][] = "Неправильно указаны категория объекта или тип продавца (арендодателя)."; break; case 'UNKNOWN_LOCATION_TYPE' : $report['errors'][] = "Недостаточно информации для определения точного местоположения объекта."; break; case 'UNKNOWN_NEWBUILDING' : $report['errors'][] = "Объявление об объекте в неизвестной новостройке."; break; case 'UNKNOWN_TYPE' : $report['errors'][] = "Неправильно указан тип сделки."; break; case 'URL_NOT_SET' : $report['errors'][] = "Не указана ссылка на объявление."; break; case 'VILLAGE_NON_TARGET_SALE' : $report['errors'][] = "В этом посёлке нельзя размещать вторичку."; break; case 'WRONG_AREA' : $report['errors'][] = "Неверно указана площадь объекта."; break; case 'WRONG_CADASTRAL' : $report['errors'][] = "Неверный или недействительный кадастровый номер."; break; case 'WRONG_FLOOR' : $report['errors'][] = "Неверно указан этаж или количество этажей в здании."; break; case 'WRONG_LOT_AREA' : $report['errors'][] = "Неверно указана площадь участка."; break; case 'WRONG_NAME' : $report['errors'][] = "Имя продавца указано некорректно."; break; case 'WRONG_PIN' : $report['errors'][] = "Неполный адрес или неточная метка на карте."; break; case 'WRONG_PRICE_PERIOD' : $report['errors'][] = "Цена не соответствует периоду аренды."; break; case 'WRONG_ROOMS' : $report['errors'][] = "Неверно указано число комнат."; break; } } } if (isset($offer['url'])) $report['url'] = $offer['url']; else $report['url'] = null; $results3 = json_decode($response, true); if (isset($results3['stats']['daily'])) { foreach ($results3['stats']['daily'] as $stats) { $report['views'] += intval($stats['cardShows']); $report['contacts'] += intval($stats['phoneShows']); $report['favorites'] = null; $report['calls'] += intval($stats['calls']); } } else { $this->logs[] = "Ошибка разбора ответа от API Яндекс.Недвижимость."; } $ad_id = $offer['internalId']; $reports[$ad_id] = $report; // Запись в сфинкс флага об ошибке размещения try { if (!is_null($this->_db_sphinx)) { if (count($reports[$ad_id]['errors']) > 0) $this->_db_sphinx->query("UPDATE objects SET ads_error = 1 WHERE id = $ad_id"); else $this->_db_sphinx->query("UPDATE objects SET ads_error = 0 WHERE id = $ad_id"); } } catch (\Exception $exception) { $this->errors[] = $exception; } if (!is_null($object_id) && $object_id == $ad_id) { $output = $reports[$ad_id]; } } catch (\Exception $exception) { $this->logs[] = $exception; } } } } else { $this->logs[] = "Ошибка разбора ответа от API Яндекс.Недвижимость."; } } catch (\Exception $exception) { $this->logs[] = $exception; } } else { $this->logs[] = "Не найден принятый и обработанный фид в Яндекс.Недвижимость."; } } else { $this->logs[] = "Ошибка разбора ответа от API Яндекс.Недвижимость."; } } break; case 'domclick' : $url = "https://my.domclick.ru/api/v1/company/$client_id/report"; $options = [ 'auth' => 'token', 'token' => $this->_getAuthToken('domclick', $client_id, $secret_key), 'method' => 'get', 'type' => 'xml', ]; if ($response = $this->_request($url, $options)) $this->logs[] = "Успешное обращение к серверу API Домклик."; else $this->logs[] = "Произошла ошибка обращения к серверу API Домклик."; if ($this->debug) $this->logs["https://my.domclick.ru/api/v1/company/$client_id/report"] = $response; $results = null; try { $xml = simplexml_load_string($response, null, LIBXML_NOCDATA); $results = json_decode(json_encode((array)$xml), true); $results = array($xml->getName() => $results); } catch (\Exception $exception) { $this->logs[] = $exception; } if (is_array($results)) { if ($results['Report']['OfferList']['Offer']) { foreach ($results['Report']['OfferList']['Offer'] as $offer) { if ($offer['@attributes']['source'] == 'feed' && isset($offer['ExternalId'])) { $report = []; $ad_id = null; $ads_url = $offer['Publication']['DomclickURL']; $report['url'] = $ads_url; $report['success'] = (!empty($ads_url)) ? true : false; if (preg_match("/\_\_(\d+)+$/", $ads_url, $matches)) { $ad_id = $matches[1]; if (!is_null($ad_id)) { $report['views'] += intval($offer['Publication']['ViewsCount']); $report['contacts'] = null; $report['favorites'] = null; $report['calls'] += intval($offer['Publication']['CallsCount']); } } $ad_id = $offer['ExternalId']; $reports[$ad_id] = $report; // Запись в сфинкс флага об ошибке размещения try { if (!is_null($this->_db_sphinx)) { if (count($reports[$ad_id]['errors']) > 0) $this->_db_sphinx->query("UPDATE objects SET ads_error = 1 WHERE id = $ad_id"); else $this->_db_sphinx->query("UPDATE objects SET ads_error = 0 WHERE id = $ad_id"); } } catch (\Exception $exception) { $this->errors[] = $exception; } if (!is_null($object_id) && $object_id == $ad_id) { $output = $reports[$ad_id]; } } } } } break; } $this->logs['save_report_status'] = $this->saveReports($service_id, $agency_id, $reports, $is_manual); if (!$is_manual) echo "
 Отчёт о сохранении статистики: " . var_export($this->logs['save_report_status'], true) ."
"; if ($offset) { return $this->getStats($service_id, $period, $client_id, $secret_key, $ext_user_id, $object_id, $is_manual, $agency_id, $offset); } else { if (!is_null($object_id)) { if (!$is_manual) echo "
 Результат выборки статистики: " . var_export($output, true) ."
"; return $output; } else { if (!$is_manual) echo "
 Результат выборки статистики: " . var_export($reports, true) ."
"; return $reports; } } } public function getReports($service_id = null, $agency_id = null, $object_id = null) { $processed_at = date('Y-m-d H:i:s', strtotime('-1 hours')); $sql = "SELECT * FROM `ads_stats` WHERE `object_id` = '$object_id' AND `agency_id` = '$agency_id'"; if (!is_null($service_id)) { $sql .= " AND `service_id` = '$service_id' LIMIT 1"; } $sql .= " ORDER BY `processed_at` DESC"; if ($query = mysql_query($sql)) { if (mysql_num_rows($query) > 0) { $reports = []; while ($row = mysql_fetch_assoc($query)) { $service_id = intval($row['service_id']); if ($serviceName = $this->getServiceName($service_id)) { $report = [ 'views' => (!is_null($row['views'])) ? intval($row['views']) : '-', 'contacts' => (!is_null($row['contacts'])) ? intval($row['contacts']) : '-', 'favorites' => (!is_null($row['favorites'])) ? intval($row['favorites']) : '-', 'calls' => (!is_null($row['calls'])) ? intval($row['calls']) : '-', 'url' => strval($row['url']), 'errors' => array_unique(json_decode($row['errors'])), ]; if (!isset($reports[$serviceName])) $reports[$serviceName] = $report; else continue; } } return $reports; } } return null; } public function saveReports($service_id = null, $agency_id = null, $reports = [], $is_manual = false) { if (is_null($service_id) || $service_id == 0) return false; if (is_null($agency_id) || $agency_id == 0) return false; if (count($reports) > 0) { $is_manual = ($is_manual) ? '1' : '0'; $processed_at = date('Y-m-d H:i:s'); $sql = "DELETE FROM `ads_stats` WHERE `service_id` = '$service_id' AND (`agency_id` = '$agency_id' OR `agency_id` = 0)"; $sql2 = "INSERT INTO `ads_stats` ( `object_id`, `service_id`, `views`, `contacts`, `favorites`, `calls`, `url`, `errors`, `is_error`, `is_manual`, `agency_id`, `status`, `processed_at` ) VALUES "; $ids = []; $values = []; foreach ($reports as $object_id => $report) { $errors = json_encode($report['errors'], JSON_UNESCAPED_UNICODE); if ($errors == "[]" || $errors == "null") $errors = null; $views = 'NULL'; if (!is_null($report['views'])) $views = $report['views']; $contacts = 'NULL'; if (!is_null($report['contacts'])) $contacts = $report['contacts']; $favorites = 'NULL'; if (!is_null($report['favorites'])) $favorites = $report['favorites']; $calls = 'NULL'; if (!is_null($report['calls'])) $calls = $report['calls']; $url = 'NULL'; if (!is_null($report['url'])) $url = "'$report[url]'"; if (is_null($errors)) $errors = 'NULL'; else $errors = "'".addslashes($errors)."'"; $is_error = (count($report['errors']) > 0) ? '1' : '0'; $status = ($report['success']) ? '1' : '0'; $values[] = "( '$object_id', '$service_id', $views, $contacts, $favorites, $calls, $url, $errors, '$is_error', '$is_manual', '$agency_id', '$status', '$processed_at' )"; $ids[] = $object_id; } $sql .= " AND `object_id` IN (" . implode(', ', $ids) . ")"; $sql2 .= implode(', ', $values); if (((count($ids) > 0) ? mysql_query($sql) : true) && mysql_query($sql2)) return ['success' => true, 'query' => [ 'sql' => ((count($ids) > 0) ? $sql : null), 'sql2' => $sql2, ], 'object_ids' => $ids, 'processed' => count($ids) ]; else return ['success' => false, 'query' => [ 'sql' => ((count($ids) > 0) ? $sql : null), 'sql2' => $sql2, ], 'object_ids' => $ids, 'processed' => count($ids), 'errors' => mysql_error() ]; } return false; } public function getApiSettings($agency_id = null, $only_active = true) { $settings = []; if (is_null($agency_id)) $agency_id = User::getUserAgencyID(); $sql = "SELECT * FROM `users_api` AS `api` WHERE `api`.`agency_id` = '$agency_id'"; if ($only_active) $sql .= " AND `status` > 0"; if ($query = mysql_query($sql)) { if (mysql_num_rows($query) > 0) { while ($row = mysql_fetch_assoc($query)) { $service_id = $row['service_id']; if ($serviceName = $this->getServiceName($service_id)) { $settings[$serviceName] = [ 'service_id' => $row['service_id'], 'client_id' => $row['client_id'], 'secret_key' => $row['secret_key'], 'ext_user_id' => $row['ext_user_id'], ]; } } } } return $settings; } public function testAdvertApi($service = null, $client_id = null, $secret_key = null, $ext_user_id = null) { if (empty($service)) $service = null; if (empty($client_id)) $client_id = null; if (empty($secret_key)) $secret_key = null; if (empty($ext_user_id)) $ext_user_id = null; $this->errors = []; if (is_null($service)) $this->errors[] = 'Не указана площадка для получения статистики'; if (is_null($client_id) && (strtolower($service) == 'avito' || strtolower($service) == 'domclick')) $this->errors[] = 'Не указан `client_id` для получения статистики'; if (is_null($secret_key)) $this->errors[] = 'Не указан `secret_key` для получения статистики'; if (is_null($ext_user_id) && strtolower($service) == 'avito') $this->errors[] = 'Не указан `ext_user_id` обязательный для API Avito'; $result = false; if (is_null($service) || (is_null($client_id) && (strtolower($service) == 'avito' || strtolower($service) == 'domclick')) || is_null($secret_key)) return ['success' => $result, 'errors' => $this->errors]; $this->_session_key .= "_test"; switch (strtolower($service)) { case 'avito' : $url = "https://api.avito.ru/token/?grant_type=client_credentials&client_id=$client_id&client_secret=$secret_key"; $options = [ 'auth' => 'bearer', 'token' => $this->_getAuthToken('avito', $client_id, $secret_key), 'method' => 'post', 'type' => 'json' ]; $result = $this->_request($url, $options, true); if ($this->debug) $this->logs["https://api.avito.ru/token/?grant_type=client_credentials&client_id=$client_id&client_secret=$secret_key"] = $result; break; case 'cian' : $url = "https://public-api.cian.ru/v1/get-last-order-info"; $options = [ 'auth' => 'bearer', 'token' => $this->_getAuthToken('cian', null, $secret_key), 'type' => 'json' ]; $result = $this->_request($url, $options, true); if ($this->debug) $this->logs["https://public-api.cian.ru/v1/get-last-order-info"] = $result; break; case 'yandex' : $url = "https://api.realty.yandex.net/2.0/crm/offers"; $options = [ 'auth' => 'oauth', 'token' => $this->_getAuthToken('yandex', null, $secret_key), 'method' => 'get', 'type' => 'json', 'headers' => [ 'X-Authorization: Vertis crm-dff153a8ef1a90d3bff5ee378dee416606cf8915' ], ]; $result = $this->_request($url, $options, true); if ($this->debug) $this->logs["https://api.realty.yandex.net/2.0/crm/offers"] = $result; break; case 'domclick' : $token = $this->_getAuthToken('domclick', $client_id, $secret_key); $url = "https://public-api.domclick.ru/stats/v1/companies/$client_id/offers?token=$token&limit=10"; $options = [ 'method' => 'get', 'type' => 'json', ]; $result = $this->_request($url, $options, true); if ($this->debug) $this->logs["https://my.domclick.ru/api/v1/company/$client_id/report"] = $result; break; } return $result; } private function _getAgencies() { $ids = []; $sql = "SELECT * FROM `users` WHERE (now() <= DATE_ADD( `date_tarif`, INTERVAL ( SELECT `t`.`period` FROM `tariffs` `t` WHERE t.id = `id_tarif` LIMIT 1 ) DAY) ) AND `blocked` = 0"; $results = mysql_query($sql); while($agency = mysql_fetch_assoc($results)) { $ids[] = $agency['id']; } return array_unique($ids); } public function run($service = null, $agency_id = null) { if (is_null($service)) throw new Exception("Service must be set."); if (is_numeric($service) && !is_null($this->getServiceName($service))) $service = $this->getServiceName($service); if (!is_null($agency_id)) $agencies = [$agency_id]; else $agencies = $this->_getAgencies(); if (!is_null($service) && count($agencies)) { foreach ($agencies as $agency_id) { $settings = $this->getApiSettings($agency_id, true); if (isset($settings[$service])) { if ($_GET['dev']) var_export($settings[$service]); $period = [ 'date_from' => date('Y-m-d', strtotime("-6 month")), 'date_to' => date('Y-m-d'), ]; if ($service == 'yandex') { $period['date_from'] = date('Y-m-d', strtotime('-119 days')); } else if ($service == 'cian') { $period['date_from'] = date('Y-m-d', strtotime('-179 days')); } else if ($service == 'avito') { $period['date_from'] = date('Y-m-d', strtotime('-269 days')); } if ($_GET['dev']) var_export($period); $service_id = $settings[$service]['service_id']; $client_id = $settings[$service]['client_id']; $secret_key = $settings[$service]['secret_key']; $ext_user_id = $settings[$service]['ext_user_id']; $this->getStats($service_id, $period, $client_id, $secret_key, $ext_user_id, null, false, $agency_id); } } } } public function set_api_id($api_id){ $this->_api_id = $api_id; } public function on_message($service = null, $client_id = null, $secret_key = null, $ext_user_id = null, $api_id) { if($api_id > 0){ $this->set_api_id($api_id); } if (empty($service)) $service = null; if (empty($client_id)) $client_id = null; if (empty($secret_key)) $secret_key = null; if (empty($ext_user_id)) $ext_user_id = null; $this->errors = []; if (is_null($service)) $this->errors[] = 'Не указана площадка для получения статистики'; if (is_null($client_id) && (strtolower($service) == 'avito' || strtolower($service) == 'domclick')) $this->errors[] = 'Не указан `client_id` для получения статистики'; if (is_null($secret_key)) $this->errors[] = 'Не указан `secret_key` для получения статистики'; if (is_null($ext_user_id) && strtolower($service) == 'avito') $this->errors[] = 'Не указан `ext_user_id` обязательный для API Avito'; $result = false; if (is_null($service) || (is_null($client_id) && (strtolower($service) == 'avito' || strtolower($service) == 'domclick')) || is_null($secret_key)) return ['success' => $result, 'errors' => $this->errors]; // $this->_session_key .= "_test"; switch (strtolower($service)) { case 'avito' : $url = "https://api.avito.ru/messenger/v3/webhook"; $url_webhook = 'https://joywork.ru/webhooks/avito_mess.php?api='.$api_id; $options = [ 'auth' => 'bearer', 'token' => $this->_getAuthToken('avito', $client_id, $secret_key), 'method' => 'post', 'type' => 'json', 'data' => [ 'url' => $url_webhook, "version" => "3" ], ]; //var_dump($options); $result = json_decode($this->_request($url, $options),true); if($result['ok']){ $result['success'] = true; if(!empty($this->_agency_id)){ $sql = "UPDATE `users_api` SET `is_messages` = '1' WHERE agency_id={$this->_agency_id} AND service_id = 1"; $this->_db->query($sql); //$this->add_users_service($service, $client_id, $secret_key, $ext_user_id); } } else { return ['success' => false, 'errors' => $result['result']['message']]; } if ($this->debug) $this->logs["https://api.avito.ru/messenger/v3/webhook"] = $result; break; case 'cian' : if(!empty($this->_agency_id)){ $url_webhook = 'https://joywork.ru/webhooks/cian/'.$this->_agency_id.'/cian_mess.php'; if(!file_exists($_SERVER['DOCUMENT_ROOT']."/webhooks/cian/".$this->_agency_id."/cian_mess.php")){ if (!is_dir($_SERVER['DOCUMENT_ROOT'] . "/webhooks/cian")) { mkdir($_SERVER['DOCUMENT_ROOT'] . "/webhooks/cian"); } if (!is_dir($_SERVER['DOCUMENT_ROOT'] . "/webhooks/cian/".$this->_agency_id)) { mkdir($_SERVER['DOCUMENT_ROOT'] . "/webhooks/cian/".$this->_agency_id); } copy($_SERVER['DOCUMENT_ROOT'] ."/webhooks/cian_mess.php", $_SERVER['DOCUMENT_ROOT'] ."/webhooks/cian/".$this->_agency_id."/cian_mess.php"); } $url = "https://public-api.cian.ru/v2/subscribe-webhooks"; $options = [ 'auth' => 'bearer', 'token' => $this->_getAuthToken('cian', null, $secret_key), 'type' => 'json', 'data' => [ 'webhookTypes' => ["offersMessagesIncoming", "offersMessagesApiOutgoing", "offersMessagesLkOutgoing"], 'url' => $url_webhook, ], ]; $result = json_decode($this->_request($url, $options),true); //var_dump($result); if(isset($result['result']['errors'])){ return ['success' => false, 'errors' => $result['result']['message']]; } else { $result['success'] = true; if(!empty($this->_agency_id)){ $sql = "UPDATE `users_api` SET `is_messages` = '1' WHERE agency_id={$this->_agency_id} AND service_id = 2"; $this->_db->query($sql); } } if ($this->debug) $this->logs["https://public-api.cian.ru/v2/subscribe-webhooks"] = $result; } break; } // $result['logs'] = $this->logs; return $result; } public function off_message($service = null, $client_id = null, $secret_key = null, $ext_user_id = null, $api_id) { if($api_id > 0){ $this->set_api_id($api_id); } if (empty($service)) $service = null; if (empty($client_id)) $client_id = null; if (empty($secret_key)) $secret_key = null; if (empty($ext_user_id)) $ext_user_id = null; $this->errors = []; if (is_null($service)) $this->errors[] = 'Не указана площадка для получения статистики'; if (is_null($client_id) && (strtolower($service) == 'avito' || strtolower($service) == 'domclick')) $this->errors[] = 'Не указан `client_id` для получения статистики'; if (is_null($secret_key)) $this->errors[] = 'Не указан `secret_key` для получения статистики'; if (is_null($ext_user_id) && strtolower($service) == 'avito') $this->errors[] = 'Не указан `ext_user_id` обязательный для API Avito'; $result = false; if (is_null($service) || (is_null($client_id) && (strtolower($service) == 'avito' || strtolower($service) == 'domclick')) || is_null($secret_key)) return ['success' => $result, 'errors' => $this->errors]; // $this->_session_key .= "_test"; switch (strtolower($service)) { case 'avito' : $url = "https://api.avito.ru/messenger/v1/webhook/unsubscribe"; $options = [ 'auth' => 'bearer', 'token' => $this->_getAuthToken('avito', $client_id, $secret_key), 'method' => 'post', 'type' => 'json', 'data' => [ 'url' => 'https://joywork.ru/webhooks/avito_mess.php?api='.$api_id, "version" => "3" ], ]; $result = json_decode($this->_request($url, $options),true); if($result['ok']){ $result['success'] = true; if(!empty($this->_agency_id)){ $sql = "UPDATE `users_api` SET `is_messages` = '0' WHERE agency_id={$this->_agency_id} AND service_id = 1"; $this->_db->query($sql); //$this->add_users_service($service, $client_id, $secret_key, $ext_user_id); } } else { return ['success' => false, 'errors' => $result['result']['message']]; } if ($this->debug) $this->logs["https://api.avito.ru/messenger/v1/webhook/unsubscribe"] = $result; break; case 'cian' : if(!empty($this->_agency_id)){ $url_webhook = 'https://joywork.ru/webhooks/cian/'.$this->_agency_id.'/cian_mess.php'; $url = "https://public-api.cian.ru/v2/unsubscribe-webhooks"; $options = [ 'auth' => 'bearer', 'token' => $this->_getAuthToken('cian', null, $secret_key), 'type' => 'json', 'data' => [ 'url' => $url_webhook, 'webhookTypes' => ['offersMessages', 'systemMessages' ] ], ]; $result = json_decode($this->_request($url, $options),true); if(isset($result['result']['errors'])){ return ['success' => false, 'errors' => $result['result']['message']]; } else { $result['success'] = true; $sql = "UPDATE `users_api` SET `is_messages` = '0' WHERE agency_id={$this->_agency_id} AND service_id = 2"; $this->_db->query($sql); //$this->add_users_service($service, $client_id, $secret_key, $ext_user_id); } if ($this->debug) $this->logs["https://public-api.cian.ru/v2/unsubscribe-webhooks"] = $result; } break; } // $result['logs'] = $this->logs; return $result; } public function send_message($service = null, $client_id = null, $secret_key = null, $ext_user_id = null, $text, $chatId) { if (empty($service)) $service = null; if (empty($client_id)) $client_id = null; if (empty($secret_key)) $secret_key = null; if (empty($ext_user_id)){ $ext_user_id = null; } else { $ext_user_id = trim(str_replace(' ','',$ext_user_id)); } $this->errors = []; if (is_null($service)) $this->errors[] = 'Не указана площадка для получения статистики'; if (is_null($client_id) && (strtolower($service) == 'avito' || strtolower($service) == 'domclick')) $this->errors[] = 'Не указан `client_id` для получения статистики'; if (is_null($secret_key)) $this->errors[] = 'Не указан `secret_key` для получения статистики'; if (is_null($ext_user_id) && strtolower($service) == 'avito') $this->errors[] = 'Не указан `ext_user_id` обязательный для API Avito'; $result = false; if (is_null($service) || (is_null($client_id) && (strtolower($service) == 'avito' || strtolower($service) == 'domclick')) || is_null($secret_key)) return ['success' => $result, 'errors' => $this->errors]; // $this->_session_key .= "_test"; switch (strtolower($service)) { case 'avito' : $url = "https://api.avito.ru/messenger/v1/accounts/{$ext_user_id}/chats/{$chatId}/messages"; $options = [ 'auth' => 'bearer', 'token' => $this->_getAuthToken('avito', $client_id, $secret_key), 'method' => 'post', 'type' => 'json', 'data' => [ "message"=> [ "text"=> $text, ], "type"=> "text" ], ]; //var_dump($options); $result = json_decode($this->_request($url, $options),true); if(isset($result['created'])){ $result['created_at'] = date('d.m.Y H:i', $result['created']); } //var_dump($result); if ($this->debug) $this->logs["https://api.avito.ru/messenger/v1/accounts/{$ext_user_id}/chats/{$chatId}/messages"] = $result; break; case 'cian' : $url = "https://public-api.cian.ru/v1/send-message"; $options = [ 'auth' => 'bearer', 'token' => $this->_getAuthToken('cian', null, $secret_key), 'type' => 'json', 'data' => [ 'chatId' => $chatId, 'content' => [ 'text' => $text ], ], ]; // var_dump($options); $result = json_decode($this->_request($url, $options), true); //var_dump($result); if(isset($result['result']['errors'])){ return ['success' => false, 'errors' => $result['result']['message']]; } else { $result['success'] = true; $result['created_at'] = date('d.m.Y H:i'); } if ($this->debug) $this->logs["https://public-api.cian.ru/v1/send-message"] = $result; break; } // $result['logs'] = $this->logs; return $result; } public function get_agent($service = null, $client_id = null, $secret_key = null, $ext_user_id = null, $agent_id) { if (empty($service)) $service = null; if (empty($client_id)) $client_id = null; if (empty($secret_key)) $secret_key = null; if (empty($ext_user_id)){ $ext_user_id = null; } else { $ext_user_id = trim(str_replace(' ','',$ext_user_id)); } $this->errors = []; if (is_null($service)) $this->errors[] = 'Не указана площадка для получения статистики'; if (is_null($client_id) && (strtolower($service) == 'avito' || strtolower($service) == 'domclick')) $this->errors[] = 'Не указан `client_id` для получения статистики'; if (is_null($secret_key)) $this->errors[] = 'Не указан `secret_key` для получения статистики'; if (is_null($ext_user_id) && strtolower($service) == 'avito') $this->errors[] = 'Не указан `ext_user_id` обязательный для API Avito'; $result = false; if (is_null($service) || (is_null($client_id) && (strtolower($service) == 'avito' || strtolower($service) == 'domclick')) || is_null($secret_key)) return ['success' => $result, 'errors' => $this->errors]; // $this->_session_key .= "_test"; switch (strtolower($service)) { case 'cian' : $url = "https://public-api.cian.ru/v1/get-agents?page=0&pageSize=1&userIds=".$agent_id; $options = [ 'auth' => 'bearer', 'token' => $this->_getAuthToken('cian', null, $secret_key), 'type' => 'json' ]; // var_dump($options); $result = json_decode($this->_request($url, $options), true); //var_dump($result); if(isset($result['result']['errors'])){ return ['success' => false, 'errors' => $result['result']['message']]; } else { $result['success'] = true; } if ($this->debug) $this->logs["https://public-api.cian.ru/v1/get-agents?page=0&pageSize=1&userIds=".$agent_id] = $result; break; } // $result['logs'] = $this->logs; return $result; } public function get_chat($api, $chat_id){ if(empty($chat_id)){ return ['success' => false, 'errors' => "Пустой чат id"]; } if($api['id'] > 0){ $this->set_api_id($api['id']); } $client_id = trim($api['client_id']); $secret_key = trim($api['secret_key']); $ext_user_id = trim(str_replace(' ','',$api['ext_user_id'])); if(!empty($api['token'])){ $this->_tokens['avito'] = array('expires'=>$api['expires_in'], 'token' => $api['token']); } $service = 'avito'; if (empty($client_id)) $client_id = null; if (empty($secret_key)) $secret_key = null; if (empty($ext_user_id)) $ext_user_id = null; $this->errors = []; if (is_null($service)) $this->errors[] = 'Не указана площадка для получения статистики'; if (is_null($client_id) && (strtolower($service) == 'avito' || strtolower($service) == 'domclick')) $this->errors[] = 'Не указан `client_id` для получения статистики'; if (is_null($secret_key)) $this->errors[] = 'Не указан `secret_key` для получения статистики'; if (is_null($ext_user_id) && strtolower($service) == 'avito') $this->errors[] = 'Не указан `ext_user_id` обязательный для API Avito'; $result = false; if (is_null($service) || (is_null($client_id) && (strtolower($service) == 'avito' || strtolower($service) == 'domclick')) || is_null($secret_key)) return ['success' => $result, 'errors' => $this->errors]; $url = "https://api.avito.ru/messenger/v2/accounts/{$ext_user_id}/chats/{$chat_id}"; $options = [ 'auth' => 'bearer', 'token' => $this->_getAuthToken('avito', $client_id, $secret_key), 'method' => 'get', 'type' => 'json', ]; $result = json_decode($this->_request($url, $options),true); $result['success'] = true; return $result; } } ?>