Wszystkie artykuły
Playbook8 min czytania

Obsługa zwrotów psuje się po cichu, więc przetestuj zwroty za zakupy w aplikacji w środowisku sandbox, zanim zrobi to prawdziwy klient

Twoja obsługa zwrotów uruchamia się dopiero po tym, jak klient już odszedł, więc błąd w niej pozostaje niewidoczny, dopóki nie zacznie kosztować prawdziwych pieniędzy. Oba sklepy pozwalają najpierw uruchomić zwrot w środowisku testowym. Oto jak przetestować zwroty za zakupy w aplikacji w App Store i Google Play, zanim jeden z nich stanie się prawdziwy.

iPhone i telefon z Androidem pod lupą na ciemnym biurku, symbolizujące testowanie zwrotów za zakupy w aplikacji, zanim staną się prawdziwe

Najważniejsze wnioski

  • Testowanie StoreKit w Xcode pozwala zwrócić zakup lokalnie przez kliknięcie strzałki zwrotu w Transaction Manager, co uruchamia nasłuchiwacz Transaction.updates twojej aplikacji, ale nigdy nie kontaktuje się z Apple, więc App Store Server Notification nie jest wysyłane.
  • Aby przetestować stronę serwerową u Apple, skieruj sandboxowy adres URL App Store Server Notifications V2 na swój backend: wtedy zwrot w sandbox dostarczy prawdziwe REFUND, a prośba o zwrot dostarczy CONSUMPTION_REQUEST na twój serwer.
  • Punkt końcowy Apple Request a Test Notification wysyła powiadomienie typu TEST na skonfigurowany przez ciebie adres URL i zwraca testNotificationToken, więc możesz potwierdzić, że twój webhook jest osiągalny, zanim zadziała jakiekolwiek prawdziwe zdarzenie.
  • Sandbox Apple nigdy nie ponawia nieudanego powiadomienia, więc webhook, który jest niedostępny w chwili wysyłki z sandbox, gubi zdarzenie bez drugiej próby, ta sama klasa pomyłki, która później kosztuje cię prawdziwe okno zwrotu.
  • Google Play daje testerom licencji metodę płatności Test card, approves then charges back, która uruchamia PendingRefundReviewNotification chwilę po zakupie, więc możesz przećwiczyć swoją 24-godzinną odpowiedź orders.reviewrefund.
  • Dla testera licencji w Google Play niepotwierdzony zakup jest automatycznie zwracany po 3 minutach zamiast 3 dni, na które czeka produkcja, więc zepsuta ścieżka potwierdzania zawodzi szybko i głośno podczas testów.
  • Nieprzetestowany moduł obsługi zwrotów to ten, który utrzymuje płatny dostęp klienta po zwrocie, a od 3 sierpnia 2026 nieprzetestowana odpowiedź na obciążenie zwrotne w Google Play może kosztować cię cenę zakupu pomniejszoną o opłatę serwisową Play plus opłatę banku.

Twoja obsługa zwrotów to jedyna ścieżka kodu, która uruchamia się dopiero po tym, jak klient już odszedł. Nic w twoim zwykłym QA jej nie dotyka, bo żeby do niej dotrzeć, musisz naprawdę dostać zwrot. Więc wychodzi nieprzetestowana, leży cicho przez miesiące, a potem zawodzi na prawdziwym zwrocie, gdzie awaria kosztuje pieniądze, a nie czerwony test. Rozwiązaniem jest przestać traktować zwrot jako coś, co ci się przydarza, i zacząć uruchamiać go celowo. Zarówno Apple, jak i Google pozwalają uruchomić zwrot w środowisku testowym i obserwować reakcję serwera. Oto jak przetestować zwroty za zakupy w aplikacji w App Store i Google Play, zanim płacący klient udowodni, że twój moduł obsługi był zepsuty.

Trzy środowiska, w których może zadziałać zwrot, i tylko jedno z nich to produkcja

Są trzy oddzielne miejsca, w których można wyzwolić zwrot Apple lub Google podczas budowania, i nie są wymienne. Dwa z nich możesz wyzwalać na żądanie. Trzecie to produkcja, gdzie nigdy nie chcesz spotkać błędu zwrotu po raz pierwszy. Pułapką jest założenie, że łatwy wariant, lokalne testowanie w Xcode, dowodzi działania całego potoku. Dowodzi działania twojej aplikacji. Nie mówi nic o twoim serwerze.

Testowanie StoreKit w Xcode jest lokalne, więc sprawdza twoją aplikację i nic więcej

