Все статьи
Руководство7 мин чтения

Order ID из App Store в чеке клиента показывает, что он купил и вернул ли Apple уже деньги

Эндпоинт Look Up Order ID от Apple превращает order ID из чека App Store в подписанные транзакции, с датой и причиной возврата. Как использовать его при письмах о возврате, чего он не умеет и чем от него отличается order ID в Google Play.

Рабочее место поддержки с почтой на ноутбуке и iPhone с чеком о покупке, где order ID из App Store открывает разговор о возврате

Главное

  • Apple присылает по почте чек с order ID при каждой встроенной покупке, а ещё клиенты находят свои order ID в истории покупок App Store.
  • Эндпоинт Look Up Order ID в App Store Server API (GET /inApps/v1/lookup/{orderId}) для действительного order ID возвращает одну или несколько подписанных транзакций, так что поддержка видит productId и purchaseDate без догадок.
  • Декодированная транзакция App Store содержит revocationDate и revocationReason, поэтому проверка order ID показывает, вернул ли Apple деньги за покупку. Причина 1 означает, что Apple вернул деньги из-за реальной или предполагаемой проблемы в приложении.
  • Look Up Order ID возвращает OrderLookupStatus 1 и не возвращает массив signedTransactions, если order ID недействителен для вашего приложения. Это признак неверного чека или покупки в другом приложении.
  • Look Up Order ID недоступен в среде sandbox Apple, а лимит запросов в продакшене составляет 10 запросов в секунду на приложение и применяется на почасовой основе.
  • Разработчики не могут оформлять возвраты в App Store. Решение принимает Apple на reportaproblem.apple.com, а единственный шаг разработчика с доказательствами это ответ на CONSUMPTION_REQUEST в течение 12 часов.
  • Google Play присылает по почте order ID за каждую разовую покупку и каждое продление подписки, и разработчик может найти этот order ID в Play Console и вернуть деньги напрямую. По словам Play Console, возврат нельзя отменить.

Прежде чем отвечать на письмо клиента с iPhone о возврате, попросите order ID из App Store в его чеке от Apple. Эта одна строка, пропущенная через эндпоинт Look Up Order ID от Apple, скажет вам, какой продукт он купил, когда и вернул ли Apple уже деньги. Без неё вы сверяете скриншот и адрес почты со своей базой и надеетесь на лучшее. С ней вы за секунды понимаете, кто перед вами: платящий клиент, клиент, которому Apple уже вернул деньги, или человек с чеком из другого приложения.

Откуда берётся order ID из App Store

Документация Apple тут конкретна. Когда клиенты совершают одну или несколько встроенных покупок в вашем приложении, App Store присылает им чек по почте, и в этом чеке есть order ID. Ещё клиенты находят свои order ID в истории покупок App Store. История покупок Apple доступна на reportaproblem.apple.com и в приложении App Store в разделе Приложения и история покупок, по умолчанию показывает последние 90 дней и имеет фильтры для более старых покупок.

Значит, ключ у клиента уже есть. Вашей форме поддержки нужно только спросить его.

Почему адреса почты недостаточно

Apple не передаёт вам адрес почты Apple Account клиента. Адрес, с которого пишут в поддержку, может не иметь ничего общего с аккаунтом, который платил. Если при покупке вы задаёте appAccountToken, вы можете связать транзакцию со своим ID пользователя, но только со своей стороны. Order ID работает со стороны клиента, через чек, который он может переслать одним касанием.

Что возвращает Look Up Order ID

Look Up Order ID входит в App Store Server API и доступен начиная с версии 1.1.0. Вы вызываете GET https://api.storekit.apple.com/inApps/v1/lookup/{orderId} с подписанным JWT. По словам Apple, ответ строится на истории встроенных покупок клиента, независимо от того, устанавливал ли он приложение, удалял или ставил заново.

Поле или поведениеЧто говорит документация AppleЧто с этим делает поддержка
OrderLookupStatus 0Действительный order ID. Ответ содержит массив из одной или нескольких подписанных транзакцийДекодировать каждую и прочитать покупку
OrderLookupStatus 1Ответ не содержит массив signedTransactionsСчитать order ID недействительным для вашего приложения. Попросить правильный чек
productId и purchaseDateApple называет эти поля для поддержки клиентовПодтвердить, что и когда куплено
revocationDateМомент, когда App Store вернул деньги за транзакцию или отозвал её из Семейного доступаЕсли поле заполнено, Apple уже вернул клиенту деньги
revocationReason0: возврат по другим причинам, например случайная покупка. 1: возврат из-за реальной или предполагаемой проблемы в вашем приложении1 это сигнал о продукте, а не просто обращение в поддержку
appAccountTokenUUID, который вы задали при покупке, если задалиСвязать заказ со своей записью пользователя
price и currencyApple просит не использовать их для сверки выручкиДля денег используйте отчёты App Store Connect
SandboxЭндпоинт недоступен в среде sandboxТестировать только на order ID из продакшена
Лимит запросов10 запросов в секунду на приложение, применяется почасово. Превышение получает HTTP 429 с заголовком Retry-AfterХватает для поддержки, но не для массовых проверок

Действителен ли чек для моего приложения?

Именно на этот вопрос OrderLookupStatus отвечает первым. 1 означает, что order ID не соответствует покупкам в вашем приложении. Обычные случаи это опечатка, чек от другого приложения или чек вообще не из App Store. При 1 ничего не возвращайте, не начисляйте и не восстанавливайте. Попросите клиента ещё раз проверить чек.

Вернул ли Apple уже деньги за эту покупку?

Проверьте revocationDate в каждой декодированной транзакции. Если поле заполнено, Apple уже вернул деньги за покупку или отозвал её из Семейного доступа, и деньги у клиента. Ваши App Store Server Notifications должны были прислать REFUND по той же транзакции, так что это ещё и дешёвый способ убедиться, что сервер действительно отозвал доступ.

Разработчик сравнивает распечатанный чек App Store со строками транзакций на ноутбуке и проверяет order ID из App Store, прежде чем ответить на запрос о возврате

Чего order ID не может в App Store

Он не может оформить возврат. У разработчиков нет кнопки возврата в App Store. Решения о возвратах принимает Apple, и статья поддержки Apple отправляет клиентов на reportaproblem.apple.com, где они выбирают «Я хочу», затем «Запросить возврат средств», указывают причину и выбирают покупку. Apple также пишет, что ожидающий платёж нельзя вернуть, пока клиент не получил чек по почте.

Единственное место, где у вас есть голос, это CONSUMPTION_REQUEST от Apple. Когда клиент просит Apple о возврате, Apple может прислать это уведомление, и у вас есть 12 часов, чтобы ответить через Send Consumption Information. Проверка order ID это инструмент поддержки. Она не открывает это окно и не продлевает его.

Во что обходится письмо о возврате, если пропустить проверку

Поддержка без order ID это место, где деньги утекают тихо. Три сценария повторяются снова и снова.

  • Жест доброй воли поверх возврата. Apple возвращает деньги за покупку, клиент пишет ещё и вам, а поддержка выдаёт бесплатные кредиты или лишний месяц. Каждый подаренный кредит работает на вычислениях, вызовах API и хранилище, за которые платите вы, и всё это на аккаунте, которому деньги уже вернули.
  • Доступ, который так и не отозвали. Если обработка REFUND дала сбой, клиент после возврата продолжает пользоваться сервисом. Проверка, которая показывает revocationDate, когда ваша база всё ещё говорит «активен», это баг-репорт с ценником.
  • Не тот аккаунт, не то решение. Если восстановить доступ или начислить кредит аккаунту из пересланного письма, когда order ID принадлежит другому человеку, платный сервис получит тот, кто ничего не покупал.

Ни одному из этих сценариев не нужен чарджбэк или дедлайн, чтобы ударить по деньгам. Это просто ответы поддержки без фактов. Один вызов API на обращение убирает догадки.

Значит ли revocationReason 1, что я сделал что-то не так?

Не обязательно. По словам Apple, причина 1 означает возврат из-за реальной или предполагаемой проблемы в вашем приложении. Слово «предполагаемой» здесь многое значит. Но скопление возвратов с причиной 1 по одному продукту после одного релиза это самый ясный отзыв о продукте, который даёт вам Apple. Считайте их.

Чем отличается order ID в Google Play

Google Play устроен наоборот. В документации Google по платежам сказано, что пользователи получают письмо с уникальным order ID за каждую разовую покупку продукта, за первую покупку подписки и за каждое регулярное продление, а order ID можно использовать для управления возвратами в Play Console. Вы ищете в Управлении заказами по order ID или полному адресу почты пользователя и возвращаете деньги сами.

ВопросOrder ID из App StoreOrder ID из Google Play
Где клиент его находитЧек по почте и история покупок App StoreЧек по почте за каждую покупку и каждое продление
Как вы его проверяетеLook Up Order ID в App Store Server APIПоиск в Управлении заказами в Play Console
Можно ли по нему вернуть деньгиНет. Решает AppleДа. Полные возвраты и частичные для встроенных покупок и подписок
Окно для доказательств при возвратеCONSUMPTION_REQUEST, 12 часов, решает AppleПроверка чарджбэка через orders.reviewrefund, 24 часа
Можно ли отменить возвратНе вамиНет. По словам Play Console, возврат нельзя отменить

В Google Play order ID важнее, потому что кнопку нажимаете вы. По словам Play Console, возврат за последний заказ подписки сразу удаляет подписку и отменяет будущие продления, а возврат за более старый заказ это только возврат, и подписка остаётся активной. Частичные возвраты поддерживаются только для заказов, оформленных начиная с марта 2018 года, а платное приложение частично вернуть нельзя.

Поставьте order ID в начало процесса поддержки по возвратам

  • Просите order ID в форме поддержки, с подсказкой в одну строку: он есть в письме с чеком от Apple или Google Play.
  • На iOS вызовите Look Up Order ID, декодируйте каждую транзакцию и покажите поддержке productId, purchaseDate, revocationDate и revocationReason на одном экране.
  • Если OrderLookupStatus равен 1, остановитесь и попросите правильный чек. Ничего не выдавайте.
  • Если revocationDate заполнено, убедитесь, что доступ на вашем сервере уже отозван, и закройте обращение. Никаких жестов доброй воли сверху.
  • Если оно не заполнено и клиент хочет вернуть деньги, отправьте его на reportaproblem.apple.com и держите обработчик CONSUMPTION_REQUEST готовым к 12-часовому окну. RefundHalt отвечает на этот запрос данными о потреблении, которые запрашивает Apple.
  • На Android найдите точный заказ в Play Console, прежде чем возвращать деньги, и осознанно выбирайте между простым возвратом и возвратом с отзывом доступа.

Частые вопросы

Как разработчику проверить order ID из App Store?
Вызовите эндпоинт Look Up Order ID в App Store Server API, GET https://api.storekit.apple.com/inApps/v1/lookup/{orderId}, с подписанным JWT. Действительный order ID возвращает OrderLookupStatus 0 и одну или несколько подписанных транзакций, которые вы декодируете, чтобы прочитать productId, purchaseDate и детали возврата, если они есть. Эндпоинт недоступен в sandbox.
Где клиент находит свой order ID из App Store?
В чеке, который Apple присылает по почте при каждой встроенной покупке, и в истории покупок App Store на reportaproblem.apple.com или в разделе Приложения и история покупок в приложении App Store. История покупок по умолчанию показывает последние 90 дней и имеет фильтры для более старых покупок.
Могу ли я вернуть деньги за покупку в App Store по order ID?
Нет. Разработчики не могут оформлять возвраты в App Store. Решает Apple, когда клиент запрашивает возврат на reportaproblem.apple.com. Ваша часть это ответ на CONSUMPTION_REQUEST от Apple в течение 12 часов через Send Consumption Information.
Как понять, что Apple уже вернул деньги за покупку?
Проверьте order ID и посмотрите revocationDate в каждой декодированной транзакции. Если поле заполнено, Apple вернул деньги за покупку или отозвал её из Семейного доступа. revocationReason 0 означает другие причины, например случайную покупку, а 1 реальную или предполагаемую проблему в вашем приложении.
Что означает OrderLookupStatus 1?
Это значит, что order ID недействителен для вашего приложения, и в ответе нет массива signedTransactions. Обычно клиент прислал чек от другого приложения, ошибся в ID или прислал чек не из App Store. Попросите правильный чек, прежде чем что-либо выдавать.

Источники и дополнительное чтение

RefundHalt

Автопилот возвратов для App Store и Google Play

Читайте дальше

Deep dive8 мин чтения

Возвраты за оплату через веб-checkout в iOS теперь идут к вам, а не к Apple, и банковские споры тоже

Американские приложения для iPhone теперь могут отправлять покупателей на веб-страницу оплаты. Apple заявляет, что не может помочь с возвратами по таким покупкам, поэтому обработка возвратов, чарджбэки и комиссии за спор в $15 переходят к вам. Что меняется, сколько это стоит и как держать число споров на низком уровне.

Deep dive8 мин чтения

Возврат за платное приложение никогда не доходит до вашего сервера, поэтому заметить его должно само приложение

Возвраты за приложения с оплатой при покупке обходят все уведомления, которые слушает ваш сервер. Google дает покупателям два часа на возврат и удаляет приложение, Apple по вашему договору может вернуть деньги в течение 90 дней, и ни один из них не запрашивает доказательств. Здесь разобрано, что сообщает каждый магазин, сколько это стоит и как проверить возврат в приложении.

Следующий запрос на возврат уже в пути.

Настройте RefundHalt за то время, что уходит на чтение очередного письма в поддержку о возврате, который вы не успели оспорить.