在获取 Apple 的公钥时,我不断收到 401 未经授权的错误。
在[14]中:print(f“获取公钥时出错:{response.status_code} {response.text}”) 获取公钥时出错:401 未经身份验证
我已验证密钥 ID、发行者 ID 和私钥文件均正确,并且私钥具有管理员访问权限。服务器时间已正确设置为 UTC。鉴于此,我无法确定可能导致该问题的原因。有什么见解吗?
def generate_apple_developer_token():
# Load the private key in PEM format
with open(PRIVATE_KEY_FILE, 'rb') as key_file:
private_key = serialization.load_pem_private_key(
key_file.read(),
password=None,
backend=default_backend()
)
# JWT header
headers = {
"alg": "ES256", # Algorithm: Elliptic Curve
"kid": KEY_ID, # Key ID from Apple Developer
"typ": "JWT" # Type: JWT
}
# JWT payload
payload = {
"iss": ISSUER_ID, # Issuer ID from Apple Developer
"iat": int(datetime.utcnow().timestamp()), # Issued at time
"exp": int((datetime.utcnow() + timedelta(minutes=10)).timestamp()), # Expiration (max 10 minutes)
"aud": "appstoreconnect-v1", # Audience
}
# Encode the header and payload as base64
header_base64 = base64.urlsafe_b64encode(json.dumps(headers).encode()).decode().rstrip("=")
payload_base64 = base64.urlsafe_b64encode(json.dumps(payload).encode()).decode().rstrip("=")
# Concatenate header and payload
message = f"{header_base64}.{payload_base64}".encode()
# Sign the message using ECDSA with SHA256
signature = private_key.sign(
message,
ec.ECDSA(hashes.SHA256())
)
# Convert the DER-encoded signature to raw format (r and s concatenated)
der_to_raw_ecdsa_format = lambda der: der[4:36] + der[-32:]
# Convert the signature to raw format (64 bytes)
signature_64 = der_to_raw_ecdsa_format(signature)
# Base64 URL-encode the signature
signature_base64 = base64.urlsafe_b64encode(signature_64).decode().rstrip("=")
# Concatenate header, payload, and signature to form the JWT
jwt_token = f"{header_base64}.{payload_base64}.{signature_base64}"
return jwt_token
def get_apple_public_keys():
try:
# Generate a fresh JWT
developer_token = generate_apple_developer_token()
# Set up headers with the authorization token
headers = {
"Authorization": f"Bearer {developer_token}"
}
# Fetch the public keys from Apple
response = requests.get('https://api.storekit.itunes.apple.com/in-app-purchase/publicKeys', headers=headers)
# Log the response if it's not successful
if response.status_code != 200:
print(f"Error fetching public keys: {response.status_code} {response.text}")
response.raise_for_status() # Raises an exception for 4xx/5xx errors
# Parse and return the public keys
response_data = response.json()
keys = response_data.get('keys')
if not keys:
print("No 'keys' found in the response from Apple.")
return []
return keys
except requests.exceptions.RequestException as e:
print(f"Error fetching Apple's public keys: {e}")
return []
我还尝试使用jwt来实现jwt令牌
def generate_apple_developer_token():
with open(PRIVATE_KEY_FILE, 'r') as f:
private_key = f.read().strip()
print('this is the key', private_key)
# JWT header
headers = {
"alg": "ES256", # Apple uses ES256 (Elliptic Curve)
"kid": KEY_ID,
"typ": "JWT"
}
# JWT payload
payload = {
"iss": ISSUER_ID,
"iat": int(datetime.utcnow().timestamp()), # Issued at time
"exp": int((datetime.utcnow() + timedelta(minutes=10)).timestamp()), # Expiration (max 10 minutes)
"aud": "appstoreconnect-v1",
}
# Generate and return the JWT
return jwt.encode(payload, private_key, algorithm="ES256", headers=headers)
无论哪种情况,我都检查了 jwt.io 中的令牌,它们是正确的,但由于某种原因,它们未能通过身份验证
Apple 支持在这里给了我答案,它有效
https://developer.apple.com/forums/thread/766360
改用这个库https://github.com/apple/app-store-server-library-python