简体   繁体   中英

Instagram API Basic Display: Problem with requesting access_token

I was following Instagram API Basic Display documentation. I've created Facebook App, configured Instagram Basic Display, added Test User, Authenticated the Test User using GET request:

https://api.instagram.com/oauth/authorize
  ?app_id={app-id}
  &redirect_uri={redirect-uri}
  &scope=user_profile,user_media
  &response_type=code

But when I try to request access_token using POST request from the documentation: I receive ERROR 400 with message "You must provide a client_id". However, documentation says nothing about client_id and Instagram Basic Display doesn't provide client_id.

在此处输入图像描述

What am I doing wrong? Has any of you had similar problem?

You should make a POST request to https://api.instagram.com/oauth/access_token with the parameters in the body , NOT the Params. Make sure that the "x-www-form-urlencoded" option is enable.

在此处输入图像描述

See a more detailed answer here: https://stackoverflow.com/a/60851414/1908112

I managed to get mine working by using GuzzleHttp\Client like this.

Step 1 . get the Authorization Code $code

Step 2 . Get the short-lived AccessToken

Short-Lived Access tokens are valid for just 1 hour.

$aAccessToken = $this->fetchAccessToken( $code );
$short_lived_access_token = $aAccessToken[ 'access_token' ];
$user_id                  = $aAccessToken[ 'user_id' ];

Step 3 (optional)

If you want the Long-Lived token, which is valid for 60days, you can immediately exchange the $short_lived_access_token.

$aLongLivedTokenResult   =           = $this->GetLongLivedToken( $short_lived_access_token );
$long_lived_access_token = $aLongLivedTokenResult[ 'access_token' ];
$expires_in = $aLongLivedTokenResult[ 'expires_in' ];

long_lived_access_token and expires_in can be saved and when the token has expired after 60 days you can refresh it.

Step 4 Now you can fetch the user media like this.

Bear in mind that the long_lived_access_token expires and before you FETCH you should actually check if the token has expired and if it has, exchange it to get a new one. And the token recycling begins.

    $aQueryString = [
        'fields'       => 'id,media_url,permalink,timestamp,caption',
        'access_token' => $long_lived_access_token,

    ];
    $uri = 'https://graph.instagram.com/{$user_id}/media?' . http_build_query( $aQueryString ) );

//functions

Because the fetchAccessToken function uses the POST method, Adding content-type = application/x-www-form-urlencoded on the headers alone didn't really work. form_params on the options did the trick for me.

private function fetchAccessToken(){
    $aOptions = [
      'app_id'       => $this->provider->AppID,
      'app_secret'   => $this->provider->AppSecret,
      'grant_type'   => 'authorization_code',
      'redirect_uri' => $this->provider->getRedirectUri(),
      'code'         => $accessCode,       
    ];

    $client   = new Client( [
        'base_uri' => 'https://api.instagram.com',
        'headers'  => [
            'content-type' => 'application/x-www-form-urlencoded',
        ],
    ] );


    $response = $client->request( 'POST', 'oauth/access_token', [
        'form_params' => $aOptions,
    ] );
    return json_decode( $response->getBody(), true );

}

private function GetLongLivedToken( $access_token )
{

    $aOptions = [
        'grant_type'    => 'ig_exchange_token',
        'client_secret' => $this->provider->AppSecret,
        'access_token'  => $access_token,

    ];

    $response =  new Client( [
        'base_uri' => 'https://graph.instagram.com',
    ] )->request( 'GET', 'access_token?' . http_build_query( $aOptions ) );

    $stream   = $response->getBody();
    $contents = $stream->getContents();
    return json_decode( $contents, true ); 

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM