Java中使用Spotify API时授权码无效问题求助
问题分析与修复方案
核心问题1:授权码的一次性特性
Spotify的授权码(code)是一次性有效的。你先调用同步方法authorizationCode_Sync()完成了授权码交换,后续异步方法authorizationCode_Async()再复用同一个code,就会触发Invalid authorization code错误。
核心问题2:未请求offline_access权限范围
要获取refresh token,必须在生成授权URI时显式添加offline_access scope。你的AuthorizationCodeUriExample代码未设置任何scope,默认不会返回refresh token。
修复步骤
1. 修正授权URI生成代码,添加必要Scope
修改授权请求构建逻辑,加入offline_access及业务所需的其他scope(如user-read-private):
import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.SpotifyHttpManager; import se.michaelthelin.spotify.requests.authorization.authorization_code.AuthorizationCodeUriRequest; import java.net.URI; import java.util.concurrent.CancellationException; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; public class AuthorizationCodeUriExample { private static final String clientId = "<client_id>"; private static final String clientSecret = "<client_secret>"; private static final URI redirectUri = SpotifyHttpManager.makeUri("https://example.com/spotify-test-uri"); private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setClientId(clientId) .setClientSecret(clientSecret) .setRedirectUri(redirectUri) .build(); private static final AuthorizationCodeUriRequest authorizationCodeUriRequest = spotifyApi.authorizationCodeUri() // 添加offline_access以获取refresh token,可追加其他需要的权限 .scope("offline_access user-read-private") .build(); public static void authorizationCodeUri_Sync() { final URI uri = authorizationCodeUriRequest.execute(); System.out.println("URI: " + uri.toString()); } public static void authorizationCodeUri_Async() { try { final CompletableFuture<URI> uriFuture = authorizationCodeUriRequest.executeAsync(); final URI uri = uriFuture.join(); System.out.println("URI: " + uri.toString()); } catch (CompletionException e) { System.out.println("Error: " + e.getCause().getMessage()); } catch (CancellationException e) { System.out.println("Async operation cancelled."); } } public static void main(String[] args) { authorizationCodeUri_Sync(); } }
提示:只需调用同步或异步生成URI的其中一种即可,无需重复调用。
2. 修正授权码交换代码,确保授权码仅使用一次
修改代码,每次交换都使用全新的授权码,且只保留同步/异步其中一种调用逻辑:
import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.SpotifyHttpManager; import se.michaelthelin.spotify.exceptions.SpotifyWebApiException; import se.michaelthelin.spotify.model_objects.credentials.AuthorizationCodeCredentials; import se.michaelthelin.spotify.requests.authorization.authorization_code.AuthorizationCodeRequest; import org.apache.hc.core5.http.ParseException; import java.io.IOException; import java.net.URI; import java.util.concurrent.CancellationException; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; public class AuthorizationCodeExample { private static final String clientId = "<client ID>"; private static final String clientSecret = "<client secret>"; private static final URI redirectUri = SpotifyHttpManager.makeUri("https://example.com/spotify-test-uri"); // 每次都替换为新获取的授权码 private static final String code = "<new_authorization_code>"; private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() .setClientId(clientId) .setClientSecret(clientSecret) .setRedirectUri(redirectUri) .build(); private static final AuthorizationCodeRequest authorizationCodeRequest = spotifyApi.authorizationCode(code) .build(); public static void authorizationCode_Sync() { try { final AuthorizationCodeCredentials authorizationCodeCredentials = authorizationCodeRequest.execute(); spotifyApi.setAccessToken(authorizationCodeCredentials.getAccessToken()); spotifyApi.setRefreshToken(authorizationCodeCredentials.getRefreshToken()); System.out.println("Expires in: " + authorizationCodeCredentials.getExpiresIn()); System.out.println("Refresh Token: " + authorizationCodeCredentials.getRefreshToken()); } catch (IOException | SpotifyWebApiException | ParseException e) { System.out.println("Error: " + e.getMessage()); } } public static void main(String[] args) { authorizationCode_Sync(); // 若使用异步,注释同步调用,打开下面的异步调用 // authorizationCode_Async(); } }
额外注意事项
- 每次授权跳转得到的
code仅能使用一次,失效后需重新获取新code。 - 确保Spotify开发者后台配置的
Redirect URI与代码中完全一致,包括协议、域名、路径,大小写敏感。 - 生产环境中避免用
join()阻塞异步线程,推荐使用thenAccept()等异步回调处理结果。
内容的提问来源于stack exchange,提问作者Rickity2207
相关产品推荐
相关产品推荐

