苹果开发者apple_developer_api
之前研究了苹果超级签,为了⽅便的注册udid并且下载描述⽂件,特意写此API,⽅便程序调⽤2022.1.8 更新
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# project: 4⽉
# author: NinEveN
# date: 2020/4/17
# pip install pyjwt
import base64
import logging
import os
import time
from collections import namedtuple
from functools import wraps
import jwt
import requests
f import settings
logger = Logger(__name__)
# developer.apple/documentation/appstoreconnectapi/creating_api_keys_for_app_store_connect_api #  appstoreconnect.apple/access/api 去申请秘钥
#
proxies ={}
timeout =120
def request_format_log(req):
try:
logger.info(f"url:{req.url} header:{req.headers} code:{req.status_code} body:{t}")
except Exception as e:
<(e)
return req
# 需要和model⾥⾯的对应起来
capability_info =[
[],
["PUSH_NOTIFICATIONS"],
[
"PERSONAL_VPN",
"PUSH_NOTIFICATIONS",
"NETWORK_EXTENSIONS",
],
[
"PERSONAL_VPN",
"PUSH_NOTIFICATIONS",
"NETWORK_EXTENSIONS",
"WALLET",
"ICLOUD",
"INTER_APP_AUDIO",
"ASSOCIATED_DOMAINS",
"APP_GROUPS",
"HEALTHKIT",
"HOMEKIT",
"WIRELESS_ACCESSORY_CONFIGURATION",
"APPLE_PAY",
"DATA_PROTECTION",
"SIRIKIT",
"MULTIPATH",
"HOT_SPOT",
"NFC_TAG_READING",
"CLASSKIT",
"AUTOFILL_CREDENTIAL_PROVIDER",
"ACCESS_WIFI_INFORMATION",
"COREMEDIA_HLS_LOW_LATENCY",
]
]
def get_capability(s_type):
return capability_info[s_type]
class DevicesAPI(object):
# developer.apple/documentation/appstoreconnectapi/devices
def__init__(self, base_uri, jwt_headers):
self.headers = jwt_headers
self.devices_url ='%s/devices'% base_uri
def list_devices(self, query_parameters=None):
"""
:param query_parameters:
:return:
200 DevicesResponse OK  Content-Type: application/json
400 ErrorResponse Bad Request An error occurred with your request. Content-Type: application/json            403 ErrorResponse Forbidden Request not authorized. Content-Type: application/json
"""
params ={
"fields[devices]":"addedDate, deviceClass, model, name, platform, status, udid",
"filter[platform]":"IOS",
"limit":200
}
if query_parameters:
for k, v in query_parameters.items():
params[k]= v
return request_format_log(
<(self.devices_url, params=params, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
def list_enabled_devices(self):
return self.list_devices({"filter[status]":"ENABLED"})
def list_disabled_devices(self):
return self.list_devices({"filter[status]":"DISABLED"})
def list_device_by_device_id(self, device_id):
return self.list_devices({"filter[id]": device_id})
def register_device(self, device_name, device_udid, platform="IOS"):
"""
:param device_name:
:param device_udid:
:param platform:
:
return:
201 DeviceResponse Created Content-Type: application/json
400 ErrorResponse Bad Request An error occurred with your request. Content-Type: application/json            403 ErrorResponse Forbidden Request not authorized. Content-Type: application/json
409 ErrorResponse Conflict The provided resource data is not valid. Content-Type: application/json
"""
json ={
'data':{
'data':{
'type':'devices',
'attributes':{
'name': device_name,
'udid': device_udid,
'platform': platform  # IOS or MAC_OS
}
}
}
return request_format_log(
requests.post(self.devices_url, json=json, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
def read_device_information(self, device_id):
"""
:
param device_id:
:return:
200 DeviceResponse OK Content-Type: application/json
400 ErrorResponse Bad Request An error occurred with your request. Content-Type: application/json
403 ErrorResponse Forbidden Request not authorized. Content-Type: application/json
404 ErrorResponse Not Found Resource not found. Content-Type: application/json
"""
base_url ='%s/%s'%(self.devices_url, device_id)
params ={
"fields[devices]":"addedDate, deviceClass, model, name, platform, status, udid",
}
return request_format_log(
<(base_url, params=params, headers=self.headers, proxies=self.proxies, timeout=self.timeout))
def enabled_device(self, device_id, device_name):
dify_registered_device(device_id, device_name,'ENABLED')
def disabled_device(self, device_id, device_name):
dify_registered_device(device_id, device_name,'DISABLED')
def modify_registered_device(self, device_id, device_name, status):
"""
:param device_id:
:param device_name:
:param status:
:return:
200 DeviceResponse OK Content-Type: application/json
400 ErrorResponse Bad Request An error occurred with your request. Content-Type: application/json
403 ErrorResponse Forbidden Request not authorized. Content-Type: application/json
404 ErrorResponse Not Found Resource not found. Content-Type: application/json
409 ErrorResponse Conflict The provided resource data is not valid. Content-Type: application/json
"""
base_url ='%s/%s'%(self.devices_url, device_id)
json ={
'data':{
'type':'devices',
'id': device_id,
'attributes':{
'name': device_name,
'status': status
}
}
}
return request_format_log(
requests.patch(base_url, json=json, headers=self.headers, proxies=self.proxies, timeout=self.timeout))
class BundleIDsAPI(object):
# developer.apple/documentation/appstoreconnectapi/bundle_ids
def__init__(self, base_uri, jwt_headers):
self.headers = jwt_headers
self.bundle_ids_url ='%s/bundleIds'% base_uri
def register_bundle_id(self, bundle_id_name, bundle_id_identifier, platform="IOS", seed_id=''):
def register_bundle_id(self, bundle_id_name, bundle_id_identifier, platform="IOS", seed_id=''):
"""
:param bundle_id_name:
:param bundle_id_identifier:
:param platform:
:param seed_id:
:return:
201 BundleIdResponse Created Content-Type: application/json
苹果apple id注册
400 ErrorResponse Bad Request An error occurred with your request. Content-Type: application/json            403 ErrorResponse Forbidden Request not authorized. Content-Type: application/json
409 ErrorResponse Conflict The provided resource data is not valid. Content-Type: application/json
"""
json ={
'data':{
'type':'bundleIds',
'attributes':{
'name': bundle_id_name,
'identifier': bundle_id_identifier,
'platform': platform,
'seedId': seed_id
}
}
}
return request_format_log(
requests.post(self.bundle_ids_url, json=json, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
def delete_bundle_id_by_id(self, bundle_id):
"""
:param bundle_id:
:
return:
204 No Content
400 ErrorResponse Bad Request An error occurred with your request. Content-Type: application/json            403 ErrorResponse Forbidden Request not authorized. Content-Type: application/json
404 ErrorResponse Not Found Resource not found. Content-Type: application/json
409 ErrorResponse Conflict The provided resource data is not valid. Content-Type: application/json
"""
base_url ='%s/%s'%(self.bundle_ids_url, bundle_id)
json ={}
return request_format_log(
requests.delete(base_url, json=json, headers=self.headers, proxies=self.proxies, timeout=self.timeo
ut))
def list_bundle_ids(self, query_parameters=None):
"""
:param query_parameters:
:return:
200 BundleIdsResponse  OK  Content-Type: application/json
400 ErrorResponse Bad Request An error occurred with your request. Content-Type: application/json            403 ErrorResponse Forbidden Request not authorized. Content-Type: application/json
"""
params ={
"fields[bundleIds]":"identifier, name, platform, profiles, seedId",
# "filter[platform]": "IOS",
"limit":200
}
if query_parameters:
for k, v in query_parameters.items():
params[k]= v
return request_format_log(
<(self.bundle_ids_url, params=params, headers=self.headers, proxies=self.proxies,
timeout=self.timeout))
def list_bundle_id_by_identifier(self, identifier):
return self.list_bundle_ids({"filter[identifier]": identifier})
def list_bundle_id_by_id(self, bundle_id):
return self.list_bundle_ids({"filter[id]": bundle_id})
def modify_bundle_id(self, bundle_id, bundle_name):
"""
"""
:param bundle_id:
:param bundle_name:
:return:
200 BundleIdResponse OK Content-Type: application/json
400 ErrorResponse Bad Request An error occurred with your request. Content-Type: application/json            403 ErrorResponse Forbidden Request not authorized. Content-Type: application/json
404 ErrorResponse Not Found Resource not found. Content-Type: application/json
409 ErrorResponse Conflict The provided resource data is not valid. Content-Type: application/json
"""
base_url ='%s/%s'%(self.bundle_ids_url, bundle_id)
json ={
'data':{
'type':'bundleIds',
'id': bundle_id,
'attributes':{
'name': bundle_name,
}
}
}
return request_format_log(
requests.patch(base_url, json=json, headers=self.headers, proxies=self.proxies, timeout=self.timeout))
class BundleIDsCapabilityAPI(object):
# developer.apple/documentation/appstoreconnectapi/bundle_id_capabilities
def__init__(self, base_uri, jwt_headers):
self.headers = jwt_headers
self.bundle_ids_capability_url ='%s/bundleIdCapabilities'% base_uri
def disable_capability(self, bundle_id, capability_type):
"""
:param capability_type:
:param bundle_id:
:return:
204 No Content
400 ErrorResponse Bad Request An error occurred with your request. Content-Type: application/json            403 ErrorResponse Forbidden Request not authorized. Content-Type: application/json
404 ErrorResponse Not Found Resource not found. Content-Type: application/json
409 ErrorResponse Conflict The provided resource data is not valid. Content-Type: application/json
"""
base_url ='%s/%s_%s'%(self.bundle_ids_capability_url, bundle_id, capability_type)
json ={}
return request_format_log(
requests.delete(base_url, json=json, headers=self.headers, proxies=self.proxies, timeout=self.timeout))
def enable_capability(self, bundle_id, capability_type):
"""
:param bundle_id:
:param capability_type:
:return:
201 BundleIdCapabilityResponse Created Content-Type: application/json
400 ErrorResponse Bad Request An error occurred with your request. Content-Type: application/json            403 ErrorResponse Forbidden Request not authorized. Content-Type: application/json
409 ErrorResponse Conflict The provided resource data is not valid. Content-Type: application/json
"""
json ={
'data':{
'type':'bundleIdCapabilities',
'attributes':{
'capabilityType': capability_type,# 'PUSH_NOTIFICATIONS',#PERSONAL_VPN
'settings':[]
},
'relationships':{
'bundleId':{
'data':{
'id': bundle_id,
'type':'bundleIds',
}
}