Пример по шагам

Для примера рассмотрим полный цикл получения доступа к данным, начиная от регистрации новой интеграции. При этом мы будем рассматривать прямую работу с API авторизации, но вы можете либо воспользоваться нашей готовой библиотекой на PHP для упрощения разработки, либо готовыми библиотеками сторонних вендоров, которые можно найти по ссылке.

Мы разрабатывали авторизацию, основываясь на протоколе oAuth 2.0, поэтому вы можете найти в открытых источниках много примеров и документацию, описывающих взаимодействие и логику выполнения запросов.

1. Регистрация приложения

Все начинается с того, что вам необходимо зайти в раздел Интеграции того аккаунта, в котором вы будете осуществлять поддержку интеграции в будущем. Обратите внимание:

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

После нажатия на кнопку Создать Интеграцию, в появившейся форме, вам необходимо указать Название интеграции, выбрать требуемые доступы и указать описание. Также необходимо указать Redirect URI – url страницы получения токенов и загрузить логотип интеграции.

  • Название интеграции (не более 255 символов) – отображается на странице интеграций, модальном окне для предоставления доступов, а также участвует в поиске по странице интеграций.
  • Описание интеграции (не более 65000 символов) – отображается в модальном окне интеграции в аккаунте пользователя. Допускается использование html верстки.
  • Ссылка для перенаправления – ссылка на ваш сайт, который будет обрабатывать работу с ключами. Важно, что домен должен быть защищен SSL сертификатом, если вы планируете использовать интеграцию более, чем в одном аккаунте. Также мы периодически проверяем доступность домена, как обязательное условие для работы интеграции.
  • Предоставить доступ – минимальный набор необходимых разрешений для работы интеграции. Подробнее про разрешения можно прочитать в статье.
  • Иконка интеграции (130х100 jpeg/jpg/png/gif) – отображается в списке интеграций, а также в окне запроса доступа у пользователя

Кроме этих пунктов администраторам аккаунта, в котором создана интеграция, будут доступны: id интеграции, секретный ключ интеграции, код авторизации (после включения интеграции).

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

Обратите внимание, что Secret key и Integration ID привязаны к интеграции и будут показаны только в вашем аккаунте разработчика.

2. Получение Authorization code

Напомним, что это временный ключ, который действует только 20 минут и с его помощью вам необходимо в течении этого времени получить refresh token и access токен. Он является временным, т.к. может быть перехвачен, но в случае перехвата злоумышленник не сможет с ним ничего сделать, если вы не сообщите ему ключи приложения, известные только администраторам аккаунта, в котором создана интеграция.

Получить Authorization code можно тремя способами:

  1. Скопировать из модального окна установленной интеграции. Этот случай подойдет, если вам необходимо проинтегрировать только один аккаунт amoCRM. Подробнее можно прочитать в разделе Упрощенная авторизация.
  2. Если в вашей интеграции есть виджет, то при его установке вы получите Webhook на указанный в настройках интеграции Redirect URI.
  3. Получить код через после перенаправления пользователя на указанный Redirect URI.

Вы можете упростить разработку при использовании способа получения ключа через GET-параметры, используя готовую Кнопку amoCRM.

