我试图用C#调用spotify API.
不幸的是,我已经陷入了获取访问令牌的困境
不幸的是,我已经陷入了获取访问令牌的困境
这就是我试图得到它的方式:
private static async Task<string> GetAccessToken() { SpotifyToken token = new SpotifyToken(); string postString = string.Format("grant_type=client_credentials"); byte[] byteArray = Encoding.UTF8.GetBytes(postString); string url = "https://accounts.spotify.com/api/token"; WebRequest request = WebRequest.Create(url); request.Method = "POST"; request.Headers.Add("Authorization","Basic {Encoded myClientIdXXX:myAppSecretYYY}"); request.ContentType = "application/x-www-form-urlencoded"; request.ContentLength = byteArray.Length; using (Stream dataStream = request.GetRequestStream()) { dataStream.Write(byteArray,byteArray.Length); using (WebResponse response = await request.GetResponseAsync()) { using (Stream responseStream = response.GetResponseStream()) { using (StreamReader reader = new StreamReader(responseStream)) { string responseFromServer = reader.ReadToEnd(); token = JsonConvert.DeserializeObject<SpotifyToken>(responseFromServer); } } } } return token.access_token; }
但是我收到一个错误:
Der Remoteserver hat einen Fehler zurückgegeben: (400) Ungültige Anforderung.
这意味着:
The remote server returned an error: (400) Bad Request.
我在这做错了什么?
我在spotify上注册了我的应用程序,并在请求标题中设置了clientId和secret …
提前致谢
解决方法
您是否真的需要从头开始编写自己的客户端来构建WebRequests等?为什么不使用像
SpotifyAPI-NET这样的现有客户端?
无论如何,你可以在GitHub上看到他们是如何做到的:
using Newtonsoft.Json; using SpotifyAPI.Web.Enums; using SpotifyAPI.Web.Models; using System; using System.Collections.Specialized; using System.Diagnostics; using System.IO; using System.Net; using System.Text; using System.Threading; namespace SpotifyAPI.Web.Auth { public class AutorizationCodeAuth { public delegate void OnResponseReceived(AutorizationCodeAuthResponse response); private SimpleHttpServer _httpServer; private Thread _httpThread; public String ClientId { get; set; } public String RedirectUri { get; set; } public String State { get; set; } public Scope Scope { get; set; } public Boolean ShowDialog { get; set; } /// <summary> /// Will be fired once the user authenticated /// </summary> public event OnResponseReceived OnResponseReceivedEvent; /// <summary> /// Start the auth process (Make sure the internal HTTP-Server ist started) /// </summary> public void DoAuth() { String uri = GetUri(); Process.Start(uri); } /// <summary> /// Refreshes auth by providing the clientsecret (Don't use this if you're on a client) /// </summary> /// <param name="refreshToken">The refresh-token of the earlier gathered token</param> /// <param name="clientSecret">Your Client-Secret,don't provide it if this is running on a client!</param> public Token RefreshToken(string refreshToken,string clientSecret) { using (WebClient wc = new WebClient()) { wc.Proxy = null; wc.Headers.Add("Authorization","Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(ClientId + ":" + clientSecret))); NameValueCollection col = new NameValueCollection { {"grant_type","refresh_token"},{"refresh_token",refreshToken} }; String response; try { byte[] data = wc.UploadValues("https://accounts.spotify.com/api/token","POST",col); response = Encoding.UTF8.GetString(data); } catch (WebException e) { using (StreamReader reader = new StreamReader(e.Response.GetResponseStream())) { response = reader.ReadToEnd(); } } return JsonConvert.DeserializeObject<Token>(response); } } private String GetUri() { StringBuilder builder = new StringBuilder("https://accounts.spotify.com/authorize/?"); builder.Append("client_id=" + ClientId); builder.Append("&response_type=code"); builder.Append("&redirect_uri=" + RedirectUri); builder.Append("&state=" + State); builder.Append("&scope=" + Scope.GetStringAttribute(" ")); builder.Append("&show_dialog=" + ShowDialog); return builder.ToString(); } /// <summary> /// Start the internal HTTP-Server /// </summary> public void StartHttpServer(int port = 80) { _httpServer = new SimpleHttpServer(port,AuthType.Authorization); _httpServer.OnAuth += HttpServerOnOnAuth; _httpThread = new Thread(_httpServer.Listen); _httpThread.Start(); } private void HttpServerOnOnAuth(AuthEventArgs e) { OnResponseReceivedEvent?.Invoke(new AutorizationCodeAuthResponse() { Code = e.Code,State = e.State,Error = e.Error }); } /// <summary> /// This will stop the internal HTTP-Server (Should be called after you got the Token) /// </summary> public void StopHttpServer() { _httpServer = null; } /// <summary> /// Exchange a code for a Token (Don't use this if you're on a client) /// </summary> /// <param name="code">The gathered code from the response</param> /// <param name="clientSecret">Your Client-Secret,don't provide it if this is running on a client!</param> /// <returns></returns> public Token ExchangeAuthCode(String code,String clientSecret) { using (WebClient wc = new WebClient()) { wc.Proxy = null; NameValueCollection col = new NameValueCollection { {"grant_type","authorization_code"},{"code",code},{"redirect_uri",RedirectUri},{"client_id",ClientId},{"client_secret",clientSecret} }; String response; try { byte[] data = wc.UploadValues("https://accounts.spotify.com/api/token",col); response = Encoding.UTF8.GetString(data); } catch (WebException e) { using (StreamReader reader = new StreamReader(e.Response.GetResponseStream())) { response = reader.ReadToEnd(); } } return JsonConvert.DeserializeObject<Token>(response); } } } public struct AutorizationCodeAuthResponse { public String Code { get; set; } public String State { get; set; } public String Error { get; set; } } }