PHP-библиотека

Основы

Для начала необходимо скачать библиотеку для взаимодействия с amoCRM. Она находится в примере php виджета, который можно скачать внизу страницы. Библиотеку необходимо положить в корень вашего веб сервера, и его домен должен быть второго уровня. После чего, можно создать index файл, который будет содержать базовые настройки и подключение этой библиотеки. Так же надо чтобы виджет был в статусе public, т.к. создаваемые далее endpoint доступны только для публичных виджетов.

  1. <?php
  2.  
  3. header('Content-type: text/html;charset="utf-8"'); //отправка заголовка, сообщающего браузеру какую кодировку использовать (utf-8)
  4.  
  5. define('AMO_DOMAIN', 'amocrm.ru'); //домен CRM
  6. define('AMO_PROTOCOL', 'https'); //протокол CRM
  7. define('CHECK_LIB_VERSION', true); //проверять ли наличие новой версии библиотеки
  8. define('AUTO_BUILD', true); //автоматически собирать виджет при обращении, в противном случае необходимо каждый раз, после изменения файлов, обращаться к контроллеру builder (описанно ниже).
  9.  
  10. require_once __DIR__.'/widget_lib.phar'; //подключение самой библиотеки.
  11.  

Теперь, необходимо создать папку /widget/ в которой будет происходить разработка виджета. В ней создаем всю структуру виджета и дополнительные файлы.

Файл /widget/widget.php

Файл /widget/widget.php должен содержать в себе класс Widget, который наследует системный класс \Helpers\Widgets.

  1. <?php
  2. namespace new_widget;
  3. defined('LIB_ROOT') or die();
  4. class Widget extends \Helpers\Widgets
  5. {
  6.   /*
  7.     Сюда мы добавим логику нашего виджета
  8.   */
  9. }
  10. ?>

Класс Widget должен содержать в себе методы, которые выполняют роль точек входа в виджет. Эти методы должны иметь уровень доступа строже, чем public (т.е. protected и/или private). Точка входа должна иметь название, начинающееся с префикса endpoint_, например: endpoint_get().

  1. <?php
  2. namespace new_widget;
  3. defined('LIB_ROOT') or die();
  4.  
  5. class Widget extends \Helpers\Widgets
  6. {
  7.   public function endpoint_get()
  8.   {
  9.     /*
  10.       Это точка входа "endpoint_get()"
  11.     */
  12.   }
  13.  
  14.   public function endpoint_set()
  15.   {
  16.     /*
  17.       Это точка входа "endpoint_set()"
  18.     */
  19.   }
  20.  
  21.   protected function endpoint_SomeoneElse()
  22.   {
  23.     /*
  24.       Это точка входа "endpoint_SomeoneElse()"
  25.     */
  26.   }
  27.  
  28.   protected function endpoint_happy()
  29.   {
  30.     /*
  31.       Это точка входа "endpoint_happy()"
  32.     */
  33.   }
  34. }
  35. ?>

Обращение к точке входа происходит по следующему URL: /#ACCOUNT#/#CONTROLLER#[/#METHOD#[/#ENDPOINT#]], где #ACCOUNT# - ваш аккаунт в системе, #CONTROLLER# - для обращения к точке входа виджета должен быть иметь значение loader, #METHOD# - код виджета (код должен содержать только строчные буквы!), #ENDPOINT# - сама точка входа.
Например: /test/loader/addcontact/get/

CONTROLLER так же может иметь значение builder. В этом случае METHOD и ENDPOINT указывать не нужно. Обращение к контроллеру builder соберет наш виджет для работы с контроллером loader и создаст zip архив для загрузки на amoCRM.

При первом обращении к контроллеру loader и после каждого изменения в файлах виджета необходимо вызывать контроллер builder. Или установить значение константы AUTO_BUILD как true (описано выше)

Так же, следует помнить, что для работы с сервером amoCRM при обращении к точке входа должны передаваться amouser и amohash. Их можно посмотреть в настройке профиля пользователя в системе (/settings/profile/). Поле amouser - E-Mail пользователя, amohash - ключ для авторизации в API.

Библиотека для работы с виджетами позволяет напрямую взаимодействовать с системой с помощью точек входа (смотрите выше). Для примера создадим виджет, добавляющий контакт в amoCRM.