Wbudowane testowanie StoreKit w Xcode działa na pliku konfiguracyjnym na twoim Macu, bez podróży w obie strony do Apple. Otwórz StoreKit Transaction Manager z paska debugowania, wybierz zakupioną transakcję i kliknij zakrzywioną strzałkę zwrotu. Transakcja przełącza się na zwróconą, a nasłuchiwacz Transaction.updates twojej aplikacji uruchamia się dokładnie tak, jak w warunkach rzeczywistych. Możesz też wywołać beginRefundRequest, aby wyświetlić prawdziwy arkusz zwrotu, a w środowisku Xcode wybrany przez ciebie problem mapuje się jeden do jednego na RevocationReason, przy czym zwrot jest stosowany natychmiast. To najszybszy sposób, aby udowodnić, że twój klient odcina dostęp w chwili, gdy revocationDate staje się różne od nil. To także wszystko, co lokalne testowanie może ci powiedzieć, bo nic tutaj nigdy nie dociera do serwerów Apple, więc App Store Server Notification nie jest wysyłane. Twój backend niczego się nie dowiaduje.

Sandbox to miejsce, w którym twój serwer w końcu słyszy o zwrocie

Aby przetestować tę połowę integracji, która decyduje o pieniądzach, twój serwer, potrzebujesz sandboxa Apple. Skonfiguruj sandboxowy adres URL App Store Server Notifications V2 w App Store Connect, zaloguj testera sandbox na urządzeniu i kup. Teraz zwrot w sandbox dostarcza prawdziwe powiadomienie REFUND na twój backend, a prośba o zwrot przy produkcie zużywalnym lub odnawialnym automatycznie dostarcza CONSUMPTION_REQUEST, ten sam podpisany payload, który dostanie twój serwer produkcyjny. Zanim cokolwiek uruchomisz, wywołaj punkt końcowy Request a Test Notification. Każe on serwerowi App Store wysłać powiadomienie typu TEST na skonfigurowany przez ciebie adres URL i wręcza ci testNotificationToken, który przekazujesz do Get Test Notification Status, aby potwierdzić dostarczenie. Jeśli ta podróż w obie strony nie działa, prawdziwe powiadomienie też nie zadziała.

ŚrodowiskoCo może wyzwolićCo dowodziCzego nie potrafi
Testowanie StoreKit w XcodeZwrot przez Transaction Manager lub arkusz beginRefundRequestTwoja aplikacja reaguje na zwrot lokalnie, w kilka sekundNigdy nie kontaktuje się z Apple, więc powiadomienie serwerowe nie jest wysyłane
SandboxPrawdziwe REFUND i CONSUMPTION_REQUEST na twój serwer, plus powiadomienie TEST na żądanieTwój backend odbiera, weryfikuje i działa na podstawie podpisanego payloadNie ponawia powiadomienia, którego twój punkt końcowy nie odebrał
ProdukcjaKażdy zwrot, za prawdziwe pieniądzeNic, czego chciałbyś się tu dowiedzieć najpierwNie możesz cofnąć kosztu błędu

Jak przetestować zwroty za zakupy w aplikacji w App Store

Wykonaj to w tej kolejności, od taniego sprawdzenia klienta do pełnej podróży w obie strony po stronie serwera. Każdy krok sprawdza inny element, a te późniejsze to te, za które produkcja naprawdę wystawia ci rachunek.

  • Utwórz klucz In-App Purchase w Users and Access, Integrations, In-App Purchase w App Store Connect i użyj go do podpisania swoich wywołań App Store Server API.
  • Skieruj swój sandboxowy adres URL App Store Server Notifications V2 na swój backend, następnie wywołaj Request a Test Notification i potwierdź, że payload TEST dociera i weryfikuje się względem łańcucha certyfikatów Apple.
  • W Transaction Manager Xcode zwróć zakup i potwierdź, że twoja aplikacja odbiera uprawnienie w chwili, gdy ustawione jest revocationDate.
  • Zaloguj testera sandbox, kup produkt zużywalny, poproś o zwrot i potwierdź, że twój serwer odbiera CONSUMPTION_REQUEST oraz potrafi złożyć i wysłać odpowiedź Send Consumption Information z dużym zapasem wewnątrz 12-godzinnego okna.
  • Zwróć zakup w sandbox i potwierdź, że powiadomienie REFUND dociera do twojego serwera, że odbierasz dostęp lub odejmujesz saldo produktu zużywalnego oraz że powtórne dostarczenie tego samego powiadomienia nie stosuje się podwójnie.
