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

Три сповіщення про повернення коштів у App Store надходять після рішення Apple, а REFUND_REVERSED повертає продаж назад

Apple надсилає чотири повідомлення про повернення коштів через App Store Server Notifications V2, і більшість застосунків обробляють лише два. REFUND каже відкликати доступ, REFUND_DECLINED означає зберегти продаж, а REFUND_REVERSED повертає продаж назад і просить відновити те, що ви забрали. Ось що вимагає кожне з них.

Смартфон, що показує квитанцію про оплату поряд із поверненим конвертом і однією монетою, ілюструючи сповіщення про повернення коштів у App Store, які Apple надсилає після ухвалення рішення про повернення

Головне

  • Apple надсилає чотири повідомлення, пов'язані з поверненням коштів, через App Store Server Notifications V2. CONSUMPTION_REQUEST запитує ваші дані, а REFUND, REFUND_DECLINED і REFUND_REVERSED повідомляють результат після того, як Apple вже ухвалила рішення.
  • Сповіщення REFUND означає, що App Store повернув кошти за транзакцію. Воно містить revocationDate і revocationReason і є вашим сигналом відкликати право доступу, прив'язане до цієї однієї транзакції, а не до кожної покупки цього продукту.
  • revocationReason має два значення. 1 означає, що повернення надано через проблему з вашим продуктом, а 0 означає, що його надано з іншої причини. Значення про проблему це сигнал якості, який варто логувати й відстежувати в трендах.
  • REFUND_DECLINED означає, що Apple відхилила запит клієнта на повернення. Ви зберігаєте продаж і нічого не змінюєте, що безпечно лише тоді, коли ви не відкликали доступ до остаточного рішення.
  • REFUND_REVERSED означає, що Apple скасувала раніше надане повернення, зазвичай після того, як клієнт його оскаржує. Поля відкликання зникають з транзакції, а власна інструкція Apple полягає в тому, що якщо ви відкликали контент, ви маєте його відновити.
  • Відповідайте на всі чотири сповіщення кодом HTTP 200. Якщо ваш сервер був недоступний і пропустив одне, ендпоінт Get Refund History дає змогу знайти повернені транзакції за ідентифікатором транзакції та узгодити їх.
  • Повернення за минулий період підписки не завжди означає, що доступ має завершитися. Якщо новіший оплачений період усе ще активний, відкликання на старій транзакції відрізає клієнта, який усе оплатив.

Apple вирішує щодо вашого повернення, а потім продовжує говорити. Щойно результат визначено, App Store надсилає вашому серверу одне з трьох сповіщень про повернення коштів у App Store, і кожне вимагає іншого кроку. REFUND каже, що гроші зникли і вам слід забрати доступ. REFUND_DECLINED каже, що клієнт програв запит і ви зберігаєте продаж. REFUND_REVERSED каже, що Apple скасувала повернення, яке вже надала, тож продаж знову ваш і ви маєте повернути те, що забрали. Більшість застосунків підключають перше і тихо ігнорують два інших. Саме так платний клієнт опиняється відрізаним від того, за що заплатив.

Ці три відокремлені від CONSUMPTION_REQUEST, єдиного повідомлення про повернення, яке просить відповіді. Сповіщення після рішення не хочуть суперечки. Вони хочуть HTTP 200 і правильну зміну доступу клієнта. Ось що означає кожне, які саме поля несуть факти і де витікають гроші, коли ви обробляєте їх неправильно.

Чотири сповіщення про повернення, і яке з них хоче відповіді

App Store Server Notifications V2 це єдиний потік. Ви спрямовуєте його на одну URL, і Apple надсилає туди кожен тип сповіщення, тож ви вже отримуєте всі чотири повідомлення про повернення, обробляєте ви їх чи ні. Чотири з типів стосуються повернень, і лише одне з них є запитанням.

СповіщенняЩо вам повідомляє AppleВаша діяОчікується відповідь
CONSUMPTION_REQUESTКлієнт попросив повернення, і Apple хоче ваші даніSend Consumption Information протягом 12 годинТак, справжні дані
REFUNDApp Store повернув кошти за транзакціюВідкликати право доступу для цієї транзакціїНі, HTTP 200
REFUND_DECLINEDApp Store відхилив поверненняЗберегти доступ, нічого не мінятиНі, HTTP 200
REFUND_REVERSEDApple скасувала надане поверненняВідновити контент, який ви відкликалиНі, HTTP 200

