错题集(已解决):python通过JWT(jsonWebToken)默认ES256编码连苹果App Store Connect API报错Could not deserialize key data

1 篇文章 0 订阅
1 篇文章 0 订阅

最近苹果账号不知道咋的弄出来一个账号密码登陆后需要手机验证码双重认证登陆,很麻烦于是想通过App Store Connect API直连导出财务日志之类的东西。
苹果提供了一套JWT的验证连接方式,关于JWT网上介绍很多在此对细节略过不表。
而完成登陆简单点讲就是需要在发送向指定http地址的get请求头中添加JWT。具体生成JWT的过程如下(前两步)。

在这里插入图片描述

1. 生成API key

https://developer.apple.com/documentation/appstoreconnectapi/creating_api_keys_for_app_store_connect_api
登陆itunes connect后按指示点选即可,最后设置好密钥权限后点击下载唯一的私钥文件,文件名默认为"AuthKey_XXXXXXXXXX.p8",其中<xx…x>部分为该密钥ID
在这里插入图片描述

2.生成json Web Token

https://developer.apple.com/documentation/appstoreconnectapi/generating_tokens_for_api_requests
JWT包含三部分,最终格式为<header>.<payload>.<sign>,好在python并不需要我们自己去转码,直接按照官网指点构造好各个部分使用pyjwt包自动构造就行了。
下面直接上代码

import time, jwt

# 1. Create the JWT header
header  = {
	"alg": "ES256",
	"kid": "XXXXXXXXXX",	# your own key ID 
	"typ": "JWT"
}
# 2.1 Create the JWT payload
payload = {
	"iss": "XXX-XXX-XXX-XXX-XXX", 
	# 在Store Connect上可以点击复制 iss ID
	"exp": int(time.time()) + 60*10,  
	# token最长有效时间20min,这里设置为10min
	"aud": "appstoreconnect-v1"
}
# 2.2 privateKey 直接打开导入
privatekey = open('D:/AuthKey_S93MFC6GNN.p8', 'r').read()
# 3. Sign the JWT
nc = jwt.encode(payload=payload, key=privatekey, algorithm='ES256', headers=header) 

运行如下:这里需要注意,苹果采用的ES256编码方式,key是需要分段(\n)的,密钥头尾的"—BEGIN PRIVATE KEY—"也是必须的。之前我一直直接复制privatekey以文本的形式输入,在HS256下正常但是ES256会报错ValueError: Could not deserialize key data。还以为是什么PEM、SSH之类编解码方式的问题折腾了半天,最后受到这篇文章(感谢 http://www.mamicode.com/info-detail-1470498.html )的提醒才想到也许仅仅是格式问题。因此直接使用open的形式打开.p8密钥文件,就没有问题了。
在这里插入图片描述
在得到JWT后,苹果给出的示例连接是:
在这里插入图片描述
也就是说发送一个带Header的get请求到如上网址,下面用request来写(附curl转request: http://curl.trillworks.com ):
在这里插入图片描述报安全原因的拒绝访问,说明JWT已经生效(如果是JWT有问题会报401)

3. 连接

产生密钥后利用这个密钥去连接App Store Connect API,这里尝试连接的是销售和趋势中的销量( https://developer.apple.com/documentation/appstoreconnectapi/download_sales_and_trends_reports )


# 4. Include the signed JWT in the authorization header of each App Store Connect API request
import requests
str_dtt = '2019-03-10'  # 指定想要得到的日期
str_vnd = '00000000'  # 你自己的vendorNumber
str_url = "https://api.appstoreconnect.apple.com/v1/salesReports?filter[reportDate]=%s&filter[reportSubType]=SUMMARY&filter[reportType]=SALES&filter[frequency]=WEEKLY&filter[vendorNumber]=%s" % (str_dtt, str_vnd)
# 苹果这个接口有一堆又臭又长的Query string Parameters,简直恶心
# 其中vendorNumber就是供应商编号,在itunesConnect登陆后"付款和财务报告"页左上角可以找到

mdl_rqt = requests.get(
	str_url, 
	headers={
		'Content-Type': 'application/a-gzip',  
		# 增加Content-Type是因为苹果本API返回数据格式为gzip
		'Authorization': 'Bearer %s'%str(nc, encoding='utf-8')  
		# 指定JWT
	}, 
	timeout=30
)  
# 5. 将get回来的content使用gzip解码
import gzip
print(gzip.decompress(mdl_rqt.content).decode("utf-8"))

不过此API的参数设置有个奇怪的地方,就是当filter[reportSubType]=Detailed的时候,会莫名报filter[vendorNumber]错误···搞不懂。除此以外一切正常如下。
在这里插入图片描述
完成。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值