Усі статті
Playbook8 хв читання

Обробка повернень ламається непомітно, тому протестуйте повернення за вбудовані покупки в sandbox раніше, ніж це зробить реальний клієнт

Ваша обробка повернень запускається лише після того, як клієнт уже пішов, тому помилка в ній лишається невидимою, поки не почне коштувати реальних грошей. Обидва магазини дозволяють спершу запустити повернення в тестовому середовищі. Ось як протестувати повернення за вбудовані покупки в App Store і Google Play до того, як повернення стане реальним.

iPhone і телефон на Android під збільшувальним склом на темному столі, що символізують тестування повернень за вбудовані покупки до того, як вони стануть реальними

Головне

  • Тестування StoreKit у Xcode дозволяє повернути покупку локально, натиснувши стрілку повернення в Transaction Manager. Це запускає слухач Transaction.updates вашого застосунку, але ніколи не звертається до Apple, тому App Store Server Notification не надсилається.
  • Щоб протестувати серверну сторону в Apple, спрямуйте sandbox-URL App Store Server Notifications V2 на ваш бекенд: тоді повернення в sandbox доставить справжній REFUND, а запит на повернення доставить CONSUMPTION_REQUEST на ваш сервер.
  • Ендпоінт Apple Request a Test Notification надсилає сповіщення типу TEST на налаштований вами URL і повертає testNotificationToken, тому ви можете переконатися, що ваш вебхук доступний, перш ніж спрацює реальна подія.
  • Sandbox в Apple ніколи не повторює невдале сповіщення, тому вебхук, який недоступний у момент надсилання із sandbox, втрачає подію без другої спроби. Це той самий клас промаху, який згодом коштує вам реального вікна повернення.
  • Google Play дає ліцензійним тестувальникам спосіб оплати Test card, approves then charges back, який запускає PendingRefundReviewNotification за кілька миттєвостей після покупки, тож ви можете відрепетирувати свою 24-годинну відповідь orders.reviewrefund.
  • Для ліцензійного тестувальника в Google Play непідтверджена покупка автоматично повертається через 3 хвилини замість 3 днів у продакшені, тому зламаний шлях підтвердження дає збій швидко й помітно в тестуванні.
  • Обробник повернень, який ви ніколи не тестували, це той, що лишає платний доступ клієнта, який отримав повернення, активним. А з 3 серпня 2026 року непротестована відповідь на чарджбек у Google Play може коштувати вам ціни покупки за вирахуванням сервісного збору Play плюс комісія банку.

Ваша обробка повернень це єдиний шлях коду, який запускається лише після того, як клієнт уже пішов. Ніщо у вашому звичайному QA його не торкається, бо щоб до нього дістатися, вам треба реально отримати повернення. Тому він виходить непротестованим, тихо лежить місяцями, а потім дає збій на реальному поверненні, де збій коштує грошей, а не червоного тесту. Розв'язок у тому, щоб перестати вважати повернення чимось, що стається з вами, і почати запускати його навмисно. І Apple, і Google дозволяють запустити повернення в тестовому середовищі й подивитися, як реагує ваш сервер. Ось як протестувати повернення за вбудовані покупки в App Store і Google Play до того, як платний клієнт доведе, що ваш обробник був зламаний.

Три середовища, у яких може спрацювати повернення, і лише одне з них продакшн

Є три окремі місця, де можна запустити повернення Apple чи Google, поки ви розробляєте, і вони не взаємозамінні. Два з них ви можете запускати на вимогу. Третє це продакшн, де ви ніколи не хочете вперше зустріти помилку повернення. Пастка в тому, щоб вважати, що легкий варіант, локальне тестування в Xcode, доводить роботу всього конвеєра. Він доводить роботу вашого застосунку. Він нічого не каже про ваш сервер.

Тестування StoreKit у Xcode локальне, тому воно перевіряє ваш застосунок і нічого більше

