如何从Spotify API获取访问令牌? [java]

huangapple go评论68阅读模式
英文:

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&#39;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(&quot;POST&quot;);
http.setDoOutput(true);
http.setRequestProperty(&quot;content-type&quot;, &quot;application/x-www-form-urlencoded&quot;);
String data = &quot;grant_type=client_credentials&amp;client_id=&quot; + Endpoints.CLIENT_ID + &quot;&amp;client_secret=&quot; + Endpoints.CLIENT_SECRET + &quot;&quot;;
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(&quot;\n&quot;);
currentLine = Lines.readLine();
}
this.accessToken = String.valueOf(JsonParser.parseString(String.valueOf(response)).getAsJsonObject().getAsJsonObject(&quot;access_token&quot;));
this.expiresIn = String.valueOf(JsonParser.parseString(String.valueOf(response)).getAsJsonObject().getAsJsonObject(&quot;expires_in&quot;));
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&#39;ve tried it, just a thing on the Santhosh answer, I&#39;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>

huangapple
  • 本文由 发表于 2020年9月14日 07:00:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/63876345.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定