Smartfon trzymany w małym imadle stołowym pod lampą warsztatową z pęsetą obok, urządzenie w trakcie testu symbolizujące przećwiczenie zwrotu, zanim stanie się prawdziwy

Jak przećwiczyć zwrot i obciążenie zwrotne w Google Play

Google Play nie ma trybu lokalnego jak Xcode. Wszystko działa na serwerach Google, ale testerzy licencji sprawiają, że jest to darmowe i bezpieczne. Dodaj swoje testowe konta Google jako testerów licencji w Play Console, a otrzymają zestaw testowych metod płatności, które nigdy nie pobierają prawdziwych pieniędzy. Google oznacza każdy zakup testowy informacją na środku okna zakupu, a podatki nie są obliczane. Dla testowania zwrotów liczy się, który instrument testowy wybierzesz, bo każdy z nich prowadzi do innego wyniku.

Testowa metoda płatnościCo symulujeDlaczego byś jej użył
Test instrument, always approvesCzysty udany zakupPrzygotuj zamówienie, które potem możesz zwrócić lub odebrać
Test instrument, always declinesNieudana płatnośćPotwierdź, że przy odrzuceniu nic nie przyznajesz
Slow test card, approves after a few minutesOczekujący zakup, który później się udajePrzećwicz obsługę PENDING, zanim przyznasz dostęp
Slow test card, declines after a few minutesOczekujący zakup, który później zawodziPotwierdź, że oczekujące odrzucenie nigdy nie wycieka uprawnienia
Test card, approves then charges backObciążenie zwrotne zainicjowane przez użytkownikaUruchom PendingRefundReviewNotification i przećwicz swoją 24-godzinną odpowiedź

Wyzwól zwrot, obciążenie zwrotne i automatyczny zwrot za potwierdzenie

  • Kup testową kartą approve-then-charge-back, a PendingRefundReviewNotification wyląduje w twoim temacie Real-time Developer Notifications chwilę później. Odpowiedz na nie jednym wywołaniem orders.reviewrefund, bo Google zachowuje tylko twoją pierwszą odpowiedź.
  • Zwróć i odbierz testowe zamówienie z zakładki Orders w Play Console, aby uruchomić VoidedPurchaseNotification, i potwierdź, że twój serwer wycofuje uprawnienie.
  • Celowo zostaw zakup testera licencji niepotwierdzony. Google zwraca go automatycznie po 3 minutach zamiast 3 dni, na które pozwala produkcja, i wysyła ci e-mailem informację o anulowaniu, więc zepsuta ścieżka potwierdzania ujawnia się w minuty, a nie czwartego dnia na produkcji.

Ile naprawdę kosztuje nieprzetestowana ścieżka zwrotu

Moduł obsługi zwrotów to nie ozdoba. To kod, który powstrzymuje cię przed płaceniem za obsługę kogoś, kto już ci nie płaci. Kiedy zawodzi po cichu, zwrot i tak przechodzi, ale dostęp, saldo i wydatki za nimi nie ustają.

Prześledź pieniądze. Kiedy Apple lub Google zwraca zakup, ty oddajesz cenę sprzedaży, a sklep oddaje swoją prowizję, i jak dotąd bilans jest wyrównany. Nie wraca to wszystko, co już wydałeś na dostarczenie produktu: obliczenia za wygenerowanym wynikiem, wywołania model API, pamięć na to, co użytkownik zapisał, wypłata, którą już wysłałeś twórcy. Moduł obsługi zwrotów, który nigdy nie odbiera dostępu, pozwala użytkownikowi po zwrocie dalej wydawać to z twojego budżetu, a w systemie nie zostaje nic, co by go odcięło.

Dwa okna dowodowe wyostrzają sprawę. CONSUMPTION_REQUEST, którego nigdy nie przećwiczyłeś w sandbox, to odpowiedź, którą wyślesz zniekształconą lub późno, a Apple często przyznaje zwrot domyślnie, gdy twoja odpowiedź nie dociera wewnątrz 12 godzin. Odpowiedź na obciążenie zwrotne w Google Play, której nigdy nie uruchomiłeś testową kartą, to 24-godzinne okno, które kaleczysz na żywo, a od 3 sierpnia 2026 przegrane obciążenie zwrotne w Play kosztuje cię cenę zakupu pomniejszoną o opłatę serwisową Play plus opłatę banku za obciążenie zwrotne. Każda z tych awarii jest odtwarzalna za darmo najpierw w środowisku testowym. Żadna nie jest tania na produkcji.