Полная логика способа получения ключа через GET-параметры заключается в следующем:

  1. Пользователь, у которого вы хотите запросить доступ, находится у вас на сайте и может открыть предложенную вами ссылку.
    Внимание: Очень важно, чтобы для пользователя весь процесс был максимально прозрачен и понятен. При клике на ссылку пользователь должен однозначно понимать, что далее произойдет запрос его доступов в его аккаунте amoCRM, должен понимать какую интеграцию он включает.

    Именно поэтому мы предлагаем использовать нашу брендированную кнопку, описание которой вы можете найти на странице Кнопка amoCRM
  2. Генерация ссылки, по которой должен перейти пользователь. Вам необходимо отправить пользователя на URL https://www.amocrm.ru/oauth?client_id={Integration ID}&state={параметр состояния, который будет возвращен вам на Redirect URI}.
    Integration ID вам уже известен. А state – это сгенерированный вами строковый параметр, возможно хеш. State нужен для того, чтобы при получении ответа от amoCRM, вы могли проверить его достоверность, сравнив отправленный ключ и полученный в результате, чтобы удостовериться в отсутствии подмены CSRF.
  3. Перейдя по ссылке, пользователь увидит логотип вашей интеграции, который вы загружали при ее создании, название, а также перечень доступов, которые запрашивает приложение.

    Открывать данную страницу мы советуем как модальное окно – в popup. Это позволит пользователю не терять контекста страницы, которая открыла popup.

  4. В случае, если пользователь не авторизован – ему будет предложено авторизоваться в amoCRM, иначе пользователю будет дан выбор из аккаунтов, где он является администратором.
  5. После выбора аккаунта и нажатия кнопки Разрешить, интеграция будет установлена в выбранный аккаунт, а пользователь перенаправлен на указанный в настройках интеграции Redirect URI c GET-параметрами code, referer, state, from_widget. Параметр code содержит Authorization code, параметр referer – адрес аккаунта пользователя, параметр state – строку, которую вы передавали при открытии окна, если строка не была передана, данный параметр возвращен не будет. Если мы отправляем Webhook после установки виджета, то вам дополнительно придет GET-параметр from_widget
  6. В случае, если пользователь нажмет кнопку Отказать приложению в доступе, он будет перенаправлен на Redirect URI с GET-параметром error=access_denied, а также GET-параметром state, если он был передан.

3. Обмен кода авторизации на access token и refresh token

Получив Authorization code, вам необходимо сделать запрос на специальный метод /oauth2/access_token, описанный ниже. В ответ вы получите пару Access и Refresh token, а также время в секундах, через которое токен истекает.

Access токен аналогичен ключу сессии. Его можно сохранить в приложении и использовать для запросов к API до истечения времени его жизни. Токен должен быть доступен только вашему приложению, поэтому не рекомендуется сохранять его в cookies браузера, открытых конфигурационных файлах и т. п.

URL метода

POST /oauth2/access_token

Параметры

Параметр Описание
client_id ID интеграции
client_secret Секрет интеграции
grant_type Тип авторизационных данных (для кода авторизации – authorization_code)
code Полученный код авторизации
redirect_uri Redirect URI указанный в настройках интеграции

Параметры ответа

Параметр Описание
token_type Тип токена (Bearer)
expires_in Время в секундах, показывающее через сколько токен истечет
access_token Access токен
refresh_token Refresh токен

Пример запроса


{
  "client_id": "xxxx",
  "client_secret": "xxxx",
  "grant_type": "authorization_code",
  "code": "xxxxxxx",
  "redirect_uri": "https://test.test"
}

Пример ответа


{
  "token_type": "Bearer",
  "expires_in": 86400,
  "access_token": "xxxxxx",
  "refresh_token": "xxxxx"
}

Получение Access токен по коду авторизации, реализация на bash


curl https://subdomain.amocrm.ru/oauth2/access_token -d \
'{"client_id":"xxx-xxx-xxx-xxx-xxx","client_secret":"xxxxxx","grant_type":"authorization_code","code":"xxxxxxxx","redirect_uri":"https://test.test/"}' \
-H 'Content-Type:application/json' \
-X POST
       

Получение Access токен по коду авторизации, реализация на PHP



<?php
$subdomain = 'test'; //Поддомен нужного аккаунта
$link = 'https://' . $subdomain . '.amocrm.ru/oauth2/access_token'; //Формируем URL для запроса

/** Соберем данные для запроса */
$data = [
	'client_id' => 'xxxx',
	'client_secret' => 'xxxx',
	'grant_type' => 'authorization_code',
	'code' => 'xxxxxx',
	'redirect_uri' => 'https://test.ru/',
];