Що насправді повідомляє вам сповіщення REFUND

REFUND спрацьовує, коли App Store успішно повернув клієнту кошти за транзакцію. Воно стосується кожного типу покупки: витратного продукту, невитратного продукту, автоматично поновлюваної підписки та неповторюваної підписки. Підписана транзакція всередині сповіщення тепер несе два поля, яких вона не мала до повернення, і ці два поля це вся історія.

revocationDate і revocationReason несуть факти

revocationDate це час UNIX у мілісекундах, коли App Store повернув кошти за транзакцію або відкликав її. revocationReason повідомляє вам категорію повернення і приймає рівно два значення.

revocationReasonЗначення за AppleЩо з цього читати
1Повернення надано через проблему з продуктомСигнал якості або доставки. Логуйте його, відстежуйте тренд і шукайте закономірність в одному продукті чи одному білді
0Повернення надано з іншої причиниЗвичайне повернення. Відкличте право доступу і рухайтеся далі

Сама наявність revocationDate у транзакції вже є прапорцем. Якщо ви пізніше отримаєте транзакцію і вона має revocationDate, ця покупка була повернена, зі сповіщенням чи без. Читайте причину поруч, щоб хвиля повернень зі значенням 1 на одному релізі не проскочила повз вас як шум.

Відкликайте за транзакцією, а не за продуктом

Пастка тут у тому, щоб відкликати забагато. REFUND називає одну транзакцію. Воно не каже вам вимкнути кожну покупку, яку клієнт коли-небудь зробив для цього ідентифікатора продукту. Власна настанова Apple полягає в тому, щоб перевірити, який доступ клієнт усе ще має, перш ніж щось відрізати, бо права доступу перекриваються. Класичний випадок це підписка: повернення потрапляє на минуломісячне поновлення, тоді як цьогомісячне поновлення активне й повністю оплачене. Відкличте на рівні продукту і ви щойно відрізали чинного, платного клієнта через повернення за період, який уже завершився.

REFUND_DECLINED означає, що ви вже виграли, тож не скасовуйте це

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

Якщо ваш код реагує на CONSUMPTION_REQUEST, забираючи доступ клієнта до того, як Apple ухвалить рішення, REFUND_DECLINED це момент, коли це рішення вибухає. Apple залишила ваші гроші, а ви відрізали клієнта, чиє повернення відхилили. Тепер цей клієнт платить за продукт, яким не може користуватися, відкриває звернення до підтримки і запам'ятовує це. Виправлення це правило, а не функція: відкликайте на REFUND, ніколи на запиті. REFUND_DECLINED це просто підтвердження Apple, що раннє відкликання було б хибним рішенням.

REFUND_REVERSED це сповіщення, яке вам платить

REFUND_REVERSED це те, яке майже ніхто не обробляє, і саме воно повертає вам гроші. Apple надсилає його, коли скасовує раніше надане повернення, зазвичай після того, як клієнт оскаржує це повернення. Поля відкликання, які REFUND додав до транзакції, знову видаляються, тож покупка знову читається як оплачена. Apple викладає завдання розробника в одному реченні: якщо ваш застосунок відкликав контент чи послуги внаслідок пов'язаного повернення, він має їх відновити. Це стосується будь-якого типу покупки, від витратного продукту до автоматично поновлюваної підписки.

Проблема, що виникає через тижні

Справжнє запитання, яке розробники ставлять на власних форумах Apple, це час. REFUND_REVERSED може надійти через тижні після початкового REFUND, задовго після того, як період підписки завершився. Чи відновлюєте ви доступ тоді? Відновіть те, що транзакція насправді надає, обмежене тим, що ця транзакція покриває. Для витратного чи невитратного продукту знову увімкніть розблокування. Для періоду підписки, який уже минув, ви не роздаєте новий час, ви виправляєте запис, щоб історія клієнта була точною і будь-яке ще чинне право доступу знову стало активним. Відновіть конкретну транзакцію, і ваша логіка перекриття вирішить, що зараз активне.

Монета, яку кладуть назад поряд зі смартфоном, ілюструючи скасоване повернення в App Store, що повертає продаж розробнику

Де гроші, коли робити це правильно

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

REFUND: припиніть платити за обслуговування клієнта, якому повернули кошти

