Вводная информация
Меня зовут Вячеслав Родионов, я руководитель IT отдела в makeROI, мы занимаемся разработками для amoCRM. С amoCRM работаю несколько лет и иногда сталкиваюсь во всевозможных чатах с вопросами о авторизации в amoCRM. Это первая статья - решил ее написать, что бы помочь комьюнити и постараться повысить качество решений.
Начнем с самого простого - авторизации. Как не странно именно в ней возникает кучу сложностей у новичков. Когда начинал работать с amoCRM она мне тоже показалась страшной, но я погрузился и изучил ее полностью.
Мой привычный стек - Laravel, но для простоты в этом примере буду использовать натив.
Примеры максимально упрощены - нет ни обработки исключений, ни логгирования, валидации, даже повторяющиеся между примерами блоки не инкапсулированные в функции, не говоря об ОПП. Это сделано осознанно для максимального упрощения. Так же будут разжёваны все тонкости, касательно amoCRM, но весьма поверхностно относительно PHP (предполагая, что вы их знаете, или пойдете гуглить). Статься рассчитана на стажеров/джунов.
Стек
- PHP 7.4
- Composer
- Библиотека официалов - amocrm/amocrm-api-library
Что будем делать?
- Авторизуемся в amoCRM
- Настроим автоматическое обновление токенов доступа
- Создадим пару сделок
Итак, погнали
Подготовка
Нам нужно подготовить следующее:
- Аккаунт amoCRM (у меня - shalalala.amocrm.ru), и ваш пользователь - админ
- Хостинг с PHP 7.4, Composer, доступом по SSH
- Ваш собственный домен, который будет подключен к хостингу (у меня shalalala.amocrm.dev (что бы не было путаницы отдельно проясню amocrm.dev - мой собственный домен, который не имеет отношения к amocrm.ru, и я создал домен 3-его уровня)).
Создание интеграции со стороны amoCRM
Для начала нам нужно подготовить интеграцию. Она настраивается через интерфейс аккаунта amoCRM. Важно - нужно что бы пользователь был админом, иначе ничего не получится.
Для следующего этапа нужно подумать об архитектуре. Этот простейший пример будет иметь три эндпоинта:
- /api/credentials.php - это метод для авторизации (amoCRM будет сюда отправлять авторизационные данные)
- /api/account-info.php - этот метод выведет нам информацию об аккаунте
- /api/lead-create.php - этот метод создаст тестовую сделку и вернет ее ID.
Развертка проекта
Я развернул проект в PhpStorm, подключившись по SFTP к хостингу. На снимке видно что проект пустой - только хостинг заботливо положил туда index.html с затычкой на которой написано, что сайт создан. Так как проект пустой, я буду сразу же загружать на хостинг, а не запускать локальный веб-сервер.
Первое, с чего стоит начать - удалить index.html и развернуть composer.
К сожалению в разработке amoCRM есть люди которые не знают что такое composer, а тем более не используют его как настольный инструмент. Если это так, я рекомендую остановиться и пойти изучать, например здесь - https://habr.com/ru/post/439200/.
Перейдем в директорию проекта и запустим установку пакета командой composer require amocrm/amocrm-api-library
Авторизация и сохранения токена доступа
Алгоритм:
- При включении интеграции со стороны amoCRM на указанный в настройках эндпоинт будет отправлен запрос, содержащий авторизационный код.
- Мы берем полученный код, секретный ключ интеграции, айди интеграции, и ссылку (все что мы указывали или посмотрели в настройках виджета) и отправляем в авторизационный сервис amoCRM.
- amoCRM возвращает нам связку токенов доступа (access и refresh), мы их сохраняем.
- При любых запросах к amoCRM используем access токен.
Реализация
Конфиги будем хранить в .env файле, токен сохранять в json файл.
Первым делом создадим конфиг .env, в котором укажем доступы.
Теперь нам нужен простейший скрипт который будет резолвится по нашему эндпоинту авторизации.
Он проверяет, что в запросе был передан код, подгружает конфиги из .env, собирает на основе их класс клиента API из библиотеки (устанавливая ему домен), после этого получает с помощью кода авторизации объект токена, стерилизует его в json и сохраняет в файл.
Теперь включаем и отключаем нашу интеграцию. Если все хорошо, то вы увидите что вашему пользователю был выдан доступ, а в вашем проекте появился файл token.json.
У меня не появился токен и пользователь. Что делать?
Значит что то сделали не правильно. Как это найти? Наш скрипт то не пишет логи. Да очень просто. Нужно просто сымитировать запрос amoCRM и посмотреть ошибку. Как это сделать?
Еще может быть ситуация что при отладке напрямую все ок, а при включении/отключении виджета ничего не происходит. У меня такое было пару раз - оказалось что я только делегировал домен и амо еще о нем не знало и отправляло данные не на мой хостинг, а на прошлый айпи домена. Решилось тем что подождал пару часов.
Запросы к API - получение информации об аккаунте
Создадим второй файл и напишем второй файл, результатом выполнения которого будет получения информации об аккаунте.
Начало файла точно такое же мы собираем объект клиента, указываем ему домен. Дальше мы собираем объект авторизационного токена из нашего token.json, а затем устанавливаем его в клиент.
Далее используем сервис получения информации об аккаунте $apiClient->account() и используем метод getCurrent(), что бы получить информацию о текущем аккаунте.
Преобразуем ее в массив с помощью метода toArray() и выводим.
Запросы к API - создание сделки
Предположим, у нас есть сайт, на котором есть форма из двух полей - Название товара и его стоимость (Нереалистичный пример, но осознанно не хочу в текущем гайде использовать сущность контакт), и есть задача:
Нужно создавать сделку с названием "Новая сделка %название товара%", в кастомное поле "Название товара" записывать название товара, в бюджет сделки записывать стоимость товара, а в кастомное поле "Маржинальность" записывать 50% от стоимость товара.
Предположим, название и стоимость сайт передает на наш эндпоинт GET-запросом.
Подготовка
Если поле Бюджет уже есть в amoCRM, то остальные поля кастомные, их нужно создать. Поэтому первым делом через интерфейс создадим необходимую структуру полей.
Разработка
Нам нужно будет точно так же собрать клиент, создать модель сделки, а потом сохранить ее в amoCRM. Библиотека реализует очень простой и интуитивно-понятный интерфейс для всех действий.
Тут кода побольше, поэтому разделил на два скриншота.
Вначале проверка на наличие переменные, уже знакомые действия получение кофигов, сбора клиента и авторизации, получения токена и установки в клиент, а далее простой расчет поле - название товара, названия сделки, бюджета и маржинальности для использования в дальшейшем.
Далее нам нужно собрать модель сделки - специальный объект из библиотеки, который отправим в API с помощью клиента. Вначале все просто - установим название и цену. Далее чуть сложнее - устанавливаем громоздкий метод коллекции кастомных полей. Если пиглядется можно понять, что создается экземпляр коллекции CustomFieldsValuesCollection, а затем с помощью метода add() в него добавляется два объекта для каждого кастомного поля - Текстового и Числового. В каждом указывается айди из env и значение, которое мы рассчитали выше.
На текущий момент у нас есть локально собранная модель. Теперь ее нужно сохранить в амо. Важно понимать это.
После этого с помощью метода leads() клиента API и метода addOne() мы отправляем собранную модель в amoCRM. amoCRM возвращает id сделки и мы можем его получить с помощью метода getId() для вывода.
После этого переходим по URL, имитируя посланный GET-запрос: https://shalalala.amocrm.dev/api/lead-create.php?product_name=Печенье&product_price=3670
Вот и все :)
Обновление токенов
То что написано ниже - моя попытка просто изложить работу O2Auth протокола.
Выше можно было заметить что токена нам дали два - access и refresh. Мы особо не погружались как оно работает (спасибо библиотеке), но при всех запросах выше мы использовали только access токен. Зачем же нужен refrersh?
На самом деле access токен живет недолго - всего 24 часа с момента выпуска. Это сделано из соображений безопасности. Для его обновления и нужен refresh.
С помощью отдельного метода можно заменить refresh токен на новую связку access и refresh. Подробнее про токены можно почитать тут. При этому старый refresh и access перестанут работать.
Есть реферш токеном не пользоваться месяц (не обновлять по нему аксесс), то он тоже перестанет быть валидным.
Есть два решения обновления токенов
- обновление по планировщику - каждый день (а лучше два раза обновляем токен принудительно)
- обновление по потребности - в случае если мы делаем запрос в амо, а токен умер, мы попробуем его обновить и сделать запрос
Обновление по планировщику
Собираем клиент и с помощью OAuth клиента получаем новый токен из старого и сохраняем его.
Этот скрипт можно повесить на планировщик CRONTAB и регулярно обновлять токен.
Обновление по потребности
Собираем клиент и с помощью OAuth клиента получаем новый токен из старого и сохраняем его.
Библиотека позволяет установить колбэк с помощью метода onAccessTokenRefresh(), который запустится в случае если придется обновить токен при запросе.
Реализуем его в метод api/account-info.php
Теперь вы можете проверить - открыть файл с токеном и стереть (или изменить) accessToken, после отправить GET- запрос на метод - https://shalalala.amocrm.dev/api/account-info.php.
Вы получите ту же самую страницу - при первом запросе amoCRM ответило ошибкой, после этого библиотека обновила токен и повторила запрос. В файле с токеном вы тоже увидите изменения.
Как лучше поступать?
Я рекомендую обновлять по планировщику. Это не так элегантно но можно быть уверенным, что токены не погибнут, например, если месяц не будет запросов. Так же можно настроить обработку ошибок и в случае их отправлять алерты в соответствующие сервисы.
Заключение
Мы подключились к апи, использовали библиотеку, получили инфо об аккаунте, создали сделку.
Проект на github.
Первый опыт написания подобной статьи, посмотрим насколько она оказалась полезной. Буду рад выслушать комментарии. Я на связи в телеграм - @makeroi.