· Developers · 6 min czytania

Przesyłanie zrzutów ekranu App Store przez App Store Connect API

Przesyłanie zrzutów ekranu App Store przez App Store Connect API
TL;DR. Przesłanie zrzutu ekranu przez App Store Connect API to sekwencja czterech kroków na obraz: utwórz appScreenshotSet dla odpowiedniego języka i urządzenia, zarezerwuj appScreenshot (Apple zwraca podpisane z góry adresy URL fragmentów), wyślij bajty przez PUT, a następnie wykonaj PATCH rezerwacji z uploaded: true i sumą MD5 pliku. Uwierzytelnianie to 20-minutowy JWT podpisany kluczem .p8. Nic z tego nie jest trudne — wszystko jest żmudne. Oto rzeczywista sekwencja — i skrót, jeśli wolisz tego nie budować.

Dokumentacja Apple na ten temat jest rzetelna i niemal nieczytelna — przepływ jest rozproszony po kilkunastu stronach referencyjnych bez jednego kompletnego przykładu. Ten wpis to jeden przewodnik, w kolejności, z dokładnymi endpointami i nazwami pól. Napisany dla kogoś, kto zastanawia się, czy budować integrację, czy sięgnąć po narzędzie, które już ją ma.

Model obiektów, do którego przesyłasz

Zrzuty ekranu nie są podpięte bezpośrednio do aplikacji. Zwisają na łańcuchu obiektów, który trzeba przejść od góry do dołu:

  • appStoreVersion — konkretna wersja, którą edytujesz (musi być w stanie edytowalnym).
  • appStoreVersionLocalization — jedna na każdy język App Store (en-US, de-DE, ja i tak dalej).
  • appScreenshotSet — jeden na każdy typ wyświetlacza wewnątrz lokalizacji (iPhone 6,7", iPad 13" itd.).
  • appScreenshot — pojedynczy obraz, maksymalnie 10 na zestaw.

W pełni zlokalizowana lista w 50 językach, obejmująca dwa rozmiary iPhone'a i jeden rozmiar iPada, to 50 × 3 zestawy, każdy zawierający do 10 zrzutów ekranu. To mnożenie jest całym powodem, dla którego ludzie to automatyzują, zamiast klikać w interfejsie webowym.

Krok 0 — 20-minutowy JWT

Każde żądanie oprócz samych przesyłań bajtów wymaga nagłówka Authorization: Bearer z tokenem JSON Web Token, który podpisujesz samodzielnie. Potrzebujesz trzech rzeczy z App Store Connect: issuer ID, key ID oraz pliku klucza prywatnego .p8, który pobierasz raz przy tworzeniu klucza (Apple nigdy więcej go nie pokazuje).

Token jest podpisywany algorytmem ES256 — ECDSA na krzywej P-256 z SHA-256 — przy użyciu tego klucza .p8. Nagłówek zawiera kid; ładunek zawiera issuer jako iss, odbiorcę jako dosłowny ciąg appstoreconnect-v1 oraz exp nie więcej niż 20 minut po iat. Apple odrzuca wszystko o dłuższym czasie życia, więc regenerujesz token często — twórz świeży token na każdą partię zamiast próbować utrzymać jeden otwarty.

Podpisz to dowolną biblioteką JWT obsługującą ES256 (jsonwebtoken, PyJWT, cokolwiek używa twój stos), przekaż zawartość .p8 jako klucz i umieść wynik w nagłówku Authorization w każdym z poniższych wywołań.

Krok 1 — utwórz zestaw zrzutów ekranu

Zestaw jest przypisany do jednej lokalizacji i jednego typu wyświetlacza. Wysyłasz POST do /v1/appScreenshotSets z screenshotDisplayType w atrybutach i relacją wskazującą na appStoreVersionLocalization, który chcesz wypełnić.

Popularne typy wyświetlaczy: APP_IPHONE_67 (6,7", 1290 × 2796), aktualny rozmiar dla dużego iPhone'a, oraz APP_IPAD_PRO_3GEN_129 (12,9", 2048 × 2732). Jedna przydatna rzecz, którą Apple teraz robi: zrzuty ekranu dla największego rozmiaru iPhone'a są ponownie wykorzystywane w mniejszych klasach iPhone'ów, a największy rozmiar iPada w mniejszych iPadach — więc w praktyce często potrzebujesz tylko jednego zestawu dla iPhone'a i jednego dla iPada na lokalizację, a nie po jednym na fizyczne urządzenie. Odpowiedź zwraca id zestawu, który przenosisz do kolejnego wywołania. Jeśli zestaw dla danej lokalizacji/typu już istnieje, użyj go ponownie zamiast tworzyć duplikat.

Krok 2 — zarezerwuj zrzut ekranu

Nie przesyłasz pliku za jednym razem. Najpierw go rezerwujesz: podajesz Apple nazwę pliku i dokładny rozmiar w bajtach, a on zwraca plan przesyłania. Wysyłasz POST do /v1/appScreenshots z atrybutami fileName i fileSize oraz relacją do zestawu z kroku 1.

Odpowiedź to interesująca część. Wewnątrz atrybutów nowego zrzutu ekranu otrzymujesz uploadOperations — tablicę opisującą dokładnie, jak wysłać bajty. Dla małego pliku to jedna operacja; dla dużego Apple dzieli go na kilka. Każdy wpis podaje method (PUT), podpisany z góry url, bajtowy offset i length do wysłania oraz requestHeaders do dołączenia.

Krok 3 — wyślij bajty przez PUT

