You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
571 lines
21 KiB
571 lines
21 KiB
<?php
|
|
|
|
abstract class FormHandler {
|
|
protected $nextHandler;
|
|
|
|
public function __construct($nextHandler = null) {
|
|
$this->nextHandler = $nextHandler;
|
|
}
|
|
|
|
public function handle($data) {
|
|
if ($this->nextHandler) {
|
|
return $this->nextHandler->handle($data);
|
|
}
|
|
return ['success' => true, 'message' => 'Форма обработана'];
|
|
}
|
|
|
|
|
|
public function formatData($data) {
|
|
if (is_string($data)) {
|
|
parse_str($data, $parsedData); // Преобразуем строку в массив
|
|
$data = $parsedData;
|
|
}
|
|
$formattedMessage = "Данные формы:\n\n";
|
|
|
|
// Проходим по всем полям данных и добавляем их в сообщение
|
|
foreach ($data as $key => $value) {
|
|
$formattedMessage .= sprintf("%s: %s\n", $key, $value);
|
|
}
|
|
|
|
return $formattedMessage;
|
|
}
|
|
}
|
|
|
|
define('WEBHOOK_URL', 'https://b24-f0tsii.bitrix24.ru/rest/10/z5k521mjfkmk7pqj/');
|
|
$utm_data = get_utm_data();
|
|
|
|
class b24Handler extends FormHandler {
|
|
|
|
public function handle($data) {
|
|
// Логика отправки в Mailchimp
|
|
error_log("Отправка в b24: " . json_encode($data));
|
|
|
|
// Вызываем следующий обработчик в цепочке
|
|
return parent::handle($data);
|
|
}
|
|
|
|
function b24_get_or_create_contact($phone, $name, $email, $utm, $userID = null, $isSubscribe) {
|
|
$contactId = null;
|
|
$error = null;
|
|
$foundContacts = [];
|
|
|
|
if (empty($email) && empty($phone) && empty($userID)) {
|
|
return ['contact_id' => null, 'error' => 'Не указаны контактные данные'];
|
|
}
|
|
|
|
// Получаем telegram username если указан userID
|
|
$tg_username = '';
|
|
if (!empty($userID)) {
|
|
$tg_username = get_user_meta($userID, 'tg_username', true);
|
|
}
|
|
|
|
// 1. Поиск по всем возможным комбинациям (включая userID)
|
|
$searchFilters = [];
|
|
|
|
if (!empty($userID)) {
|
|
$searchFilters[] = ['UF_CRM_1744373080655' => $userID];
|
|
}
|
|
|
|
if (!empty($phone)) $searchFilters[] = ['PHONE' => $phone];
|
|
if (!empty($email)) $searchFilters[] = ['EMAIL' => $email];
|
|
|
|
foreach ($searchFilters as $filter) {
|
|
$response = b24_request('crm.contact.list', [
|
|
'filter' => $filter,
|
|
'select' => ['ID', 'NAME', 'PHONE', 'EMAIL', 'UF_CRM_1744373080655', 'IM']
|
|
]);
|
|
|
|
if (!empty($response['result'])) {
|
|
$foundContacts = array_merge($foundContacts, $response['result']);
|
|
}
|
|
}
|
|
|
|
// 2. Обработка найденных контактов
|
|
if (!empty($foundContacts)) {
|
|
$bestMatch = null;
|
|
$maxMatches = 0;
|
|
|
|
foreach ($foundContacts as $contact) {
|
|
$matches = 0;
|
|
|
|
if (!empty($userID) && isset($contact['UF_CRM_1744373080655']) && $contact['UF_CRM_1744373080655'] == $userID) {
|
|
$matches += 3;
|
|
}
|
|
|
|
if (!empty($phone) && valueExists($contact['PHONE'] ?? [], $phone)) $matches++;
|
|
if (!empty($email) && valueExists($contact['EMAIL'] ?? [], $email)) $matches++;
|
|
|
|
if ($matches > $maxMatches) {
|
|
$maxMatches = $matches;
|
|
$bestMatch = $contact;
|
|
}
|
|
}
|
|
|
|
if ($bestMatch) {
|
|
$contactId = $bestMatch['ID'];
|
|
$updateFields = [];
|
|
|
|
if ($name && (empty($bestMatch['NAME']) || $bestMatch['NAME'] != $name)) {
|
|
$updateFields['NAME'] = $name;
|
|
}
|
|
|
|
if (!empty($phone) && !valueExists($bestMatch['PHONE'] ?? [], $phone)) {
|
|
$updateFields['PHONE'][] = ['VALUE' => $phone, 'VALUE_TYPE' => 'MOBILE'];
|
|
}
|
|
|
|
if (!empty($email) && !valueExists($bestMatch['EMAIL'] ?? [], $email)) {
|
|
$updateFields['EMAIL'][] = ['VALUE' => $email, 'VALUE_TYPE' => 'WORK'];
|
|
}
|
|
|
|
// Добавляем Telegram если есть username и его еще нет в контакте
|
|
if (!empty($tg_username) && !imExists($bestMatch['IM'] ?? [], $tg_username)) {
|
|
$updateFields['IM'][] = [
|
|
'VALUE' => $tg_username,
|
|
'VALUE_TYPE' => 'TELEGRAM',
|
|
'TYPE_ID' => 'TELEGRAM'
|
|
];
|
|
}
|
|
|
|
if (!empty($utm)) {
|
|
$updateFields['UTM_SOURCE'] = $utm;
|
|
}
|
|
|
|
if (!empty($userID) && (!isset($bestMatch['UF_CRM_1744373080655']) || $bestMatch['UF_CRM_1744373080655'] != $userID)) {
|
|
$updateFields['UF_CRM_1744373080655'] = $userID;
|
|
}
|
|
|
|
if ($isSubscribe) {
|
|
$updateFields['UF_CRM_1744562461053'] = true;
|
|
}
|
|
|
|
if (!empty($updateFields)) {
|
|
$updateResponse = b24_request('crm.contact.update', [
|
|
'id' => $contactId,
|
|
'fields' => $updateFields
|
|
]);
|
|
|
|
if (!empty($updateResponse['error'])) {
|
|
$error = 'Ошибка обновления: '.$updateResponse['error'];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// 3. Создание нового контакта если не найдено совпадений
|
|
else {
|
|
$utm_source = get_utm_data()['utm_source'] ?? '';
|
|
$utm_medium = get_utm_data()['utm_medium'] ?? '';
|
|
$utm_campaign = get_utm_data()['utm_campaign'] ?? '';
|
|
$utm_content = get_utm_data()['utm_content'] ?? '';
|
|
$utm_term = get_utm_data()['utm_term'] ?? '';
|
|
|
|
$newContact = [
|
|
'fields' => [
|
|
'NAME' => $name,
|
|
'SOURCE_ID' => "WEB",
|
|
'TYPE_ID' => "CLIENT",
|
|
'OPENED' => "Y",
|
|
'UTM_SOURCE' => $utm_source,
|
|
'UTM_MEDIUM' => $utm_medium,
|
|
'UTM_CAMPAIGN' => $utm_campaign,
|
|
'UTM_CONTENT' => $utm_content,
|
|
'UTM_TERM' => $utm_term,
|
|
]
|
|
];
|
|
|
|
if (!empty($phone)) {
|
|
$newContact['fields']['PHONE'][] = ['VALUE' => $phone, 'VALUE_TYPE' => 'MOBILE'];
|
|
}
|
|
if (!empty($email)) {
|
|
$newContact['fields']['EMAIL'][] = ['VALUE' => $email, 'VALUE_TYPE' => 'WORK'];
|
|
}
|
|
if (!empty($utm)) {
|
|
$newContact['fields']['UTM_SOURCE'] = $utm;
|
|
}
|
|
if (!empty($userID)) {
|
|
$newContact['fields']['UF_CRM_1744373080655'] = $userID;
|
|
}
|
|
if ($isSubscribe) {
|
|
$newContact['fields']['UF_CRM_1744562461053'] = true;
|
|
}
|
|
// Добавляем Telegram при создании нового контакта
|
|
if (!empty($tg_username)) {
|
|
$newContact['fields']['IM'][] = [
|
|
'VALUE' => $tg_username,
|
|
'VALUE_TYPE' => 'TELEGRAM',
|
|
'TYPE_ID' => 'TELEGRAM'
|
|
];
|
|
}
|
|
|
|
$response = b24_request('crm.contact.add', $newContact);
|
|
$contactId = $response['result'] ?? null;
|
|
$error = $response['error'] ?? null;
|
|
}
|
|
|
|
return ['contact_id' => $contactId, 'error' => $error];
|
|
}
|
|
|
|
// Вспомогательная функция для проверки значений
|
|
function valueExists($items, $value) {
|
|
foreach ($items as $item) {
|
|
if ($item['VALUE'] == $value) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function b24_request($method, $params = []) {
|
|
$url = WEBHOOK_URL . $method; // ТУТ ВСТАВЛЯЕМ ХУК ОТ ИНТЕГРАТОРА
|
|
$curl = curl_init();
|
|
curl_setopt_array($curl, [
|
|
CURLOPT_URL => $url,
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_POST => true,
|
|
CURLOPT_POSTFIELDS => http_build_query($params),
|
|
CURLOPT_TIMEOUT => 3, // Максимальное время выполнения запроса (в секундах)
|
|
CURLOPT_CONNECTTIMEOUT => 2, // Максимальное время ожидания соединения (в секундах)
|
|
]);
|
|
$response = curl_exec($curl);
|
|
if ($response === false) {
|
|
// Обработка ошибок
|
|
return ['error' => curl_error($curl)];
|
|
}
|
|
error_log('CURL URL: ' . $url);
|
|
error_log('CURL RESP: ' . $response);
|
|
|
|
curl_close($curl);
|
|
return json_decode($response, true);
|
|
}
|
|
|
|
function b24_send_lead($contactId, $msg, $stage, $fName, $order_total, $method, $form_title, $order_id) {
|
|
// Собираем UTM-метки из URL или POST данных
|
|
$utm_data = get_utm_data();
|
|
$utm_source = $utm_data['utm_source'] ?? '';
|
|
$utm_medium = $utm_data['utm_medium'] ?? '';
|
|
$utm_campaign = $utm_data['utm_campaign'] ?? '';
|
|
$utm_content = $utm_data['utm_content'] ?? '';
|
|
$utm_term = $utm_data['utm_term'] ?? '';
|
|
|
|
// Подготавливаем данные для сделки
|
|
$dealData = [
|
|
'fields' => [
|
|
'TITLE' => $form_title . ' - ' . $_SERVER['HTTP_HOST'],
|
|
"STAGE_ID"=> $stage,
|
|
'CONTACT_ID' => $contactId,
|
|
'CATEGORY_ID' => $fName,
|
|
'SOURCE_ID' => "WEB",
|
|
'SOURCE_DESCRIPTION' => '',
|
|
'UTM_SOURCE' => $utm_source,
|
|
'UTM_MEDIUM' => $utm_medium,
|
|
'UTM_CAMPAIGN' => $utm_campaign,
|
|
'UTM_CONTENT' => $utm_content,
|
|
'UTM_TERM' => $utm_term,
|
|
'COMMENTS' => $msg,
|
|
'OPPORTUNITY' => $order_total,
|
|
]
|
|
];
|
|
|
|
if ($order_id){
|
|
$dealData['fields']['UF_CRM_1745741833259'] = $order_id;
|
|
}
|
|
|
|
error_log('DEAL DATA: ' . json_encode($dealData));
|
|
|
|
// Отправляем данные в Bitrix24
|
|
$newDealResponse = b24_request($method, $dealData);
|
|
|
|
error_log('DEAL RESP: ' . json_encode($newDealResponse));
|
|
|
|
// Обработка ответа
|
|
$error = null;
|
|
if (!empty($newDealResponse['error'])) {
|
|
$error = $newDealResponse['error'];
|
|
} elseif (empty($newDealResponse['result'])) {
|
|
$error = 'Ошибка создания сделки';
|
|
}
|
|
|
|
return [
|
|
'success' => empty($error),
|
|
'contact_id' => $contactId,
|
|
'error' => $error,
|
|
'utm' => [
|
|
'source' => $utm_source,
|
|
'medium' => $utm_medium,
|
|
'campaign' => $utm_campaign,
|
|
'content' => $utm_content,
|
|
'term' => $utm_term
|
|
]
|
|
];
|
|
}
|
|
|
|
// Function to add lead (wraps b24_get_or_create_contact and b24_send_lead)
|
|
function b24_add_lead($phone, $name, $email, $msg, $utm, $url, $stage, $fName, $order_total = 0, $userID = null, $method = 'crm.deal.add', $form_title, $isSubscribe = false, $order_id = '') {
|
|
$contact = $this->b24_get_or_create_contact($phone, $name, $email, $utm, $userID, $isSubscribe);
|
|
|
|
if (!empty($contact['contact_id'])) {
|
|
$contactId = $contact['contact_id'];
|
|
} else {
|
|
return ['error' => $contact['error']];
|
|
}
|
|
|
|
$msg = $msg . "\nОтправлено со страницы: " . $url;
|
|
|
|
return $this->b24_send_lead($contactId, $msg, $stage, $fName, $order_total, $method, $form_title, $order_id);
|
|
}
|
|
|
|
// Function to update contact based on userID
|
|
function b24_update_contact_by_user_id($userID, $newData) {
|
|
if (empty($userID)) {
|
|
return ['success' => false, 'error' => 'Не указан ID пользователя'];
|
|
}
|
|
|
|
$user = get_user_by('ID', $userID);
|
|
if (!$user) {
|
|
return ['success' => false, 'error' => 'Пользователь не найден'];
|
|
}
|
|
|
|
// Получаем telegram username
|
|
$tg_username = get_user_meta($userID, 'tg_username', true);
|
|
|
|
// Ищем контакт по ID пользователя
|
|
$response = b24_request('crm.contact.list', [
|
|
'filter' => ['UF_CRM_1744373080655' => $userID],
|
|
'select' => ['ID', 'NAME', 'PHONE', 'EMAIL', 'UF_CRM_1744373080655', 'IM', 'UF_CRM_1744562461053']
|
|
]);
|
|
|
|
if (empty($response['result'])) {
|
|
return ['success' => false, 'error' => 'Контакт не найден в Bitrix24'];
|
|
}
|
|
|
|
$contact = $response['result'][0];
|
|
$contactId = $contact['ID'];
|
|
$updateFields = [];
|
|
|
|
// Update name if changed
|
|
if (isset($newData['name']) && $newData['name'] !== $contact['NAME']) {
|
|
$updateFields['NAME'] = $newData['name'];
|
|
}
|
|
|
|
// Update phone if changed
|
|
if (isset($newData['phone'])) {
|
|
$phoneExists = false;
|
|
foreach ($contact['PHONE'] ?? [] as $phoneItem) {
|
|
if ($phoneItem['VALUE'] === $newData['phone']) {
|
|
$phoneExists = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!$phoneExists) {
|
|
$updateFields['PHONE'] = [['VALUE' => $newData['phone'], 'VALUE_TYPE' => 'MOBILE']];
|
|
}
|
|
}
|
|
|
|
// Update email if changed
|
|
if (isset($newData['email'])) {
|
|
$emailExists = false;
|
|
foreach ($contact['EMAIL'] ?? [] as $emailItem) {
|
|
if ($emailItem['VALUE'] === $newData['email']) {
|
|
$emailExists = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!$emailExists) {
|
|
$updateFields['EMAIL'] = [['VALUE' => $newData['email'], 'VALUE_TYPE' => 'WORK']];
|
|
}
|
|
}
|
|
|
|
// Update Telegram if changed
|
|
if (!empty($tg_username) && !imExists($contact['IM'] ?? [], $tg_username)) {
|
|
$updateFields['IM'][] = [
|
|
'VALUE' => $tg_username,
|
|
'VALUE_TYPE' => 'TELEGRAM',
|
|
'TYPE_ID' => 'TELEGRAM'
|
|
];
|
|
}
|
|
|
|
if (empty($updateFields)) {
|
|
return ['success' => true, 'message' => 'Нет изменений для обновления'];
|
|
}
|
|
|
|
// Send update request
|
|
$updateResponse = b24_request('crm.contact.update', [
|
|
'id' => $contactId,
|
|
'fields' => $updateFields
|
|
]);
|
|
|
|
if (!empty($updateResponse['error'])) {
|
|
return ['success' => false, 'error' => 'Ошибка обновления: '.$updateResponse['error']];
|
|
}
|
|
|
|
return ['success' => true, 'contact_id' => $contactId];
|
|
}
|
|
}
|
|
|
|
class zohoHandler extends FormHandler {
|
|
public function handle($data) {
|
|
// Логика отправки в HubSpot
|
|
error_log("Отправка в Zoho: " . json_encode($data));
|
|
|
|
return parent::handle($data);
|
|
}
|
|
}
|
|
|
|
class tgHandler extends FormHandler {
|
|
|
|
public function handle($data) {
|
|
|
|
global $site_env;
|
|
if ($site_env->site_region == 'ru'){
|
|
$botToken = '7689949404:AAHLTKmopffoNkndHJt-rOmAIZ7Hb6aKf80';
|
|
$chatId = '-1002591296904';
|
|
}
|
|
else if ($site_env->site_region == 'ae'){
|
|
$botToken = '7589204557:AAHh2qa5mUwRBq4fUyjQzqARpk4jDfUu5Yc';
|
|
$chatId = '-1002537433508';
|
|
}
|
|
|
|
// Форматируем данные для отправки в Telegram
|
|
$message = strip_tags($this->formatData($data));
|
|
// Отправляем сообщение в Telegram
|
|
$this->sendToTelegram($botToken, $chatId, $message);
|
|
|
|
// Вызываем следующий обработчик в цепочке
|
|
return parent::handle($data);
|
|
}
|
|
|
|
// Функция для отправки данных в Telegram
|
|
private function sendToTelegram($botToken, $chatId, $message) {
|
|
$url = "https://api.telegram.org/bot$botToken/sendMessage";
|
|
$maxLength = 4096;
|
|
|
|
// Разбиваем сообщение на части, если оно длиннее лимита
|
|
$messages = str_split($message, $maxLength);
|
|
|
|
foreach ($messages as $msgPart) {
|
|
$data = [
|
|
'chat_id' => $chatId,
|
|
'text' => $msgPart,
|
|
'parse_mode' => 'HTML',
|
|
];
|
|
|
|
$options = [
|
|
'http' => [
|
|
'method' => 'POST',
|
|
'header' => "Content-Type: application/x-www-form-urlencoded\r\n",
|
|
'content' => http_build_query($data),
|
|
],
|
|
];
|
|
|
|
$context = stream_context_create($options);
|
|
$response = file_get_contents($url, false, $context);
|
|
|
|
// Логируем HTTP-код и тело ответа
|
|
$httpCode = isset($http_response_header[0]) ? $http_response_header[0] : 'No HTTP response';
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
class emailHandler extends FormHandler {
|
|
public function handle($data) {
|
|
|
|
$to = 'pro@cosmopet.shop'; // Укажите email, на который нужно отправить данные
|
|
$subject = 'Форма обработана'; // Тема письма
|
|
$message = $this->formatData($data); // Форматируем данные
|
|
|
|
$headers = ['Content-Type: text/plain; charset=UTF-8']; // Заголовки письма
|
|
|
|
// Отправляем письмо
|
|
wp_mail($to, $subject, $message, $headers);
|
|
|
|
// Вызываем следующий обработчик в цепочке
|
|
return parent::handle($data);
|
|
}
|
|
}
|
|
|
|
class FormHandlerFactory {
|
|
public static function getHandler(array $enabledHandlers) {
|
|
$handler = null;
|
|
if (in_array('email', $enabledHandlers)) {
|
|
$handler = new emailHandler($handler);
|
|
}
|
|
if (in_array('zoho', $enabledHandlers)) {
|
|
$handler = new zohoHandler($handler);
|
|
}
|
|
if (in_array('tg', $enabledHandlers)) {
|
|
$handler = new tgHandler($handler);
|
|
}
|
|
if (in_array('b24', $enabledHandlers)) {
|
|
$handler = new b24Handler($handler);
|
|
}
|
|
return $handler ?: new DefaultHandler();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
// // Пример обработки обновления профиля пользователя
|
|
// add_action('profile_update', 'handle_profile_update', 10, 2);
|
|
|
|
// function handle_profile_update($userID, $old_user_data) {
|
|
// $user = get_user_by('ID', $userID);
|
|
|
|
// $email = $user->user_email;
|
|
// $phone = get_user_meta($userID, 'billing_phone', true);
|
|
// $first_name = get_user_meta($userID, 'first_name', true);
|
|
// $last_name = get_user_meta($userID, 'last_name', true);
|
|
// $name = trim($first_name . ' ' . $last_name);
|
|
|
|
// $newData = [
|
|
// 'name' => $name,
|
|
// 'email' => $email,
|
|
// 'phone' => $phone,
|
|
// ];
|
|
|
|
// $result = b24_update_contact_by_user_id($userID, $newData);
|
|
|
|
// if (!$result['success']) {
|
|
// error_log('Ошибка обновления контакта в Bitrix24: ' . $result['error']);
|
|
// }
|
|
// }
|
|
|
|
|
|
// add_action('woocommerce_thankyou', 'add_b24_tracking_script', 10, 1);
|
|
|
|
// function add_b24_tracking_script($order_id) {
|
|
// if (!$order_id) return;
|
|
|
|
// $order = wc_get_order($order_id);
|
|
|
|
// echo '<script>
|
|
// (window.b24order = window.b24order || []).push({
|
|
// id: "' . $order_id . '",
|
|
// sum: "' . $order->get_total() . '"
|
|
// });
|
|
// </script>';
|
|
// }
|
|
|
|
function get_utm_data() {
|
|
$utm_data = [];
|
|
$utm_params = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'];
|
|
|
|
foreach ($utm_params as $param) {
|
|
$utm_data[$param] = $_GET[$param] ?? $_COOKIE[$param] ?? '';
|
|
}
|
|
|
|
return $utm_data;
|
|
}
|
|
|
|
|
|
// Функция для сохранения UTM в куки (если нужно хранить между сессиями)
|
|
function save_utm_to_cookies() {
|
|
$utm_params = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'];
|
|
|
|
foreach ($utm_params as $param) {
|
|
if (isset($_GET[$param])) {
|
|
setcookie($param, $_GET[$param], time() + 3600 * 24 * 30, '/');
|
|
}
|
|
}
|
|
}
|
|
|
|
save_utm_to_cookies();
|