Лента instagram на сайте с 2020 года: с использованием API

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

С начала 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.

Справочник по Graph API

?

Благодарю за ответ!

Была ли эта информация полезной?

Здравствуйте!

Позвольте представиться, меня зовут Марина. Более 10 лет я занимаюсь обслуживанием сайтов и развитием интернет проектов. Если вы хотите избавиться от хлопот связанных с созданием и поддержкой сайта, тогда вы попали по адресу. При работе с сайтами я предоставляю качественные услуги, ориентируясь на ваши индивидуальные потребности. Для связи со мной воспользуйтесь формой обратной связи.

Инсталента
Пожалуйста, активируйте JavaScript.
Please enable JavaScript.
return; 1