Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fatal error: Uncaught exception on page refresh #52

Closed
ghost opened this issue Sep 13, 2016 · 7 comments
Closed

Fatal error: Uncaught exception on page refresh #52

ghost opened this issue Sep 13, 2016 · 7 comments
Labels

Comments

@ghost
Copy link

ghost commented Sep 13, 2016

Hi, I am getting the following error when I refresh my Spotify web app...

Fatal error: Uncaught exception 'SpotifyWebAPI\SpotifyWebAPIException' with message 'Invalid authorization code' in /Users/user/Desktop/WEB-DEV/spotify-web-api-php-master/src/Request.php:170 Stack trace: #0 /Users/user/Desktop/WEB-DEV/spotify-web-api-php-master/src/Request.php(50): SpotifyWebAPI\Request->send('POST', 'https://account...', Array, Array) #1 /Users/user/Desktop/WEB-DEV/spotify-web-api-php-master/src/Session.php(205): SpotifyWebAPI\Request->account('POST', '/api/token', Array, Array) #2 /Users/user/Desktop/WEB-DEV/spotify-web-api-php-master/includes/api-key.php(4): SpotifyWebAPI\Session->requestAccessToken('AQAaKVCyJ2eX1vE...') #3 /Users/user/Desktop/WEB-DEV/spotify-web-api-php-master/index.php(20): include('/Users/user/Des...') #4 {main} thrown in /Users/user/Desktop/WEB-DEV/spotify-web-api-php-master/src/Request.php on line 170

I think the reason for this error is because the URL has the code from Spotify as a query string on the end. If I delete everything from ?code onwards and reload the page it works fine. I just cant figure out how to not display the query string on the URL but keep the app working.

My code is as follows...

<?php
error_reporting(-1);
ini_set('display_errors', 1);

require 'vendor/autoload.php';

$session = new SpotifyWebAPI\Session('4741073d687b495eb89b3eec754ccfba', '9dfe49b200e44dbbac18fd43b9ef8ae1', 'http://localhost:8888/spotify-web-api-php-master/');
$scopes = array(
    'playlist-read-private',
    'user-read-private',
    'user-library-modify'
);
$authorizeUrl = $session->getAuthorizeUrl(array(
    'scope' => $scopes
));
$api = new SpotifyWebAPI\SpotifyWebAPI();

if (isset($_GET['code'])) { 
    $api = new SpotifyWebAPI\SpotifyWebAPI();

    $session->requestAccessToken($_GET['code']);
    $accessToken = $session->getAccessToken();

    $api->setAccessToken($accessToken);
?>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">

    <link rel="stylesheet" href="stylesheets/app.css">
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.10/angular-ui-router.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular-animate.min.js"></script>
    <script src="js/app.js"></script>

</head>
<body ng-app="formApp">
<header>
    <div class="logo left">
        <h1>sndtrk.</h1>
    </div>
    <?php include('includes/session-info.php'); ?>
</header>
<!-- views will be injected here -->
<div class="container full-height">
    <div ui-view class="form-wrapper full-height {{ formData.one }} {{ formData.onea }} {{ formData.two }} {{ formData.twoa }} {{ formData.threea }} {{ formData.threeb }} {{ formData.threeab }} {{ formData.four }} {{ formData.five }} {{ formData.six }}"></div>
</div>
<?php include('includes/track-generator.php'); ?>
</body>
</html>
<?php
} else {
    header('Location: ' . $authorizeUrl);
    die();
} ?>

Thanks

@jwilsson
Copy link
Owner

Hi!
I think the easiest way is to have two pages.

One page (let's call it index.php) that contains your application and checks if an access token already exists (saved in a database, a session, or somewhere persistent). If an access token doesn't exist, send the user to the authorization URL with a redirect URI called callback.php.

In callback.php you exchange the $_GET['code'] for an access token, save it somewhere, and redirect the user back to index.php.

@ghost
Copy link
Author

ghost commented Sep 14, 2016

Awesome, thank you for your help! I've got it working, I think. Storing the $accessToken within a session variable and recalling it on index.php worked.

@hycday
Copy link
Contributor

hycday commented Mar 2, 2017

Hi !

I'm sorry, I'm not sure I understand this page : https://jwilsson.github.io/spotify-web-api-php/authorization.html
and I get the same error.

Here is my code, would appreciate some help :)

