反应/节点:Spotify API 错误:404 - 未找到活动设备

Posted

技术标签:

【中文标题】反应/节点:Spotify API 错误:404 - 未找到活动设备【英文标题】:React/Node: Spotify API Error: 404 - No Active Device Found 【发布时间】:2019-02-15 12:58:48 【问题描述】:

我创建了一个仅适用于 Spotify 高级用户的应用(根据 Spotify 的文档,PUT 方法不适用于非高级用户)。这是一个包含十个问题的交互式测验,播放列表会在您的 Spotify 帐户中生成,播放后您必须猜出每首歌曲的名称。它使用 NodeJS 后端生成并通过 ReactJS 显示。游戏可以在这里演示:https://am-spotify-quiz.herokuapp.com/

可以在下面查看代码:

server.js

const express = require('express');
const request = require('request');
const cors = require('cors');
const querystring = require('querystring');
const cookieParser = require('cookie-parser');

const client_id = ''; // Hiding for now
const client_secret = ''; // Hiding
const redirect_uri =  'https://am-spotify-quiz-api.herokuapp.com/callback/'; 
const appUrl = 'https://am-spotify-quiz.herokuapp.com/#';

/**
 * Generates a random string containing numbers and letters
 * @param  number length The length of the string
 * @return string The generated string
 */
var generateRandomString = function(length) 
  var text = '';
  var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

  for (var i = 0; i < length; i++) 
    text += possible.charAt(Math.floor(Math.random() * possible.length));
  
  return text;
;

var stateKey = 'spotify_auth_state';

var app = express();

app.use(express.static(__dirname + '/public'))
   .use(cors())
   .use(cookieParser());

app.get('/login', function(req, res) 

  var state = generateRandomString(16);
  res.cookie(stateKey, state);

  // scopes needed to make required functions work
  var scope = 'user-read-private ' + 
              'user-read-email ' + 
              'user-read-playback-state ' + 
              'user-top-read ' +
              'playlist-modify-public ' +
              'playlist-modify-private ' +
              'user-modify-playback-state ' +
              'user-read-playback-state';
  res.redirect('https://accounts.spotify.com/authorize?' +
    querystring.stringify(
      response_type: 'code',
      client_id: client_id,
      scope: scope,
      redirect_uri: redirect_uri,
      state: state
    ));
);

app.get('/callback/', function(req, res) 

  // your application requests refresh and access tokens
  // after checking the state parameter

  var code = req.query.code || null;
  var state = req.query.state || null;
  var storedState = req.cookies ? req.cookies[stateKey] : null;

  if (state === null || state !== storedState) 
    res.redirect(appUrl +
      querystring.stringify(
        access_token: access_token,
        refresh_token: refresh_token
      ));
   else 
    res.clearCookie(stateKey);
    var authOptions = 
      url: 'https://accounts.spotify.com/api/token',
      form: 
        code: code,
        redirect_uri: redirect_uri,
        grant_type: 'authorization_code'
      ,
      headers: 
        'Authorization': 'Basic ' + (new Buffer(client_id + ':' + client_secret).toString('base64')),
      ,
      json: true
    ;

    request.post(authOptions, function(error, response, body) 
      if (!error && response.statusCode === 200) 

        var access_token = body.access_token,
            refresh_token = body.refresh_token;

        var options = 
          url: 'https://api.spotify.com/v1/me',
          headers:  
            'Authorization': 'Bearer ' + access_token,
            'Content-Type': 'application/json' // May not need
          ,
          body:  // Likely don't need this anymore!
            'name': 'Test Playlist', 
            'public': false
          ,
          json: true
        ;

        // use the access token to access the Spotify Web API
        request.get(options, function(error, response, body) 
          console.log(body);
        );

        // we can also pass the token to the browser to make requests from there
        res.redirect(appUrl +
          querystring.stringify(
            access_token: access_token,
            refresh_token: refresh_token
          ));
       else 
        res.redirect(appUrl +
          querystring.stringify(
            error: 'invalid_token'
          ));
      
    );
  
);

// AM - May not even need this anymore!
app.get('/refresh_token', function(req, res) 

  // requesting access token from refresh token
  var refresh_token = req.query.refresh_token;
  var authOptions = 
    url: 'https://accounts.spotify.com/api/token',
    headers:  'Authorization': 'Basic ' + (new Buffer(client_id + ':' + client_secret).toString('base64')) ,
    form: 
      grant_type: 'refresh_token',
      refresh_token: refresh_token
    ,
    json: true
  ;

  request.post(authOptions, function(error, response, body) 
    if (!error && response.statusCode === 200) 
      var access_token = body.access_token;
      res.send(
        'access_token': access_token
      );
    
  );
);

