Прикріплюйте appAccountToken до кожної покупки в App Store, інакше ви не зможете захистити повернення
Apple надсилає вашому серверу CONSUMPTION_REQUEST, коли клієнт просить повернення, але в транзакції немає даних про те, хто він. appAccountToken це UUID, який пов'язує покупку з вашим користувачем. Встановіть його, і ви зможете відповісти Apple реальними даними. Пропустіть, і вам залишиться лише гадати.

Головне
- appAccountToken це UUID, який ви прикріплюєте до покупки в App Store, щоб отримана транзакція вказувала на конкретного користувача у вашій власній системі. Apple зберігає його в транзакції і повертає всюди, де ця транзакція з'являється.
- Єдине правило форматування, якого вимагає Apple, це щоб значення було коректним UUID. Передайте щось інше, id, email, склеєний рядок, і StoreKit тихо відкине це і поверне appAccountToken як nil.
- У StoreKit 2 ви задаєте його одним параметром покупки, Product.PurchaseOption.appAccountToken(_:), використовуючи стабільний UUID, який ви згенерували і зберегли для цього облікового запису.
- Встановіть його один раз на початковій покупці, і Apple переносить той самий токен через кожне продовження, повторну спробу списання та апгрейд у ланцюжку підписки.
- З 2025 року endpoint Set App Account Token дозволяє вашому серверу прикріпити токен до покупок, зроблених поза вашим застосунком, таких як погашення промокодів і просувані покупки, до яких внутрішній процес ніколи не міг дотягнутися.
- appAccountToken це те, що робить CONSUMPTION_REQUEST від Apple розв'язним. Без нього ви не зможете зіставити повернення з клієнтом, чиє використання ви маєте описати протягом 12-годинного вікна.
- Повернення, яке ви не можете ідентифікувати, це повернення, яке ви не можете захистити. Ви віддаєте гроші за покупки, які у вас були докази залишити, плюс обчислення, виклики API та виплати, які ви вже витратили на їх доставку.
Клієнт просить в Apple повернення, Apple надсилає вашому серверу CONSUMPTION_REQUEST, і у вас є дванадцять годин, щоб відповісти реальними даними про те, як ця людина користувалася продуктом. Потім ви відкриваєте сповіщення і розумієте, що поняття не маєте, хто він. Транзакція несе originalTransactionId та id продукту, але нічого, що вказувало б на обліковий запис у вашій власній базі даних. Саме цей розрив закриває appAccountToken, і якщо ви не встановили його в момент покупки, ви не зможете закрити його заднім числом для цього продажу.
appAccountToken це UUID, який ви прикріплюєте до покупки, щоб отримана транзакція в App Store несла вказівник на конкретного користувача у вашій системі. Встановіть його, і кожне питання про повернення, яке Apple коли-небудь поставить про цього клієнта, прийде з прикріпленою особою. Пропустіть, і вам доведеться гадати. Ось що це за поле, як його встановити, новий endpoint, який рятує покупки, зроблені поза вашим застосунком, і у скільки реально обходиться відсутній зв'язок, коли приходить повернення.
Що таке appAccountToken насправді
appAccountToken це непрозорий UUID, який ви генеруєте і передаєте StoreKit у момент покупки. Apple зберігає його в транзакції і повертає в інформації про транзакцію для цієї покупки, і він там залишається. Словами Apple, це "UUID, який пов'язує транзакцію з обліковим записом користувача у вашому власному сервісі". Єдине правило форматування це те, що він має бути UUID. Apple не читає його, не перевіряє, на що він посилається, і її не хвилює, що він означає на вашому боці. Це зв'язок, яким керуєте ви.
Оскільки він живе в транзакції, він повертається всюди, де з'являється транзакція. Підписана транзакція в серверному сповіщенні, відповідь App Store Server API Get Transaction Info і кожне продовження в ланцюжку підписки несуть один і той самий токен, якщо ви встановили його на початковій покупці. Один UUID, прикріплений одного разу, супроводжує білінг клієнта протягом усього його життя.
Це має бути справжній UUID, інакше він тихо зникне
Єдине правило, якого вимагає Apple, це формат. StoreKit 2 вимагає UUID за RFC 4122. Якщо ви передасте склеєний рядок, цілочисельний id або email, StoreKit не викине помилку. Він відкине значення, і транзакція повернеться з appAccountToken рівним nil. Розробники постійно на це натрапляють, і симптом завжди один і той самий, той чи інший варіант "appAccountToken відсутній у корисному навантаженні транзакції" на власних форумах Apple, майже завжди тому що передане значення не було коректним UUID. Згенеруйте справжній UUID на боці сервера, збережіть його для облікового запису і ніколи не передавайте StoreKit нічого іншого.
Як встановити його в момент покупки
У StoreKit 2 це єдиний параметр покупки. Згенеруйте UUID на своєму сервері, коли користувач реєструється або вперше доходить до оформлення, збережіть його в записі облікового запису і передайте це саме значення у виклик покупки.
Сигнатура це Product.PurchaseOption.appAccountToken(_ token: UUID), а покупка виглядає як try await product.purchase(options: [.appAccountToken(token)]). Коли транзакція повертається, перевірена через App Store Server API або доставлена серверним сповіщенням, вона несе цей UUID, і ваш сервер знаходить клієнта одним запитом.
Використовуйте один стабільний токен на обліковий запис
Не генеруйте новий токен для кожної покупки одного й того самого користувача. Apple повертає токен при продовженнях, повторних спробах списання та апгрейдах у тому самому ланцюжку, тому стабільний UUID на обліковий запис дає вам чисту нитку від першої покупки через кожну майбутню подію. Токен, який змінюється від покупки до покупки, рве цю нитку і зводить нанівець увесь сенс. Один обліковий запис, один токен, повторно використовуваний щоразу, коли цей обліковий запис купує.
Endpoint, який рятує покупки поза застосунком
До 2025 року була діра. Якщо клієнт погашав промокод або купував просувану внутрішню покупку прямо з App Store, ваш застосунок ніколи не запускав процес покупки, тому appAccountToken не було де встановити. Ці транзакції приходили анонімними і такими й залишалися.
WWDC 2025 закрив цю прогалину за допомогою endpoint Set App Account Token. Ваш сервер викликає PUT /inApps/v1/transactions/{originalTransactionId}/appAccountToken в App Store Server API з UUID у тілі, і Apple встановлює токен на цій транзакції. Це працює для кожного типу продукту, охоплює погашення промокодів і просувані покупки, а значення, яке ви надсилаєте, перезаписує будь-який токен, що вже є в транзакції. Тепер ви можете пов'язати покупку заднім числом, зі свого сервера, без того щоб вона взагалі проходила через ваш застосунок.

