Начальная интеграция со Stripe

Adapty поддерживает web2app-флоу подписок, отслеживая веб-платежи и подписки, оформленные через Stripe.

Интеграция охватывает покупки, инициированные через веб (Stripe Checkout, hosted payment pages или кастомные веб-флоу), и синхронизирует их с доступом в мобильном приложении и аналитикой.

Она полезна в следующих сценариях:

  • Автоматическое предоставление доступа к платным функциям пользователям, которые оплатили на сайте, а затем установили приложение и вошли в аккаунт
  • Хранение всей аналитики подписок в едином дашборде Adapty (включая когорты, прогнозы и весь остальной аналитический инструментарий)

Несмотря на то что веб-покупки становятся всё популярнее для приложений, Apple App Store разрешает использование альтернативных платёжных систем вместо встроенных покупок только для цифровых товаров и только в США. Убедитесь, что вы не продвигаете веб-подписки внутри приложения для других стран — иначе приложение может быть отклонено или заблокировано.

Ниже описаны шаги по настройке интеграции со Stripe.

Эта интеграция ориентирована на отслеживание и синхронизацию веб-покупок через Stripe. Если вам нужно направить пользователей из приложения на веб-страницу оплаты, см. Веб-пейволы.

1. Подключите Stripe к Adapty

Интеграция в основном базируется на том, что Adapty получает данные о подписках от Stripe через вебхук. Поэтому нужно связать аккаунт Adapty с аккаунтом Stripe: предоставить API-ключи и настроить URL вебхука Adapty в Stripe. Чтобы автоматизировать настройку вебхука, установите приложение Adapty в Stripe:

Шаги ниже одинаковы как для Production-, так и для Test-режима Stripe, однако для каждого из них потребуются разные API-ключи.

  1. Определите, в каком режиме вы подключаете Stripe — тестовом или боевом. Если сначала вы настраиваете в тестовом режиме, шаги ниже нужно будет повторить и для боевого.

  2. Перейдите в Stripe App Marketplace и установите приложение Adapty. Обратите внимание, что режим песочницы не поддерживает установку приложений — это можно сделать только в Production- или Test-режиме.

stripe1.png
  1. Выдайте приложению необходимые разрешения — это позволит Adapty получать доступ к данным и истории подписок. Затем нажмите Continue to app settings, чтобы продолжить.

В нижней части всплывающего окна с разрешениями можно выбрать, устанавливать приложение в Live- или Test-режиме.

stripe2.png
  1. Во всплывающем окне сгенерируйте новый ограниченный ключ. Для этого потребуется подтвердить личность через email, Touch ID или ключ безопасности. После генерации ключ больше не будет доступен для просмотра, поэтому сразу сохраните его в менеджере паролей или защищённом хранилище.
stripe4.png
  1. Скопируйте сгенерированный ключ из всплывающего окна и перейдите в App Settings → Stripe в Adapty. Вставьте ключ в поле Stripe App Restricted API Key соответствующего режима. Обратите внимание, что для Test- и Live-режима нужны разные ключи.
Stripe3.png

Готово! Теперь создайте продукты в Stripe и добавьте их в Adapty.

Устаревший способ установки
  1. Перейдите в Developers → API Keys в Stripe:
6549602-CleanShot_2023-12-06_at_17.29.122x.webp
  1. Нажмите кнопку Reveal live (test) key button рядом с заголовком Secret key, скопируйте ключ и перейдите в App Settings → Stripe в Adapty. Вставьте ключ туда:
2989508-CleanShot_2023-12-07_at_14.59.122x.webp
  1. Затем скопируйте URL вебхука из нижней части той же страницы в Adapty. Перейдите в DevelopersWebhooks в Stripe и нажмите кнопку Add endpoint:
e7149f5-CleanShot_2023-12-07_at_17.31.392x.webp
  1. Вставьте URL вебхука из Adapty в поле Endpoint URL. Выберите Latest API version в поле Version вебхука. Затем выберите следующие события:

    • charge.refunded
    • customer.subscription.created
    • customer.subscription.deleted
    • customer.subscription.paused
    • customer.subscription.resumed
    • customer.subscription.updated
    • invoice.created
    • invoice.updated
    • payment_intent.succeeded
cbc5404-CleanShot_2023-12-07_at_17.36.232x.webp
  1. Нажмите «Add endpoint», затем нажмите «Reveal» под разделом «Signing secret». Этот ключ используется для декодирования данных вебхука на стороне Adapty — скопируйте его после раскрытия:
0460cbb-CleanShot_2023-12-07_at_17.52.582x.webp
  1. Наконец, вставьте этот ключ в App Settings → Stripe в Adapty в поле «Stripe Webhook Secret»:
055db20-CleanShot_2023-12-07_at_14.56.212x.webp

2. Создайте продукты в Stripe

