Как правильно обрабатывать обновление токенов с помощью Spotify SDK и Swift 3. Код Ошибки=3840

tl; dr Я получаю: JSON text did not start with array or object and option to allow fragments not set. Если я пытаюсь получить токен и No refresh token available in the session! если я пытаюсь обновить токен.

Я пытаюсь настроить обновление токена для Objective-C Spotify iOS SDK beta-25 в Swift 3. Я использую сервер Heroku и скрипт Ruby, предоставленный Spotify, изменен на мои учетные данные.

require 'sinatra'
require 'net/http'
require 'net/https'
require 'base64'
require 'encrypted_strings'
require 'json'

CLIENT_ID = ENV['xxx']
CLIENT_SECRET = ENV['xxx']
ENCRYPTION_SECRET = ENV['xxx']
CLIENT_CALLBACK_URL = ENV['xxx://returnafterlogin']
AUTH_HEADER = "Basic " + Base64.strict_encode64(CLIENT_ID + ":" + CLIENT_SECRET)
SPOTIFY_ACCOUNTS_ENDPOINT = URI.parse("https://accounts.spotify.com")

get '/' do
"Working"    
end

post '/swap' do

    # This call takes a single POST parameter, "code", which
    # it combines with your client ID, secret and callback
    # URL to get an OAuth token from the Spotify Auth Service,
    # which it will pass back to the caller in a JSON payload.

    auth_code = params[:code]

    http = Net::HTTP.new(SPOTIFY_ACCOUNTS_ENDPOINT.host, SPOTIFY_ACCOUNTS_ENDPOINT.port)
    http.use_ssl = true

    request = Net::HTTP::Post.new("/api/token")

    request.add_field("Authorization", AUTH_HEADER)

    request.form_data = {
        "grant_type" => "authorization_code",
        "redirect_uri" => CLIENT_CALLBACK_URL,
        "code" => auth_code
    }

    response = http.request(request)

    # encrypt the refresh token before forwarding to the client
    if response.code.to_i == 200
        token_data = JSON.parse(response.body)
        refresh_token = token_data["refresh_token"]
        encrypted_token = refresh_token.encrypt(:symmetric, :password => ENCRYPTION_SECRET)
        token_data["refresh_token"] = encrypted_token
        response.body = JSON.dump(token_data)
    end

    status response.code.to_i
    return response.body
end

post '/refresh' do

    # Request a new access token using the POST:ed refresh token

    http = Net::HTTP.new(SPOTIFY_ACCOUNTS_ENDPOINT.host, SPOTIFY_ACCOUNTS_ENDPOINT.port)
    http.use_ssl = true

    request = Net::HTTP::Post.new("/api/token")

    request.add_field("Authorization", AUTH_HEADER)

    encrypted_token = params[:refresh_token]
    refresh_token = encrypted_token.decrypt(:symmetric, :password => ENCRYPTION_SECRET)

    request.form_data = {
        "grant_type" => "refresh_token",
        "refresh_token" => refresh_token
    }

    response = http.request(request)

    status response.code.to_i
    return response.body

end

установлено:

SPTAuth.defaultInstance().tokenSwapURL = URL(string: SpotifyCredentials.tokenSwapURLSwap)
SPTAuth.defaultInstance().tokenRefreshURL = URL(string: SpotifyCredentials.tokenSwapURLRefresh)

теперь пользователь больше не может войти в систему, и я получаю ошибка, размещенная сверху. Если я удаляю tokenSwapURL и tokenRefreshURL, все работает снова, но пользователь должен повторно auth каждые 60 минут.

если я пытаюсь обновить токен с уже зарегистрированным пользователем, я получаю:

"No refresh token available in the session!"

if SPTAuth.defaultInstance().session != nil {
        print("needs login")
        SPTAuth.defaultInstance().renewSession(SPTAuth.defaultInstance().session, callback: { error, session in
            if error != nil {
                print("(error?.localizedDescription)") // "No refresh token available in the session!"
                return
            }
        })
}

что я упустил? Помощь очень ценится.

2 ответов


я смог создать службу обновления токенов для Spotify со следующим Git:

https://github.com/adamontherun/SpotifyTokenRefresh

все, что вам нужно сделать, это следовать инструкциям ссылки Heroku в проекте git.

enter image description here

Я пытался связаться с автором проекта, но он не смог сказать мне, почему мой подход не работает но его есть. Все, что я могу вам оставить, это работать Deploy to Heroku ссылка.


краткое резюме: предполагая, что ваш синтаксический анализ JSON работает правильно, проблема заключается в неправильном JSON (на стороне сервера).


текст JSON не начинался с массива или объекта, и опция разрешить фрагменты не установлены

может быть брошен  ' s JSONSerialization.jsonObject(with:options:) возвращает

объект Foundation из данных JSON в data или

nil если сообщение об ошибке происходит.

уродливый JSON"nil вместо токена "текущий токен получает nilled" результат: "пользователь больше не может войти в систему"

возможные объяснения для получения искаженного JSON включают:

обычно это происходит из-за какого-то предупреждающего сообщения, выбрасываемого с вашего сервера, не помещая его в массив ответов. Например, в PHP некоторые "предупреждающие сообщения" не попадают в Ваш массив, чтобы при наконец, используйте " echo json_encode ($RESPONSE_ARR)", это не формат JSON. - https://stackoverflow.com/a/38680699/3419541

из того же так страница:

вам нужно отладить это в приложении iOS. Сначала преобразуйте данные в строку, распечатайте ее и проверьте. Если строка выглядит нормально, то распечатайте сами данные-иногда людям удается добавить 0 байтов или управляющих символов, или два маркера порядка байтов или что-то подобное которые невидимы в строке, но не являются законными JSON. - https://stackoverflow.com/a/38681179/3419541