Reputation: 514
I am trying to use sales report API from App Store Connect API with Python script here.
import jwt
import requests
import time
import json
KEY_ID = "XXXXXXXXX"
ISSUER_ID = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
# EXPIRATION_TIME = int(round(time.time() + (20.0 * 60.0))) # 20 minutes timestamp
PATH_TO_KEY = '/Users/164187.victor/Documents/Credentials/App_Store_Connect_RR/AuthKey_XXXXXXXXX.p8'
# pseudo, removed secret info
# read the file, currently binary but have tried string too
with open(PATH_TO_KEY, 'r+b') as keyfile:
secret = keyfile.read()
expir = round(time.time() + 20 * 60)
# sign the token with the iss, time, key, and kid with the correct alg
token = jwt.encode({'iss': ISSUER_ID,
'exp': expir,
'aud': 'appstoreconnect-v1'},
secret, algorithm='ES256',
headers={'alg': 'ES256', 'kid': KEY_ID, 'typ': 'JWT'})
# decode the bytes and create the get request header
headers = {'Authorization': f'Bearer {token}'}
params = {'filter[reportSubType]': 'SUMMARY', 'filter[reportType]': 'SALES', 'filter[frequency]':'DAILY', 'filter[vendorNumber]': 'XXXXXXXX'}
# send the get request
r = requests.get('https://api.appstoreconnect.apple.com/v1/salesReports',
headers=headers, params=params)
# Write the response in a pretty printed JSON file
with open('output.json', 'w') as out:
out.write(json.dumps(r.json(), indent=4))
and i got this result in my json output file:
{
"errors": [
{
"status": "401",
"code": "NOT_AUTHORIZED",
"title": "Authentication credentials are missing or invalid.",
"detail": "Provide a properly configured and signed bearer token, and make sure that it has not expired. Learn more about Generating Tokens for API Requests https://developer.apple.com/go/?id=api-generating-tokens"
}
]
}
What i have tried:
is there anything to solve this problem? i already stuck at this for 1 week pls help
Upvotes: 1
Views: 6912
Reputation: 2238
It seemed your code originates from this Gist, it uses authlib to create JWT token. But import jwt
statement in your code indicates you have switched to PyJWT, don't mix up two packages, they have different ways to use.
For PyJWT
:
import jwt
token_data = jwt.encode(
{
'iss': ISSUER_ID,
'aud': 'appstoreconnect-v1',
'exp': expiry
},
secret,
headers={
'kid': KEY_ID
},
algorithm='ES256'
)
print(token_data.decode('UTF-8'))
For authlib
:
from authlib.jose import jwt
token_data = jwt.encode(
{
"alg": "ES256",
"kid": KEY_ID,
"typ": "JWT"
},
{
"iss": ISSUER_ID,
"exp": expir,
"aud": "appstoreconnect-v1"
},
secret
)
print(token.decode())
For both ways, don't forget invoke decode()
before being used in request headers.
Another better option would be using applaud – a Python client library for accessing App Store Connect API, you simply pass the credentials to initialize a Connection
object, applaud
does the rest for you:
# Create the Connection
connection = Connection(ISSUER_ID, KEY_ID, PRIVATE_KEY)
r = connection.sales_reports().filter(
report_sub_type=SalesReportsEndpoint.ReportSubType.SUMMARY, # or "SUMMARY"
report_type=SalesReportsEndpoint.ReportType.SALES, # or "SALES"
frequency=SalesReportsEndpoint.Frequency.MONTHLY, # or "MONTHLY"
report_date='2021-12',
vendor_number='12345678',
).get()
r.save('output.txt', decompress=True)
You can find your vendor number in Payments and Financial Reports. Example code is here.
Full disclosure, I'm original author of applaud.
Upvotes: 0
Reputation: 93
Given the link in your error, https://developer.apple.com/go/?id=api-generating-tokens, you are missing the iat(Issued at Time) and the scope parameters in your payload.
Upvotes: 0