Nieprzetestowana ścieżkaJak zawodzi na produkcjiIle cię kosztuje
Moduł obsługi REFUNDUżytkownik po zwrocie zachowuje dostępObliczenia, wywołania API, pamięć i wypłaty, które dalej na niego wydajesz
Odpowiedź CONSUMPTION_REQUESTZniekształcona lub wysłana po 12 godzinachApple przyznaje zwrot domyślnie, więc tracisz sprzedaż i wydatek
Odpowiedź orders.reviewrefundPominięta lub błędna wewnątrz 24 godzinOd 3 sierpnia 2026 cena zakupu pomniejszona o opłatę serwisową Play plus opłata banku za obciążenie zwrotne

Krótka lista kontrolna, zanim wdrożysz obsługę zwrotów

Nie potrzebujesz laboratorium. Potrzebujesz raz zobaczyć, jak każde zdarzenie trafia do twojego kodu.

  • Twoja aplikacja odbiera dostęp w chwili, gdy transakcja StoreKit pokazuje revocationDate, potwierdzone w Transaction Manager Xcode.
  • Twój sandboxowy adres URL serwera odbiera powiadomienie TEST i weryfikuje je względem certyfikatów Apple.
  • Sandboxowe REFUND odbiera dostęp lub odejmuje saldo, a powtórne dostarczenie nie liczy się podwójnie.
  • Sandboxowe CONSUMPTION_REQUEST produkuje prawidłową odpowiedź Send Consumption Information z dużym zapasem wewnątrz 12 godzin.
  • PendingRefundReviewNotification od Google z testowej karty obciążenia zwrotnego produkuje dokładnie jedno wywołanie orders.reviewrefund.
  • Niepotwierdzony testowy zakup w Google Play jest automatycznie zwracany w 3 minuty, a twoje uzgadnianie to zauważa.

Przejdź tę listę raz, a obsługa zwrotów przestaje być kodem, o którym masz nadzieję, że działa. Staje się kodem, który widziałeś w działaniu.

Często zadawane pytania

Czy mogę przetestować zwrot w App Store bez prawdziwego zakupu?
Tak. Testowanie StoreKit w Xcode pozwala zwrócić zakup lokalnie przez Transaction Manager, bez prawdziwych pieniędzy i bez konta App Store, co uruchamia nasłuchiwacz Transaction.updates twojej aplikacji. Nie wysyła powiadomienia serwerowego, więc testuje tylko twoją aplikację, a nie twój backend.
Czy lokalne testowanie StoreKit wysyła App Store Server Notifications?
Nie. Testowanie StoreKit w Xcode działa w całości na twoim Macu na lokalnej konfiguracji i nigdy nie kontaktuje się z serwerami Apple, więc App Store Server Notification, w tym REFUND lub CONSUMPTION_REQUEST, nigdy nie jest wysyłane. Użyj sandboxa, aby przetestować swój serwer.
Jak przetestować odpowiedź na obciążenie zwrotne w Google Play?
Użyj metody płatności testera licencji o nazwie Test card, approves then charges back. Uruchamia PendingRefundReviewNotification chwilę po zakupie, to samo powiadomienie, które wysyła prawdziwe obciążenie zwrotne banku, więc możesz przećwiczyć swoją 24-godzinną odpowiedź orders.reviewrefund.
Dlaczego mój testowy zakup w Google Play zostaje zwrócony po kilku minutach?
Dla testerów licencji Google automatycznie zwraca zakup po 3 minutach, jeśli twoja aplikacja go nie potwierdziła, i wysyła ci e-mailem informację o anulowaniu. Produkcja czeka 3 dni, ale testerzy dostają przyspieszoną wersję, więc zepsuta ścieżka potwierdzania ujawnia się szybko.
Czy sandbox Apple ponawia nieudane powiadomienie o zwrocie?
Nie. Sandbox nie ponawia App Store Server Notifications, więc jeśli twój punkt końcowy jest niedostępny, gdy zadziała zwrot w sandbox, powiadomienie zostaje zgubione bez drugiej próby. Najpierw potwierdź, że twój adres URL jest osiągalny, za pomocą Request a Test Notification.

Źródła i materiały dodatkowe

RefundHalt

Autopilot zwrotów dla App Store i Google Play

Czytaj dalej

Kolejny wniosek o zwrot jest już w drodze.

Skonfiguruj RefundHalt w czasie potrzebnym na przeczytanie kolejnej wiadomości od pomocy technicznej o zwrocie, którego nie udało Ci się zakwestionować.