Как добавить подписки через Stripe: тарифы, пробный период, вебхуки и неудачные платежи
Чтобы добавить подписки через Stripe, создайте продукт с регулярной ценой в панели Stripe, отправляйте клиентов с сервера в Stripe Checkout в режиме подписки, а вебхук пусть сообщает приложению, когда каждый платёж проходит, не проходит, меняется или завершается. Храните статус подписки у пользователя и открывайте доступ по нему, а не по странице успеха. Добавьте кнопку «Управление оплатой», которая открывает размещённый клиентский портал Stripe: там люди смогут сменить карту, тариф и отменить подписку, и вам не придётся строить эти экраны.
Этот гайд опирается на как добавить оплату в приложение, который описывает разовый Checkout, тестовый режим и запуск. Здесь мы сосредоточимся на том, что отличает регулярные списания. Данные о Stripe взяты из его документации по состоянию на сентябрь 2026 года.
Почему подписки сложнее разовых платежей
Разовый платёж происходит, пока клиент в вашем приложении. Подписка продолжает работать и после его ухода: продления каждый месяц, карты, у которых истекает срок, апгрейды в середине периода, отмены, которые вступают в силу в конце периода. Ваше приложение узнаёт об этом только через вебхуки. Большинство багов с подписками возникает, когда считают первый платёж всей историей.
Ваши варианты
| Подход | Что вы строите | Подходит для |
|---|---|---|
| Payment Link с регулярной ценой | Только ссылку | Проверки спроса; доступ выдаёте вручную |
| Checkout (режим подписки) + клиентский портал | Серверный маршрут, вебхук, кнопку управления оплатой | Большинства SaaS-приложений и членств |
| API подписок со своей платёжной формой | Гораздо больше: интерфейс оплаты, аутентификация, повторы | Приложений с необычными схемами оплаты |
| Провайдер merchant of record | Похоже на Checkout | Продавцов, которые хотят, чтобы провайдер занимался налогом с продаж |
Для большинства приложений оптимальный выбор — Checkout плюс портал. Сравните провайдеров в гайде Stripe vs Paddle vs Lemon Squeezy, если вас беспокоит обработка налогов.
Сначала спланируйте цены в Stripe
В Stripe продукт — это то, что вы продаёте («Pro-тариф»), а цена — это то, как вы берёте плату за него («$20 в месяц», «$200 в год»). У одного продукта может быть несколько цен. Решите:
- Какие тарифы вы предлагаете и что каждый открывает в приложении
- Ежемесячно, ежегодно или оба варианта
- Будет ли пробный период и нужна ли карта заранее
Создайте продукты и цены в тестовом режиме и сохраните их ID — на них ссылается ваше приложение. Если цены ещё не определены, прочитайте как назначить цену SaaS-продукту и freemium или пробный период.
Жизненный цикл подписки, который нужно обрабатывать
В обзоре подписок Stripe перечислены возможные статусы. Для доступа важнее всего следующие:
| Статус | Что значит | Открывать доступ? |
|---|---|---|
trialing | Пробный период | Да |
active | Всё в порядке | Да |
incomplete | Первый платёж ещё не завершён; Stripe даёт клиенту 23 часа | Нет |
incomplete_expired | Первый платёж так и не прошёл | Нет |
past_due | Последний платёж не прошёл или не был совершён; возможны повторы | На ваше усмотрение; многие приложения дают короткий льготный период |
unpaid | Повторы закончились, счета остаются открытыми, новых попыток нет | Нет: по документации Stripe доступ нужно отозвать |
canceled | Завершена; возобновить нельзя | Нет |
paused | Пробный период закончился без способа оплаты и был переведён в паузу | Нет |
Сохраняйте статус у пользователя или аккаунта и открывайте доступ на его основе. Обновляйте статус каждый раз, когда приходит соответствующий вебхук.
События вебхуков, которые нужно обрабатывать
| Событие | Что делает приложение |
|---|---|
checkout.session.completed | Связать ID нового клиента и подписки Stripe с вашим пользователем |
invoice.paid | Отметить подписку активной и записать новый конец периода |
invoice.payment_failed | Сообщить пользователю, что карта не прошла, и дать ссылку на портал |
invoice.payment_action_required | Попросить пользователя пройти аутентификацию карты |
customer.subscription.updated | Обновить тариф, статус и запланированную отмену |
customer.subscription.deleted | Убрать платный доступ |
customer.subscription.trial_will_end | Напомнить пользователю до конца пробного периода; Stripe отправляет это за три дня |
Правила обработчика из документации Stripe по вебхукам по-прежнему действуют: проверяйте подпись по сырому телу, быстро возвращайте 2xx, обрабатывайте дубликаты и события не по порядку, готовьтесь к повторам. Идею вебхука объясняет гайд что такое вебхук, а все правила подробно перечислены в гайде про оплату.
Пошагово
- Создайте продукты и цены в тестовом режиме Stripe.
- Добавьте секреты: секретный ключ, ID цен и позже секрет подписи вебхука. Никогда не кладите их во фронтенд-код.
- Страница тарифов: кнопка каждого тарифа вызывает ваш сервер, который создаёт Checkout Session в режиме подписки для залогиненного пользователя. Передавайте ID пользователя, чтобы вебхук мог сопоставить платёж с аккаунтом.
- Эндпоинт вебхука: проверяйте подписи и обрабатывайте события выше, обновляя одну запись подписки на пользователя.
- Ограничивайте функции по сохранённому статусу и тарифу, проверяя это на сервере для каждого защищённого действия, а не только по скрытым кнопкам.
- Клиентский портал: настройте его в панели Stripe (на какие тарифы можно переходить, можно ли отменять), затем добавьте кнопку «Управление оплатой», которая создаёт сессию портала на сервере и перенаправляет туда.
- Неудачные платежи: в настройках биллинга Stripe выберите поведение повторов и то, что происходит после последней попытки. Показывайте баннер в приложении, пока статус
past_due. - Протестируйте весь жизненный цикл, затем опубликуйте приложение и зарегистрируйте боевой вебхук.
Промпты для ИИ-конструктора
Добавь подписочный биллинг через Stripe. Тарифы: Starter (ID цены в STRIPE_PRICE_STARTER) и Pro (STRIPE_PRICE_PRO). Страница тарифов создаёт Checkout Session в режиме подписки на сервере с помощью STRIPE_SECRET_KEY, с ID залогиненного пользователя. Сохраняй у пользователя ID клиента Stripe, ID подписки, тариф и статус. Никогда не отдавай секретный ключ в браузер.
Добавь POST /api/stripe/webhook. Проверяй подпись через STRIPE_WEBHOOK_SECRET по сырому телу запроса. Обрабатывай checkout.session.completed, invoice.paid, invoice.payment_failed, customer.subscription.updated, customer.subscription.deleted и customer.subscription.trial_will_end. Сохраняй ID обработанных событий, чтобы игнорировать дубликаты. Обновляй статус пользователя из объекта подписки, а не из порядка, в котором пришли события.
Открывай функции Pro на сервере: только когда статус active или trialing и тариф Pro. Когда статус past_due, показывай баннер «Платёж не прошёл, обновите карту». Добавь кнопку «Управление оплатой», которая открывает клиентский портал Stripe для этого пользователя.
Апгрейды, даунгрейды и пропорции
Когда клиент меняет тариф, Stripe в документации описывает пропорциональный перерасчёт (proration): новая цена применяется к оставшейся части текущего периода. Можно посмотреть такой перерасчёт заранее или отключить его. Если тарифы с одинаковым интервалом, даты списаний не меняются; при переходе с месячного на годовой дата списания переносится на день смены. Если позволить клиентам менять тариф в портале, логику писать не придётся, но в настройках портала решите, какие переходы разрешены.
Чек-лист тестирования
Используйте тестовый режим Stripe и тестовые карты и пройдите каждое состояние:
- Новая подписка открывает нужный тариф нужному пользователю
- Закрытие вкладки сразу после оплаты всё равно открывает доступ (доказывает, что вебхук работает)
- Отклонённая карта при регистрации ничего не открывает
- Неудачное продление переводит аккаунт в past_due и показывает баннер
- Обновление карты в портале возвращает статус active
- Апгрейд и даунгрейд правильно меняют функции
- Отмена в конце периода сохраняет доступ до даты окончания, затем убирает его
- Пользователи пробного периода получают доступ, напоминание и корректно переходят на платный тариф или теряют доступ
- Повторная отправка того же события вебхука ничего не меняет
Тестовые часы Stripe (test clocks) позволяют имитировать ход времени, чтобы проверить продления без ожидания месяц. Актуальные инструкции по их использованию смотрите в документации Stripe по тестированию.
Частые ошибки
- Открытие доступа на странице успеха. Клиент может заплатить и не дойти до неё. Используйте вебхук.
- Обработка только первого платежа. Продления, неудачи и отмены приходят позже, как события.
- Проверка статуса тарифа только на фронтенде. Любой может вызвать ваш API напрямую.
- Случайно несколько подписок у одного пользователя. Проверяйте, нет ли уже подписки, перед созданием новой Checkout Session, или отправляйте существующих клиентов в портал.
- Отзыв доступа при первом неудачном продлении. Карты отказывают по скучным причинам. Короткий льготный период с понятным баннером сохраняет клиентов.
- Забытый боевой вебхук. У тестового и боевого эндпоинтов разные секреты подписи.
- Игнорирование налогов и возвратов. Определите политику возвратов и проверьте налоговые обязательства с бухгалтером до запуска.
Подписки в Mythex
Приложения, созданные на Mythex, используют ваш собственный аккаунт Stripe и ключи; кнопки подключения Stripe в одно нажатие для вашего приложения нет. Добавьте тестовые ключи и ID цен как секреты проекта, используйте промпты, похожие на приведённые выше, и проверяйте тестовыми картами Stripe в Preview. Вебхукам нужен публичный URL приложения, поэтому публикуйте приложение до регистрации эндпоинта в Stripe и опубликуйте снова после перехода на боевые ключи, чтобы живое приложение их подхватило. См. принимать оплату через Stripe и обработка вебхуков в бэкенде. Для всего продукта вокруг биллинга смотрите как создать MVP SaaS.
Вопросы
Какой самый простой способ добавить подписки через Stripe?
Создайте продукт с регулярной ценой в панели Stripe, отправляйте клиентов в Stripe Checkout в режиме подписки, обрабатывайте события подписки через вебхук и привяжите кнопку «Управление оплатой» к размещённому клиентскому порталу Stripe. Так не нужно самим строить формы карт и экраны смены тарифа.
Какие события вебхуков Stripe нужны для подписок?
Как минимум checkout.session.completed, чтобы связать новую подписку с пользователем; invoice.paid, чтобы подтверждать каждый успешный платёж; invoice.payment_failed, чтобы предупреждать о неудачных продлениях; и customer.subscription.updated и customer.subscription.deleted, чтобы отслеживать смену тарифа и отмены.
Что происходит, когда платёж по подписке не проходит?
По документации Stripe на сентябрь 2026 года, подписка обычно переходит в статус past_due, и Stripe может повторять платёж по вашим настройкам. После последней попытки настройки панели определяют, будет ли подписка отменена, помечена как unpaid или останется past_due.
Можно ли предложить бесплатный пробный период без запроса карты?
Да. Stripe поддерживает пробные периоды, а в его документации описан статус paused для пробных периодов, которые заканчиваются без способа оплаты, если это так настроено. Запрос карты заранее обычно означает меньше регистраций, но больше платящих клиентов; проверьте, что подходит вашему продукту.