Spotify 网络 api 连接在 ESP32 上被拒绝
Spotify web api connection refused on ESP32
我试图通过 ESP32 控制 spotify,但我总是收到连接被拒绝的错误。
这里我创建了一个获取accessToken的函数:
#include <WiFi.h>
#include <WiFiMulti.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
WiFiMulti wifiMulti;
const char *ca_cert =
"-----BEGIN CERTIFICATE-----\n" \
"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\n" \
"AFkCjRN8xiv10mrVbcQ86LwZdGA=\n" \
"-----END CERTIFICATE-----\n";
WiFiClientSecure *client;
void getAccessToken(){
HTTPClient http;
Serial.print("[HTTP] begin...\n");
if(!http.begin(*client, "https://accounts.spotify.com/api/token")) return;
http.addHeader("Authorization", "Basic [b64(id:secret)]");
http.addHeader("Content-type", "application/x-www-form-urlencoded");
Serial.print("[HTTP] POST...\n");
// start connection and send HTTP header
int httpCode = http.POST("grant_type=refresh_token&refresh_token=[RefreshToken]");
if(httpCode > 0) {
Serial.printf("[HTTP] POST... code: %d\n", httpCode);
String payload = http.getString();
Serial.println(payload);
} else {
Serial.printf("[HTTP] POST... failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
}
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
wifiMulti.addAP("ssid", "password");
while(wifiMulti.run() != WL_CONNECTED){
delay(50);
Serial.print(".");
}
Serial.println();
configTime(3600, 3600, "pool.ntp.org", "time.nist.gov");
struct tm timeinfo;
if(!getLocalTime(&timeinfo)) Serial.println("Failed to obtain time");
else Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
client = new WiFiClientSecure();
if (client) client -> setCACert(ca_cert);
else Serial.println("Error setting ca_cert");
}
void loop() {
getAccessToken();
delay(10000);
}
输出:
13:41:01.057 -> Thursday, March 18 2021 14:41:19
13:41:01.057 -> [HTTP] begin...
13:41:01.057 -> [V][HTTPClient.cpp:239] beginInternal(): url: https://accounts.spotify.com/api/token
13:41:01.057 -> [D][HTTPClient.cpp:287] beginInternal(): host: accounts.spotify.com port: 443 url: /api/token
13:41:01.057 -> [HTTP] POST...
13:41:01.057 -> [D][HTTPClient.cpp:573] sendRequest(): request type: 'POST' redirCount: 0
13:41:01.057 ->
13:41:01.057 -> [V][ssl_client.cpp:59] start_ssl_client(): Free internal heap before TLS 279108
13:41:01.057 -> [V][ssl_client.cpp:65] start_ssl_client(): Starting socket
13:41:01.104 -> [V][ssl_client.cpp:104] start_ssl_client(): Seeding the random number generator
13:41:01.104 -> [V][ssl_client.cpp:113] start_ssl_client(): Setting up the SSL/TLS structure...
13:41:01.104 -> [V][ssl_client.cpp:129] start_ssl_client(): Loading CA cert
13:41:01.104 -> [V][ssl_client.cpp:197] start_ssl_client(): Setting hostname for TLS session...
13:41:01.104 -> [V][ssl_client.cpp:212] start_ssl_client(): Performing the SSL/TLS handshake...
13:41:01.197 -> [E][ssl_client.cpp:36] _handle_error(): [start_ssl_client():216]: (-9984) X509 - Certificate verification failed, e.g. CRL, CA or signature check failed
13:41:01.197 -> [E][WiFiClientSecure.cpp:127] connect(): start_ssl_client: -9984
13:41:01.197 -> [V][ssl_client.cpp:265] stop_ssl_socket(): Cleaning SSL connection.
13:41:01.197 -> [D][HTTPClient.cpp:1112] connect(): failed connect to accounts.spotify.com:443
13:41:01.197 -> [W][HTTPClient.cpp:1411] returnError(): error(-1): connection refused
13:41:01.197 -> [HTTP] POST... failed, error: connection refused
13:41:01.197 -> [D][HTTPClient.cpp:394] disconnect(): tcp is closed
13:41:01.197 ->
13:41:01.197 -> [V][ssl_client.cpp:265] stop_ssl_socket(): Cleaning SSL connection.
每次我尝试向 spotify 发出请求时都会出现同样的错误 api,但示例 https 代码有效。
我尝试通过 Postman 发出请求,但成功了。
我哪里错了?
我发现我在 Arduino 的“工具”部分将调试级别设置为“详细”时得到了错误的证书IDE。
我试图通过 ESP32 控制 spotify,但我总是收到连接被拒绝的错误。
这里我创建了一个获取accessToken的函数:
#include <WiFi.h>
#include <WiFiMulti.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
WiFiMulti wifiMulti;
const char *ca_cert =
"-----BEGIN CERTIFICATE-----\n" \
"MIIGEDCCBPigAwIBAgIQBS8G4gPhQtIePtEv2M7pnzANBgkqhkiG9w0BAQsFADBN\n" \
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5E\n" \
"aWdpQ2VydCBTSEEyIFNlY3VyZSBTZXJ2ZXIgQ0EwHhcNMjAwNjIzMDAwMDAwWhcN\n" \
"MjEwOTAyMTIwMDAwWjBOMQswCQYDVQQGEwJTRTESMBAGA1UEBxMJU3RvY2tob2xt\n" \
"MRMwEQYDVQQKEwpTcG90aWZ5IEFCMRYwFAYDVQQDDA0qLnNwb3RpZnkuY29tMIIB\n" \
"IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6HWzVXakqZHjqPgKpyBCffVx\n" \
"j9Vnki7IiTrKDn4AFU2TCkNEj7BjhUg2tNwytK726zpZ3PcRJ7EEyVEkhKCTDieC\n" \
"hHawaUL0B3Xh7chgphPNEq39kw/neWAZ/gPWl+HaDB5CBrK95/z4vkIVIko1a+tl\n" \
"LBqWFcHLEhjkdq5tWnsbJgQjCxwSCQxC5U9jg8i5he4HCPNMj0LW+05pqcfdin7E\n" \
"bmkAlBxST6nHHgRSgqvH61StUx4/gEBsaeI9yET+xnj7CuL4V5LEYVXlWw94ZLtN\n" \
"XAQjBrihrBkA4uiTkwMxEfFKHNbaebILpqJ+JiGH5ovYwpI72U7ghREEwd5xKwID\n" \
"AQABo4IC6TCCAuUwHwYDVR0jBBgwFoAUD4BhHIIxYdUvKOeNRji0LOHG2eIwHQYD\n" \
"VR0OBBYEFMHE9fNvSFaGJ8CcWqfO6HRQ9/4dMCUGA1UdEQQeMByCDSouc3BvdGlm\n" \
"eS5jb22CC3Nwb3RpZnkuY29tMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggr\n" \
"BgEFBQcDAQYIKwYBBQUHAwIwawYDVR0fBGQwYjAvoC2gK4YpaHR0cDovL2NybDMu\n" \
"ZGlnaWNlcnQuY29tL3NzY2Etc2hhMi1nNi5jcmwwL6AtoCuGKWh0dHA6Ly9jcmw0\n" \
"LmRpZ2ljZXJ0LmNvbS9zc2NhLXNoYTItZzYuY3JsMEwGA1UdIARFMEMwNwYJYIZI\n" \
"AYb9bAEBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9D\n" \
"UFMwCAYGZ4EMAQICMHwGCCsGAQUFBwEBBHAwbjAkBggrBgEFBQcwAYYYaHR0cDov\n" \
"L29jc3AuZGlnaWNlcnQuY29tMEYGCCsGAQUFBzAChjpodHRwOi8vY2FjZXJ0cy5k\n" \
"aWdpY2VydC5jb20vRGlnaUNlcnRTSEEyU2VjdXJlU2VydmVyQ0EuY3J0MAwGA1Ud\n" \
"EwEB/wQCMAAwggEEBgorBgEEAdZ5AgQCBIH1BIHyAPAAdgD2XJQv0XcwIhRUGAgw\n" \
"lFaO400TGTO/3wwvIAvMTvFk4wAAAXLhDERlAAAEAwBHMEUCIASIo9eFKEVLL4cD\n" \
"xlBhAGSo82I0TRd66jvwFhx6Se79AiEAhL0I6dqaIZTsorV0XwSObs8gbh48ba5h\n" \
"XqQesmvVjH0AdgBc3EOS/uarRUSxXprUVuYQN/vV+kfcoXOUsl7m9scOygAAAXLh\n" \
"DESTAAAEAwBHMEUCIQDnnsP6nLnwtiUHORgRCBqPqFTHsPaTA9FxbmRw0gxGfAIg\n" \
"HLukydDmJy6a3f4ZXa5eJ63kUB1iQc/oai3aXSHbP6MwDQYJKoZIhvcNAQELBQAD\n" \
"ggEBAHfGtU9XU+pUAMgZoc0NenTV2fQfZl5MM5EPG/Jf0Fp4YnIIz92vReVnUvco\n" \
"MxO73E/mP15nxaXQtknQTpCn4ZBSD4OF5oMKM1M98iSGC+ZvKlk0UektOv9zrRTn\n" \
"A2JLJH695cul3nyaoqhuAWtzfFft8y6fm1Bclt1q6OvEGkNtWJ07aQFBXeaIzr4W\n" \
"kZR8sdw+EkiGk1bN/C1CMU0xBnkQE19OycfE2Ax5Qag81KwLlcdkgMtXkMie2ZV1\n" \
"ytyF8FFgyCakrFkDeDOnc5YAOpjlkD8J0uNTZIPv1rF/nA67EgAW9NFxulCqqrXb\n" \
"AFkCjRN8xiv10mrVbcQ86LwZdGA=\n" \
"-----END CERTIFICATE-----\n";
WiFiClientSecure *client;
void getAccessToken(){
HTTPClient http;
Serial.print("[HTTP] begin...\n");
if(!http.begin(*client, "https://accounts.spotify.com/api/token")) return;
http.addHeader("Authorization", "Basic [b64(id:secret)]");
http.addHeader("Content-type", "application/x-www-form-urlencoded");
Serial.print("[HTTP] POST...\n");
// start connection and send HTTP header
int httpCode = http.POST("grant_type=refresh_token&refresh_token=[RefreshToken]");
if(httpCode > 0) {
Serial.printf("[HTTP] POST... code: %d\n", httpCode);
String payload = http.getString();
Serial.println(payload);
} else {
Serial.printf("[HTTP] POST... failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
}
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
wifiMulti.addAP("ssid", "password");
while(wifiMulti.run() != WL_CONNECTED){
delay(50);
Serial.print(".");
}
Serial.println();
configTime(3600, 3600, "pool.ntp.org", "time.nist.gov");
struct tm timeinfo;
if(!getLocalTime(&timeinfo)) Serial.println("Failed to obtain time");
else Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
client = new WiFiClientSecure();
if (client) client -> setCACert(ca_cert);
else Serial.println("Error setting ca_cert");
}
void loop() {
getAccessToken();
delay(10000);
}
输出:
13:41:01.057 -> Thursday, March 18 2021 14:41:19
13:41:01.057 -> [HTTP] begin...
13:41:01.057 -> [V][HTTPClient.cpp:239] beginInternal(): url: https://accounts.spotify.com/api/token
13:41:01.057 -> [D][HTTPClient.cpp:287] beginInternal(): host: accounts.spotify.com port: 443 url: /api/token
13:41:01.057 -> [HTTP] POST...
13:41:01.057 -> [D][HTTPClient.cpp:573] sendRequest(): request type: 'POST' redirCount: 0
13:41:01.057 ->
13:41:01.057 -> [V][ssl_client.cpp:59] start_ssl_client(): Free internal heap before TLS 279108
13:41:01.057 -> [V][ssl_client.cpp:65] start_ssl_client(): Starting socket
13:41:01.104 -> [V][ssl_client.cpp:104] start_ssl_client(): Seeding the random number generator
13:41:01.104 -> [V][ssl_client.cpp:113] start_ssl_client(): Setting up the SSL/TLS structure...
13:41:01.104 -> [V][ssl_client.cpp:129] start_ssl_client(): Loading CA cert
13:41:01.104 -> [V][ssl_client.cpp:197] start_ssl_client(): Setting hostname for TLS session...
13:41:01.104 -> [V][ssl_client.cpp:212] start_ssl_client(): Performing the SSL/TLS handshake...
13:41:01.197 -> [E][ssl_client.cpp:36] _handle_error(): [start_ssl_client():216]: (-9984) X509 - Certificate verification failed, e.g. CRL, CA or signature check failed
13:41:01.197 -> [E][WiFiClientSecure.cpp:127] connect(): start_ssl_client: -9984
13:41:01.197 -> [V][ssl_client.cpp:265] stop_ssl_socket(): Cleaning SSL connection.
13:41:01.197 -> [D][HTTPClient.cpp:1112] connect(): failed connect to accounts.spotify.com:443
13:41:01.197 -> [W][HTTPClient.cpp:1411] returnError(): error(-1): connection refused
13:41:01.197 -> [HTTP] POST... failed, error: connection refused
13:41:01.197 -> [D][HTTPClient.cpp:394] disconnect(): tcp is closed
13:41:01.197 ->
13:41:01.197 -> [V][ssl_client.cpp:265] stop_ssl_socket(): Cleaning SSL connection.
每次我尝试向 spotify 发出请求时都会出现同样的错误 api,但示例 https 代码有效。
我尝试通过 Postman 发出请求,但成功了。
我哪里错了?
我发现我在 Arduino 的“工具”部分将调试级别设置为“详细”时得到了错误的证书IDE。