4

尝试调用 Apple Music API 时,我不断收到 401 错误。我正在使用 Windows 机器,下面是它的 Python 代码。


import datetime
import jwt

secret = """-----BEGIN PRIVATE KEY-----
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxx
-----END PRIVATE KEY-----"""

kid = 'ABCDEFGHI'
teamId = 'JKLMNOPQRS'
alg = 'ES256'

headers = {
    'alg': alg,
    'kid': kid
}

payload = {
    'iss': teamId,
    'iat': 1518033023,
    'exp': 1518290267
}

if __name__ == '__main__':
    '''Create an auth token'''
    token = jwt.encode(payload, secret, algorithm=alg, headers=headers)

print '----CURL----'
print ("curl -v -H 'Authorization: Bearer %s' \"https://api.music.apple.com/v1/catalog/us/playlists/pl.14362d3dfe4b41f7878939782647e0ba\" " % (token))
4

4 回答 4

3

我对字符串格式化运算符有同样的问题。因此使用这个:

"""Create an auth token"""
token = jwt.encode(payload, secret, algorithm=alg, headers=headers)
token_str = token.decode('utf-8')  # converts bytes to string

url = "https://api.music.apple.com/v1/catalog/us/playlists/pl.14362d3dfe4b41f7878939782647e0ba" 

print("curl -v -H 'Authorization: Bearer" + token_str + "\"" + url + "\"")

进一步:我假设您想直接访问数据。为此,您可以使用requests库:

import requests
request_obj = requests.get(url, headers={'Authorization': "Bearer " + token_str})
json_dict = request_obj.json()

干杯!

于 2018-02-12T17:05:57.143 回答
1

添加到 sanwall 的答案——这对我有用(Python 3.x):

from datetime import datetime
import jwt
import requests
import json

secret_key = '''-----BEGIN PRIVATE KEY-----
... your secret key here ...
-----END PRIVATE KEY-----'''

key_id  = '0123456789' # <-- your key id here
team_id = '0123456789' # <-- your team id here
alg     = 'ES256'
iat     = int(datetime.utcnow().strftime("%s")) # set issued at to now
exp     = iat + 86400 # add e.g. 24h from now for expiration (24 * 3600secs == 86400)

payload = {
    'iss': team_id,
    'iat': iat,
    'exp': exp
}

headers = {
    'alg': alg,
    'kid': key_id
}

token = jwt.encode(payload, secret_key, algorithm=alg, headers=headers)
token_str = token.decode('utf-8')

url = "https://api.music.apple.com/v1/catalog/us/songs/203709340"
print (f"curl -v -H 'Authorization: Bearer {token_str}' {url}")

或者使用请求生成的令牌字符串:

res = requests.get(url, headers={'Authorization': "Bearer " + token_str})
result = json.loads(res.text)

打印出:

{'data': [{'id': '203709340', 'type': 'songs', 'href': '/v1/catalog/us/songs/203709340', ... etc ...
于 2019-03-17T08:56:46.007 回答
0

我遇到了同样的问题,对我来说,我的 .p8 文件在多行上的密钥应该只在一行上:

-----BEGIN PRIVATE KEY-----
notarealkey5GSM49AgEGCCqGSM49AwEHBHkwdwIBAQQguWRXMHYkuFImkMGByqEPT
jaXQyO0WK1BjYpuDxIgNQ5nHRRFCuUOi8mgCgYIKoZIzj0DAQehcp0+Z+jwRANCAA
RCBFg8fL08QS36Fb8HmY+eFrDWMO00w5unCo5n8VyLhvttIZeByXlVsJrK/L3f/
F2wYmZme
-----END PRIVATE KEY-----

与:

-----BEGIN PRIVATE KEY-----
asdfg1rty5GSM49AgEGCCqGSM49AwEHBHkwdwI...
-----END PRIVATE KEY-----
于 2020-03-22T12:22:45.467 回答
0

Apple Music API 需要开发者令牌和用户令牌。虽然问题是关于 python 的,但这个答案是为未来遇到这个问题的快速开发人员准备的。

例如,

static func addPlaylistPathURLString(developerToken: String, userToken: String) -> URLRequest {
         var urlComponents = URLComponents()
         urlComponents.scheme = "https"
         urlComponents.host = "api.music.apple.com"
         urlComponents.path = "/v1/me/library/playlists/

         // Create and configure the `URLRequest`.

         var urlRequest = URLRequest(url: urlComponents.url!)
         urlRequest.httpMethod = "GET"

         urlRequest.addValue("Bearer \(developerToken)", forHTTPHeaderField: "Authorization")
         urlRequest.addValue(userToken, forHTTPHeaderField: "Music-User-Token")

         return urlRequest
     }

     func addPlaylistPathURLString(with developertoken: String, userToken: String, completion: @escaping CatalogSearchCompletionHandler) {

 guard let developerToken = refreshDeveloperToken() // its developer token 
else {
           fatalError("Developer Token not configured. See README for more details.")
             }
            let urlRequest = AppleMusicRequestFactory.addPlaylistPathURLString(developerToken: developerToken, userToken: userToken)
            print(urlRequest)

             let task = urlSession.dataTask(with: urlRequest) { (data, response, error) in
                 guard error == nil, let urlResponse = response as? HTTPURLResponse, urlResponse.statusCode == 200 else {
                     completion([], error)

                     return
                 }
                 guard
                    let data = data,
                   let json = String(data: data, encoding: .utf8)

                else { return }
                print("json:", json)
               do {
                    // do your stuffs---

                  } catch {

                 print("An error occurred: \(error.localizedDescription)")
                 }
             }

             task.resume()

        }

关于如何从开发者令牌中获取用户令牌,

func requestUserToken() {
        guard let developerToken = appleMusicManager.refreshDeveloperToken() // its developer token 
   else {
            return
        }

        if SKCloudServiceController.authorizationStatus() == .authorized {

            let completionHandler: (String?, Error?) -> Void = { [weak self] (token, error) in
                guard error == nil else {
                    print("An error occurred when requesting user token: \(error!.localizedDescription)")
                    return
                }

                guard let token = token else {
                    print("Unexpected value from SKCloudServiceController for user token.")
                    return
                }

                self?.userToken = token
                print(token)

                /// Store the Music User Token for future use in your application.
                let userDefaults = UserDefaults.standard

                userDefaults.set(token, forKey: AuthorizationManager.userTokenUserDefaultsKey)
                userDefaults.synchronize()

                if self?.cloudServiceStorefrontCountryCode == "" {
                    self?.requestStorefrontCountryCode()
                }

                NotificationCenter.default.post(name: AuthorizationManager.cloudServiceDidUpdateNotification, object: nil)
            }

            if #available(iOS 11.0, *) {
                cloudServiceController.requestUserToken(forDeveloperToken: developerToken, completionHandler: completionHandler)
            } else {
                cloudServiceController.requestPersonalizationToken(forClientToken: developerToken, withCompletionHandler: completionHandler)
            }
        }
    }
于 2020-03-26T15:37:57.917 回答