Пролог: Большое спасибо рекрутеру компании Emfy за то, что напомнил мне о моей способности быстро разбираться в незнакомых вещах ❤️

Всем привет! Это мой первый пост, и я хотел бы привнести свой вклад в сообщество, обсуждая интересные проекты и задачи с собеседований от руководителей различных компаний.

Начну, пожалуй, с того, что я PHP-разработчик, и мне нравится программировать. К сожалению, я упустил в своё время основные моменты при обучении и порой просто не обращал внимание на то, что мне не нравилось. Только совсем недавно, две недели назад, я начал изучать ООП.

Сегодня я хочу поделиться тестовым заданием, которое мне предоставила компания Emfy. Они занимаются внедрением интеграций, взаимодействуя с amoCRM. Стоит отметить, что я никогда раньше не сталкивался с API amoCRM, из-за чего возникли проблемы с усвоением новой информации по API, так как она обширна.

Не стоит боятся документации API, хотя я очень был против (поначалу)
Не стоит боятся документации API, хотя я очень был против (поначалу)

Начнем с того что мне выслали письмо следующего содержания:

Если вы перейдете в документацию amoCRM, вы увидите множество методов и примеров кода для реализации вашего скрипта, который поначалу я совсем не понимал. Когда я разбирался с документацией, я понял, что будет легче руководствоваться дополнительно пакетом, представленным API-клиентом с поддержкой основных сущностей и авторизацией по протоколу OAuth 2.0 в amoCRM с GitHub.

Честно говоря, я хотел 1000 и 1 раз отказаться от выполнения задания.

Итак, для начала работы вам потребуется аккаунт amoCRM с подпиской или бесплатной пробной версией на 14 дней (только для новых аккаунтов).

Настроить интеграцию на стороне amoMarket:

  1. Перейдите в amoМаркет, который расположен в левой боковой панели.

  2. В правом верхнем углу нажмите кнопку "+ WEB HOOKS".

  3. В открывшемся окне нужно указать ссылку, куда будет отправляться веб-хук. Второй параметр — это события, которые вы будете отслеживать. То есть, когда вы будете вносить какие-либо изменения в аккаунте amoCRM, данные с этим событием будут отправляться на ваш сервер, после чего вы можете работать с ними и производить манипуляции.

Чтобы настроить интеграцию в amoCRM, выполните следующие шаги:

  1. Добавление веб-хука:

    • Рядом с кнопкой "+ WEB HOOKS" нажмите на троеточие и выберите опцию "+ Создать интеграцию".

  2. Выбор типа интеграции:

    • В появившемся всплывающем окне выберите тип интеграции: "Внешняя" или "Приватная". Для данного примера выберите "Внешняя".

  3. Настройка интеграции:

    • Введите ссылку для перенаправления в соответствующее поле. Это основной параметр, необходимый для создания интеграции.

  4. Сохранение интеграции:

    • Нажмите кнопку "Сохранить". Во вкладке "Установленные" появится ваше новое приложение.

Поздравляем! Интеграция успешно создана.

Написание скрипта на сервере

Теперь на стороне сервера нужно написать скрипт с помощью ключей которые нам были предоставлены после создания публичной интеграции они хранятся во вкладке "ключи и доступы"

Создадим файл 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 и был бы признателен, если вы напишите, где я мог бы что-либо улучшить и если можно даже почитать литературу.

Всем большое спасибо!

Комментарии (12)