Ціна продажу зникає в мить, коли надходить REFUND. Що ви ще можете контролювати, це вартість подальшої доставки. Кожну годину, поки повернене право доступу залишається активним, ви й далі витрачаєте на речі, за які клієнт більше не платить: обчислення, виклики API моделі, сховище і будь-яку виплату творцю чи партнеру, прив'язану до його використання. Швидке відкликання на REFUND зупиняє цей лічильник. Ігнорування сповіщення означає, що ви фінансуєте продукт для того, кому магазин уже відшкодував.

REFUND_DECLINED: не перетворюйте перемогу на повернення з доброї волі

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

REFUND_REVERSED: найгірше поєднання це коли зникли і їхні гроші, і їхній доступ

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

Що налаштувати

Обробка невелика, щойно модель правильна. Прив'язуйте права доступу до ідентифікатора транзакції, щоб кожне сповіщення вказувало на одну покупку. На CONSUMPTION_REQUEST надішліть свої дані протягом 12 годин. На REFUND відкличте цю транзакцію. На REFUND_DECLINED не робіть нічого. На REFUND_REVERSED відновіть. Швидко повертайте HTTP 200 для всіх і виконуйте зміну доступу у власний час.

Для прогалини, яку залишають сповіщення, використовуйте ендпоінт Get Refund History. Якщо ваш сервер був вимкнений під час збою і пропустив REFUND, викличте пошук повернень App Store Server API для ідентифікатора транзакції за адресою /inApps/v2/refund/lookup/{transactionId} і зчитайте підписані транзакції з їхніми revocationDate і revocationReason. Він узгоджує одну транзакцію за раз і гортає повернені покупки клієнта, тож пропущений webhook не стає назавжди неправильно встановленим правом доступу.

Це та частина, яку RefundHalt виконує за вас. Він слухає всі чотири типи, відкликає на REFUND, тримає доступ недоторканим на REFUND_DECLINED і автоматично відновлює на REFUND_REVERSED, кожне прив'язане до точної транзакції. Скасоване повернення не лежить у черзі, поки платний клієнт залишається відрізаним, а відхилене ніколи не запускає відкликання, яке довелося б відмотувати назад.

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

Яка різниця між REFUND і REFUND_REVERSED?
REFUND означає, що App Store повернув кошти за транзакцію і вам слід відкликати це право доступу, тоді як REFUND_REVERSED означає, що Apple скасувала надане повернення і вам слід відновити відкликаний контент. Ці два утворюють пару: покупка може пройти REFUND, а потім, якщо суперечку клієнта скасовано, REFUND_REVERSED. Прив'язуйте зміни доступу до ідентифікатора транзакції, щоб кожне сповіщення діяло на правильній покупці.
Чи потрібно щось надсилати у відповідь на сповіщення REFUND?
Ні. На REFUND, REFUND_DECLINED і REFUND_REVERSED ви відповідаєте кодом HTTP 200 без тіла. Лише CONSUMPTION_REQUEST просить вас надіслати дані, і робить це через ендпоінт Send Consumption Information протягом 12 годин. Інші три це Apple, що повідомляє рішення, а не ставить запитання.
Що робити, коли я отримую сповіщення REFUND_DECLINED?
Нічого не змінюється, бо повернення клієнта відхилено, а ви зберігаєте продаж. Єдиний спосіб, коли REFUND_DECLINED спричиняє роботу, це якщо ви відкликали доступ зарано, до рішення Apple. Відкликайте на REFUND, а не на CONSUMPTION_REQUEST, і REFUND_DECLINED стає підтвердженням, що доступ правильно залишили недоторканим.
Чи слід відновлювати доступ, коли REFUND_REVERSED надходить через тижні після повернення?
Так, відновіть право доступу, яке надає ця конкретна транзакція. Apple зазначає, що якщо ваш застосунок відкликав контент через пов'язане повернення, він має його відновити. Для витратного чи невитратного продукту знову увімкніть розблокування. Для періоду підписки, який уже завершився, ви виправляєте запис, а не надаєте новий час, тож ваша логіка перекриття все одно вирішує, що зараз активне.
Як зловити сповіщення про повернення, яке пропустив мій сервер?
Використовуйте ендпоінт Get Refund History у App Store Server API, який шукає повернені транзакції клієнта за ідентифікатором транзакції за адресою /inApps/v2/refund/lookup/{transactionId}. Він повертає підписані транзакції з revocationDate і revocationReason, тож після збою ви можете узгодити доступ, не чекаючи на сповіщення, яке вже спрацювало. Він обробляє один ідентифікатор транзакції за виклик і гортає повернені покупки клієнта.

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

RefundHalt

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

Читайте далі

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

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