Помечайте каждую покупку в Google Play обфусцированным идентификатором аккаунта, иначе возвратный платёж придёт без возможности его отследить
Google Play позволяет проставить на каждую покупку стабильный хешированный идентификатор и считывает его обратно, когда возникает спор. Настройте это, и разбор возвратного платежа привяжется к тому самому пользователю, чьё потребление вы обязаны отчитать. Пропустите, и вы будете сопоставлять голый идентификатор заказа с догадками под 24-часовым таймером.

Главное
- Обфусцированный идентификатор аккаунта, это строка, которую вы прикрепляете к покупке в Google Play с помощью setObfuscatedAccountId. Google Play хранит её вместе с заказом и возвращает позже как obfuscatedExternalAccountId, поэтому покупку можно отследить обратно до пользователя в вашей системе, который её совершил.
- По словам Google, это поле позволяет Google Play выявлять нерегулярную активность, например когда множество устройств совершают покупки на одном аккаунте за короткий промежуток времени. Установка поля питает собственную систему проверки на мошенничество Google в момент покупки, ещё до завершения транзакции.
- Идентификатор ограничен 64 символами и не должен содержать личную информацию в открытом виде. Google говорит, что хранение PII, такого как электронные адреса, в этом поле приводит к блокировке покупок, и рекомендует вместо этого одностороннее хеширование или шифрование.
- Когда банковский возвратный платёж требует вашего разбора, Google Play отправляет PendingRefundReviewNotification, где назван заказ, а не человек. Обфусцированный идентификатор аккаунта, это ключ связи, который сопоставляет тот заказ с записью пользователя, чьё потребление вы обязаны отчитать.
- Вы отвечаете на спор, вызывая orders.reviewrefund в течение 24 часов, с refundPreference, флагом sampleContentProvided и доказательствами потребления вроде consumptionPercentageMilliunits и consumptionUsageEvents. Собрать эти доказательства можно только тогда, когда вы знаете, какому пользователю принадлежит заказ.
- Для заказов Google Play, размещённых 3 августа 2026 года или позже, проигранный возвратный платёж списывает с разработчика цену покупки за вычетом сервисной комиссии Google, плюс банковскую комиссию за возвратный платёж. Спор, на который вы не можете ответить из-за того, что не можете опознать заказ, теперь прямые расходы, а не просто потерянная продажа.
- Устанавливайте идентификатор на каждую покупку, а не только на подписки, и считывайте его обратно на стороне сервера. На клиенте он берётся из Purchase.getAccountIdentifiers, а на вашем бэкенде это поле obfuscatedExternalAccountId в записи о покупке.
Разбор возвратного платежа в Google Play приходит с названием заказа и токеном покупки. Он не сообщает вам, кто клиент. Если вы никогда не проставляли собственный идентификатор на ту покупку, вы теперь сопоставляете голый идентификатор заказа со своей таблицей пользователей под 24-часовым таймером и должны ответить доказательствами потребления, которые можете и не найти. Обфусцированный идентификатор аккаунта, это решение. Это короткая строка, которую вы прикрепляете на кассе, Google Play хранит её вместе с покупкой и возвращает вам позже, поэтому каждый заказ можно отследить до того самого пользователя, который его совершил. Вот что это за поле, почему оно решает, сможете ли вы вообще ответить на спор, и во что обходится его пропуск теперь, когда проигранный возвратный платёж стал счётом.
Что на самом деле такое обфусцированный идентификатор аккаунта
Обфусцированный идентификатор аккаунта, это одна необязательная строка, которую вы передаёте в процесс биллинга Google Play, когда клиент что-то покупает. Вы устанавливаете её с помощью setObfuscatedAccountId в билдере BillingFlowParams, и Google хранит её рядом с покупкой. Это не имя клиента, не его электронный адрес и не его аккаунт Google. Это ваш собственный идентификатор вашего собственного пользователя, записанный в форме, которую Google может хранить, не узнавая, кто этот человек.
Это строка, которую вы задаёте на кассе, а не имя
По словам Google, setObfuscatedAccountId задаёт необязательную обфусцированную строку, которая однозначно связана с учётной записью покупателя в вашем приложении. Слово обфусцированный тут выполняет реальную работу. Google не хочет ваш сырой идентификатор пользователя или что-либо, что идентифицирует человека. Ему нужен стабильный токен, который сопоставляется один к одному с пользователем на вашей стороне, и ничего более. Поле ограничено 64 символами, чего с запасом хватает для хеша и мало для чего ещё.
Google считывает его сначала для собственной проверки на мошенничество
Прежде чем поле вообще станет полезным вам, оно выполняет работу для Google. Документация по биллингу говорит, что Google Play может использовать это значение для выявления нерегулярной активности, например когда множество устройств совершают покупки на одном аккаунте за короткий промежуток времени, и что Google использует эти данные для выявления подозрительного поведения и блокировки некоторых типов мошеннических транзакций до их завершения. Так что первая выгода от установки поля находится выше по потоку, в более чистых покупках и меньшем числе мошеннических, которые позже превращаются в отмены и споры. Google перечисляет обфусцированный идентификатор аккаунта и Voided Purchases API вместе как два своих основных инструмента против злоупотреблений неспроста.
Почему это важно, когда приходит разбор возвратного платежа
Возврат, который вы видите заранее, это лёгкий случай. Трудный случай, это банковский возвратный платёж, потому что он начинается не с того, что клиент говорит с вами. Он начинается с банка, и Google Play пересылает его вам как разбор с прикреплённым таймером.
Спор называет заказ, а не человека
Когда клиент оспаривает списание в своём банке и Google нужен ваш ввод, Google Play отправляет PendingRefundReviewNotification. Это сообщение идентифицирует заказ. Оно не несёт ваш идентификатор пользователя, потому что у Google никогда не было вашего идентификатора пользователя. У него было только то, что вы проставили на покупку. Если это было ничто, вы теперь ведёте обратный поиск голого идентификатора заказа и токена покупки по собственным записям, надеясь, что залогировали токен в момент покупки, и надеясь, что совпадение однозначно. Если вы установили обфусцированный идентификатор аккаунта, покупка несёт ваш собственный хеш, вы находите пользователя одним запросом и переходите к сбору доказательств вместо охоты за личностью.
О чём на самом деле просит orders.reviewrefund
Ответ на спор означает вызов метода orders.reviewrefund в течение 24 часов. Google записывает ваш первый вызов и игнорирует остальные, поэтому первый ответ, это единственный ответ. Вот поля, которые он хочет, и каждое из полей с доказательствами предполагает, что вы уже знаете, какому пользователю принадлежит заказ.
| Поле | Обязательно | Что оно несёт |
|---|---|---|
| pendingRefundToken | Да | Токен из PendingRefundReviewNotification, на который вы отвечаете |
| refundPreference | Да | APPROVE, DECLINE или NEUTRAL, ваша рекомендация о том, должен ли Play делать возврат |
| sampleContentProvided | Да | Давали ли вы бесплатный образец, пробный период или описание функции до покупки |
| consumptionPercentageMilliunits | Необязательно | Насколько клиент потребил покупку, от 0 до 100,000 milliunits |
| consumptionUsageEvents | Необязательно | Список событий, каждое из которых случай, когда пользователь потребил или использовал купленное |

Во что на самом деле обходится пропуск
Большую часть истории Google Play возвратный платёж, который вы не могли защитить, был потерянной продажей и пожатием плечами. Это изменилось. Для заказов, размещённых 3 августа 2026 года или позже, проигранный возвратный платёж списывает с разработчика цену покупки за вычетом сервисной комиссии Google, плюс банковскую комиссию за возвратный платёж. Спор, на который вы не можете ответить, теперь строка в счёте.
Пройдём по одному заказу. Клиент оспаривает покупку на $9.99 в своём банке. Google Play отправляет разбор, и у вас есть 24 часа. Если вы пометили покупку, вы находите пользователя, видите, что он потребил большую часть купленного, и отвечаете на reviewrefund с предпочтением DECLINE и доказательствами потребления, давая Google реальную аргументацию для оспаривания нелегитимного спора. Если вы не пометили её, вы либо не можете опознать заказ вовремя, либо отвечаете с пустыми руками, спор решается без вашей стороны, и по заказу после 3 августа вы платите $9.99 за вычетом комиссии Google обратно, плюс фиксированную банковскую комиссию за возвратный платёж, которая часто оказывается около $20. На небольшой продаже одна эта фиксированная комиссия может быть больше, чем вы заработали.
- Потерянная выручка: ваша чистая доля от продажи, отменённая.
- Банковская комиссия за возвратный платёж: фиксированные расходы, устанавливаемые платёжной сетью, взимаемые сверху по заказам, размещённым после 3 августа 2026 года, чего обычный возврат никогда не несёт.
- Впустую потраченное: вычисления, вызовы сторонних API и хранилище, которые аккаунт уже использовал, потеряны независимо от того, смогли вы ответить или нет.
- Закономерность, которую вы не видите: без стабильного идентификатора аккаунта вы также не можете понять, что один и тот же пользователь оспаривает снова и снова, поэтому серийное злоупотребление читается как несвязанные разовые потери.
Как установить его, не получив блокировку покупок
Два правила покрывают почти все ошибки, которые команды делают с этим полем. Хешируйте идентификатор и устанавливайте его везде.
Хешируйте идентификатор пользователя, никогда не отправляйте PII
Не помещайте в это поле электронный адрес, телефон или любую сырую личную деталь. Google прямо говорит, что хранение PII, такого как электронные адреса, в открытом виде приводит к блокировке покупок, и рекомендует одностороннее хеширование или шифрование для генерации значения. Чистый подход, это одностороннее хеширование вашего внутреннего идентификатора пользователя, вычисляемое одинаково каждый раз, так что один и тот же пользователь всегда выдаёт одну и ту же 64-символьную строку. Также не используйте идентификатор аккаунта Google этого человека или ваш идентификатор разработчика. Значение должно что-то означать только для вашей системы.
Устанавливайте его на каждую покупку и считывайте обратно на своём сервере
Прикрепляйте идентификатор к каждому процессу биллинга, как к разовым продуктам, так и к подпискам, чтобы ни одна покупка никогда не осталась непомеченной. После покупки считывайте его в двух местах. На клиенте Purchase.getAccountIdentifiers возвращает объект, чей getObfuscatedAccountId выдаёт вам строку, которую вы установили. На вашем бэкенде серверная запись о покупке несёт её как поле obfuscatedExternalAccountId, и именно серверной копии стоит доверять, потому что спор приходит на ваш сервер, а не на устройство.
Используйте setObfuscatedProfileId, когда у одного аккаунта много профилей
Если ваше приложение позволяет одному аккаунту держать несколько профилей, стриминговое домохозяйство или игра с несколькими персонажами, установите также setObfuscatedProfileId. Это такая же хешированная 64-символьная строка без PII, привязанная к профилю, который совершил покупку. Google отмечает, что установка идентификатора профиля также требует передачи идентификатора аккаунта, поэтому отправляйте оба. В результате спор сопоставляется не только с аккаунтом, но и с тем самым профилем, который потратил деньги.
Параллель с iOS, в одной строке
У App Store та же идея под другим названием. На iOS вы прикрепляете к покупке appAccountToken, UUID, и он возвращается на транзакции и на CONSUMPTION_REQUEST, который Apple отправляет, когда клиент просит возврат. Форма проблемы идентична в обоих магазинах. Процесс спора или возврата ссылается на транзакцию, и ваш собственный идентификатор, это то, что связывает её обратно с пользователем, чьё потребление вы можете отчитать.
| Деталь | Google Play | App Store |
|---|---|---|
| Поле, которое вы устанавливаете | обфусцированный идентификатор аккаунта через setObfuscatedAccountId | appAccountToken |
| Формат | Хешированная строка, 64 символа, без PII | UUID |
| Где он возвращается | obfuscatedExternalAccountId на покупке | appAccountToken на транзакции |
| Окно, которое он питает | orders.reviewrefund, 24 часа | CONSUMPTION_REQUEST, 12 часов |
| Что вы отчитываете | Процент потребления и события использования | Поля потребления Apple |
Ничего из этого не сложно построить. Это легко пропустить, потому что день, когда вы пишете код кассы, это не день, когда приходит возвратный платёж, и стоимость пропуска невидима до того момента. RefundHalt устанавливает и отслеживает идентификатор аккаунта в обоих магазинах, поддерживает связь покупки с пользователем, чтобы спор всегда разрешался до реального клиента, и отвечает на orders.reviewrefund в Google Play и CONSUMPTION_REQUEST в Apple внутри их окон с доказательствами потребления, записанными в момент продажи. 24-часовой таймер, это не тот момент, чтобы обнаружить, что вы не можете сказать, кто купил вещь.
Частые вопросы
- Что такое обфусцированный идентификатор аккаунта в биллинге Google Play?
- Это необязательная строка, которую вы прикрепляете к покупке с помощью setObfuscatedAccountId и которая однозначно связана с учётной записью покупателя в вашем приложении. Google Play хранит её вместе с заказом, использует для выявления нерегулярной активности, например когда множество устройств покупают на одном аккаунте, и возвращает вам позже как obfuscatedExternalAccountId, чтобы вы могли связать покупку с конкретным пользователем.
- Могу ли я поместить электронный адрес или идентификатор пользователя в поле обфусцированного идентификатора аккаунта?
- Нет. Google говорит, что хранение личной информации, такой как электронные адреса, в открытом виде в этом поле приводит к блокировке покупок. Используйте одностороннее хеширование или шифрование для генерации значения, укладывайтесь в 64 символа и не используйте идентификатор аккаунта Google этого человека или ваш идентификатор разработчика.
- Как обфусцированный идентификатор аккаунта помогает с возвратным платежом в Google Play?
- Разбор возвратного платежа, PendingRefundReviewNotification, называет заказ, а не вашего пользователя. Обфусцированный идентификатор аккаунта, это ключ связи, который сопоставляет тот заказ с нужной записью пользователя, поэтому вы можете ответить на orders.reviewrefund в течение 24 часов реальными доказательствами потребления вместо догадок о том, какому клиенту принадлежит заказ.
- Устанавливать ли обфусцированный идентификатор аккаунта на подписки или только на разовые покупки?
- Устанавливайте его на каждую покупку, как на разовые продукты, так и на подписки. Любая непомеченная покупка, это та, которую вы не можете отследить обратно до пользователя, когда приходит спор или отмена, а споры могут прийти по любому типу заказа.
- В чём разница между обфусцированным идентификатором аккаунта и обфусцированным идентификатором профиля?
- Идентификатор аккаунта сопоставляет покупку с учётной записью пользователя в вашем приложении. Идентификатор профиля сопоставляет её с конкретным профилем внутри этого аккаунта, для приложений, где один аккаунт держит несколько профилей или персонажей. Оба это хешированные 64-символьные строки без PII, и Google отмечает, что установка идентификатора профиля также требует передачи идентификатора аккаунта.
Источники и дополнительное чтение
- Android Developers: Fight fraud and abuse (Play Billing)
- Android Developers: BillingFlowParams.Builder (setObfuscatedAccountId, setObfuscatedProfileId)
- Android Developers: AccountIdentifiers (getObfuscatedAccountId)
- Android Developers: Help Google dispute chargebacks
- Google Play Developer API: Method orders.reviewrefund
- Play Console Help: Chargeback cost responsibility update (August 3, 2026)
- Apple Developer: Handling refund notifications (CONSUMPTION_REQUEST, appAccountToken)
RefundHalt
Автопилот возвратов для App Store и Google Play
Читайте дальше
Неопознанное списание в банковской выписке превращается в чарджбэк, а чарджбэк обходится дороже, чем возврат
Когда клиент не может понять, за что ваше приложение списало деньги, он звонит в банк, а не вам, и этот спор оборачивается чарджбэком. Apple показывает всё как apple.com/bill и не позволяет ничего изменить. Google Play даёт задать название в выписке. Вот сколько стоит каждый вариант и что вы контролируете.
Apple может отменить уже выданный возврат средств, и отменённый возврат, который игнорирует ваш сервер, блокирует доступ клиенту, который заплатил
Когда App Store отменяет уже выданный возврат средств, он ожидает, что ваш сервер восстановит доступ, который вы отозвали. Вот как работают уведомления о возврате, отклонённом возврате и отменённом возврате в App Store и Google Play, и во что обходится каждое из них, когда вы его игнорируете.