Лента instagram на сайте с 2020 года: с использованием API
Отредактировано: 01 Июня 2020
От регулярных изменений командой фейсбука политики доступа к контенту инстаграмма, в интернете появилось множество не работающих виджитов, плагинов и прочих статей о том как создать ленту на сайте. Работоспособность данного метода вы можете увидеть в нижней части страницы.
С начала 2020 года инстаграм закрывает базовый доступ к API (instagram basic API). С этой поры работает 2 уровня доступа:
- Instagram basic display API — для ограниченной работы с возможностями инстаграм (чтение основных данных пользователей, публикация собственной ленты на сайте и т.п.);
- Instagram graph API — для создания сложных программ с использованием инстаграма (аутинтификация, работа с данными с чужих аккаунтов и т.п.).
Официальная документация по API
Для создания ленты на сайте, сперва надо зарегистрировать аккаунт разработчика на фейсбуке. Затем, создать в интерфейсе разработчика новое приложение. Для простого отображения ленты на сайте проверка приложения не требуется, и главная задача — правильно заполнить нужные поля.
Настройка приложения
После того как нажмете кнопку создать приложение, введите его название. Затем, на вкладке «Настройки -> Основное» промотайте страницу до самого низа, и нажмите кнопку добавить платформу. В предоставленном списке нажмите веб-сайт (если делаете ленту на сайте). В появившейся строке укажите адрес сайта на котором будет реализовываться лента.
Далее, в меню в подрубрике «Товары» перейдите в раздел instagram -> Basic Display и нажмите кнопку «Создать новое приложение». Укажите название приложения, Заполните поля со ссылками для авторизации oauth:
- переадресация для OAuth — https://your-site.ru/oauth/
- Отменить авторизацию, Запросы на удаление данных — https://your-site.ru/
Далее переходим на вкладку меню «Роли -> Роли», и добавляем тестового пользователя Instagram. Обратите внимание, не просто тестового пользователя, а именно Instagram, это отдельная строка. Вписываем туда адрес пользователя с нужной нам лентой. После чего заходим в соответствующий аккаунт инстаграм, в редактировании профиля ищем «Приложения и сайты -> Приглашения тестировщиков» и принимаем приглашение.
Официальное объяснение о настройке приложения
После того как дадите доступ тестовому пользователю к своему инстаграму, необходимо оформить ключ доступа (Access Token). Ключи бывают двух видов: короткий, действующий в течении часа, и длинный, на 60 дней.
Получение Access Token
Официальное объяснение о настройке краткосрочного ключа доступа
Официальное объяснение о настройке долгосрочного ключа доступа
Маркер доступа можно получать так как указано в документации, или путем использования скрипта. Cуть дальнейших действий — залогиниться тестовым пользователем, получить данные о состоянии аккаунта, записать данные в отдельный файл (в случае MODX в чанк) и выводить данный файл/чанк в соответствующем месте.
Php скрипт для получения access token с прошлой версии не изменился, за исключением того, что ключ теперь лучше оформить в отдельный запрос, который появится в статье позже. Итак, для получения токена сперва надо получить код авторизации по ссылке: введите в браузере ссылку для запроса параметра code, в которой CLIENT-ID заменить на полученный в процессе регистрации ID, а REDIRECT-URL заменить на адрес который был введен в поле OAuth redirect_uri. Код ссылки:
https://api.instagram.com/oauth/authorize
?client_id=CLIENT-ID
&redirect_uri=REDIRECT-URI
&scope=user_profile,user_media
&response_type=code
&state=1
Браузер предложит вам авторизоваться, после чего перекинет на указанный сайт, и в конце адресной строки будет код (в конце строки, примерно так: ?code=AQBx-hBsH3...#_). Этот код необходим для получения краткосрочного маркера.
- CLIENT-ID — полученный в процессе регистрации ID;
- REDIRECT-URL — адрес который был введен в приложении в поле OAuth redirect_uri.
Для получения краткосрочного токена используйте следующий php фрагмент (в случае если используете MODX, вставьте в снипет и выведете на скрытой странице):
$fields = array(
'client_id' => 'YOUR-CLIENT-ID',
'client_secret' => 'YOUR-CLIENT-SECRET',
'grant_type' => 'authorization_code',
'redirect_uri' => 'YOUR-REDIRECT-URI',
'code' => 'YOUR-CODE'
);
$url = 'https://api.instagram.com/oauth/access_token';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 9);
curl_setopt($ch, CURLOPT_POST,true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
$result = curl_exec($ch);
curl_close($ch);
$result = json_decode($result);
return "Access token:". $result->access_token ."<br> User ID:". $result->user_id;
- client_id: параметр Client Id;
- client_secret: параметр Client Secret;
- grant_type: authorization_code;
- redirect_uri: OAuth redirect_uri, который вы использовали в запросе авторизации;
- code: точный код, который вы получили на этапе авторизации;
- access_token: маркер доступа для отображения ленты;
- user_id: id пользователя чью ленту надо показывать.
Дальше, необходимо воспользоваться оформлением долгосрочного токена. А в идеале, необходим скрипт, который самостоятельно будет обновлять код с использованием соответствующей возможности API. В данной статье только разрозненные куски кода, которые я предлагаю собрать вам самостоятельно. Это не вредность, это декрет ;)
Пример кода для вывда долгосрочного маркера доступа:
<?php
$instagram_app_id = 'ID приложения';
$instagram_app_secret = 'SECRET приложения';
$instagram_app_url = 'URL страницы авторизации';
$apiBaseUrl = 'https://api.instagram.com/';
$graphBaseUrl = 'https://graph.instagram.com/';
$get_code = isset( $_GET['code'] ) ? $_GET['code'] : '';
$accessToken = '';
$user_id = '';
$hasUserAccessToken = false;
$authorizationVars = array(
'app_id' => $instagram_app_id,
'redirect_uri' => $instagram_app_url,
'scope' => 'user_profile,user_media',
'response_type' => 'code'
);
$output = '';
// формируем ссылку для авторизации
$authorizationUrl = $apiBaseUrl . 'oauth/authorize?' . http_build_query( $authorizationVars );
// проверяем получен ли код
if(!$get_code){
header("Location:$authorizationUrl");
}
// формируем ссылку для получения краткосрочного маркера
$shortAccessToken = array(
'endpoint_url' => $apiBaseUrl . 'oauth/access_token',
'type' => 'POST',
'url_params' => array(
'app_id' => $instagram_app_id,
'app_secret' => $instagram_app_secret,
'grant_type' => 'authorization_code',
'redirect_uri' => $instagram_app_url,
'code' => $get_code
)
);
// формируем ссылку для получения долгосрочного маркера
$longAccessToken = array(
'endpoint_url' => $graphBaseUrl . 'access_token',
'type' => 'GET',
'url_params' => array(
'client_secret' => $instagram_app_secret,
'grant_type' => 'ig_exchange_token'
)
);
// если полученны данные или получен код
if ( $accessToken ) { // при наличии access token
$userAccessToken = $accessToken;
$hasUserAccessToken = true;
$userId = $user_id;
} elseif ( $get_code ) { // если только GET код то получаем access token
$response = makeApiCall($shortAccessToken);
// записываем полученные данные в переменные
$accessToken = $response[access_token];
$user_id = $response[user_id];
$hasUserAccessToken = true;
// получаем долгосрочный маркер
$longAccessToken['url_params']['access_token'] = $accessToken;
$longLivedAccessTokenResponse = makeApiCall($longAccessToken);
$userAccessToken = $longLivedAccessTokenResponse['access_token'];
$userAccessTokenExpires = $longLivedAccessTokenResponse['expires_in'];
}
// функция вызова api и получения данных
function makeApiCall( $params ) {
$ch = curl_init();
$endpoint = $params['endpoint_url'];
if ( 'POST' == $params['type'] ) {
curl_setopt( $ch, CURLOPT_POSTFIELDS, http_build_query( $params['url_params'] ) );
curl_setopt( $ch, CURLOPT_POST, 1 );
} elseif ( 'GET' == $params['type'] ) {
// добавляем параметры в конец адреса
$endpoint .= '?' . http_build_query( $params['url_params'] );
}
curl_setopt( $ch, CURLOPT_URL, $endpoint );
curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, false );
curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
$response = curl_exec( $ch );
curl_close( $ch );
$responseArray = json_decode( $response, true );
if ( isset( $responseArray['error_type'] ) ) {
var_dump( $responseArray );
die();
} else {
return $responseArray;
}
}
foreach ($longLivedAccessTokenResponse as $key => $value){
$output .= $key.': '.$value.'<br>';
}
return $output;
Вывод ленты Instagram на сайте
После того как получили Access Token, используйте примерно такой код (в случае если у вас MODX, вставьте данный код в сниппет и вызывайте по крону):
<?php
$client_id='CLIENT_ID';
$token = 'ACCESS TOKEN';
$user_id = 'USER_ID';
$limit = 8; // количество фотографий для вывода
$tpl = $modx->getOption('tpl',$scriptProperties,'tpl.instafeed-item'); // шаблондля вывода элемента в MODX
$output = array();
$img = array();
$instagram_cnct = curl_init(); // инициализация cURL подключения
curl_setopt( $instagram_cnct, CURLOPT_URL, "https://graph.instagram.com/" . $user_id . "?fields=id,username,media&access_token=" . $token ); // подключаемся
curl_setopt( $instagram_cnct, CURLOPT_RETURNTRANSFER, 1 ); // просим вернуть результат
// ограничиваем по времени
curl_setopt( $instagram_cnct, CURLOPT_TIMEOUT, 9 );
curl_setopt( $instagram_cnct, CURLOPT_CONNECTTIMEOUT, 9 );
$media = json_decode( curl_exec( $instagram_cnct ) ); // получаем и декодируем данные из JSON
$data = $media->media->data;
// функция array_slice() задает количество элементов, которые нам нужно получить из массива
// если нам нужно вывести все фото, тогда: foreach($data as $key => $value) {
foreach(array_slice($data, 0, $limit) as $key => $value) {
$data_ids[] = $data[$key]->id; // создаем массив с id медиафайлов
};
$multi = curl_multi_init(); // инициализируем мультипоточный запрос cURL
foreach ($data_ids as $data_id) {
// Записываем данные по каждому отдельномуэлементу в массив
$item = curl_init();
curl_setopt($item, CURLOPT_URL, "https://graph.instagram.com/" . $data_id . "?fields=media_url,caption,permalink&access_token=" . $token ); // получаем данные файла
curl_setopt($item, CURLOPT_HEADER, false);
curl_setopt($item, CURLOPT_RETURNTRANSFER, true);
curl_setopt( $instagram_cnct, CURLOPT_TIMEOUT, 9 );
curl_setopt( $instagram_cnct, CURLOPT_CONNECTTIMEOUT, 9 );
curl_multi_add_handle($multi, $item);
$img[$data_id] = $item;
}
// читаем заклинания
$active = null;
do {
$mrc = json_decode( curl_multi_exec($multi, $active));
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active && $mrc == CURLM_OK) {
if (curl_multi_select($multi) == -1) {
continue;
}
do {
$mrc = json_decode( curl_multi_exec($multi, $active));
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
// Выводим данные элементов
foreach ($img as $data) {
$data = json_decode(curl_multi_getcontent($data));
$dataArray = array(
'link' => $data->permalink,
'img' => $data->media_url,
'description' => $data->caption
);
// записываем данные в шаблон MODX.
// Если используете другой движок, замените на соответствующий код, например php
// $output .= '<a href="'.$data->permalink.'"><img src="'.$data->media_url.'"></a>';
$output .= $modx->getChunk($tpl,$dataArray); // подключаем шаблон
curl_multi_remove_handle($multi, $img); // удаляем исполненные дескрипторы
}
curl_multi_close($multi); // закрываем мультисоединение
curl_close( $instagram_cnct ); // закрываем соединение
// записываем полученную информацию в чанк MODX
// Если используете другой движок, замените на соответствующий вашему случаю код
$chunk = $modx->getObject('modChunk', array('name' => 'block.instafeedList_2020'));
if($chunk){
$chunk->setContent($output);
$chunk->save();
}else{
$chunk = $modx->newObject('modChunk');
$chunk->set('name','block.instafeedList_2020');
$chunk->setContent($output);
$chunk->save();
}
//return $output;
Для корректной работы на хостинге / сервере должна быть установлена библиотека cURL
Если у вас MODX, то для удобства можно вынести html в отдельный чанк:
// создаем чанк с html разметкой, к примеру tpl.instafeed-item
<a href="[[+link]]" target="_blank">
<img src="[[+img]]" alt="">
</a>
// в сниппете добавляем строку определяющую шаблон
$tpl = $modx->getOption('tpl',$scriptProperties,'tpl.instafeed-item');
// данные блока foreach заменяем на
$dataArray = array(
'link' => $data->link,
'img' => $data->images->low_resolution->url
);
$output .= $modx->getChunk($tpl,$dataArray);
Результатом работы сниппета будет созданный или обновленный чанк block.instafeedList_2020, который надо вызвать в том месте шаблона, где должна располагаться лента
[[$block.instafeedList_2020]]
Доступные поля для получения информации о пользователе (в документации):
- $user->account_type — тип аккаунта пользователя. Возможные варианты: BUSINESS, MEDIA_CREATOR, PERSONAL.
- $user->id — ID пользователя.
- $user->media_count — количество медиафайлов узла User. Чтобы использовать это поле, необходимо разрешение instagram_graph_user_media.
- $user->username — имя пользователя.
- $user->media — список медиафайлов пользователя (изображения видео и т.п.).
Доступные поля для получения информации о медиафайлах (в документации):
- $data->caption — подпись к изображению или видео. Для медиафайлов в альбомах не возвращается.
- $data->id — ID медиафайла.
- $data->media_type — тип медиафайла. Возможные варианты: IMAGE, VIDEO, CAROUSEL_ALBUM.
- $data->media_url — URL медиафайла.
- $data->permalink — постоянный URL медиафайла (ссылка на файл в инстаграм).
- $data->thumbnail_url — URL миниатюры медиафайла. Доступно только для типа VIDEO.
- $data->timestamp — дата публикации медиафайла в формате ISO 8601.
- $data->username — имя пользователя, опубликовавшего медиафайл.
- $data->children — список медиафайлов в альбоме. Доступно только для типа CAROUSEL_ALBUM.
Здравствуйте!
Позвольте представиться, меня зовут Марина. Более 10 лет я занимаюсь обслуживанием сайтов и развитием интернет проектов. Если вы хотите избавиться от хлопот связанных с созданием и поддержкой сайта, тогда вы попали по адресу. При работе с сайтами я предоставляю качественные услуги, ориентируясь на ваши индивидуальные потребности. Для связи со мной воспользуйтесь формой обратной связи.