Spotify Web API - 为啥新创建的播放列表没有填充所选歌曲?

Posted

技术标签:

【中文标题】Spotify Web API - 为啥新创建的播放列表没有填充所选歌曲?【英文标题】:Spotify Web API - why is the newly created playlist not populated with chosen songs?Spotify Web API - 为什么新创建的播放列表没有填充所选歌曲? 【发布时间】:2020-06-29 23:54:38 【问题描述】:

我目前在 Codecademy - Jamming 上遇到了一个 React 项目。它使用 Spotify WEB API 创建播放列表并将其保存回用户帐户。

流程如下:

    在搜索栏中输入搜索词, 按“搜索”按钮通过隐式授予流程获取临时访问令牌并返回搜索结果, 搜索结果填充在结果列表中, 用户通过将歌曲添加到播放列表列来选择歌曲, 用户输入选择的播放列表名称并点击保存到 Spotify, 在后台,POST 方法使用所选名称创建播放列表并返回唯一 ID(Spotify.savePlaylist();见下文), 唯一 ID 用于使用另一种 POST 方法将所选歌曲填充到播放列表中。

我面临的问题是,当我点击保存到 Spotify 时,播放列表在我的帐户中创建但为空!最重要的是,我收到以下消息:

我已经浓缩为独立代码(从 React App.js 中删除),以便通过 savePlaylist() 函数模拟按钮单击(我设法重现了该问题)。下面的 Spotify 对象包含获取访问令牌、搜索歌曲以及(我感兴趣的)创建播放列表然后保存相应曲目的方法。

完成API动作的模块Spotify.js如下:

const clientId = '6acd4fb43b3443c190e390753512049d'//Create a working Spotify Web API project to get the client id
const redirectUri = 'https://www.spotify.com/uk/'; //a redirect uri that matches value in the Spotify WEB API project page
let accessToken;

//below are manual entries for the playlist name and tracks (with unique spotify URI)
const playlistTracks = ["spotify:track:6UaHTPaVvS1rasCTUs64N0", "spotify:track:6bC1z4GVrswBEw0D2pOkbT"];
const playlistName = '*** Jams II';

const Spotify = 
    getAccessToken() 
        if (accessToken) 
            return accessToken;
        

        //check for access token match
        const accessTokenMatch = window.location.href.match(/access_token=([^&]*)/);
        const expiresInMatch = window.location.href.match(/expires_in=([^&]*)/);

        if (accessTokenMatch && expiresInMatch) 
            accessToken = accessTokenMatch[1];
            const expiresIn = Number(expiresInMatch[1]);
            // This clears the parameters, allowing us to grab a new access token when it expires
            window.setTimeout(() => accessToken = '', expiresIn * 1000);
            window.history.pushState('Access Token', null, '/');
            return accessToken;
         else 
            const accessUrl = `https://accounts.spotify.com/authorize?client_id=$clientId&response_type=token&scope=playlist-modify-public&redirect_uri=$redirectUri`;
            window.location = accessUrl;
        
    ,

    search(term) 
        const accessToken = Spotify.getAccessToken();
        return fetch(`https://api.spotify.com/v1/search?type=track&q=$term`, 
            headers: 
                Authorization: `Bearer $accessToken`
            
        ).then(response => 
            return response.json();
        ).then(jsonResponse => 
            if (!jsonResponse.tracks) 
                return [];
            
            return jsonResponse.tracks.items.map(track => (
                id: track.id,
                name: track.name,
                artist: track.artists[0].name,
                album: track.album.name,
                uri: track.uri
            ));
        )
    ,

    savePlaylist(name, trackUris) 
        if (!name || !trackUris.length) 
            return;
        

        const accessToken = Spotify.getAccessToken();
        const headers =  Authorization: `Bearer $accessToken` ;
        let userId;
        console.log(trackUris);
        console.log(accessToken);

        return fetch('https://api.spotify.com/v1/me',  headers: headers 
        ).then(response => response.json()
        ).then(jsonResponse => 
            userId = jsonResponse.id;
            return fetch(`https://api.spotify.com/v1/users/$userId/playlists`, 
                headers: headers,
                method: 'POST',
                body: JSON.stringify( name: name )
            ).then(response => response.json()
            ).then(jsonResponse => 
                const playlistId = jsonResponse.id;
                return fetch(`­https://api.spotify.com/v1/users/$userId/playlists/$playlistId/tracks`,
                    
                        headers: headers,
                        method: 'POST',
                        body: JSON.stringify( uris: trackUris ) 
                    )
            )
        )
    
;

function savePlaylist() 
    Spotify.savePlaylist(playlistName, playlistTracks);
  ;

savePlaylist();

另一个小问题(可能是一种症状) - 当我第一次进行搜索时,会填充曲目列表,然后立即刷新页面。此时,重定向页面有一个附加了访问令牌和到期时间的查询字符串,如下所示:

http://localhost:3000/#access_token=BQB-F1LdIdZSW5zD7P5IIaxRbbO_jkPZL4RFkDGqzI0IDXEMS6J1P7P4MpqN2ogj-P5oNWfA7Lea2sZlI5g9qTHqNSODlBwI3hNiVjyh45pWujsgsGIaDLyjlxI6cB4PhU72Wvu10Kd_UFfDOaBmlhgmUJ8gpNjCjj6QsIEiJ38&token_type=Bearer&expires_in=3600

只有当我再次搜索该词时,才会填充曲目列表。这有关系吗?

【问题讨论】:

【参考方案1】:

尝试 - 发布 https://api.spotify.com/v1/playlists/playlist_id/tracks 而不是 - POST https://api.spotify.com/v1/users/user_id/playlists/playlist_id/tracks 当您将曲目添加到播放列表时。看到这个blog post。

【讨论】:

以上是关于Spotify Web API - 为啥新创建的播放列表没有填充所选歌曲?的主要内容,如果未能解决你的问题,请参考以下文章

Spotify Web API 客户端范围不起作用

Spotify Web API - 登录后如何扩展权限范围?

Spotify Web API 无论如何都会给我非法范围

为啥身份验证类型 - 当我们创建新的 Web APi 服务时,.NET Core 中 Web API 的个人用户帐户不可用

我可以使用 Spotify Web API 来创建 Android/iOS Web 应用程序吗?

如何使用其 Web-API 让 IOS 应用播放 Spotify 播放列表?