Архив рубрики: PHP

Битрикс24: экспорт по событию

В предыдущей статье «Bitrix24 API — разбор демо приложения третьего типа» я пообещал написать продолжение с примером выгрузки данных из Битрикс24 по событию (например, по закрытию сделки). Хотел бы написать, что не прошло и года, но… год прошёл.
Пример будет такой. Основано на реальной потребности одной организации. Нужно для всех сделок передавать данные в систему управления складскими запасами. Сделки заключает менеджер, за запасами материалов следит производственник. Т.е. после оформления сделки в Битрикс24 и перехода её в нужный стартовый статус, должен запуститься механизм производства. Нужно вовремя заказать материалы, необходимые для производства (с учётом времени, когда запасы понадобятся и текущих имеющихся запасов). Вобщем, понятно, что данные по сделке нужны в каких-то внешних системах (всё это делать в Битрикс24 не получается, да и не нужно).
Итак, приступаем. Что портебуется:

  1. Аккаунт администратора Битрикс24
  2. Сайт в интернете, куда будем отсылать данные из Битрикс24

Создаём принимающий скрипт

Мы будем подписываться на событие ONCRMDEALUPDATE (как именно подписываться, см. ниже). Это событие в Битрикс24 возникает при изменении сделки. Многие ожидают, что событие «изменения сущности» вернёт те данные, которые изменились. В большинстве случаев это было бы удобно. Но Битрикс24 возвращает только идентификатор изменившейся сущности. Определить через API что именно изменилось — вообще нельзя. Можно только где-то иметь старую копию сущности и при изменении проверить все параметры и отыскать, что же изменилось.
Итак на вход наш скрипт получит идентификатор изменившейся сделки. Не густо. Нужно самостоятельно вытянуть все данные по этой сделке. Сделать это можно через метод API crm.deal.get. Вот пример, как это может быть реализовано в php:

// Получаем идентификатор изменившейся сделки 
$deal_id = $_REQUEST['data']['FIELDS']['ID'];
// Запрашиваем данные этой сделки
$auth = $_REQUEST['auth']['access_token'];
$domain = $_REQUEST['auth']['domain'];
$data = call($domain, "crm.deal.get", array(
    "auth" => $auth,
    "id" => $deal_id    
    )
);

Функция call() взята из демо-приложения, которое рассмотрено мною в предыдущей статье. Полный код этой функции можно увидеть в файле config.php в этом репозитории.
Полезные данные будут в массиве $data[‘result’]. Для начала можно весь этот массив записать в файл для анализирования. Например, можно это сделать так:

logger('Разбираем данные по сделке. var_export($data, 1) = ' . var_export($data, 1) . "n", 'common');

Функция logger() определена всё в том же файле config.php. После анализа массива данных, станет понятно, в каких ключах есть интересующие данные.
Так я выяснил, что статус сделки приходит в значении $data[‘result’][‘STAGE_ID’]. Мне не нужны сделки с начальным статусом (т.к. эти сделки могут сорваться — они ещё прорабатываются менеджером и клиентом). В моём случае код начального статуса — NEW (сделки с таким статусом пропускаем).
Как я определял коды сделок уже не помню. Сейчас можно, например, открыть в Битрикс24 страницу с настройками статусов сделок [CRM / Настройки / Статусы сделки] и в браузерных инструментах разработчика поискать в html дереве строку «LIST[DEAL_STAGE]». Код статуса — это то, что указано в атрибуте VALUE скрытого тега input с названием name=»LIST[DEAL_STAGE][111][STATUS_ID]», где число 111 будет разным для разных статусов. Описание весьма запутанное — смотрите пример на снимке ниже:

Кроме определения статуса сделки, мне нужно было записывать сделки во внешнюю систему только один раз, а не добавлять каждый раз при изменении статуса сделки. Но данные по сделке могут измениться, поэтому при повторной отправке той же самой сделки, она будет обновлять данные.
Я работал с данными, передавая их напрямую в базу данных (без каких-либо библиотек и фреймворков). Получился такой код обработки данных заказа:


if (isset($data['result'])) {
    logger("Сделка №" . $data['result']['ID'] . " — " . $data['result']['TITLE'] . "n", 'common');
    // Проверяем, не является ли сделка новой (если новая, то ещё не обязательно, что сделка состоится)
   
 if ($data['result']['STAGE_ID'] != 'NEW') {
        logger("Обрабатываем не новую сделку" . "n", 'common');
        // Ищем эту сделку в базе, - вдруг она уже заведена
        $deal_id_search = "Сделка №" . $deal_id;
        logger('$deal_id_search = ' . $deal_id_search . "n", 'common');
        $result = SQL('SELECT COUNT(*) AS count FROM deal WHERE name LIKE CONCAT(?, "%")', $deal_id_search);
        if ($result[0]['count']) {
            logger('Сейчас будем обновлять данные по сделке' . "n", 'common');
            // Такая сделка уже заведена в базе. Но обновим её данные
            SQL('UPDATE `deal` SET `name` = ?, `date` = ?, `amount` = ?, `comment` = ? WHERE `name` LIKE CONCAT(?, "%")', "Сделка №" . $deal_id . " — " . $data['result']['TITLE'], $data['result']['CLOSEDATE'], $data['result']['OPPORTUNITY'], $data['result']['COMMENTS'], $deal_id_search);
            logger('Обновили сделку в базе. Сделка №' . $deal_id . " — " . $data['result']['TITLE'] . "n", 'common');  
        } else {
            // Такой сделки ещё нет в базе, - добавляем
            SQL('INSERT INTO `deal` (`name`, `date`, `amount`, `comment`, `accounting`) VALUES(?, ?, ?, ?, 1)', "Сделка №" . $deal_id . " — " . $data['result']['TITLE'], $data['result']['CLOSEDATE'], $data['result']['OPPORTUNITY'], $data['result']['COMMENTS']);
            logger('Добавили сделку в базу. Сделка №' . $deal_id . " — " . $data['result']['TITLE'] . "n", 'common');    
        }
    }
}

В данном коде используется функция SQL() — она определена в файле myfunctions.php. Полностью этот файл, а также целиком мой принимающий скрипт (reg-deal.php) можно посмотреть тут.

Создаём обработчик события

Чтобы скрипт, описанный выше стал выполняться каждый раз, когда в Битрикс24 изменится сделка, нужно прописать на портале Битрикс24 обработчик события. Сделать это из админки Битрикс24, к сожалению, пока невозможно. Только через API. Обработчик на событие ONCRMDEALUPDATE можно прописать кликнув на ссылке «Установить обработчик события «Обновление сделки»» из модифицированного скрипта демо-приложения, описанного в предыдущей статье. Также там есть ссылка «Просмотр установленных обработчиков событий» — для проверки, какие события прописаны на портале.

За установку обработчика отвечает код:


$data = call($_SESSION["query_data"]["domain"], "event.bind", array(
    "auth" => $_SESSION["query_data"]["access_token"],
    "EVENT" => "ONCRMDEALUPDATE",
    "HANDLER" => "http://sitename/integration/reg-deal.php"
));

После выполнения скрипта, Битрикс24 каждый раз при срабатывании собятия изменения сделки будет обращаться к скрипту, прописанному в параметре HANDLER, поэтому нужно точно убедиться что в адресе нет ошибок.

Что дальше

После того, как настроен принимающий скрипт и установлено срабатывание запроса из Битрикс24 к этому скрипту, данные будут передаваться автоматически. Но что-то может пойти не так. Например, событие в Битрикс24 сработает, но скрипт не отработает (может, ваш сайт будет временно недоступен из-за сетевых проблем). Получится необработанное событие. Нужно либо придумать механизм контроля, либо учитывать ненадёжность передачи.
Во-вторых, принимающий скрипт «торчит» в интернет, а значит любой злоумышленник может обратиться к нему и подставить фейковые данные, которые что-то сломают на вашем сайте, либо нарушат ваши данные. Значит, нужно придумать какую-то защиту, — хотя бы первичную верификацию данных и проверку, откуда исходил запрос. Данная статья не затрагивает эти вопросы! В каждой реализации это будет свой уникальный комплекс мер.