| Канал покупки | Де ви встановлюєте appAccountToken | Примітки |
|---|---|---|
| Внутрішня покупка | Параметр покупки StoreKit у момент оплати | Product.PurchaseOption.appAccountToken(UUID) |
| Погашення промокоду | Endpoint Set App Account Token, на боці сервера | Немає внутрішнього процесу, за який зачепитися, тому встановіть його після |
| Просувана внутрішня покупка з App Store | Endpoint Set App Account Token, на боці сервера | Покупка відбувається поза вашим застосунком |
| Продовження підписки | Нічого робити не потрібно | Автоматично переноситься з початкової покупки |
Де відсутній зв'язок коштує вам грошей
Сенс токена не в акуратних записах. Сенс у тому, що єдине питання Apple про повернення для розробників, CONSUMPTION_REQUEST, розв'язне лише якщо ви можете знайти клієнта, про якого воно йдеться.
Коли покупець запитує повернення за витратний товар або невідновлювану підписку, Apple надсилає вашому серверу сповіщення CONSUMPTION_REQUEST і дає вам дванадцять годин, щоб відповісти через Send Consumption Information. Ваша відповідь це дані про конкретного клієнта: скільки продукту він спожив, стаж його облікового запису, його сукупні витрати, статус доставки. appAccountToken сам по собі є одним із полів у цьому запиті, і, що важливіше, саме так транзакція сповіщення зіставляється з обліковим записом, чиє використання ви збираєтеся описати. Немає токена, немає пошуку, немає точної відповіді.
У скільки реально обходиться порожня відповідь
Неідентифіковане повернення змушує до поганого вибору. Ви можете відповісти на запит про споживання нічим, що читається як низьке споживання і підштовхує Apple до схвалення повернення, у тому числі клієнтам, які активно користувалися продуктом. Або ви можете гадати. У будь-якому разі ви повертаєте гроші за покупки, які у вас були докази захистити, і ви вже заплатили реальну вартість їх обслуговування.
Ця вартість це не ціна продажу. Витратний товар, який запустив пакет викликів API моделі, згенерував зображення, експортував відео або ініціював виплату автору, витратив реальні гроші в момент доставки. Повернення повертає платіж клієнта. Воно не повертає рахунок від провайдера. Помножте одного неідентифікованого клієнта на кожне повернення, яке він подає, і на кожного серійного повертальника, який розраховує на те, що ви не знаєте, хто він, і токен, який ви пропустили, стає найдорожчим рядком коду, який ви так і не написали.
Та сама ідея існує на Android, під іншою назвою
Google Play вирішує ідентичну проблему за допомогою setObfuscatedAccountId, який прикріплює ідентифікатор облікового запису до покупки, щоб на розбір зворотного платежу Google через orders.reviewrefund можна було відповісти з прив'язкою до реального користувача. Інший магазин, інша механіка, той самий урок: прикріпіть особу в момент покупки, інакше ви не зможете захистити спір пізніше. У App Store цей інструмент це appAccountToken, і він має бути UUID.
Три звички, які утримують токен на місці
- Генеруйте UUID на обліковий запис і зберігайте його. Один стабільний токен на клієнта, створений при реєстрації або при першому оформленні, збережений у його записі і повторно використовуваний для кожної покупки.
- Перевіряйте перед передачею. Переконайтеся, що значення є справжнім UUID у вашому коді покупки, щоб некоректний id ніколи не міг тихо перетворитися на nil токен у транзакції.
- Дозаповнюйте покупки поза застосунком. Коли приходить серверне сповіщення про погашення промокоду або про просувану покупку без токена, викличте endpoint Set App Account Token, щоб прикріпити потрібний.
Зробіть ці три речі, і кожна транзакція, яку Apple вам коли-небудь надішле, включно із запитами на повернення, прийде вже прив'язаною до клієнта, якому вона належить.
Це фундамент, на який спирається RefundHalt. Ми зчитуємо appAccountToken з кожної транзакції та серверного сповіщення, прив'язуємо його до використання, яке ми вже відстежуємо для цього облікового запису, і відповідаємо на запит про споживання від Apple протягом дванадцятигодинного вікна реальними цифрами клієнта. Токен це нитка. Встановіть його один раз, і вашому захисту від повернень буде за що триматися.
Поширені запитання
- Що таке appAccountToken у App Store?
- appAccountToken це UUID, який ви генеруєте і прикріплюєте до покупки через StoreKit, щоб отримана транзакція в App Store вказувала на конкретний обліковий запис користувача у вашій власній системі. Apple зберігає його в транзакції і повертає в інформації про транзакцію, серверних сповіщеннях і кожному продовженні в тому самому ланцюжку, що дозволяє вам пов'язати будь-яку майбутню подію, включно із запитом на повернення, з потрібним клієнтом.
- Чому мій appAccountToken дорівнює nil або відсутній?
- Майже завжди тому, що передане вами значення не було коректним UUID. StoreKit 2 вимагає UUID за RFC 4122 і тихо відкидає все інше, тому склеєний рядок, цілочисельний id або email повертаються як nil appAccountToken, хоча покупка все одно проходить успішно. Інша поширена причина це покупка, зроблена поза вашим застосунком, наприклад погашення промокоду, де не запускався внутрішній процес для встановлення токена.
- Чи можу я встановити appAccountToken після покупки, для промокодів?
- Так, з 2025 року. Endpoint Set App Account Token в App Store Server API дозволяє вашому серверу прикріпити або перезаписати токен на наявній транзакції, викликавши PUT /inApps/v1/transactions/{originalTransactionId}/appAccountToken з UUID у тілі. Це працює для кожного типу продукту і створено для покупок, зроблених поза вашим застосунком, таких як погашення промокодів і просувані внутрішні покупки.
- Чи обов'язково appAccountToken має бути UUID?
- Так. Єдине правило форматування, якого вимагає Apple, це щоб значення було коректним UUID. У решті він непрозорий, тому може посилатися на будь-який ключ облікового запису, який вам подобається, на вашому боці, але якщо це не UUID, StoreKit не збереже його, і транзакція повернеться з appAccountToken рівним nil.
- Як appAccountToken допомагає з поверненнями?
- Коли клієнт запитує повернення, Apple надсилає CONSUMPTION_REQUEST і дає вам дванадцять годин, щоб відповісти даними про цього конкретного покупця. appAccountToken це те, як ви зіставляєте транзакцію сповіщення з обліковим записом, чиє використання вам потрібно повідомити, і це одне з полів у самому запиті про споживання. Без нього ви не зможете відповісти реальним використанням, тому Apple схиляється до схвалення повернень, які у вас були докази оскаржити.
- Чи має appAccountToken бути різним для кожної покупки?
- Ні. Використовуйте один стабільний UUID на обліковий запис і повторно використовуйте його для кожної покупки, яку робить цей користувач. Apple переносить токен через продовження та апгрейди в ланцюжку підписки, тому стабільний токен дає вам чистий зв'язок у часі. Токен, який змінюється від покупки до покупки, рве цей зв'язок і ускладнює прив'язку транзакцій до того самого клієнта.
Джерела та додаткове читання
- Apple Developer: appAccountToken (StoreKit Transaction)
- Apple Developer: Product.PurchaseOption.appAccountToken(_:)
- Apple Developer: Set App Account Token (App Store Server API)
- Apple Developer: appAccountToken (App Store Server API)
- Apple Developer: ConsumptionRequest (Send Consumption Information)
- Apple Developer: Send Consumption Information
- WWDC25: Dive into App Store server APIs for In-App Purchase
RefundHalt
Автопілот повернень для App Store і Google Play
Читайте далі
Якщо не підтвердити покупку в Google Play протягом трьох днів, Google поверне за неї гроші, і ось скільки це вам коштує
Google Play автоматично повертає гроші й скасовує будь-яку покупку, яку ваш сервер не підтвердив протягом трьох днів. Це помилка інтеграції, а не рішення клієнта, і її цілком можна запобігти. Ось точне правило, чому воно спрацьовує і скільки насправді коштує вам кожен втрачений продаж.
Серійне зловживання поверненнями коштує вам двічі, ось як магазини дають вам змогу відбитися
Клієнт, який знову і знову вимагає повернення, це не випадковість. Зловживання поверненнями коштує вам повернутих грошей плюс обчислень, які ви вже витратили, і обидва магазини дають вам сигнал ідентичності, appAccountToken від Apple і obfuscated account ID від Google, щоб зв'язати цей патерн докупи.