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" \
      "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。