英文:
How to get access token from Spotify API? [java]
问题
我对Java编程相对陌生,但我对创建一个允许连接到Spotify API的程序感兴趣。我正在使用客户端凭证流授权过程,但在尝试获取访问令牌时一直出现java.io.IOException: insufficient data written
异常。我无法弄清楚我缺少哪些信息来完成请求。
我在YouTube上找到了一个完成相同过程的Python视频,他们使用了请求功能和.json()
来接收访问令牌。在Java中是否有类似的方法来完成这个过程?
try {
String str = "application/x-www-form-urlencoded";
byte[] hold = str.getBytes();
//创建URL
URL url = new URL(tokenURL);
//打开到URL的连接
conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
//设置POST头部和主体
conn.setRequestMethod("POST");
conn.setFixedLengthStreamingMode(32);
conn.setRequestProperty("Authorization", String.format("Basic %s", clientCredEncode));
conn.setRequestProperty("grant_type", "client_credentials");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36");
//验证连接
int val = conn.getResponseCode();
String response = conn.getResponseMessage();
System.out.println("response code: " + val);
System.out.println("response: " + response);
} catch (Exception e) {
System.out.println("error: " + e);
conn.disconnect();
}
PYTHON代码
这段代码在Python中执行该操作。
def spotifyAuth(clientID, clientSecret):
clientCred = f"{clientID}:{clientSecret}"
encodedClient = base64.b64encode(clientCred.encode())
tokenURL = "https://accounts.spotify.com/api/token"
method = "POST"
tokenData = {"grant_type": "client_credentials"}
tokenHeader = {"Authorization": f"Basic {encodedClient.decode()}"}
r = requests.post(tokenURL, data=tokenData, headers=tokenHeader)
tokenResponse = r.json()
accessToken = tokenResponse['access_token']
expires = tokenResponse['expires_in']
return accessToken, expires
英文:
I am fairly new to programming with Java but am interested in creating a program that allows for connection to the Spotify API. I am using the Client Credential Flow authorization process but keep getting java.io.IOException: insufficient data written
exception when trying to reach the access token. I cannot figure out what information I am missing to complete the request.
I found a YouTube video of the same process being completed in Python and they utilized the requests feature and .json() to receive the access token. Is there a similar way to complete this in Java?
try {
String str = "application/x-www-form-urlencoded";
byte[] hold = str.getBytes();
//create url
URL url = new URL(tokenURL);
//open connection to url
conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
//setup post headers and body
conn.setRequestMethod("POST");
conn.setFixedLengthStreamingMode(32);
conn.setRequestProperty("Authorization",String.format("Basic %s", clientCredEncode));
conn.setRequestProperty("grant_type", "client_credentials");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36");
//validate connection
int val = conn.getResponseCode();
String response = conn.getResponseMessage();
System.out.println("response code: " + val);
System.out.println("response: " + response);
}catch(Exception e){
System.out.println("error: " + e);
conn.disconnect();
}
PYTHON CODE
This code performs the action in python.
def spotifyAuth(clientID, clientSecret):
clientCred = f"{clientID}:{clientSecret}"
encodedClient = base64.b64encode(clientCred.encode())
tokenURL = "https://accounts.spotify.com/api/token"
method = "POST"
tokenData = {"grant_type" : "client_credentials"}
tokenHeader = {"Authorization" : f"Basic {encodedClient.decode()}"}
r = requests.post(tokenURL, data=tokenData, headers=tokenHeader)
tokenResponse = r.json()
accessToken = tokenResponse['access_token']
expires = tokenResponse['expires_in']
return accessToken, expires
答案1
得分: 2
感谢 Rup,我能够找出问题所在。我没有正确地使用 POST 方法发送任何内容。我添加了 .getOutputStream() 来发送请求和 .getInputStream() 来接收响应。
// 创建 URL 访问点
URL url = new URL(tokenURL);
// 打开到 URL 的 HTTP 连接
conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
// 设置 POST 方法和请求头
conn.setRequestMethod("POST");
conn.setRequestProperty("Authorization", String.format("Basic %s", clientCredEncode));
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
// 设置要发送的请求体
String body = "grant_type=client_credentials";
// 计算并设置内容长度
byte[] out = body.getBytes(StandardCharsets.UTF_8);
int length = out.length;
conn.setFixedLengthStreamingMode(length);
// 连接到 HTTP
conn.connect();
// 发送字节到 Spotify
try (OutputStream os = conn.getOutputStream()) {
os.write(out);
}
// 接收访问令牌
InputStream result = conn.getInputStream();
s = new String(result.readAllBytes());
//System.out.println(s);
英文:
Thanks to Rup I was able to identify the issue. I was not properly sending anything with the POST. I added .getOutputStream() so send the request and .getInputStream() to receive the response.
//create url access point
URL url = new URL(tokenURL);
//open http connection to url
conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
//setup post function and request headers
conn.setRequestMethod("POST");
conn.setRequestProperty("Authorization",String.format("Basic %s", clientCredEncode));
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
//set body for posting
String body = "grant_type=client_credentials";
//calculate and set content length
byte[] out = body.getBytes(StandardCharsets.UTF_8);
int length = out.length;
conn.setFixedLengthStreamingMode(length);
//connect to http
conn.connect();
//}
//send bytes to spotify
try(OutputStream os = conn.getOutputStream()) {
os.write(out);
}
//receive access token
InputStream result = conn.getInputStream();
s = new String(result.readAllBytes());
//System.out.println(s);
答案2
得分: 0
以下是翻译好的代码部分:
import com.google.gson.JsonParser;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
public class SpotifyToken {
public String accessToken = "";
public String expiresIn = "";
public void get() throws IOException {
URL url = new URL(Endpoints.TOKEN);
HttpURLConnection http = (HttpURLConnection) url.openConnection();
http.setRequestMethod("POST");
http.setDoOutput(true);
http.setRequestProperty("content-type", "application/x-www-form-urlencoded");
String data = "grant_type=client_credentials&client_id=" + Endpoints.CLIENT_ID + "&client_secret=" + Endpoints.CLIENT_SECRET;
byte[] out = data.getBytes(StandardCharsets.UTF_8);
OutputStream stream = http.getOutputStream();
stream.write(out);
BufferedReader Lines = new BufferedReader(new InputStreamReader(http.getInputStream()));
String currentLine = Lines.readLine();
StringBuilder response = new StringBuilder();
while (currentLine != null) {
response.append(currentLine).append("\n");
currentLine = Lines.readLine();
}
this.accessToken = String.valueOf(JsonParser.parseString(String.valueOf(response)).getAsJsonObject().getAsJsonObject("access_token"));
this.expiresIn = String.valueOf(JsonParser.parseString(String.valueOf(response)).getAsJsonObject().getAsJsonObject("expires_in"));
http.disconnect();
}
}
public class Endpoints {
public static final String CLIENT_ID = "YOUR_CLIENT_ID";
public static final String CLIENT_SECRET = "YOUR_CLIENT_SECRET";
public static final String TOKEN = "https://accounts.spotify.com/api/token";
}
如果您感兴趣,以下是相同操作的 cURL 命令:
curl --request POST \
--url 'https://accounts.spotify.com/api/token' \
--header 'content-type: application/x-www-form-urlencoded' \
--data grant_type=client_credentials \
--data client_id=YOUR_CLIENT_ID \
--data client_secret=YOUR_CLIENT_SECRET \
我使用了 这个工具 将 cURL 转换为 Java 代码。
<details>
<summary>英文:</summary>
For anyone whos looking for the same, Here's a better one
import com.google.gson.JsonParser;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
public class SpotifyToken {
public String accessToken = "";
public String expiresIn = "";
public void get() throws IOException {
URL url = new URL(Endpoints.TOKEN);
HttpURLConnection http = (HttpURLConnection) url.openConnection();
http.setRequestMethod("POST");
http.setDoOutput(true);
http.setRequestProperty("content-type", "application/x-www-form-urlencoded");
String data = "grant_type=client_credentials&client_id=" + Endpoints.CLIENT_ID + "&client_secret=" + Endpoints.CLIENT_SECRET + "";
byte[] out = data.getBytes(StandardCharsets.UTF_8);
OutputStream stream = http.getOutputStream();
stream.write(out);
BufferedReader Lines = new BufferedReader(new InputStreamReader(http.getInputStream()));
String currentLine = Lines.readLine();
StringBuilder response = new StringBuilder();
while (currentLine != null) {
response.append(currentLine).append("\n");
currentLine = Lines.readLine();
}
this.accessToken = String.valueOf(JsonParser.parseString(String.valueOf(response)).getAsJsonObject().getAsJsonObject("access_token"));
this.expiresIn = String.valueOf(JsonParser.parseString(String.valueOf(response)).getAsJsonObject().getAsJsonObject("expires_in"));
http.disconnect();
}
}
The class Endpoints.java will be
public class Endpoints {
public static final String CLIENT_ID = "YOUR_CLIENT_ID";
public static final String CLIENT_SECRET = "YOUR_CLIENT_SECRET";
public static final String TOKEN = "https://accounts.spotify.com/api/token";
}
If it interests you, here is the cURL command for the same:
curl --request POST
--url 'https://accounts.spotify.com/api/token'
--header 'content-type: application/x-www-form-urlencoded'
--data grant_type=client_credentials
--data client_id=YOUR_CLIENT_ID
--data client_secret=YOUR_CLIENT_SECRET \
I used [this][1] tool to convert cURL to java code.
[1]: https://reqbin.com/req/java/c-w7oitglz/convert-curl-to-http-request
</details>
# 答案3
**得分**: 0
谢谢您提供的代码。我已经尝试过了,关于Santhosh的回答,我遇到了一个ClassCastException错误:
class com.google.gson.JsonPrimitive无法转换为class
com.google.gson.JsonObject(com.google.gson.JsonPrimitive和
com.google.gson.JsonObject位于“app”的未命名模块中)
这些调用:
getAsJsonObject().getAsJsonObject("access_token")
getAsJsonObject().getAsJsonObject("expires_in")
应该这样使用:
getAsJsonObject().getAsJsonPrimitive("access_token")
getAsJsonObject().getAsJsonPrimitive("expires_in")
<details>
<summary>英文:</summary>
Thank you for your code. I've tried it, just a thing on the Santhosh answer, I've a ClassCastException:
class com.google.gson.JsonPrimitive cannot be cast to class
com.google.gson.JsonObject (com.google.gson.JsonPrimitive and
com.google.gson.JsonObject are in unnamed module of loader 'app')
These calls:
getAsJsonObject().getAsJsonObject("access_token")
getAsJsonObject().getAsJsonObject("expires_in")
work this way:
getAsJsonObject().getAsJsonPrimitive("access_token")
getAsJsonObject().getAsJsonPrimitive("expires_in")
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论