Пролог: Большое спасибо рекрутеру компании Emfy за то, что напомнил мне о моей способности быстро разбираться в незнакомых вещах ❤️
Всем привет! Это мой первый пост, и я хотел бы привнести свой вклад в сообщество, обсуждая интересные проекты и задачи с собеседований от руководителей различных компаний.
Начну, пожалуй, с того, что я PHP-разработчик, и мне нравится программировать. К сожалению, я упустил в своё время основные моменты при обучении и порой просто не обращал внимание на то, что мне не нравилось. Только совсем недавно, две недели назад, я начал изучать ООП.
Сегодня я хочу поделиться тестовым заданием, которое мне предоставила компания Emfy. Они занимаются внедрением интеграций, взаимодействуя с amoCRM. Стоит отметить, что я никогда раньше не сталкивался с API amoCRM, из-за чего возникли проблемы с усвоением новой информации по API, так как она обширна.
Начнем с того что мне выслали письмо следующего содержания:
Если вы перейдете в документацию amoCRM, вы увидите множество методов и примеров кода для реализации вашего скрипта, который поначалу я совсем не понимал. Когда я разбирался с документацией, я понял, что будет легче руководствоваться дополнительно пакетом, представленным API-клиентом с поддержкой основных сущностей и авторизацией по протоколу OAuth 2.0 в amoCRM с GitHub.
Честно говоря, я хотел 1000 и 1 раз отказаться от выполнения задания.
Итак, для начала работы вам потребуется аккаунт amoCRM с подпиской или бесплатной пробной версией на 14 дней (только для новых аккаунтов).
Настроить интеграцию на стороне amoMarket:
Перейдите в amoМаркет, который расположен в левой боковой панели.
В правом верхнем углу нажмите кнопку "+ WEB HOOKS".
В открывшемся окне нужно указать ссылку, куда будет отправляться веб-хук. Второй параметр — это события, которые вы будете отслеживать. То есть, когда вы будете вносить какие-либо изменения в аккаунте amoCRM, данные с этим событием будут отправляться на ваш сервер, после чего вы можете работать с ними и производить манипуляции.
Чтобы настроить интеграцию в amoCRM, выполните следующие шаги:
Добавление веб-хука:
Рядом с кнопкой "+ WEB HOOKS" нажмите на троеточие и выберите опцию "+ Создать интеграцию".
Выбор типа интеграции:
В появившемся всплывающем окне выберите тип интеграции: "Внешняя" или "Приватная". Для данного примера выберите "Внешняя".
Настройка интеграции:
Введите ссылку для перенаправления в соответствующее поле. Это основной параметр, необходимый для создания интеграции.
Сохранение интеграции:
Нажмите кнопку "Сохранить". Во вкладке "Установленные" появится ваше новое приложение.
Поздравляем! Интеграция успешно создана.
Написание скрипта на сервере
Теперь на стороне сервера нужно написать скрипт с помощью ключей которые нам были предоставлены после создания публичной интеграции они хранятся во вкладке "ключи и доступы"
Создадим файл config.php в котором мы будем хранить свои ключи.
<?php
return [
'clientId' => 'Секретный ключ',
'clientSecret' => 'ID интеграции',
'redirectUri' => 'https://example.com',
'accessToken' => 'Долгосрочный токен',
'baseDomain' => 'ваш_логин.amocrm.ru'
];
В powershell выполните команду можно с помощью composer:
composer require amocrm/amocrm-api-library
Теперь создадим файл index.php для написание основного функционала из ТЗ
<?php
require_once 'vendor/autoload.php';
require_once 'config.php';
use AmoCRM\Client\AmoCRMApiClient;
use League\OAuth2\Client\Token\AccessToken;
use AmoCRM\Models\NoteType\CommonNote;
use AmoCRM\Exceptions\AmoCRMApiException;
use AmoCRM\Helpers\EntityTypesInterface;
class AmoCRMWebhookHandler {
private $apiClient;
private $config;
public function __construct(array $config) {
$this->config = $config;
$this->apiClient = new AmoCRMApiClient(
$config['clientId'],
$config['clientSecret'],
$config['redirectUri']
);
$this->setupApiClient();
}
private function setupApiClient() {
$accessToken = new AccessToken([
'access_token' => $this->config['accessToken'],
'expires' => time() + (10 * 365 * 24 * 60 * 60)
]);
$this->apiClient->setAccessToken($accessToken)
->setAccountBaseDomain($this->config['baseDomain']);
}
public function handleWebhook() {
$rawData = file_get_contents('php://input');
parse_str($rawData, $data);
$this->logData($data);
$this->processLeads($data);
echo "Webhook processed successfully";
}
private function logData($data) {
file_put_contents('webhook_log.txt', json_encode($data, JSON_PRETTY_PRINT), FILE_APPEND);
}
private function processLeads($data) {
if (isset($data['leads']['add'])) {
$this->handleAddedLeads($data['leads']['add']);
}
if (isset($data['leads']['update'])) {
$this->handleUpdatedLeads($data['leads']['update']);
}
}
private function handleAddedLeads(array $leads) {
foreach ($leads as $lead) {
$noteText = "Создана сделка: {$lead['name']}. Ответственный: {$lead['responsible_user_id']}. Время добавления: " . date('Y-m-d H:i:s', $lead['created_at']);
$this->addNoteToLead($lead['id'], $noteText);
}
}
private function handleUpdatedLeads(array $leads) {
foreach ($leads as $lead) {
$noteText = "Изменена сделка: {$lead['name']}. Время изменения: " . date('Y-m-d H:i:s', $lead['updated_at']);
$this->addNoteToLead($lead['id'], $noteText);
}
}
private function addNoteToLead($leadId, $noteText) {
$note = new CommonNote();
$note->setEntityId($leadId)->setText($noteText);
try {
$this->apiClient->notes(EntityTypesInterface::LEADS)->addOne($note);
} catch (AmoCRMApiException $e) {
error_log("Ошибка при добавлении заметки: " . $e->getMessage());
}
}
}
$handler = new AmoCRMWebhookHandler(require 'config.php');
$handler->handleWebhook();
Теперь кода мы подключили библиотеку и файл конфигурации к нашему файлу index.php можно написать обработчик веб-хука для системы AmoCRM.
Он использует объектно-ориентированный подход для организации кода и делит его на логические компоненты, что делает его более читабельным и легко поддерживаемым. Вот основные действия, которые выполняет этот скрипт:
1. Загрузка зависимостей и конфигурации
Скрипт начинается с подключения файла vendor/autoload.php
, который загружает все необходимые зависимости, установленные через Composer, и файла config.php
, содержащего конфигурационные параметры (например, данные аутентификации API).
2. Инициализация API клиента AmoCRM
Создается экземпляр класса AmoCRMApiClient
с использованием учетных данных API из конфигурации. Клиент API настраивается с помощью метода setupApiClient()
, где создается и устанавливается объект AccessToken
для аутентификации запросов к AmoCRM.
3. Обработка данных веб-хука
Получение данных: Скрипт читает "сырые" данные из потока ввода (обычно отправляемые через POST-запросы веб-хуком).
Логирование: Данные логируются в файл
webhook_log.txt
для отладки и аудита.Обработка событий по сделкам: Проверяются и обрабатываются события добавления (
add
) и обновления (update
) сделок в AmoCRM. Для каждой сделки создаются текстовые заметки о произошедших изменениях.
4. Методы для добавления заметок
Для каждой сделки (лид), которая была добавлена или обновлена, создается заметка в AmoCRM с помощью объекта CommonNote
. Заметка включает информацию о названии сделки, ответственном лице и времени добавления или изменения. Заметки добавляются к соответствующим сделкам через API.
5. Обработка ошибок
Всякий раз, когда при добавлении заметки возникает ошибка API (вызывается исключение AmoCRMApiException
), сообщение об ошибке записывается в журнал ошибок сервера.
6. Инициализация и выполнение обработчика
Создается объект AmoCRMWebhookHandler
с конфигурационными параметрами, после чего вызывается метод handleWebhook()
для обработки входящих данных веб-хука.
В целом, этот скрипт автоматизирует обработку веб-хуков от AmoCRM, упрощая управление сделками и связанной с ними информацией в CRM системе, и делает этот процесс более удобным для дальнейшего анализа и отслеживания.
P.S: Я хочу развиваться в направлении PHP и был бы признателен, если вы напишите, где я мог бы что-либо улучшить и если можно даже почитать литературу.
Всем большое спасибо!