Dla każdej operacji odczytaj fragment pliku od offset na długość length bajtów i wyślij go przez PUT na podany url, dokładnie z requestHeaders podanymi przez Apple. Te adresy URL są podpisane z góry, więc nie wysyłasz tutaj swojego JWT — dodanie nagłówka Authorization może faktycznie zepsuć podpisane żądanie. Wiele operacji może działać równolegle, ale Apple ogranicza agresywne przesyłanie, więc opakuj je w mechanizm ponawiania z narastającym opóźnieniem, zamiast wysyłać wszystko naraz.

Krok 4 — zatwierdź z uploaded: true i sumą MD5

Przesłanie bajtów niczego nie zmienia, dopóki nie powiadomisz Apple, że rezerwacja jest kompletna. Wykonaj PATCH zrzutu ekranu z uploaded: true i sourceFileChecksum — sumą MD5 całego pliku jako ciąg szesnastkowy małymi literami. To kontrola integralności Apple: jeśli suma kontrolna nie zgadza się z tym, co dotarło, przetwarzanie kończy się niepowodzeniem.

Po PATCH zasób trafia do przetwarzania po stronie Apple. Odpytuj assetDeliveryState zrzutu ekranu, aż osiągnie stan ukończony — i odczytaj jego errors, jeśli się nie powiedzie, bo właśnie tam pojawiają się problemy z nieprawidłowymi wymiarami i kanałem alfa. PUT i PATCH mogą się oba powieść, a zrzut ekranu może zostać odrzucony kilka minut później podczas przetwarzania. Nie zakładaj, że 2xx przy commicie oznacza gotowe — obserwuj stan dostarczenia.

Krok 5 — ustaw kolejność wyświetlania

Zrzuty ekranu wracają w kolejności, w jakiej zostały utworzone, co rzadko jest kolejnością, jaką chcesz pokazać. Kolejność zestawu to osobna relacja. Wykonaj PATCH /v1/appScreenshotSets/{id}/relationships/appScreenshots z tablicą identyfikatorów zrzutów ekranu — kolejność tablicy jest kolejnością wyświetlania w sklepie.

Ograniczenia, które Apple faktycznie egzekwuje

  • Tylko PNG lub JPEG. Bez HEIC, bez WebP. Jeśli twój renderer wypluwa cokolwiek innego, najpierw skonwertuj.
  • Brak kanału alfa. Spłaszcz przezroczystość do jednolitego tła i eksportuj RGB. Zagubiony kanał alfa to jedno z najczęstszych cichych odrzuceń podczas przetwarzania.
  • Dokładne wymiary dla każdego typu wyświetlacza. Obraz musi dokładnie odpowiadać rozmiarowi pikseli danego typu wyświetlacza — bez odchyleń o kilka pikseli, bez powiększania. Plik 1290 × 2796 trafia do zestawu APP_IPHONE_67 i nigdzie indziej.
  • Do 10 na zestaw. Maksymalnie dziesięć zrzutów ekranu na lokalizację na typ wyświetlacza.
  • Tylko wersja edytowalna. Możesz modyfikować zestawy tylko w wersji, która jest w stanie edytowalnym; wersja już w recenzji jest zablokowana.

Dlaczego to więcej pracy, niż się wydaje

Każde pojedyncze wywołanie jest proste. Koszt tkwi we wszystkim wokół nich: podpisywanie i odnawianie 20-minutowego tokenu, obliczanie sum MD5, dzielenie plików zgodnie z uploadOperations, obsługa ponowień przy częściowym przesyłaniu, odpytywanie stanu dostarczenia, mapowanie twoich lokalizacji na kody lokalizacji Apple i robienie tego wszystkiego ponad 150 razy dla porządnie zlokalizowanej listy. Zbudowanie tego niezawodnie to weekend uwierzytelniania, fragmentowanych przesyłań i obsługi błędów — a potem musisz to utrzymywać za każdym razem, gdy Apple dodaje nowy typ wyświetlacza.

Jeśli chcesz mieć tę sekwencję bez pisania jej samodzielnie, akcja deliver z Fastlane opakowuje to samo API i jest standardową ścieżką open source. Rozwiązuje przesyłanie — nie rysuje zrzutów ekranu ani nie pisze podpisów.

…albo pomiń to wszystko

API przenosi tylko gotowe obrazy. Coś nadal musi zaprojektować karuzelę, napisać podpisy i przetłumaczyć je na każdy język — a to jest ta część, która faktycznie zajmuje czas. Mokbi robi to już dziś: projektuje zrzuty ekranu, tworzy szkic treści na stronie aplikacji i tłumaczy całość na 50 języków, a następnie eksportuje każdy obraz w dokładnych wymiarach wymaganych dla każdego typu wyświetlacza przez to API — PNG, RGB, bez alfa, właściwy rozmiar — więc przesyłanie nie odbija się na etapie stanu dostarczenia.

Potem publikuje. Dla App Store Mokbi uruchamia dokładnie tę sekwencję rezerwacji i zatwierdzenia pod maską — przesyłając twoje zrzuty ekranu i metadane oraz przygotowując wersję gotową do przesłania przez ciebie — więc nigdy nie dotykasz JWT ani fragmentowanego PUT-a. Apple nadal wymaga finalnego przesłania i swojej recenzji; wszystko do tego momentu jest zrobione za ciebie. Dla Google Play publikuje bezpośrednio do sklepu. Tak czy inaczej otrzymujesz wynik API bez pisania kodu, z projektem, tekstami i tłumaczeniem na 50 języków już gotowymi.

Co przeczytać dalej

Otwórz edytor →