Интеграция GetCourse и AmoCRM

2021.09.23
Рассмотрим интеграцию GetCourse с AmoCRM через процессы в формах и WebHook (на свой скрипт) в GetCourse, и API AmoCRM
php

На стороне GetCourse есть форма регистрации, точнее форма заказа курса, куда пользователь вводит свои данные и после отправки формы эти данные сохраняются в БД GetCourse и должны отправляться в AmoCRM где нужно:

[block info]Интеграция GetCourse с AmoCRM происходит через WebHook из процесса отправки формы на GetCourse. WebHook отправляется на свой сервис где данные передаются в AmoCRM по API

GetCourse

Страницы и формы

Страниц может быть несколько (Сайт => Страницы), и не все они обязательно содержат формы для ввода данных, но нас интересуют именно формы.

Страницы сайта

Переходим на нужную страницу, затем в режим редактирования.

На странице нас интересует форма. После ее создания можно выбрать запускаемый процесс.

Запускаемый процесс при отправке формы

В форме регистрации могут быть дополнительные поля пользователя (Пользователи => Дополнительные поля). У поля есть заголовок, это столбец (и его название) в таблице пользователей. Это поле можно отправить вебхуком по нужному адресу, однако тогда в имени поля не должно быть пробелов, но допустима кириллица.

Дополнительные поля пользователя

Администратор может предоставить ссылку на страницу с формой с дополнительными GET параметрами, которые могут быть записаны в данные пользователя. Например ссылка може выглядеть так:

https://domain.zone/registration?ssid=613dec8192284ca806beea57&cookie_id=d1c4d9f8f086404d8e43186f972c3475&block_id=618e637a0cb0aaee1e38c4d3

И эти параметры будут записаны в сессию пользователя. Их можно найти в профиле пользователя в разделе сессии (ссылка на идентификатор сессии).

Данные сессии пользователя, те самые GET параметры в ссылке на форму регистрации/заказа курса:

Данные сессии пользователя, те самые GET параметры в ссылке на форму регистрации/заказа курса

Теперь можно перейти к процессам (по другому они называются бизнес-процессы).

Процессы и WebHook

Переходим в конкретный процесс со страницы списка процессов, во вкладку "Процесс".

Блоки процесса

Среди всех блоков процесса для вебхука нужен блок Операции, выбираем Задачи и Вызвать url.

Блоки процесса

Затем вводим нужный URL адрес вебхука и в GET параметры записываем что необходимо отправить:

Настройка WebHook

Протестировать вебхук можно там же на странице блоков процесса (кнопка Тестирование).

AmoCRM

В AmoCRM необходимо проверить наличие покупателя, и если его нет, то необходимо создать. Критерий поиска email. Но поиск покупателя по email невозможен, вместо этого необходимо искать контакты с этим email.

Возможен целевой поиск по произвольному полю через фильтрацию AmoCRM, которая на данный момент находится в тестировании и нужно запрашивать доступ. Быстро (в течении 2 дней) не удалось получить доступ, пришлось использовать имеющееся средство поиска query параметр.

Доступ к тестированию фильтрации предоставили только через 2 недели.

query это критерий поиска списка сущностей по частичному вхождению строки в любом поле сущности, однако этот параметр близится к deprecated, в связи с внедрением фильтрации.

Рассмотрим поиск/создание и связку сущностей.

В коде ниже опущен экспорт классов (use) для минимизации кода.

Найдем контакт по query=email:

$filter = new ContactsFilter();
$filter->setQuery($_GET["email"]);

// загружаем все контакты по этому емейлу
try{
  $contacts = $amoApiClient->contacts()->get($filter, ["customers"]);
}
catch(AmoCRMApiNoContentException $e){
  
  // не удалось найти контакты - создаем
  
  $contact = new ContactModel();
  $contact->setName($sUserName);

  $customFields = new CustomFieldsValuesCollection();
  $contact->setCustomFieldsValues($customFields);

	// добавление кастомного поля email по id поля
  $emailField = (new MultitextCustomFieldValuesModel())->setFieldId(450419);
  $customFields->add($emailField);
  $emailField->setValues(
    (new MultitextCustomFieldValueCollection())
      ->add(
        (new MultitextCustomFieldValueModel())
          ->setValue($_GET["email"])
      )
  );

  // добавляем новый контакт в AmoCRM (который только создали)
  $contact = $amoApiClient->contacts()->addOne($contact);

  $contacts = new ContactsCollection();
  $contacts->add($contact);
}

Теперь мы имеем коллекцию контактов, первый элемент которой является нашим испомым.

Важно не превысить лимит обращений к API AmoCRM, для этого можно использовать sleep(1).

Найдем покупателя или создадим если его еще не было:

// достаем покупателя
$customer = null;
foreach($contacts as $contact)
{
  if($customer = $contact->getCustomers())
    break;
}

// если найден покупатель - получаем о нем полную информацию и список контактов
if($customer)
{
  $customer = $customer->first();
  $customer = $amoApiClient->customers()->getOne($customer->getId(), ["contacts"]);
  echo "founded customer" . $customer->getName() ."\n";
}
// если не найден покупатель - создаем и установим ему первый контакт
else
{
  // cоздадим покупателя
  $customer = new CustomerModel();
  $customer->setName($sUserName);
  $customer->setNextDate(time() + 60*60*24*30);

  try{
     $customer = $amoApiClient->customers()->addOne($customer);
  }
  catch(Exception $e){
    header("Content-type: text/plain;");
    print_r($e->getValidationErrors());
    exit;
  }

  // привязываем новый контакт к покупателю
  $links = new LinksCollection();
  $links->add($customer);
  $amoApiClient->contacts()->link($contacts->first(), $links);

  $customer = $amoApiClient->customers()->getOne($customer->getId(), ["contacts"]);
}

Имея сущность покупателя, можно ее обновить, заполним кастомные поля:

$customFields = $customer->getCustomFieldsValues();

if(!$customFields)
{
  $customFields = new CustomFieldsValuesCollection();
  $customer->setCustomFieldsValues($customFields);
}

// добавление индекс доставки
$zipFieldValues = (new NumericCustomFieldValuesModel())->setFieldId(805311);
$customFields->add($zipFieldValues);
$zipFieldValues->setValues(
  (new TextCustomFieldValueCollection())
    ->add(
      (new TextCustomFieldValueModel())
        ->setValue($_GET["delivery_zip"])
    )
);

// обновление покупателя
$amoApiClient->customers()->updateOne($customer);

Итог

Интеграция оказалась достаточно интересной. Оба сервиса предоставляют хорошо документированные и удобные средства для гибкой интеграции. Большую часть времени заняло изучение этих средств.

В телеграм канале DevOps от первого лица можно оставить комментарий или почитать интересные истории из практики DevOps