Если вы настраиваете интеграцию в тестовом режиме, перед выполнением этого шага убедитесь, что Stripe также переключён в Test mode.

Перейдите в Product catalog в Stripe и создайте продукты, которые хотите продавать, а также их тарифные планы. Обратите внимание, что Stripe позволяет создавать несколько тарифных планов для одного продукта — это удобно для настройки предложений без необходимости создавать дополнительные продукты.

b202e2e-CleanShot_2023-12-06_at_15.06.262x.webp

На данный момент Adapty поддерживает только тарифы Flat rate ($9,99/месяц) и Package pricing ($9,99/10 единиц), так как они аналогичны моделям из сторов. Варианты Tiered pricing, Usage-based fee и Customer chooses price не поддерживаются.

3. Добавьте продукты Stripe в Adapty

Продукты обязательны! Обязательно создайте продукты Stripe в дашборде Adapty. Adapty отслеживает события только для транзакций, связанных с этими продуктами, поэтому не пропускайте этот шаг — иначе события транзакций не будут создаваться.

Мы относимся к Stripe так же, как к App Store и Google Play: это просто ещё один стор, где вы продаёте цифровые продукты. Настройка аналогична: просто добавьте продукты Stripe (а именно их product_id и price_id) в раздел Products в Adapty:

stripe-add-product.webp

ID продуктов в Stripe выглядят как prod_..., а ID цен — как price_.... Их легко найти для каждого продукта в Product Catalog в Stripe, открыв любой продукт:

14a72d7-CleanShot_2023-12-06_at_17.32.512x.webp

После добавления всех необходимых продуктов следующий шаг — сообщить Stripe, какой пользователь совершает покупку, чтобы Adapty мог её зафиксировать.

4. Обогатите покупки на сайте идентификатором пользователя

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

Чтобы уровни доступа были согласованы на всех платформах (веб и мобайл), необходимо использовать единый идентификатор пользователя, который Adapty сможет распознать из вебхуков. Это может быть email пользователя, номер телефона или любой другой ID из вашей системы авторизации.

Определите, какой идентификатор вы хотите использовать для идентификации пользователей. Затем найдите в коде место, где инициируется платёж через Stripe, и добавьте этот идентификатор в объект metadata объекта Stripe Subscription (sub_...) или Checkout Session (ses_...) как customer_user_id:

{'customer_user_id': "YOUR_USER_ID"}

Это единственное дополнение в коде, которое вам нужно сделать. После этого Adapty будет разбирать все вебхуки от Stripe, извлекать metadata и корректно связывать подписки с вашими пользователями.

Идентификатор пользователя обязателен

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

Если вы не передаёте customer_user_id в metadata, у вас будет возможность настроить Adapty так, чтобы он искал customer_user_id в других местах: в поле email объекта Customer в Stripe или в поле client_reference_id объекта Session в Stripe.

Подробнее о настройке поведения при создании профиля читайте ниже.

Объект Customer в Stripe также обязателен

Если вы используете Checkout Sessions, убедитесь, что создаёте Customer в Stripe, установив customer_creation в значение always.

5. Предоставьте доступ пользователям на мобильном устройстве

Чтобы мобильные пользователи, пришедшие с веба, могли получить доступ к платным функциям, просто вызовите Adapty.activate() или Adapty.identify() с тем же customer_user_id, который вы передали на предыдущем шаге (см. Идентификация пользователей для получения подробной информации).

6. Протестируйте интеграцию

Убедитесь, что вы выполнили все шаги выше как для Sandbox, так и для Production. Транзакции, совершённые в Test-режиме Stripe, будут считаться Sandbox-транзакциями в Adapty.

Готово!

Теперь ваши пользователи могут оформлять покупки на сайте и получать доступ к платным функциям в приложении. А вся аналитика подписок будет собрана в одном месте.

Поведение при создании профиля

Adapty должна привязать покупку к профилю пользователя, чтобы он был доступен на мобильном устройстве — поэтому по умолчанию профили создаются при получении вебхуков от Stripe. Вы можете выбрать, что использовать в качестве идентификатора пользователя в Adapty:

  1. По умолчанию и рекомендуется: customer_user_id, переданный в metadata на шаге 4 выше
  2. email из объекта Customer в Stripe (см. документацию Stripe)
  3. client_reference_id из объекта Session в Stripe (см. документацию Stripe)

Вы можете настроить, какой идентификатор использовать, в App Settings → Stripe.

Примечание: если конкретная транзакция из Stripe не содержит указанного идентификатора, профиль не будет создан вовсе. Транзакция останется анонимной до тех пор, пока её не подхватит какой-либо профиль (например, если вы воспользуетесь S2S validate и вручную сообщите нам об этой транзакции).