Вбудоване тестування StoreKit у Xcode працює з конфігураційним файлом на вашому Mac, без звернення до Apple. Відкрийте StoreKit Transaction Manager із панелі налагодження, виберіть оплачену транзакцію й натисніть вигнуту стрілку повернення. Транзакція перемикається на повернену, і слухач Transaction.updates вашого застосунку спрацьовує точно так, як це було б у реальності. Ви також можете викликати beginRefundRequest, щоб показати справжній аркуш повернення, і в середовищі Xcode вибрана вами проблема зіставляється один до одного з RevocationReason, а повернення застосовується негайно. Це найшвидший спосіб довести, що ваш клієнт відрізає доступ у той момент, коли revocationDate стає не-nil. Це ж і все, що може сказати локальне тестування, бо тут ніщо ніколи не досягає серверів Apple, тому App Store Server Notification не надсилається. Ваш бекенд не дізнається нічого.

Sandbox це місце, де ваш сервер нарешті дізнається про повернення

Щоб протестувати ту половину вашої інтеграції, яка вирішує про гроші, ваш сервер, вам потрібен sandbox Apple. Налаштуйте sandbox-URL App Store Server Notifications V2 в App Store Connect, увійдіть під sandbox-тестувальником на пристрої й здійсніть покупку. Тепер повернення в sandbox доставляє справжнє сповіщення REFUND на ваш бекенд, а запит на повернення за витратним чи автооновлюваним товаром доставляє CONSUMPTION_REQUEST, той самий підписаний payload, який отримає ваш продакшн-сервер. Перш ніж щось запускати, викличте ендпоінт Request a Test Notification. Він каже серверу App Store надіслати сповіщення типу TEST на налаштований вами URL і видає вам testNotificationToken, який ви передаєте в Get Test Notification Status, щоб підтвердити доставку. Якщо цей цикл не працює, реальне сповіщення теж не спрацює.

СередовищеЩо воно може запуститиЩо воно доводитьЩо воно не може
Тестування StoreKit у XcodeПовернення через Transaction Manager або аркуш beginRefundRequestВаш застосунок реагує на повернення локально, за секундиНіколи не звертається до Apple, тому серверне сповіщення не надсилається
SandboxСправжні REFUND і CONSUMPTION_REQUEST на ваш сервер, плюс сповіщення TEST на вимогуВаш бекенд отримує, перевіряє і діє за підписаним payloadНе повторює сповіщення, яке ваш ендпоінт не зміг отримати
ПродакшнКожне повернення, за реальні грошіНічого, що ви хотіли б дізнатися тут першимВи не можете скасувати вартість помилки

Як протестувати повернення за вбудовані покупки в App Store

Виконуйте в такому порядку, від дешевої перевірки клієнта до повного серверного циклу. Кожен крок перевіряє свою частину, і саме за пізні кроки продакшн реально виставляє вам рахунок.

  • Створіть ключ In-App Purchase у розділі Users and Access, Integrations, In-App Purchase в App Store Connect і використовуйте його для підпису ваших викликів App Store Server API.
  • Спрямуйте ваш sandbox-URL App Store Server Notifications V2 на ваш бекенд, потім викличте Request a Test Notification і переконайтеся, що payload TEST приходить і перевіряється за ланцюжком сертифікатів Apple.
  • У Transaction Manager Xcode поверніть покупку й переконайтеся, що ваш застосунок знімає право доступу в той момент, коли встановлено revocationDate.
  • Увійдіть під sandbox-тестувальником, купіть витратний товар, запросіть повернення й переконайтеся, що ваш сервер отримує CONSUMPTION_REQUEST і може зібрати й надіслати відповідь Send Consumption Information із добрим запасом усередині 12-годинного вікна.
  • Поверніть покупку в sandbox і переконайтеся, що сповіщення REFUND досягає вашого сервера, що ви відкликаєте доступ або списуєте баланс витратного товару і що повторна доставка того самого сповіщення не застосовується двічі.
Смартфон, затиснутий у маленьких настільних лещатах під робочою лампою, з пінцетом поруч, пристрій на випробуванні, що символізує репетицію повернення до того, як воно стане реальним

Як відрепетирувати повернення й чарджбек у Google Play