Автор: Олег Ехлаков

PHP MongoDB — получаем _id только что созданной записи (MongoID)

Ситуация: мы хотим получить _id только что созданной нами записи. То есть, например, мы создали юзера и хотим знать айдишник, который MongoDB присвоила ему. Делается это очень просто:
Добавляем элемент:

$x = array(‘foo’ => ‘bar’);
$c->insert($x); 

Проверяем внутренности $x:

var_dump($x);
array(2) {
  [«_id»]=>
  object(MongoId)#2 (0) {
  }
  [«foo»]
  string(7) «bar» 

 

Таким образом, для того, чтобы узнать _id, достаточно вывести $x[‘_id’]

Автор: AlexWinner

PHP: Защита процесса авторизации от SQL-инъекций

Раньше, при разработки сайтов, никогда особо не акцентировал свое внимание на защиту от т.з. «SQL-инъекций». Что это такое думаю много говорить не стоит, просто процитирую, что об этом пишут на сайте php.net:

Принудительное внедрение вредоносных инструкций в SQL-запросы — методика, в которой взломщик создает или изменяет текущие SQL-запросы для работы со скрытыми данными, их изменения или даже выполнения опасных команд операционной системы на сервере базы данных. Атака выполняется на базе приложения, строящего SQL-запросы из пользовательского ввода и статических переменных.

Читать

PHP: Проверка URL-адреса

Задача: необходимо проверить на валидность и существование URL, который отправляется пользователем через форму на сайте.

Для решения этой задачи написал простую функцию проверки, которую собственно и привожу ниже:
Читать

Как настроить отправку почты средствами php-функции mail в Ubuntu?

Итак, задача: настроить на локальном сервере, под управлением ОС Ubuntu отправку почты стредствами php-функции mail().

1. Установка SendMail из репозитория Ubuntu

sudo apt-get install sendmail

2. Проверка работоспособность smtp-сервера при помощи коммандной строки и telnet-протокола

# telnet localhost smtp
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 localhost6.localdomain6 ESMTP Sendmail 
8.14.3/8.14.3/Debian-9.2ubuntu1; Thu, 9 Dec 2010 15:31:17 +0200;
(No UCE/UBE) logging access from: localhost.localdomain(OK)-
localhost.localdomain [127.0.0.1]
HELO localhost
250 localhost6.localdomain6 Hello localhost.localdomain [127.0.0.1], 
pleased to meet you
MAIL FROM: no-reply@gmail.com
250 2.1.0 no-reply@gmail.com... Sender ok
RCPT TO: my_exist@gmail.com
250 2.1.5 my_exist@gmail.com... Recipient ok
DATA
354 Enter mail, end with "." on a line by itself
test message
.
250 2.0.0 oB9DVHsE004837 Message accepted for delivery

В результате выполнения последовательности комманд на указанный емейл (my_exist@gmail.com) должно прийти сообщение («test message»).

3. Настройка php.ini

gedit /etc/php5/apache2/php.ini

Находим и редактируем следующую строчку

sendmail_path = /usr/sbin/sendmail -t -i

4.  Проверка функции mail()

<?

echo  mail («my_exist@gmail.com»,«test message»,
«test message»
,«From:no-reply@gmail.com»);

?>

Настройка завершена

Автор: Sergiy Kamolov

Как скачать дамп базы данных имея доступ по ftp?

Столкнулся с задачей, когда доступ к файлам проекта открыт только по ftp, при этом база данных находиться на другом сервере и доступ к ней ограничен. Возник вопрос: возможно ли получить дамп базы имея доступ по ftp?

Ответ очень прост: “Всё возможно верующему” ( Евангелие от Марка 9:14-29)

Итак, что нам нужно будет сделать: Читать