Особенности и ограничения библиотеки

Все запросы должны перенаправляться на ваш файл index.php в корневой директории. Если у Вас стоит веб-сервер apache и вы распаковали в его корень архив с библиотекой, то там уже имеется файл .htaccess с инструкциями для mod_rewrite (убедитесь, что он включен)

По-умолчанию в объекте вашего виджета уже имеются ссылки на объекты
- контактов - $this->contacts
- компаний - $this->company
- cделок - $this->leads
- примечаний - $this->notes
- задач - $this->tasks
- информации по аккаунту - $this->account->current()
Первые пять объектов имеют два метода get и set, параметры которых описаны в файле примере widget.php Объекты contacts и company имеют еще метод links() который соответствует подобному методу в API.

Для отправки cURL запросов на сторонний сервис можно использовать встроенный класс
\Helpers\Curl::init($url,[$post=FALSE],[$cookie=FALSE]);
где:
$url — ссылка, куда отправляется запрос,
$post — массив для передачи (если он заполнен, то запрос будет отправлен по методу POST),
$cookie — TRUE/FALSE использовать ли куки-файл или нет

Любые приходящие из GET или POST параметры нужно получать через
\Helpers\Route::param(#ELEMENT_KEY#)

Метод \Helpers\Route::param(#ELEMENT_KEY#) так же доступен как $this->param(#ELEMENT_KEY#)

Получение настроек текущего виджета в amoCRM возможно путем вызова
$this->account->current('widget');

Для работы с языковыми сообщениями можно использовать встроенный класс
\Helpers\I18n::get('settings.enums.yes')
Все языковые сообщения должны быть описаны в директории /widget/i18n/#lang#.json

Создание собственной Web-странички

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

Создадим файл с html-формой и назовём его form.php

  1. <!DOCTYPE html>
  2.   <meta charset="utf-8">
  3.   <title>Добавление контакта</title>
  4. </head>
  5.   <div id="wrapper">
  6.     <header>
  7.       <h1>Создание контакта</h1>
  8.     </header>
  9.     <div id="contact_form">
  10.       <form action="test/loader/addcontact/add?amouser=test@mail.ru&amohash=63bcbb0169df507cf144320b9c9a79af443efd1e" method="post">
  11.         <div class="field">
  12.           <label for="contact_name">Имя</label><input id="contact_name" type="text" name="name">
  13.         </div>
  14.         <div class="field">
  15.           <label for="contact_company">Компания</label><input id="contact_company" type="text" name="company">
  16.         </div>
  17.         <div class="field">
  18.           <label for="contact_position">Должность</label><input id="contact_position" type="text" name="position">
  19.         </div>
  20.         <div class="field">
  21.           <label for="contact_phone">Телефон</label><input id="contact_phone" type="tel" name="phone">
  22.         </div>
  23.         <div class="field">
  24.           <label for="contact_email">E-mail</label><input id="contact_email" type="email" name="email">
  25.         </div>
  26.         <div class="field">
  27.           <label for="contact_web">Web-сайт</label><input id="contact_web" type="url" name="web">
  28.         </div>
  29.         <div class="field">
  30.           <label for="contact_jabber">Jabber</label><input id="contact_jabber" type="text" name="jabber">
  31.         </div>
  32.         <div class="field">
  33.           <label for="contact_scope">Сфера деятельности</label>
  34.           <select id="contact_scope" name="scope[]" size="5" multiple>
  35.             <option value="it">IT, телекоммуникации, связь, электроника</option>
  36.             <option value="auto">Автосервис, автобизнес</option>
  37.             <option value="bookkeeping">Бухгалтерия, аудит</option>
  38.             <option value="restaurants">Рестораны, фастфуд</option>
  39.             <option value="economy">Экономика, финансы</option>
  40.           </select>
  41.         </div>
  42.         <div>
  43.           <button type="submit">Создать контакт</button>
  44.           <button type="reset">Очистить форму</button>
  45.         </div>
  46.       </form>
  47.     </div>
  48.   </div>
  49. </body>
  50. </html>

Для того чтобы форма выглядела более или менее прилично, добавим стили для неё. Создадим файл main.css со следующим содержимым:

  1. label
  2. {
  3.   float: left;
  4.   padding-right: 10px;
  5. }
  6.  
  7. #contact_form
  8. {
  9.   float: left;
  10.   margin: 6px 10px;
  11. }
  12.  
  13. .field
  14. {
  15.   clear: both;
  16.   text-align: right;
  17.   line-height: 2em;
  18. }

И подключим стили в html-файле, описанном выше. Для этого в теге <head>, сразу за тегом </title>, вставим следующую строку:

<link rel="stylesheet" type="text/css" href="main.css" media="all">

Создание манифеста

Манифест виджета - это файл с описанием и настройками виджета в формате JSON. Рекомендуется название, описание и другую статичную информацию выносить в файлы локализации виджета (смотрите ниже).

  1. {
  2.   "widget": {
  3.     "name": "widget.name",
  4.     "description": "widget.description",
  5.     "short_description": "widget.short_description",
  6.     "code": "AddContact",
  7.     "secret_key": "305ce9d34a329cbf1d0678e348s2d30dcdb6bae6d81832add4cd6584fbce4d33",
  8.     "version": "1.0.0",
  9.     "locale": ["ru","en"],
  10.     "installation": true
  11.   }
  12. }

Создание файлов локализации

Файл локализации - это файл в формате JSON, содержащий перевод статичной информации, используемой при разработке виджета. Эти файлы редактируются по мере написания логики виджета, в зависимости от необходимости ввода той или иной новой информации.

Создадим два файла локализации для нашего примера: на английском и на русском языках соответственно.

  1. {
  2.     "widget":{
  3.         "name":"Добавление контактов и сделок",
  4.         "short_description":"Виджет добавляет контакты, сделки, после чего привязывает некоторые сделки к некоторым контактам",
  5.         "description":"Виджет добавляет контакты, сделки, после чего привязывает некоторые сделки к некоторым контактам"
  6.     },
  7.   "exceptions":{
  8.     "error": "Ошибка",
  9.     "name": "Не заполнено имя контакта",
  10.     "email": {
  11.       "empty": "Не заполнен E-mail контакта"
  12.     },
  13.     "custom_fields": {
  14.       "undefined": "Невозможно получить дополнительные поля",
  15.       "unknown": "В amoCRM отсутствуют следующие поля"
  16.     },
  17.     "contacts": {
  18.       "error": "Невозможно получить список контактов"
  19.     },
  20.     "user_already_exists": "Такой контакт уже существует в amoCRM"
  21.   },
  22.   "custom_fields": {
  23.     "scope": {
  24.       "name": "Сфера деятельности",
  25.       "fields": {
  26.         "it": "IT, телекоммуникации, связь, электроника",
  27.         "auto": "Автосервис, автобизнес",
  28.         "bookkeeping": "Бухгалтерия, аудит",
  29.         "restaurants": "Рестораны, фастфуд",
  30.         "economy": "Экономика, финансы"
  31.       }
  32.     }
  33.   }
  34. }

Файл англоязычной локализации

  1. {
  2.     "widget":{
  3.         "name":"Adding contacts and leads",
  4.         "short_description":"Widget adds contacts, leads, and then binds some leads from some contacts",
  5.         "description":"Widget adds contacts, leads, and then binds some leads from some contacts"
  6.     },
  7.   "exceptions":{
  8.     "error": "Error",
  9.     "name": "Not filled a contact name",
  10.     "email": {
  11.       "empty": "Not filled a contact email"
  12.     },
  13.     "custom_fields": {
  14.       "undefined": "Can not get the additional fields",
  15.       "unknown": "In amoCRM missing the following fields"
  16.     },
  17.     "contacts": {
  18.       "error": "Unable to get a list of contacts"
  19.     },
  20.     "user_already_exists": "This contact already exists in amoCRM"
  21.   },
  22.   "custom_fields": {
  23.     "scope": {
  24.       "name": "Sphere of activity",
  25.       "fields": {
  26.         "it": "In IT, telecommunications, communications, electronics",
  27.         "auto": "Auto Service, Autp Business",
  28.         "bookkeeping": "Accounting, Auditing",
  29.         "restaurants": "Restaurants, fast food",
  30.         "economy": "Economy, Finances"
  31.       }
  32.     }
  33.   }
  34. }

Программирование виджета

Создадим пустой класс Widget, который наследует системный класс \Helpers\Widgets, а затем сделаем в нём точку входа, которую назовём add

  1. class Widget extends \Helpers\Widgets
  2. {
  3.   protected function endpoint_add()
  4.   {
  5.     /* Здесь будет наш код*/
  6.   }
  7. }

Создадим внутренний метод get_data() (помеченный модификатором private), который будет получать данный из формы, и записывать их во внутреннее свойство $data, а затем поместим его вызов в точку входа.

  1. class Widget extends \Helpers\Widgets
  2. {
  3.   private
  4.     $data;
  5.    
  6.   protected function endpoint_add()
  7.   {
  8.     $this->get_data();
  9.   }
  10.  
  11.   private function get_data()
  12.   {
  13.     #Получаем данные из POST-запроса
  14.     $data=array(
  15.       'name'=>isset($_POST['name']) ? $_POST['name'] : '',
  16.       'company'=>isset($_POST['company']) ? $_POST['company'] : '',
  17.       'position'=>isset($_POST['position']) ? $_POST['position'] : '',
  18.       'phone'=>isset($_POST['phone']) ? $_POST['phone'] : '',
  19.       'email'=>isset($_POST['email']) ? $_POST['email'] : '',
  20.       'web'=>isset($_POST['web']) ? $_POST['web'] : '',
  21.       'jabber'=>isset($_POST['jabber']) ? $_POST['jabber'] : '',
  22.       'scope'=>isset($_POST['scope']) && is_array($_POST['scope']) ? $_POST['scope'] : array()
  23.     );
  24.    
  25.     #Если не указано имя или e-mail контакта - уведомляем
  26.     if(empty($data['name']))
  27.       die(\Helpers\I18n::get('exceptions.name')); #Данные берутся из файлов локализации (смотрите выше)
  28.     if(empty($data['email']))
  29.       die(\Helpers\I18n::get('exceptions.email'));
  30.     $this->data=$data;
  31.   }
  32. }

Создадим внутренний метод get_custom_fields_info() для получения информации о нужных нам полях в amoCRM и сохраним его результат в переменной $custom_fields в точке входа.

  1. class Widget extends \Helpers\Widgets
  2. {
  3.   private
  4.     $data;
  5.    
  6.   protected function endpoint_add()
  7.   {
  8.     $this->get_data();
  9.     $custom_fields=$this->get_custom_fields_info();
  10.   }
  11.  
  12.   private function get_data()
  13.   {
  14.     #Получаем данные из POST-запроса
  15.     $data=array(
  16.       'name'=>isset($_POST['name']) ? $_POST['name'] : '',
  17.       'company'=>isset($_POST['company']) ? $_POST['company'] : '',
  18.       'position'=>isset($_POST['position']) ? $_POST['position'] : '',
  19.       'phone'=>isset($_POST['phone']) ? $_POST['phone'] : '',
  20.       'email'=>isset($_POST['email']) ? $_POST['email'] : '',
  21.       'web'=>isset($_POST['web']) ? $_POST['web'] : '',
  22.       'jabber'=>isset($_POST['jabber']) ? $_POST['jabber'] : '',
  23.       'scope'=>isset($_POST['scope']) && is_array($_POST['scope']) ? $_POST['scope'] : array()
  24.     );
  25.    
  26.     #Если не указано имя или e-mail контакта - уведомляем
  27.     if(empty($data['name']))
  28.       die(\Helpers\I18n::get('exceptions.name')); #Данные берутся из файлов локализации (смотрите выше)
  29.     if(empty($data['email']))
  30.       die(\Helpers\I18n::get('exceptions.email'));
  31.     $this->data=$data;
  32.   }
  33.  
  34.   private function get_custom_fields_info()
  35.   {
  36.     #Получаем информацию по текущему аккаунту
  37.     $account=$this->account->current();
  38.     #Поля, ID которых нам нужно собрать
  39.     $need=array_flip(array('POSITION','PHONE','EMAIL','WEB','IM','SCOPE'));
  40.     if(isset($account['custom_fields'],$account['custom_fields']['contacts']))
  41.       do
  42.       {
  43.         foreach($account['custom_fields']['contacts'] as $field)
  44.           if(is_array($field) && isset($field['id']))
  45.           {
  46.             if(isset($field['code']) && isset($need[$field['code']]))
  47.               $fields[$field['code']]=(int)$field['id'];
  48.             #SCOPE - нестандартное поле, поэтому обрабатываем его отдельно
  49.             elseif(isset($field['name']) && $field['name']==\Helpers\I18n::get('custom_fields.scope.name'))
  50.               $fields['SCOPE']=$field;
  51.              
  52.             $diff=array_diff_key($need,$fields);
  53.             if(empty($diff))
  54.               break 2;
  55.           }
  56.         if(isset($diff))
  57.           die(\Helpers\I18n::get('exceptions.custom_fields.unknown').': '.join(', ',$diff));
  58.         else
  59.           die(\Helpers\I18n::get('exceptions.custom_fields.undefined'));
  60.       }
  61.       while(false);
  62.     else
  63.       die(\Helpers\I18n::get('exceptions.custom_fields.undefined'));
  64.     return isset($fields) ? $fields : false;
  65.   }
  66. }

Теперь нам необходимо узнать, существует ли контакт с указанным E-mail у пользователя. Для этого создадим внутренний метод is_contact_exists() и сделаем соответствующую проверку в точке входа.

  1. class Widget extends \Helpers\Widgets
  2. {
  3.   private
  4.     $data;
  5.    
  6.   protected function endpoint_add()
  7.   {
  8.     $this->get_data();
  9.     $custom_fields=$this->get_custom_fields_info();
  10.     if($this->is_contact_exists())
  11.       die(\Helpers\I18n::get('exceptions.user_already_exists'));
  12.   }
  13.  
  14.   private function get_data()
  15.   {
  16.     #Получаем данные из POST-запроса
  17.     $data=array(
  18.       'name'=>isset($_POST['name']) ? $_POST['name'] : '',
  19.       'company'=>isset($_POST['company']) ? $_POST['company'] : '',
  20.       'position'=>isset($_POST['position']) ? $_POST['position'] : '',
  21.       'phone'=>isset($_POST['phone']) ? $_POST['phone'] : '',
  22.       'email'=>isset($_POST['email']) ? $_POST['email'] : '',
  23.       'web'=>isset($_POST['web']) ? $_POST['web'] : '',
  24.       'jabber'=>isset($_POST['jabber']) ? $_POST['jabber'] : '',
  25.       'scope'=>isset($_POST['scope']) && is_array($_POST['scope']) ? $_POST['scope'] : array()
  26.     );
  27.    
  28.     #Если не указано имя или e-mail контакта - уведомляем
  29.     if(empty($data['name']))
  30.       die(\Helpers\I18n::get('exceptions.name')); #Данные берутся из файлов локализации (смотрите выше)
  31.     if(empty($data['email']))
  32.       die(\Helpers\I18n::get('exceptions.email'));
  33.     $this->data=$data;
  34.   }
  35.  
  36.   private function get_custom_fields_info()
  37.   {
  38.     #Получаем информацию по текущему аккаунту
  39.     $account=$this->account->current();
  40.     #Поля, ID которых нам нужно собрать
  41.     $need=array_flip(array('POSITION','PHONE','EMAIL','WEB','IM','SCOPE'));
  42.     if(isset($account['custom_fields'],$account['custom_fields']['contacts']))
  43.       do
  44.       {
  45.         foreach($account['custom_fields']['contacts'] as $field)
  46.           if(is_array($field) && isset($field['id']))
  47.           {
  48.             if(isset($field['code']) && isset($need[$field['code']]))
  49.               $fields[$field['code']]=(int)$field['id'];
  50.             #SCOPE - нестандартное поле, поэтому обрабатываем его отдельно
  51.             elseif(isset($field['name']) && $field['name']==\Helpers\I18n::get('custom_fields.scope.name'))
  52.               $fields['SCOPE']=$field;
  53.              
  54.             $diff=array_diff_key($need,$fields);
  55.             if(empty($diff))
  56.               break 2;
  57.           }
  58.         if(isset($diff))
  59.           die(\Helpers\I18n::get('exceptions.custom_fields.unknown').': '.join(', ',$diff));
  60.         else
  61.           die(\Helpers\I18n::get('exceptions.custom_fields.undefined'));
  62.       }
  63.       while(false);
  64.     else
  65.       die(\Helpers\I18n::get('exceptions.custom_fields.undefined'));
  66.     return isset($fields) ? $fields : false;
  67.   }
  68.  
  69.   private function is_contact_exists()
  70.   {    
  71.     $params=array(
  72.       'query'=>$this->data['email']
  73.     );
  74.     if($contacts=$this->contacts->get($params))
  75.       return$contacts;
  76.     return false;
  77.   }
  78. }

Наконец, можем создать контакт в amoCRM. Для этого напишем внутренний метод add_new_contact ($custom_fields), принимающий в качестве параметра массив с информацией, которую мы собрали в методе get_custom_fields_info() и вызовем его в точке входа.

  1. class Widget extends \Helpers\Widgets
  2. {
  3.   private
  4.     $data;
  5.    
  6.   protected function endpoint_add()
  7.   {
  8.     $this->get_data();
  9.     $custom_fields=$this->get_custom_fields_info();
  10.     if($this->is_contact_exists())
  11.       die(\Helpers\I18n::get('exceptions.user_already_exists'));
  12.     $this->add_new_contact($custom_fields);
  13.   }
  14.  
  15.   private function get_data()
  16.   {
  17.     #Получаем данные из POST-запроса
  18.     $data=array(
  19.       'name'=>isset($_POST['name']) ? $_POST['name'] : '',
  20.       'company'=>isset($_POST['company']) ? $_POST['company'] : '',
  21.       'position'=>isset($_POST['position']) ? $_POST['position'] : '',
  22.       'phone'=>isset($_POST['phone']) ? $_POST['phone'] : '',
  23.       'email'=>isset($_POST['email']) ? $_POST['email'] : '',
  24.       'web'=>isset($_POST['web']) ? $_POST['web'] : '',
  25.       'jabber'=>isset($_POST['jabber']) ? $_POST['jabber'] : '',
  26.       'scope'=>isset($_POST['scope']) && is_array($_POST['scope']) ? $_POST['scope'] : array()
  27.     );
  28.    
  29.     #Если не указано имя или e-mail контакта - уведомляем
  30.     if(empty($data['name']))
  31.       die(\Helpers\I18n::get('exceptions.name')); #Данные берутся из файлов локализации (смотрите выше)
  32.     if(empty($data['email']))
  33.       die(\Helpers\I18n::get('exceptions.email'));
  34.     $this->data=$data;
  35.   }
  36.  
  37.   private function get_custom_fields_info()
  38.   {
  39.     #Получаем информацию по текущему аккаунту
  40.     $account=$this->account->current();
  41.     #Поля, ID которых нам нужно собрать
  42.     $need=array_flip(array('POSITION','PHONE','EMAIL','WEB','IM','SCOPE'));
  43.     if(isset($account['custom_fields'],$account['custom_fields']['contacts']))
  44.       do
  45.       {
  46.         foreach($account['custom_fields']['contacts'] as $field)
  47.           if(is_array($field) && isset($field['id']))
  48.           {
  49.             if(isset($field['code']) && isset($need[$field['code']]))
  50.               $fields[$field['code']]=(int)$field['id'];
  51.             #SCOPE - нестандартное поле, поэтому обрабатываем его отдельно
  52.             elseif(isset($field['name']) && $field['name']==\Helpers\I18n::get('custom_fields.scope.name'))
  53.               $fields['SCOPE']=$field;
  54.              
  55.             $diff=array_diff_key($need,$fields);
  56.             if(empty($diff))
  57.               break 2;
  58.           }
  59.         if(isset($diff))
  60.           die(\Helpers\I18n::get('exceptions.custom_fields.unknown').': '.join(', ',$diff));
  61.         else
  62.           die(\Helpers\I18n::get('exceptions.custom_fields.undefined'));
  63.       }
  64.       while(false);
  65.     else
  66.       die(\Helpers\I18n::get('exceptions.custom_fields.undefined'));
  67.     return isset($fields) ? $fields : false;
  68.   }
  69.  
  70.   private function is_contact_exists()
  71.   {    
  72.     $params=array(
  73.       'query'=>$this->data['email']
  74.     );
  75.     if($contacts=$this->contacts->get($params))
  76.       return$contacts;
  77.     return false;
  78.   }
  79.  
  80.   private function add_new_contact($custom_fields)
  81.   {
  82.     $contact=array(
  83.       'name'=>$this->data['name'],
  84.       'custom_fields'=>array(
  85.         array(
  86.           'id'=>$custom_fields['EMAIL'],
  87.           'values'=>array(
  88.             array(
  89.               'value'=>$this->data['email'],
  90.               'enum'=>'WORK'
  91.             )
  92.           )
  93.         )
  94.       )
  95.     );
  96.    
  97.     if(!empty($this->data['company']))
  98.       $contact+=array('company_name'=>$this->data['company']);
  99.    
  100.     if(!empty($this->data['position']))
  101.       $contact['custom_fields'][]=array(
  102.         'id'=>$custom_fields['POSITION'],
  103.         'values'=>array(
  104.           array(
  105.             'value'=>$this->data['position']
  106.           )
  107.         )
  108.       );
  109.    
  110.     if(!empty($this->data['phone']))
  111.       $contact['custom_fields'][]=array(
  112.         'id'=>$custom_fields['PHONE'],
  113.         'values'=>array(
  114.           array(
  115.             'value'=>$this->data['phone'],
  116.             'enum'=>'OTHER'
  117.           )
  118.         )
  119.       );
  120.      
  121.     if(!empty($this->data['web']))
  122.       $contact['custom_fields'][]=array(
  123.         'id'=>$custom_fields['WEB'],
  124.         'values'=>array(
  125.           array(
  126.             'value'=>$this->data['web']
  127.           )
  128.         )
  129.       );
  130.      
  131.     if(!empty($this->data['jabber']))
  132.       $contact['custom_fields'][]=array(
  133.         'id'=>$custom_fields['IM'],
  134.         'values'=>array(
  135.           array(
  136.             'value'=>$this->data['jabber'],
  137.             'enum'=>'JABBER'
  138.           )
  139.         )
  140.       );
  141.    
  142.     if(!empty($this->data['scope']))
  143.     {
  144.       foreach($this->data['scope'] as &$enum)
  145.         $enum=trim(\Helpers\I18n::get('custom_fields.scope.fields.'.$enum));
  146.       unset($enum);
  147.      
  148.       $intersect=array_intersect($custom_fields['SCOPE']['enums'],$this->data['scope']);
  149.      
  150.       foreach($intersect as $k=>$v)
  151.         $values[]=array(
  152.           'value'=>$v,
  153.           'enum'=>$k
  154.         );
  155.      
  156.       $scope=array(
  157.         'id'=>(int)$custom_fields['SCOPE']['id'],
  158.         'values'=>$values
  159.       );
  160.      
  161.       $contact['custom_fields'][]=$scope;
  162.     }
  163.    
  164.     $request['add'][]=$contact;
  165.     $this->contacts->set($request);
  166.   }
  167. }

Теперь PHP-логика нашего виджета готова!

Отладка

Заметим, что для отладки на локальных хостах, можно использовать метод \Helpers\Debug::vars($var_for_debug[, $name_of_debug_block]), который выводит свёрстанную страницу с отладочной информацией. Первым параметром передаётся переменная, которую нужно отладить, а вторым (необязательным) параметром можно передать название отладочного блока. При загрузке виджета к нам на аудирование не забывайте удалять отладочные выводы.

  1. $str='Строка';
  2. \Helpers\Debug::vars($str,'Важная информация');

В ходе разработки своего виджета для интеграции с amoCRM, Вы можете столкнуться с числовыми кодами состояний или ошибок, возвращаемых вместе с ответом нашим API. Для того чтобы понять, что именно означает тот или иной код вы можете воспользоваться нашим справочником ответов API или использовать метод \Helpers\Curl::get_error_code($code), который возвращает сообщение ошибки по её числовому коду.

  1. $code=206;
  2. echo \Helpers\Curl::get_error_code($code); //contacts set - request is empty

Упаковка и загрузка

Если при работе вы указали значение константы AUTO_BUILD как true то в папке, где вы создавали виджет должна быть автоматически создана структура /widgets/code/ (если же этой папки нет, вам необходимо обратиться к контроллеру builder вручную) где code - код виджета. В ней содержится архив widget.zip, который необходимо загрузить на amoCRM в разделе /settings/dev/

Качаем PHP-библиотеку для разработки виджетов

Вы всегда можете скачать актуальную версию php-библиотеки по ссылке, расположенной ниже:

Скачать

А пример, приведённый на этой странице, доступен здесь:

Скачать