У Google Play немає локального режиму, як у Xcode. Усе працює із серверами Google, але ліцензійні тестувальники роблять це безкоштовно й безпечно. Додайте ваші тестові акаунти Google як ліцензійних тестувальників у Play Console, і вони отримають набір тестових способів оплати, які ніколи не списують реальні гроші. Google позначає кожну тестову покупку сповіщенням посеред діалогу покупки, і податки не розраховуються. Для тестування повернень важливо, який тестовий інструмент ви виберете, бо кожен з них веде до свого результату.

Тестовий спосіб оплатиЩо він імітуєНавіщо його використовувати
Test instrument, always approvesЧиста успішна покупкаСтворити замовлення, яке потім можна повернути чи відкликати
Test instrument, always declinesНевдалий платіжПереконатися, що при відхиленні ви нічого не видаєте
Slow test card, approves after a few minutesОчікувана покупка, яка згодом проходить успішноПеревірити обробку PENDING до видачі доступу
Slow test card, declines after a few minutesОчікувана покупка, яка згодом провалюєтьсяПереконатися, що очікуване відхилення ніколи не видає право доступу
Test card, approves then charges backЧарджбек, ініційований користувачемЗапустити PendingRefundReviewNotification і відрепетирувати вашу 24-годинну відповідь

Запустіть повернення, чарджбек і автоповернення за підтвердженням

  • Купіть за допомогою тестової картки approve-then-charge-back, і PendingRefundReviewNotification прийде у вашу тему Real-time Developer Notifications миттєвостями пізніше. Відповідайте на нього одним викликом orders.reviewrefund, бо Google зберігає лише вашу першу відповідь.
  • Поверніть і відкличте тестове замовлення у вкладці Orders в Play Console, щоб запустити VoidedPurchaseNotification, і переконайтеся, що ваш сервер знімає право доступу.
  • Навмисно лишіть покупку ліцензійного тестувальника непідтвердженою. Google автоматично повертає її через 3 хвилини замість 3 днів, які допускає продакшн, і надсилає вам лист про скасування, тож зламаний шлях підтвердження проявляється за хвилини, а не на четвертий день у продакшені.

Скільки насправді коштує непротестований шлях повернення

Обробник повернень це не прикраса. Це код, який зупиняє витрати на обслуговування того, хто вам більше не платить. Коли він дає збій тихо, повернення все одно проходить, але доступ, баланс і витрати за ними не припиняються.

Простежте за грошима. Коли Apple чи Google повертає покупку, ви повертаєте ціну продажу, а магазин повертає свою комісію, і поки що баланс рівний. Що не повертається, так це все, що ви вже витратили на доставку продукту: обчислення за згенерованим результатом, виклики model API, сховище для того, що зберіг користувач, виплата, яку ви вже надіслали автору. Обробник повернень, який ніколи не відкликає доступ, дозволяє користувачеві, що отримав повернення, продовжувати витрачати це за ваш рахунок, і в системі не лишається нічого, що б його відрізало.

Два вікна доказів роблять це різкіше. CONSUMPTION_REQUEST, який ви ніколи не відпрацьовували в sandbox, це відповідь, яку ви надішлете некоректною чи із запізненням, і Apple часто надає повернення за замовчуванням, коли ваша відповідь не приходить усередині 12 годин. Відповідь на чарджбек у Google Play, яку ви ніколи не запускали з тестовою карткою, це 24-годинне вікно, яке ви втрачаєте наживо, і з 3 серпня 2026 року програний чарджбек у Play коштує вам ціни покупки за вирахуванням сервісного збору Play плюс комісія банку за чарджбек. Кожен із цих збоїв відтворюваний безкоштовно в тестовому середовищі спершу. Жоден із них не дешевий у продакшені.

Непротестований шляхЯк він дає збій у продакшеніСкільки він вам коштує
Обробник REFUNDКористувач, що отримав повернення, зберігає доступОбчислення, виклики API, сховище і виплати, які ви продовжуєте на нього витрачати
Відповідь CONSUMPTION_REQUESTНекоректна або надіслана після 12 годинApple надає повернення за замовчуванням, тому ви втрачаєте продаж і витрати
Відповідь orders.reviewrefundПропущена або хибна всередині 24 годинЗ 3 серпня 2026 року, ціна покупки за вирахуванням сервісного збору Play плюс комісія банку за чарджбек

Короткий чек-лист перед тим, як випускати обробку повернень

Вам не потрібна лабораторія. Вам треба один раз побачити, як кожна подія доходить до вашого коду.

  • Ваш застосунок знімає доступ у той момент, коли транзакція StoreKit показує revocationDate, підтверджено в Transaction Manager Xcode.
  • Ваш sandbox-URL сервера отримує сповіщення TEST і перевіряє його за сертифікатами Apple.
  • Sandbox REFUND відкликає доступ або списує баланс, а повторна доставка не рахується двічі.
  • Sandbox CONSUMPTION_REQUEST породжує валідну відповідь Send Consumption Information із добрим запасом усередині 12 годин.
  • PendingRefundReviewNotification від Google з тестової картки чарджбека породжує рівно один виклик orders.reviewrefund.
  • Непідтверджена тестова покупка в Google Play автоматично повертається за 3 хвилини, і ваша звірка це помічає.

Пройдіть цей список один раз, і обробка повернень перестане бути кодом, який ви сподіваєтеся працює. Вона стане кодом, який ви бачили в роботі.

Поширені запитання

Чи можу я протестувати повернення в App Store без реальної покупки?
Так. Тестування StoreKit у Xcode дозволяє повернути покупку локально через Transaction Manager, без реальних грошей і без акаунта App Store, що запускає слухач Transaction.updates вашого застосунку. Воно не надсилає серверне сповіщення, тому тестує лише ваш застосунок, а не ваш бекенд.
Чи надсилає локальне тестування StoreKit App Store Server Notifications?
Ні. Тестування StoreKit у Xcode працює цілком на вашому Mac із локальною конфігурацією й ніколи не звертається до серверів Apple, тому App Store Server Notification, включно з REFUND чи CONSUMPTION_REQUEST, ніколи не надсилається. Використовуйте sandbox, щоб протестувати ваш сервер.
Як мені протестувати відповідь на чарджбек у Google Play?
Використовуйте спосіб оплати ліцензійного тестувальника Test card, approves then charges back. Він запускає PendingRefundReviewNotification за миттєвості після покупки, те саме сповіщення, що надсилає справжній чарджбек банку, тож ви можете відрепетирувати вашу 24-годинну відповідь orders.reviewrefund.
Чому моя тестова покупка в Google Play повертається за кілька хвилин?
Для ліцензійних тестувальників Google автоматично повертає покупку через 3 хвилини, якщо ваш застосунок її не підтвердив, і надсилає вам лист про скасування. Продакшн чекає 3 дні, але тестувальники отримують прискорену версію, тож зламаний шлях підтвердження проявляється швидко.
Чи повторює sandbox Apple невдале сповіщення про повернення?
Ні. Sandbox не повторює App Store Server Notifications, тому якщо ваш ендпоінт недоступний, коли спрацьовує повернення в sandbox, сповіщення втрачається без другої спроби. Спершу переконайтеся, що ваш URL доступний, за допомогою Request a Test Notification.

Джерела та додаткове читання

RefundHalt

Автопілот повернень для App Store і Google Play

Читайте далі

Deep dive7 хв читання

Те, у скільки повернення коштує вашому застосунку, більше за ціну, яку ви віддаєте назад

Повернена ціна це найменший рядок у рахунку. Повернення також скасовує комісію магазину, тож ви втрачаєте свою частку, а обчислення, виклики API, сховище та виплати, які ви вже витратили, зникають. Chargeback у Google Play після 3 серпня 2026 додає згори банківський збір. Ось повний рахунок.

Deep dive8 хв читання

Повернення коштів за підписку працює не так, як повернення за разову покупку, і те, скільки ви маєте права голосу, вирішує магазин, у якому ви перебуваєте

Повернення за підписку скасовує цілий розрахунковий період, а не окремий продаж. У App Store вирішує Apple, а ваш сервер лише дізнається результат. У Google Play ви самі обираєте повне чи пропорційне повернення. Ось як кожен магазин обробляє повернення за підписки і в що обходиться вам одне з них.

Наступний запит на повернення вже в дорозі.

Налаштуйте RefundHalt за час, потрібний, щоб прочитати черговий лист у підтримку про повернення, яке ви не встигли оскаржити.