You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

无需用户数据,如何通过Spotify Web API获取艺人基础信息?

解决Spotify API 401未授权问题(非用户中心请求)

我完全懂你的困惑——之前很多API像SongKick/LastFM直接传密钥就能用,但Spotify的API规则不一样,哪怕是非用户相关的公开数据请求,现在也需要通过Client Credentials Flow获取访问令牌,不能直接裸发请求。

下面是修改后的可运行代码,你只需要把YOUR_CLIENT_IDYOUR_CLIENT_SECRET替换成你在Spotify开发者后台创建应用时拿到的对应值就行:

// 替换成你的Spotify客户端ID和密钥
const CLIENT_ID = 'YOUR_CLIENT_ID';
const CLIENT_SECRET = 'YOUR_CLIENT_SECRET';
let accessToken = '';

// 获取访问令牌
const getAccessToken = async () => {
  const response = await fetch('https://accounts.spotify.com/api/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      'Authorization': 'Basic ' + btoa(CLIENT_ID + ':' + CLIENT_SECRET)
    },
    body: 'grant_type=client_credentials'
  });
  const data = await response.json();
  accessToken = data.access_token;
};

// 预获取令牌
getAccessToken();

// find template and compile it
var templateSource = document.getElementById('results-template').innerHTML,
    template = Handlebars.compile(templateSource),
    resultsPlaceholder = document.getElementById('results'),
    playingCssClass = 'playing',
    audioObject = null;

var fetchTracks = function (albumId, callback) {
    $.ajax({
        url: 'https://api.spotify.com/v1/albums/' + albumId,
        headers: {
          'Authorization': 'Bearer ' + accessToken
        },
        success: function (response) {
            callback(response);
        },
        error: function(xhr) {
          // 如果令牌过期,重新获取再重试
          if (xhr.status === 401) {
            getAccessToken().then(() => {
              fetchTracks(albumId, callback);
            });
          }
        }
    });
};

var searchAlbums = function (query) {
    $.ajax({
        url: 'https://api.spotify.com/v1/search',
        headers: {
          'Authorization': 'Bearer ' + accessToken
        },
        data: { q: query, type: 'album' },
        success: function (response) {
            resultsPlaceholder.innerHTML = template(response);
        },
        error: function(xhr) {
          if (xhr.status === 401) {
            getAccessToken().then(() => {
              searchAlbums(query);
            });
          }
        }
    });
};

results.addEventListener('click', function (e) {
    var target = e.target;
    if (target !== null && target.classList.contains('cover')) {
        if (target.classList.contains(playingCssClass)) {
            audioObject.pause();
        } else {
            if (audioObject) {
                audioObject.pause();
            }
            fetchTracks(target.getAttribute('data-album-id'), function (data) {
                audioObject = new Audio(data.tracks.items[0].preview_url);
                audioObject.play();
                target.classList.add(playingCssClass);
                audioObject.addEventListener('ended', function () {
                    target.classList.remove(playingCssClass);
                });
                audioObject.addEventListener('pause', function () {
                    target.classList.remove(playingCssClass);
                });
            });
        }
    }
});

document.getElementById('search-form').addEventListener('submit', function (e) {
    e.preventDefault();
    searchAlbums(document.getElementById('query').value);
}, false);

关键修改点说明:

  • 添加了getAccessToken函数,通过Client Credentials Flow获取访问令牌(有效期1小时),代码还加入了401重试逻辑,自动刷新过期令牌。
  • 所有API请求都新增了Authorization: Bearer {accessToken}请求头,这是Spotify API强制要求的认证方式。
  • 注意:前端代码直接暴露Client Secret存在安全风险,如果是生产环境应用,建议把令牌获取逻辑放到后端,前端从后端拿令牌;但做Demo/测试的话,这样写完全没问题。

你把这段代码放到JSFiddle里,替换好Client ID和Secret,就能正常运行了。

内容的提问来源于stack exchange,提问作者armyofda12mnkeys

火山引擎 最新活动