Она отобразится в Analytics, но не в разделах, которые работают с подсчётом профилей (LTV, Cohorts, Conversions и т. д.), и не будет видна в Event feed.

Есть и четвёртый вариант — вообще не создавать профили, но это не рекомендуется из-за перечисленных выше ограничений в Analytics.

Текущие ограничения

Повышение, понижение тарифа и пропорциональный расчёт

Изменения подписки — например, переход на более дорогой или дешёвый тариф — могут приводить к пропорциональным начислениям. Adapty не учитывает их при расчёте дохода. Лучше всего отключить эти опции вручную через дашборд Stripe. Также можно отключить их, установив значение атрибута proration_behaviour в none через Stripe API.

Отмена подписок

В Stripe есть два варианта отмены подписки:

  1. Немедленная отмена: подписка отменяется сразу с пропорциональным расчётом или без него
  2. Отмена в конце периода: подписка отменяется по истечении текущего расчётного периода (аналогично встроенным подпискам в сторах).

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

Проблемы с оплатой и льготный период

Когда у пользователя возникает проблема с оплатой, Adapty генерирует событие billing issue и доступ отзывается. Льготный период Stripe пока не поддерживается — это будет реализовано в будущих версиях.

Возвраты

Adapty отслеживает только полные возвраты. Частичные возвраты и пропорциональные расчёты в настоящее время не поддерживаются.

Уникальность идентификаторов транзакций

Adapty сопоставляет профили и транзакции с помощью store_transaction_id и store_original_transaction_id. Они должны быть уникальными в рамках тестовой и Production-среды.

Почему это важно

Если один и тот же ID транзакции существует в обеих средах, Adapty считает их одной транзакцией, что приводит к:

  • Переносу тестовых уровней доступа и ID продуктов на Production-покупки
  • Некорректным ID продуктов и средам в ответах API
  • Нарушению привязки профилей и событий подписок

Как обеспечить уникальность

ID счетов (invoice) в Stripe могут совпадать в Test- и Live-средах. Чтобы избежать конфликтов между средами, выберите один из подходов:

Вариант 1: Нумерация счетов на уровне аккаунта с префиксами для каждой среды

Настройте префиксы отдельно для каждой среды:

  1. В дашборде Stripe переключитесь в Test mode.
  2. Перейдите в Settings → Billing → Invoices.
  3. Установите Invoice numbering в значение Sequentially across your account.
  4. Задайте Invoice prefix как TEST- (или другой префикс, уникальный для тестовой среды).
  5. Переключитесь в Live mode и повторите шаги 2–4, используя LIVE- (или другой префикс, уникальный для боевой среды) в качестве префикса.

Вариант 2: Нумерация счетов на уровне пользователя

Установите Invoice numbering в Stripe settings -> Billing -> Invoices в значение Sequentially for each customer (customer-level).

Даже при такой настройке, если вы удалите счёт, Stripe может повторно использовать этот ID для новых счетов того же пользователя. Поэтому по возможности избегайте удаления счетов.

Adapty отслеживает разовые (не подписочные) покупки через Stripe Checkout (mode=payment) или Payment Links только в том случае, если Stripe генерирует счёт (invoice) для покупки. По умолчанию Stripe не создаёт счёт для разовых покупок через Checkout. В этом случае payment_intent.succeeded приходит без данных о счёте, чего недостаточно для записи транзакции в Adapty.

Чтобы отслеживать разовые покупки через Checkout в Adapty, включите создание счёта при создании сессии. Тогда Stripe сгенерирует счёт и отправит связанные события invoice.created и invoice.updated, которые Adapty обработает для записи транзакции.

Получите больше от данных Stripe

После интеграции со Stripe Adapty сразу готова предоставлять аналитику. Чтобы максимально использовать данные Stripe, вы можете настроить дополнительные интеграции Adapty для пересылки событий Stripe — и собрать всю аналитику подписок в едином дашборде Adapty.

Для более детальной аналитики вы можете добавить variation_id в metadata Stripe, чтобы привязывать покупки к конкретным экземплярам пейвола. Это особенно полезно при реализации собственных веб-пейволов, когда вы хотите отслеживать, показ какого именно пейвола привёл к конверсии.

Обратите внимание, что variation_id считывается из metadata только объектов Stripe Subscription (sub_...) и Checkout Session (ses_...):

{
  'customer_user_id': "YOUR_USER_ID",
  'variation_id': "YOUR_VARIATION_ID"
}

Интеграции, которые можно использовать для пересылки и анализа событий Stripe:

Поддерживаемые события Stripe

Adapty поддерживает следующие события Stripe:

  • charge.refunded
  • customer.subscription.created
  • customer.subscription.deleted
  • customer.subscription.paused
  • customer.subscription.resumed
  • customer.subscription.updated
  • invoice.created
  • invoice.updated
  • payment_intent.succeeded