console.log('Listening on 8888');
app.listen(process.env.PORT || 8888);

我有一个 react 组件,它会在用户登录后立即显示,名为 premium.js。如果你需要所有的代码,你可以看到它here。以下是我的游戏需要的两种 PUT 方法;一个用于关闭随机播放功能,另一个用于播放播放列表:

 removeShuffle() 
    axios(
      url: 'https://api.spotify.com/v1/me/player/shuffle?state=false',
      method: "PUT",
      headers: 
        'Authorization': 'Bearer ' + this.state.accesstoken
      
    )
      .then((response) => 
        console.log(response)
      )
      .catch((error) => 
        console.log(error)
      )

  

  // Then... play the playlist to get started
  playPlaylist(contextUri) 
    axios(
      url: 'https://api.spotify.com/v1/me/player/play',
      method: "PUT",
      data: 
        context_uri: contextUri
      ,
      headers: 
        'Authorization': 'Bearer ' + this.state.accesstoken
      
    )
      .then((response) => 
        console.log(response)
      )
      .catch((error) => 
        console.log(error)
      )
  

当我作为游戏的创造者尝试时,这些都可以正常工作;但是,我让另一个高级用户尝试了它并发现了这个错误:

这似乎没有多大意义,因为我发现此错误发生在其他用户身上,无论他们使用的是 Windows 还是 Mac。有谁知道这意味着什么,我该如何解决?提前致谢!

【问题讨论】:

【参考方案1】:

我也一直在使用 Spotify 的 API,但在不活动期后尝试 PUT https://api.spotify.com/v1/me/player/play 时最终遇到了同样的错误,其中没有设备被标记为活动(我不知道确切的时间,但不超过几个小时)。

显然必须将一台设备设置为active,这样才能成功调用play端点。

如果要将设备状态更改为active,根据their documentation,可以先尝试GET https://api.spotify.com/v1/me/player/devices获取可用设备列表:

// Example response

  "devices" : [ 
    "id" : "5fbb3ba6aa454b5534c4ba43a8c7e8e45a63ad0e",
    "is_active" : false,
    "is_private_session": true,
    "is_restricted" : false,
    "name" : "My fridge",
    "type" : "Computer",
    "volume_percent" : 100
   ]


然后通过调用player endpoint PUT https://api.spotify.com/v1/me/player 选择一个可用的设备,包括:

device_ids 必填。一个 JSON 数组,包含应该开始/传输播放的设备的 ID。 例如:device_ids:["74ASZWbe4lXaubB36ztrGX"] 注意:虽然接受数组,但目前仅支持单个 device_id。提供多个将返回 400 Bad Request playtrue 如果你想马上开始玩的话。

您自己很可能没有收到该错误,因为您的其中一台设备在您测试时已经处于活动状态。如果您自己的帐户在几个小时内没有任何活动,然后尝试调用 v1/me/player/play 端点,我希望您会收到相同的错误。

一个简单的解决方法是让你的测试用户开始在 Spotify 应用上播放一首歌曲(不管是哪一个),然后暂停它,然后触发你的调用v1/me/player/play 端点的应用程序。那不应该再返回 No active device found 错误了。

【讨论】:

【参考方案2】:

据我了解,您正在尝试播放不属于当前用户 (/me) 的播放列表,这可能是导致错误的原因。

【讨论】:

不幸的是,根据 Spotify 文档,我需要保持原样的链接......并且我在 URL 中有一些带有 /me/ 的 POST 功能,适用于使用该应用程序的其他用户。

以上是关于反应/节点:Spotify API 错误:404 - 未找到活动设备的主要内容,如果未能解决你的问题,请参考以下文章

Spotify API 在尝试获取播客信息时返回 404 未找到

Spotify API 创建播放列表返回 错误: 状态:400,消息:'解析 JSON 时出错。'

使用邮递员 404 端点发现 api 身份验证

Spotify API 错误 403 用户未批准应用程序:尝试访问应用程序所有者以外的其他用户的用户信息时

从 Spotify 的 Discover Weekly Playlist 获取曲目时未找到 404

人脸 API - Person Group PUT 操作期间出现错误 404