调用App Store Connect Api
对iOS的证书、描述文件、账号、设备等管理,之前都去苹果开发者中心操作,官网上操作也比较繁杂,想搞一些自动化之类的,更是麻烦,有时候官网都打不开……
其实苹果还提供里一套API接口,创建证书、创建账号、增加devices等等,这些都可以调用命令操作,可以按需来完成自动化操作或批量操作。
API接口地址:https://api.appstoreconnect.apple.com
文档地址:https://developer.apple.com/documentation/appstoreconnectapi
有人可能看完文档还是不知道怎么下手,简述一下步骤:
1. 生成token
(1)key 和iss以及.p8文件生成就不累述
(2) 构造header
algorithm = 'ES256' base_api_url = "https://api.appstoreconnect.apple.com"
header = { "alg": algorithm, "kid": key, "typ": "JWT" }
(3)构造payload
# payload = { "iss": iss, "exp": int(time.mktime((datetime.now() + timedelta(minutes=20)).timetuple())), "aud": "appstoreconnect-v1" }
(4)生成token
token = jwt.encode(payload=payload, key=private_key, algorithm=algorithm, headers=header).decode('ascii') return token
(5)封装请求处理
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
比如我们以增加设备id为例:
def set_devices(api_token, data): """ 增加devices信息 :param api_token: :param data: :return: """ set_device_url = '/v1/devices' res = base_call(set_device_url, api_token, 'post', data) return res
post_data = { "data": { "attributes": { "name": i.split(',')[0], "platform": "IOS", "udid": i.split(',')[1] }, "type": "devices" } } res = api.set_devices(api_token, post_data) if res.status_code != 201: print(res.json()['errors'][0]['detail']) else: print("add time:", res.json()['data']['attributes']['addedDate'])
这里的参数组装需要注意,需要参考文档一层层组装参数,data包含自子参数,子参数再包含子参数
完整的代码示例:
# -*- coding:utf-8 -*- # Author: drew # create time: 2020-07030 # update time: # app store connect api import jwt import time import json import requests from datetime import datetime, timedelta algorithm = 'ES256' base_api_url = "https://api.appstoreconnect.apple.com" def get_token(key, iss, key_file): """ :param key: :param iss: :param key_file: :return: """ # 读取私钥 private_key = open(key_file, 'r').read() # 构造header header = { "alg": algorithm, "kid": key, "typ": "JWT" } # 构造payload payload = { "iss": iss, "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).decode('ascii') return token 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 # ------------------ 获取具体接口的方法 ------------------ 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 } res = base_call(get_devices_url, api_token, 'get', data) return res def set_devices(api_token, data): """ 增加devices信息 :param api_token: :param data: :return: """ set_device_url = '/v1/devices' res = base_call(set_device_url, api_token, 'post', data) return res def update_devices(api_token, id, data,): """ 增加devices信息 :param id: :param api_token: :param data: :return: """ set_device_url = '/v1/devices/{%s}' % id res = base_call(set_device_url, api_token, 'patch', data) return res """ if __name__ == "__main__": ios_api_key = 'T8****8AD8' ios_api_issuer = '69a**9-b79b-4**3-e053-5b**1a4d1' file_key = "/Users/drew/.private_keys/AuthKey_T85LR***8.p8" token_api = get_token(ios_api_key, ios_api_issuer, file_key) # get_udid() post_data = { "data": { "attributes": { "name": "zb", "platform": "IOS", "udid": "80b677c2c****e476caf61ba0d34274000" }, "type": "devices" } } res = set_udid(token_api, post_data) print(res) """
本文来自博客园,作者:drewgg,转载请注明原文链接:https://www.cnblogs.com/drewgg/p/13452033.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?