/**
 * Нам необходимо инициировать запрос к серверу.
 * Воспользуемся библиотекой cURL (поставляется в составе PHP).
 * Вы также можете использовать и кроссплатформенную программу cURL, если вы не программируете на PHP.
 */
$curl = curl_init(); //Сохраняем дескриптор сеанса cURL
/** Устанавливаем необходимые опции для сеанса cURL  */
curl_setopt($curl,CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl,CURLOPT_USERAGENT,'amoCRM-oAuth-client/1.0');
curl_setopt($curl,CURLOPT_URL, $link);
curl_setopt($curl,CURLOPT_HTTPHEADER,['Content-Type:application/json']);
curl_setopt($curl,CURLOPT_HEADER, false);
curl_setopt($curl,CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($curl,CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($curl,CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($curl,CURLOPT_SSL_VERIFYHOST, 2);
$out = curl_exec($curl); //Инициируем запрос к API и сохраняем ответ в переменную
$code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
/** Теперь мы можем обработать ответ, полученный от сервера. Это пример. Вы можете обработать данные своим способом. */
$code = (int)$code;
$errors = [
	400 => 'Bad request',
	401 => 'Unauthorized',
	403 => 'Forbidden',
	404 => 'Not found',
	500 => 'Internal server error',
	502 => 'Bad gateway',
	503 => 'Service unavailable',
];

try
{
	/** Если код ответа не успешный - возвращаем сообщение об ошибке  */
	if ($code < 200 && $code > 204) {
		throw new Exception(isset($errors[$code]) ? $errors[$code] : 'Undefined error', $code);
	}
}
catch(\Exception $e)
{
	die('Ошибка: ' . $e->getMessage() . PHP_EOL . 'Код ошибки: ' . $e->getCode());
}

/**
 * Данные получаем в формате JSON, поэтому, для получения читаемых данных,
 * нам придётся перевести ответ в формат, понятный PHP
 */
$response = json_decode($out, true);

$access_token = $response['access_token']; //Access токен
$refresh_token = $response['refresh_token']; //Refresh токен
$token_type = $response['token_type']; //Тип токена
$expires_in = $response['expires_in']; //Через сколько действие токена истекает

4. Получение нового access token по его истечении

Из предыдущего пункта вы заметили, что вместе с Access token был также возвращен Refresh token. Он необходим для продолжения работы с API, по истечении срока действия Access токена, т.е. это довольно частая операция.

Refresh token имеет два существенных ограничения его жизни:

  1. Refresh токен действует всего 3 месяца. Если интеграция не используется в течение 3 месяцев, не было ни одного запроса на актуализацию ключа, то интеграция потеряет доступ к данным и будем необходимо повторно запрашивать разрешение у пользователя на доступ к его аккаунту
  2. Refresh token можно обменять только один раз. После отправки его в метод и получения новой пары access token/refresh token старый refresh token становится не актуальным. И после получения нового refresh token его необходимо обязательно сохранить, иначе придется вновь перезапрашивать доступ у пользователя.
  3. По истечении срока действия возможность получения Access токена по нему становится невозможной. Для обмена необходимо сделать запрос на специальный метод с действительным Refresh токеном. В ответ вы получите новый Access и Refresh токены.

    URL метода

    POST /oauth2/access_token

    Параметры

    Параметр Описание
    client_id ID интеграции
    client_secret Секрет интеграции
    grant_type Тип авторизационных данных (для refresh токена – refresh_token)
    refresh_token Refresh токен
    redirect_uri Redirect URI указанный в настройках интеграции

    Параметры ответа

    Параметр Описание
    token_type Тип токена (Bearer)
    expires_in Время в секундах, показывающее через сколько токен истечет
    access_token Access токен
    refresh_token Refresh токен

    Пример запроса

    
    {
      "client_id": "xxxx",
      "client_secret": "xxxx",
      "grant_type": "refresh_token",
      "refresh_token": "xxxxx",
      "redirect_uri": "https://test.test"
    }
    

    Пример ответа

    
    {
      "token_type": "Bearer",
      "expires_in": 86400,
      "access_token": "xxxxxx",
      "refresh_token": "xxxxx"
    }
    

    Получение Access токен по Refresh токену, реализация на bash

    
    curl https://subdomain.amocrm.ru/oauth2/access_token -d \
    '{"client_id":"xxx-xxx-xxx-xxx-xxx","client_secret":"xxxxxx","grant_type":"refresh_token","refresh_token":"xxxxxxxx","redirect_uri":"https://test.test/"}' \
    -H 'Content-Type:application/json' \
    -X POST
            

    Получение Access токен по коду авторизации, реализация на PHP

    
    
    <?php
    $subdomain = 'test'; //Поддомен нужного аккаунта
    $link = 'https://' . $subdomain . '.amocrm.ru/oauth2/access_token'; //Формируем URL для запроса
    
    /** Соберем данные для запроса */
    $data = [
    	'client_id' => 'xxxx',
    	'client_secret' => 'xxxx',
    	'grant_type' => 'authorization_code',
    	'code' => 'xxxxxx',
    	'redirect_uri' => 'https://test.ru/',
    ];
    
    /**
     * Нам необходимо инициировать запрос к серверу.
     * Воспользуемся библиотекой cURL (поставляется в составе PHP).
     * Вы также можете использовать и кроссплатформенную программу cURL, если вы не программируете на PHP.
     */
    $curl = curl_init(); //Сохраняем дескриптор сеанса cURL
    /** Устанавливаем необходимые опции для сеанса cURL  */
    curl_setopt($curl,CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl,CURLOPT_USERAGENT,'amoCRM-oAuth-client/1.0');
    curl_setopt($curl,CURLOPT_URL, $link);
    curl_setopt($curl,CURLOPT_HTTPHEADER,['Content-Type:application/json']);
    curl_setopt($curl,CURLOPT_HEADER, false);
    curl_setopt($curl,CURLOPT_CUSTOMREQUEST, 'POST');
    curl_setopt($curl,CURLOPT_POSTFIELDS, json_encode($data));
    curl_setopt($curl,CURLOPT_SSL_VERIFYPEER, 1);
    curl_setopt($curl,CURLOPT_SSL_VERIFYHOST, 2);
    $out = curl_exec($curl); //Инициируем запрос к API и сохраняем ответ в переменную
    $code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    curl_close($curl);
    /** Теперь мы можем обработать ответ, полученный от сервера. Это пример. Вы можете обработать данные своим способом. */
    $code = (int)$code;
    $errors = [
    	400 => 'Bad request',
    	401 => 'Unauthorized',
    	403 => 'Forbidden',
    	404 => 'Not found',
    	500 => 'Internal server error',
    	502 => 'Bad gateway',
    	503 => 'Service unavailable',
    ];
    
    try
    {
    	/** Если код ответа не успешный - возвращаем сообщение об ошибке  */
    	if ($code < 200 && $code > 204) {
    		throw new Exception(isset($errors[$code]) ? $errors[$code] : 'Undefined error', $code);
    	}
    }
    catch(\Exception $e)
    {
    	die('Ошибка: ' . $e->getMessage() . PHP_EOL . 'Код ошибки: ' . $e->getCode());
    }
    
    /**
     * Данные получаем в формате JSON, поэтому, для получения читаемых данных,
     * нам придётся перевести ответ в формат, понятный PHP
     */
    $response = json_decode($out, true);
    
    $access_token = $response['access_token']; //Access токен
    $refresh_token = $response['refresh_token']; //Refresh токен
    $token_type = $response['token_type']; //Тип токена
    $expires_in = $response['expires_in']; //Через сколько действие токена истекает
    
            

    5. Запросы к API с передачей access token

    C помощью полученного Access токена вы можете легко делать запросы к API приложения. Для этого потребуется немного изменить запросы, которые сейчас делаются к API.

    Вам не нужно больше отправлять куки-файлы с каждым запросом, а также авторизовываться с параметрами USER_LOGIN и USER_HASH, вместо этого необходимо добавить заголовок Authorization: Bearer {access токен}.

    Пример запроса к методу account

    
    <?php
    $subdomain = 'test'; //Поддомен нужного аккаунта
    $link = 'https://' . $subdomain . '.amocrm.ru/api/v2/account'; //Формируем URL для запроса
    /** Получаем access_token из вашего хранилища */
    $access_token = 'xxxx';
    /** Формируем заголовки */
    $headers = [
    	'Authorization: Bearer ' . $access_token
    ];
    /**
     * Нам необходимо инициировать запрос к серверу.
     * Воспользуемся библиотекой cURL (поставляется в составе PHP).
     * Вы также можете использовать и кроссплатформенную программу cURL, если вы не программируете на PHP.
     */
    $curl = curl_init(); //Сохраняем дескриптор сеанса cURL
    /** Устанавливаем необходимые опции для сеанса cURL  */
    curl_setopt($curl,CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl,CURLOPT_USERAGENT,'amoCRM-oAuth-client/1.0');
    curl_setopt($curl,CURLOPT_URL, $link);
    curl_setopt($curl,CURLOPT_HTTPHEADER, $headers);
    curl_setopt($curl,CURLOPT_HEADER, false);
    curl_setopt($curl,CURLOPT_SSL_VERIFYPEER, 1);
    curl_setopt($curl,CURLOPT_SSL_VERIFYHOST, 2);
    $out = curl_exec($curl); //Инициируем запрос к API и сохраняем ответ в переменную
    $code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    curl_close($curl);
    /** Теперь мы можем обработать ответ, полученный от сервера. Это пример. Вы можете обработать данные своим способом. */
    $code = (int)$code;
    $errors = [
    	400 => 'Bad request',
    	401 => 'Unauthorized',
    	403 => 'Forbidden',
    	404 => 'Not found',
    	500 => 'Internal server error',
    	502 => 'Bad gateway',
    	503 => 'Service unavailable',
    ];
    
    try
    {
    	/** Если код ответа не успешный - возвращаем сообщение об ошибке  */
    	if ($code < 200 && $code > 204) {
    		throw new Exception(isset($errors[$code]) ? $errors[$code] : 'Undefined error', $code);
    	}
    }
    catch(\Exception $e)
    {
    	die('Ошибка: ' . $e->getMessage() . PHP_EOL . 'Код ошибки: ' . $e->getCode());
    }
    
    

    Подобным образом можно делать запросы ко всем методам API, на которые у токена хватает прав.

    6. Обработка ошибок

    В ходе отработки всей вышеуказанной логики может возникать ряд исключений, которые необходимо обрабатывать, рассмотрим каждое из них:

    1. Если пользователь не дал разрешение на доступ к аккаунту, в случае использования кнопки amoCRM, будет вызвана функция, которая передана в одном из параметров. Подробней можно прочесть в разделе Кнопка amoCRM. Если же страница была открыта не кнопкой, то в случае отказа будет произведен редирект на Redirect URI c GET-параметром error=access_denied.
    2. Если администратор аккаунта деактивировал установку интеграции, то выданные ей access_token будут отозваны. При обращении к API вы получите HTTP код 401. Для продолжения работы интеграции интегратору необходимо снова получить авторизацию для его интеграции у пользователя.
    3. Если вы не записали актуальный refresh token, он был утерян, либо прошло более 3 месяцев, то для возобновления работы интеграции вам опять необходимо пройти процесс авторизации приложения.
    4. Если вами были утеряны основные ключи интеграции или вы случайно их опубликовали, то вы можете обновить секретный ключ в модальном окне интеграции в аккаунте, где она была создана. После обновления Secret Key интеграции вам необходимо обновить секретный ключ в конфигурациях ваших интеграциях.

    Смотрите также

    Библиотека
    Кнопка на сайт