因为以前很少 接触苹果的模块,后面要用到 才发现 苹果开发者后台也有API接口 可以调用,下面下面这个就是苹果接口的文档
Apple Developer Documentationhttps://developer.apple.com/documentation/appstoreconnectapi文档里说了 接口使用 jwt进行令牌验证,此处就不多说了
根据前面的文章(苹果个人开发者自动发包(超级签)教程(1)-UDID获取_描述文件自动注册uuid到服务器-优快云博客
)获取到UUID之后 接下去就是用苹果提供的API把用户的UUID写入到开发者平台账号中
1、获取苹果token(jwt)
2、添加设备到列表
3、获取开发者证书(可有可无)
4、获取设备列表(校验设备是否添加成功,也可以检验该证书下用户是否已经满员)
5、添加配置信息并下载Profile文件(自动打包用到)
下面说下主要部分的代码,因为需要在macos上跑所以用了python写(代码比较简陋东并西凑的)
导入需要的包
import jwt
import time
import json
import requests
import base64
from datetime import datetime, timedelta
#通用方法
def base_call(url, token, method="get", data=None):
"""
:param url:
:param token:
:param method:
:param data:
:return:
"""
re_header = {"Authorization": "Bearer %s" % token}
r = {}
url = base_api_url + url
requests.adapters.DEFAULT_RETRIES = 1
req = requests.session()
req.keep_alive = False
if method.lower() == "get":
r = req.get(url, params=data, headers=re_header)
elif method.lower() == "post":
re_header["Content-Type"] = "application/json"
r = req.post(url=url, headers=re_header, data=json.dumps(data))
elif method.lower() == "patch":
re_header["Content-Type"] = "application/json"
r = req.patch(url=url, headers=re_header, data=json.dumps(data))
return r
1、获取苹果token
这个不多讲直接上代码
def get_token():
"""
:param key:
:param iss:
:param key_file:
:return:
"""
# 读取私钥
private_key = open('p8文件地址', 'r').read()
# 构造header
header = {
"alg": 'ES256',
"kid": 'apikey苹果给的10个字符',
"typ": "JWT"
}
# 构造payload
payload = {
"iss": '苹果给的32位字符加上-有36位',
"exp": int(time.mktime((datetime.now() + timedelta(minutes=20)).timetuple())),
"aud": "appstoreconnect-v1"
}
token = jwt.encode(payload=payload, key=private_key,
algorithm=algorithm, headers=header)
return token
2、添加设备到列表
这个步骤是把前面获取到的UUID 写入到苹果的后台去
def add_devices(api_token, udid, name):
"""
添加devices信息
:param api_token: 上一个接口获取到的token
:param udid:
:param name: 自定义 可以是申请的用户在app中对应的id
:return:
"""
post_data = {
"data": {
"attributes": {
"name": name,
"platform": "IOS",
"udid": udid
},
"type": "devices"
}
}
add_device_url = '/v1/devices'
res = base_call(add_device_url, api_token, 'post', post_data)
# obj = json.loads(res.content)
if res.content == None:
return None
jsondata = json.loads(res.content)
if ('errors' in jsondata):
return None
return jsondata
3、获取开发者证书
该步骤可有可无,如果开发者不变的情况下 直接写死也行
def get_certificates(api_token,certificateType, data=None):
"""
获取证书列表
:param api_token:
:param certificateType: 'DEVELOPMENT'写死
:param data:
:return:
"""
get_certificates_url = '/v1/certificates'
if data is None:
data = {
"filter[certificateType]": certificateType, #DEVELOPMENT
# "filter[status]": "ENABLED",
"limit": 100
}
res = base_call(get_certificates_url, api_token, 'get', data)
if res.content == None:
return None
jsondata = json.loads(res.content)
if ('errors' in jsondata):
return None
return jsondata["data"][0]["id"]
4、获取设备列表
该步骤可有可无主要是当时多个开发者账号 平均分配下,后面生成Profile文件也需要(前面添加设备成功的话可以记录在本地存储)
def get_devices(api_token, data=None):
"""
获取devices信息
:param api_token:
:param data:
:return:
"""
get_devices_url = '/v1/devices'
if data is None:
data = {
"filter[platform]": "IOS",
# "filter[status]": "ENABLED",
"limit": 100
}
print(data)
res = base_call(get_devices_url, api_token, 'get', data)
if res.content == None:
return None
jsondata = json.loads(res.content)
if ('errors' in jsondata):
return None
return jsondata
5、添加配置信息并下载Profile文件
该步骤比较重要 生成embedded.mobileprovision文件这个文件中写入了可以安装的苹果设备标识生成包的时候需要,这个步骤用到了前面获取到的设备列表(可以存本地),这个文件可以针对单个用户只写入他一个设备信息,也可以全部写入.我这边为了偷懒就全部写入了
def add_profiles(api_token, proname, identifier, certificateID, devices):
"""
添加配置信息
:param api_token: token令牌
:param proname: 配置名称
:param identifier: 开发者ID
:param certificateID: 证书ID
:param devices: 设备集合 结构dict(
type='devices',
id=item['id']
)
:return:
"""
#调试解析
# post_data = {
# "data": {
# "attributes": {
# "name": "helloword2",
# "profileType": "IOS_APP_DEVELOPMENT"
# },
# "relationships": {
# "bundleId": {
# "data": {
# "id": "25V84Y68DN",
# "type": "bundleIds"
# }
# },
# "certificates": {
# "data": [{
# "id": "XNR4UDDMSR",
# "type": "certificates"
# }]
# },
# "devices": {
# "data": [{
# "id": "DSALNMH4J4",
# "type": "devices"
# }]
# }
# },
# "type": "profiles"
# }
# }
objdata = dict(
data=dict(
attributes=dict(
name=proname,
profileType='IOS_APP_DEVELOPMENT'
),
relationships=dict(
bundleId=dict(
data=dict(
id=identifier,
type='bundleIds'
)
),
certificates=dict(
data=[dict(
id=certificateID,
type='certificates'
)]
),
devices=dict(
data=devices
)
),
type='profiles'
)
)
# print(type(objdata)) #打印调试
# j=json.dumps(objdata)
# print(j)
add_profiles_url = '/v1/profiles'
res = base_call(add_profiles_url, api_token, 'post', objdata)
# print(res.__dict__)
if res.content == None:
return None
jsondata = json.loads(res.content)
if ('errors' in jsondata):
return None
encon=jsondata["data"]["attributes"]["profileContent"]
con = base64.b64decode(encon)
save_txt(con, "embedded.mobileprovision") #根据自己情况处理
return 'ok'
到此 和苹果api交互的结束,接下去就是本地打包的了