in ./index.php :

<?php
error_reporting(-1);
ini_set('display_errors', 1);

require 'vendor/autoload.php';

$session = new SpotifyWebAPI\Session('CLIENT_ID', 'CLIENT_SECRET', 'https://mysite.com/callback');
$scopes = array(
    'playlist-read-private',
    'user-read-private',
    'user-read-recently-played'
);
$authorizeUrl = $session->getAuthorizeUrl(array(
    'scope' => $scopes
));

$api = new SpotifyWebAPI\SpotifyWebAPI();

if (isset($_GET['code'])) { 
    $api = new SpotifyWebAPI\SpotifyWebAPI();

    $session->requestAccessToken($_GET['code']);
    $accessToken = $session->getAccessToken();

    $api->setAccessToken($accessToken);


?>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">

</head>
<body>
   <?php 

 ?>
</body>
</html>


<?php
} else {

    header('Location: ' . $session->getAuthorizeUrl($scopes));
    die();
} ?>

then in ./callback/index.php :

<?php
error_reporting(-1);
ini_set('display_errors', 1);

require '../vendor/autoload.php';

$session = new SpotifyWebAPI\Session('CLIENT_ID', 'CLIENT_SECRET', 'https://mysite.com/callback');

$api = new SpotifyWebAPI\SpotifyWebAPI();

if (isset($_GET['code'])) {
    $session->requestAccessToken($_GET['code']);
    $api->setAccessToken($session->getAccessToken());

    $artist = $api->getMyHistory(array('limit' => 4));

    for ($i=0; $i < $artist->limit ; $i++) {

        $track = $api->getTrack($artist->items[$i]->track->id);
        echo '<img src="'.$track->album->images[2]->url.'" />';
        echo '<a href="'.$artist->items[$i]->track->external_urls->spotify.'" target="_blank">'.$artist->items[$i]->track->artists[0]->name.' - '. $artist->items[$i]->track->name . ' </a> <br/>';

    }

} else {
    $scopes = [
    'scope' => [
    'playlist-read-private',
    'user-read-private',
    'user-read-recently-played'
        ],
    ];

    header('Location: ' . $session->getAuthorizeUrl($scopes));
}

What happens is that if I go to https://mysite.com/ I immediately get redirected to https://mysite.com/callback?code=XXXXXXX and the result that I want is displayed. However if I refresh, I get this uncaught exception.

Could you please help me to understand your authorization doc page ?

thanks !

@jwilsson
Copy link
Owner

jwilsson commented Mar 2, 2017

@hycday Instead of printing the history in ./callback/index.php, save the token somewhere (PHP session, database, etc.) and redirect the user back to index.php.

In index.php, check if you got a token. If there is one, use it and print the history. If not, send the user to the Spotify authorization page.

Sloppy, untested example using PHP sessions: https://gist.github.com/jwilsson/07f30721b5a3378c78bf4c86cdc92b98

I can agree that the docs could be more clear, though. I'll look at updating it.

@hycday
Copy link
Contributor

hycday commented Mar 2, 2017

thank you @jwilsson
it's more clear now !

@hycday
Copy link
Contributor

hycday commented Mar 3, 2017

just out of curiosity, I managed to do it in PHP session (then each user will see their own tracks), but when I do it with a database, I am facing a problematic : they all see my tracks.

Indeed, in the database, (in which I have a token field, a timestamp field, and a userid field), I need to insert a row with a token (or update it for same userid, if timestamp is expired and userid exists), but I just used a fake userid manually inputed, so therefore, their is only one user, and hence they all see my tracks.

Is there a function to identify the user via some sort of ID, proper to Spotify ? or basically the database approach is not applicable ?

If I remove the userid field, how will I know which token to retrieve from the database, for each user...

Do you see what I mean ?

@jwilsson
Copy link
Owner

jwilsson commented Mar 5, 2017

@hycday Let's not hijack this issue anymore, drop me a line at jonathan.wilsson at gmail and we can discuss further there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants