Buy itunes apple com verifyreceipt

То, что нужно знать о проверке чека App Store (App Store receipt)

В StackOverflow по-прежнему появляется много вопросов о валидации App Store чеков, поэтому мы решили написать статью на эту тему в формате вопросов и ответов.

Что представляет собой App Store чек?

Это зашифрованный файл в формате PKCS#7, который содержит в себе информацию обо всех покупках в приложении. Находится в бандле приложения и его можно легко получить, вызвав: Bundle.main.appStoreReceiptURL .

Всегда ли есть этот файл?

Если приложение было скачано из App Store, то да, всегда. А если было установлено через Xcode или Testflight, то первоначально у приложения sandbox-чек отсутствует до первой покупки или восстановления чека.

Что значит «провалидировать чек»?

Это означает расшифровать файл, получить JSON дату и сверить совершенные пользователем покупки. Сделать это можно локально или отправив запрос в Apple.

В каких случаях разработчику требуется валидация чека?

Для валидации только что совершенной покупки.
Когда у многих был джейлбрейк это было актуально: существовали утилиты для подделки чека. Сейчас эта проблема перестала быть острой, потому что джейлбрейк стал редкостью.

При восстановлении покупок.
Если пользователь переустановил ваше приложение или запустил с другого устройства, вы должны предоставить ему доступ к функционалу, за который он уже заплатил. Расшифровав App Store чек, вы сможете выяснить, была ли приобретена встроенная покупка.

При покупке авто-возобновляемых подписок.
Для определения текущего статуса подписки и даты истечения.

Какие покупки можно восстановить при валидации?

Существует 4 вида встроенных покупок:

  • расходуемые (consumable purchases),
  • нерасходуемые (non-consumable purchases),
  • невозобновляемые подписки (non-renewing subscriptions),
  • авто-возобновляемые подписки (auto-renewable Subscriptions).
    Восстановить можно все, кроме расходуемых покупок. К ним можно отнести, например, монетки в вашем приложении – что-то, что можно купить сколько угодно раз. Вы должны сами сохранять текущее количество монеток у пользователя на своем сервере.

Какие способы валидации существуют?

  • локальная валидация с использованием OpenSSL,
  • валидация по запросу в Apple прямо с iOS устройства,
  • валидация по запросу в Apple с использованием вашего сервера.

Какой способ валидации лучше?

Локальная валидация сложна и требует много времени и усилий на реализацию. А еще вы должны будете добавить OpenSSL библиотеку в ваш проект. В некоторых случаях придется обновлять чек.

Apple не рекомендует проверять чеки на самом iOS-устройстве. Это небезопасно: запрос можно перехватить с помощью man-in-the-middle атаки.

Лучше всего валидировать чеки на сервере. Тем более, что Apple время от времени добавляет туда новые поля, например, grace_period_expires_date и subscription_group_identifier . На своем сервере мы сможете быстро вносить изменения без обновления приложения. А еще предыдущие два метода валидации можно легко обмануть, просто поменяв системное время на iOS устройстве.

Для чего нужен Shared Secret?

Это специальная строка-ключ, которая необходима для расшифровки чеков с авто-возобновляемыми покупками. Apple использует Shared secret как параметр в HTTPS запросе к Apple.

Где взять Shared Secret?

Перейдите в App Store Connect, откройте приложение, перейдите во вкладку Функции, в разделе Встроенные покупки увидите кнопку Общий ключ для приложения. Сгенерируйте новый ключ, если его еще нет.

Пример кода для валидации чека

Это пример валидации чека на iOS. Не забудьте заменить значение YOUR_SHARED_SECRET на ваш shared secret.

Получив data , сконвертируйте его в Dictionary :

Пример расшифрованного App Store чека

Здесь можно посмотреть пример чека с двумя транзакциями в приложении с авто-возобновляемой подпиской.

В чем отличия между in_app и latest_receipt_info ?

latest_receipt_info содержит все транзакции, включая продления авто-возобновляемых покупок. Вам стоит использовать только этот массив.

in_app содержит транзакции нерасходуемых покупок и невозобновляемых подписок. Еще здесь дублируется первая транзакция вашей авто-возобновляемой подписки. Расходуемые покупки тоже появятся в массиве in_app , но потом исчезнут, когда разработчик завершит транзакцию.

Читайте также:  Все виды часов apple iwatch

Заключение

Мы в Apphud реализовали валидацию App Store чеков для приложений с авто-возобновляемыми подписками в удобном open-source SDK. А еще Apphud помогает отслеживать статус подписки, анализировать ключевые метрики, автоматически предлагать скидки отписавшимся пользователям и многое другое. Если при работе с подписками вы испытываете боль, попробуйте наше решение бесплатно.

Источник

iOS in-app purchases, часть 3: серверная валидация покупок

Всем привет, я Кирилл, СТО Adapty. Я делал систему серверной валидации для наших SDK.

Сегодня как раз и расскажу про серверную верификацию покупок на iOS. Это третья статья из серии о внедрении внутренних покупок на iOS, советую познакомиться с остальными:

iOS in-app purchases часть 3: серверная валидация покупки. — Вы тут

Серверная валидация (server-side receipt validation) — это способ проверить подлинность покупки. В отличие от проверки покупки на устройстве, серверная валидация происходит, внимание, на сервере. Валидация означает, что устройство или сервер обращаются к серверам Apple и спрашивают, действительно ли была покупка и валидная ли она.

Зачем валидировать покупки

Стоит отметить, что серверная валидация не обязательна, встроенные покупки и подписки будут работать и без неё. Но она даёт ряд преимуществ:

Продвинутая аналитика платежей, особенно актуальная для подписок, потому что все события после активации происходят без участия устройства. Если не сделать серверную обработку покупок, вы не будете знать статус подписки в конкретный момент времени: продлил ли пользователь подписку, отменил ее, есть ли проблема с платежом и тд.

Проверка подлинности покупки, то есть вы будете уверены, что это не фродовая транзакция, а значит, пользователь заплатил деньги за ваш продукт.

Кроссплатформенные подписки. Зная в живом режиме статус подписки пользователя, можно синхронизировать его с другими платформами. Например, пользователь, оформивший подписку на iOS, сможет пользоваться сервисом на Android, Web и других платформах.

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

По нашему опыту, один первый пункт — достаточная причина делать обработку покупок на сервере.

Валидация платежей

В целом процесс валидации платежей на iOS можно описать схемой:

Получение shared secret

Чтобы отправить запрос на валидацию платежа, необходимо предоставить shared secret, с помощью которого авторизуется запрос. Получить его можно в App Store Connect.

Shared secret может быть создан для конкретного приложения (app-specific) или же для всех приложений в аккаунте (primary).

Чтобы получить secret для конкретного приложения, необходимо открыть страницу данного приложения в App Store Connect, перейти в раздел In-App Purchases → Manage и кликнуть на ссылку App-Specific Shared Secret. В открывшемся окне можно будет создать новый или скопировать существующий токен.

Чтобы получить secret для всех приложений в аккаунте, необходимо открыть страницу Users and Access и перейти на вкладку Shared Secret.

Запрос на валидацию платежа

После получения shared secret вы можете отправлять квитанцию (receipt) для валидации на сервер Apple. Это делается с помощью запроса verifyReceipt. Нужно отправить POST-запрос на https://buy.itunes.apple.com/verifyReceipt. В JSON теле запроса нужно отправить shared secret в поле password и receipt в поле receipt-data . Также есть опциональный параметр exclude-old-transactions . Если его значение true, то для каждой авто-возобновляемой подписки вернётся только последняя транзакция, вместо всей истории продлений.

Пейлоад запроса на валидацию платежа

Если вы работаете в Sandbox режиме, то есть тестируете покупки, запросы на валидацию надо отправлять на https://sandbox.itunes.apple.com/verifyReceipt. Shared secret, формат пейлоада и ответа остаются без изменений.

Важно отметить, что receipt, созданный в Sandbox, нельзя будет провалидировать на Production сервере, и наоборот.

Поэтому в реальных системах рекомендуется всегда первый запрос отправлять на Production сервер, и, если в ответ в ключе status пришла ошибка с кодом 21007 , повторить запрос на Sandbox сервер. Такое поведение обязательно нужно включать на период ревью приложения, чтобы сотрудники Apple могли тестировать покупки, и в это же время их могут делать реальные пользователи вашего приложения.

Среди других ошибок, на которые нужно обращать внимание, — 21004 , которая говорит о том, что мы используем неправильный secret. Её важно мониторить, потому что она влияет и на пользовательский опыт, и на точность аналитики. В худшем случае, приложение могут удалить из App Store, если пользователю после покупки не даётся доступ к платным возможностям.

Читайте также:  Оборудование для полировки экрана айфонов

В случае успешной валидации ( status=0 ), в ответ приходит информация о транзакциях пользователя.

Ответ на запрос о валидации платежа

Ответ громоздкий, и в новой версии App Store Server API его упростили, но и с текущей реализацией нетрудно разобраться.

Получение статуса подписки и истории транзакций

Чтобы понимать, есть ли у пользователя доступ к платным функциям приложения, вам нужно уметь определять статус подписки. В данной версии API нет отдельного запроса на получение статуса подписки, поэтому вам в любом случае будет нужно работать с историей транзакций.

В latest_receipt_info по умолчанию хранятся все транзакции пользователя, за исключением consumable продуктов, которые завершены на стороне мобильного приложения. Таким образом, вы можете восстановить всю историю покупок пользователя. Это полезно и для аналитики, и для вычисления текущего статуса подписки.

Кажется, что сейчас транзакции всегда приходят отсортированными от самой старой к самой новой, но для надёжности я рекомендую сделать собственную сортировку по дате транзакций.

Для получения текущего статуса подписки достаточно взять хронологически последнюю транзакцию в цепочке и посмотреть на дату истечения подписки ( expires_date ). Исключением будет grace period, о нём мы поговорим чуть позже.

Для аналитических целей я рекомендую сохранять следующие поля:

product_id — текстовый идентификатор продукта, который был куплен.

transaction_id — числовой уникальный идентификатор транзакции. У каждой покупки/продления будет свой идентификатор, его можно использовать, чтобы понимать, была ли ранее обработана данная транзакция.

original_transaction_id — числовой уникальный идентификатор цепочки транзакций. При активации подписки/триала он будет совпадать с transaction_id, но при последующих продлениях transaction_id будет меняться, а original_transaction_id будет одинаковым. Это удобно для того, чтобы отслеживать количество продлений.

purchase_date и original_purchase_date — дата транзакции и дата оригинальной транзакции по аналогии с предыдущем пунктом.

expires_date — дата истечения подписки

cancellation_date — дата рефанда, а не отмены подписки, как может показаться из названия. Если в ответе есть это поле, значит, вы можете отозвать доступ пользователя к приложению, а также учесть в аналитике, что деньги за эту транзакцию не будут выплачены.

is_in_intro_offer_period — флаг, показывающий, был ли использован интро оффер при активации подписки.

is_trial_period — флаг, показывающий, был ли использован триал при активации подписки.

offer_code_ref_name — оффер код, который был использован при активации подписки.

promotional_offer_id — текстовый идентификатор промо оффера, который был использован при переходе на текущий период подписки.

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

PURCHASED — пользователь сам купил продукт.

FAMILY_SHARED — пользователь получил продукт в рамках семейной подписки.

На WWDC 2021 Apple сообщили, что позже в транзакцию добавят поле appAccountToken , которое содержит идентификатор пользователя в вашей системе. Этот идентификатор должен быть в формате UUID и задаётся на стороне мобильного приложения в момент инициализации покупки. Если задан, то он будет возвращаться во всех транзакциях в этой цепочке (продления, проблемы с биллингом и тд.), а значит вы легко сможете понять, какой пользователь сделал покупку.

Также стоит следить за параметром subscription_group_identifier . Если у пользователя ранее была транзакция с активным триалом или интро оффером, то в рамках данной группы подписок, пользователю больше недоступны триал и интро оффер, и это нужно отслеживать со стороны сервера.

Информация о продлении подписки, grace period и billing issue

В pending_renewal_info лежит информация о продлении подписки. Она позволяет понять, что произойдёт с подпиской в следующем периоде. Например, если вы обнаружили, что пользователь отменил автопродление, вы можете предложить ему переход на другой план или промо оффер. Отслеживать такие события удобно с помощью серверных уведомлений, о которых я скоро расскажу.

Информация о продлении подписки

product_id — текстовый идентификатор продукта, который был куплен.

auto_renew_product_id — текстовый идентификатор продукта, который активируется в следующем периоде. Если он отличается от текущего ( product_id ), значит пользователь сменил тип подписки.

auto_renew_status — флаг, показывающий будет ли продлена подписка на следующий период.

expiration_intent — причина истечения подписки. Возможные значения:

1 — пользователь сам отменил подписку.

2 — подписка отменилась из-за проблем с оплатой.

3 — пользователь не согласился на повышение цены

4 — продукт подписки не был доступен для продления, например, если его удалили из App Store Connect.

5 — неизвестная причина.

grace_period_expires_date — дата истечения grace period, если он включен для вашего приложения. В этом случае пользователю должны быть доступны платные функции приложения до даты, указанной здесь, а не до той, которая указана в самой транзакции. Если есть этот ключ, вы можете сообщить пользователю о том, что ему нужно обновить данные карты для оплаты или пополнить баланс.

Читайте также:  Замена кнопки mute iphone

is_in_billing_retry_period — флаг, показывающий находится ли подписка в статусе billing retry. Это значит, что подписка не была отменена, но при этом Apple не смог списать деньги за продление и будет пытаться делать это в течение 60 дней.

offer_code_ref_name — оффер код, который будет использован в следующем периоде подписки.

promotional_offer_id — текстовый идентификатор промо оффера, который будет использован в следующем периоде подписки.

price_consent_status — флаг, показывающий, согласился ли пользователь с грядущим повышением цены на подписку. Если его значение 0, то вам стоит предложить пользователю другой продукт или промо оффер, чтобы он не прекратил подписку.

Consumable, non-consumable и невозобновляемые подписки

Если у пользователя нет авто-возобновляемых продуктов, то ключи latest_receipt_info и pending_renewal_info не возвращаются. В таком случае, транзакции стоит искать в receipt → in_app. Формат транзакций похож на авто-возобновляемые транзакции, но в нём нет полей истечения, продления, офферов и других эксклюзивных для авто-возобновляемых транзакций параметров.

Стоит отметить, что receipt → in_app приходит и для авто-возобновляемых транзакций, но лучше использовать latest_receipt_info , потому что в нём будет наиболее актуальная информация по подписке.

Серверные уведомления о транзакциях

Некоторое время назад требовалось написать сложную систему, чтобы отслеживать изменения в состоянии подписок. Например, чтобы понять, продлилась подписка или нет, нужно было за сутки до её истечения раз в час отправлять запрос на сервер Apple, чтобы узнать её статус. Apple постепенно добавлял серверные уведомления, и в настоящее время практически все важные события, связанные с подписками, покрыты серверными уведомлениями. Это очень удобно: как только со стороны Apple произошло какое-то изменение, вы можете получить информацию об этом на своём сервере. То есть вы будете получать информацию о новых покупках, продлениях, проблемах с платежами и так далее. Это позволяет собирать более точную аналитику, а также упрощает менеджмент состояния подписчика.

Настроить получение серверных уведомлений можно в App Store Connect. Необходимо открыть страницу приложения, перейти в раздел General → App Information, указать желаемую ссылку в поле URL for App Store Server Notifications и сохранить изменения.

Серверное уведомление

Формат серверных уведомлений похож на ответ валидации платежа. Информация о транзакциях лежит в unified_receipt → latest_receipt_info . В ключе password лежит shared secret для вашего приложения, таким образом вы можете убедиться в подлинности запроса. В ключе notification_type указан тип события. На мой взгляд, самые полезные:

DID_CHANGE_RENEWAL_STATUS — пользователь выключил или (намного реже) включил автопродление подписки. Если автопродление выключили, надо пытаться вернуть пользователя в число активных подписчиков.

DID_FAIL_TO_RENEW — подписку не получилось продлить из-за проблем с оплатой. Стоит сообщить пользователю об этом, чтобы у него не отменилась подписка автоматически.

DID_RENEW — подписка успешно продлилась.

REFUND — пользователю вернули деньги за покупку. Нужно закрыть ему доступ к функциям, которые давала эта покупка и отразить рефанд (потерю денег) в аналитике.

Заключение

Серверная валидация значительно улучшает качество аналитики, которую вы можете собирать со своего приложения. Она также усложняет несанкционированный доступ к платному контенту и позволяет делать мультиплатформенные подписки. При этом реализация валидации может занять довольно много времени, особенно если нужна высокая точность данных, а значит надо учитывать много сайд-кейсов: upgrade подписки, cross grade подписки, trial период, promo/introductory offers, grace period, возвраты, семейные подписки и тд. Плюс нужно знать и учитывать различные нюансы, например, что для подписок, которые продлеваются больше года, Apple снижает комиссию с 30% до 15%.

Если вы хотите получить работающую серверную валидацию и продвинутую аналитику с самого начала жизни вашего приложения и не хотите разрабатывать всё это самостоятельно, вам стоит попробовать Adapty. Мы делаем этот сервис не только для технической реализации подписок:

Встроенная аналитика позволяет быстро понять основные метрики приложения.

А/Б тесты увеличивают выручку приложения.

Интеграции с внешними системами позволяют отправлять транзакции в сервисы атрибуции и продуктовой аналитики.

Промо кампании уменьшают отток аудитории.

Open source SDK позволяет интегрировать подписки в приложение за несколько часов.

Серверная валидация и API для работы с другими платформами.

Познакомьтесь подробнее с этими возможностями, чтобы быстрее внедрить подписки в своё приложение и улучшить конверсии.

Источник

Оцените статью