Владелец подписного сервиса сталкивается сразу с тремя связанными событиями: деньги списаны, подписка продлена, доступ открыт. Если обрабатывать их независимо, пользователь может получить лишний период, потерять уже оплаченный доступ или столкнуться с новым списанием после отмены.
Надёжное правило звучит так: биллинг меняет срок доступа только после проверки объекта платежа, а каждое подтверждённое списание применяет один раз. Отмена запрещает будущие списания, но сама по себе не означает возврат денег или немедленное закрытие доступа.
Какую задачу решает этот процесс
Процесс нужен владельцу подписного сервиса, который продаёт доступ на повторяющиеся периоды. Система должна знать, за какую подписку пришли деньги, на какой срок продлить доступ и что делать при отмене или отказе.
Результат — согласованный жизненный цикл:
- Пользователь явно соглашается на условия повторных списаний.
- Первый платёж проходит через платёжный сервис.
- Биллинг сохраняет разрешённый идентификатор способа оплаты и планирует следующее продление.
- После подтверждённого платежа система один раз меняет дату доступа.
- Отмена останавливает будущие списания, а оплаченный период заканчивается по установленному правилу.
Здесь рассматривается повторный платёжный цикл с согласием и отменой. Разовая оплата — отдельный сценарий: в ней нет расписания продлений и состояния подписки.
Какие данные и правила подготовить
До разработки полезно составить реестр данных. Он показывает, какая система сообщает значение и кто отвечает за правило. Ниже — заполненный синтетический образец без клиентских данных; все идентификаторы, даты и суммы условны.
| Поле | Условный пример | Источник | Ответственный | Обязательность |
|---|---|---|---|---|
customer_id | CUST-1042 | База пользователей сервиса | Владелец продукта | Обязательное |
subscription_id | SUB-2026-0042 | Собственный биллинг | Владелец продукта | Обязательное |
| Способ оплаты | Банковская карта, условный пример | Объект платежа провайдера | Разработчик интеграции | Обязательное для выбранного сценария |
payment_method_id | pm_demo_17 | Ответ платёжного провайдера | Разработчик интеграции | Условное: только если способ можно сохранить |
| Период | 30 дней | Правило тарифа | Владелец продукта | Обязательное |
| Сумма | 990,00 | Каталог тарифов | Владелец продукта | Обязательное |
| Валюта | RUB | Каталог тарифов | Владелец продукта | Обязательное |
consent_at | 2026-10-01T10:00:00Z | Журнал согласий | Ответственный заказчика | Обязательное |
payment_status | succeeded | API или webhook провайдера | Разработчик интеграции | Обязательное |
access_status | active | Собственный биллинг | Владелец продукта | Обязательное |
access_until | 2026-10-31T23:59:59Z | База управления доступом | Разработчик интеграции | Обязательное |
| Политика возврата | Не согласована | Решение заказчика | Юридический или иной уполномоченный специалист заказчика | Неизвестное до согласования |
Если таблица не помещается, прокрутите её вправо. С клавиатуры используйте стрелки.
Одних полей недостаточно. Нужно определить часовую зону, момент окончания периода, правило округления суммы, допустимые переходы состояний и действия человека при спорной операции. Неизвестное нельзя заменять предположением разработчика.
Как устроить первый платёж и сохранение способа оплаты
Платёжный API и биллинг подписки решают разные задачи. Платёжный сервис создаёт платёж, принимает подтверждение пользователя и возвращает объект с payment_id, статусом, суммой и валютой. Если выбранный способ и сценарий это поддерживают, сервис также возвращает идентификатор сохранённого способа оплаты.
Собственный биллинг хранит customer_id, subscription_id, период, сумму, валюту, дату следующего списания и состояние доступа. Именно он решает, когда создавать следующий платёж и когда прекратить продление. В документации API ЮKassa периодичность и отключение автоплатежей отнесены к стороне интегратора; повторный платёж создаётся с payment_method_id сохранённого способа.
Перед сохранением метода нужно зафиксировать согласие пользователя в форме, соответствующей правилам бизнеса и требованиям специалистов заказчика. Затем интеграция проверяет по документированным данным провайдера, что метод действительно сохранён и доступен для выбранного сценария. Поддержку конкретного способа, права магазина и договорные условия проверяют перед внедрением.
Полный номер карты, PAN и CVC в собственной базе не хранят. Биллинг работает с выданным провайдером идентификатором сохранённого способа оплаты. Возврат пользователя по return_url тоже не доказывает оплату: после redirect следует получить и проверить актуальный объект платежа.
Как продлевать доступ по подтверждённой оплате
Для учебного процесса используем собственные состояния подписки:
active— оплата подтверждена, доступ действует;grace— платёж не подтверждён, но доступ временно сохранён по правилу сервиса;past_due— разрешённые попытки закончились, требуется действие пользователя или оператора;canceled— будущие продления отключены.
Это состояния нашей модели, а не универсальный набор статусов ЮKassa или другого провайдера. Платёжный объект имеет собственные статусы, которые нужно сопоставить с состояниями подписки.
Получив webhook, обработчик проверяет актуальность и подлинность уведомления предусмотренным провайдером способом. Затем он сверяет объект платежа:
payment_idотносится к ожидаемой операции;- статус означает подтверждённую оплату;
- сумма равна ожидаемым 990,00;
- валюта — RUB;
- связанный
subscription_idравенSUB-2026-0042.
Только после всех проверок биллинг меняет доступ. Для условного периода применяется правило:
new_access_until = max(current_access_until, paid_period_start) + 30 дней.
В примере это ровно 30 × 24 часа в UTC, а не «следующий календарный месяц». В реальном проекте отдельно согласуют календарный период, часовую зону и поведение на границах месяца.
Формулу применяют один раз для уникального payment_id. Запись об обработанном платеже и новую дату доступа сохраняют в одной транзакции. Повторный webhook возвращает уже сохранённый результат и не начисляет ещё один период.
Ключ команды создания платежа и идентификатор входящего события выполняют разные роли. Например, renew:SUB-2026-0042:2026-11-01 защищает команду продления от повторного создания операции, а pay_demo_001 позволяет не применить один платёж к доступу дважды. Срок действия и формат ключей API нужно брать из документации выбранного провайдера; собственный реестр обработанных платежей должен учитывать весь необходимый бизнесу период.
Как обрабатывать отмену и неуспешное списание
Отмена будущего продления, возврат и завершение оплаченного периода — три разных действия.
Если пользователь отключает продление, биллинг устанавливает собственный признак cancel_at_period_end=true и больше не создаёт платежи по расписанию. Уже оплаченный доступ остаётся до access_until, если такое правило согласовано. Возврат запускают отдельной операцией только по утверждённой политике и с проверкой возможностей провайдера. Отмена подписки не должна автоматически обещать возврат.
При неуспешном списании система читает статус и причину из объекта платежа. Дальнейшее правило задаёт сам сервис. Бесконечные попытки опасны: пользователь не понимает, сколько раз система попробует списать деньги, а оператор получает цепочку спорных операций.
Для учебного примера действует условный предел: исходная попытка и не более двух повторов — всего три попытки. После первого отказа подписка переходит в grace; после двух неуспешных повторов — в past_due. Автоматические попытки прекращаются, пользователь получает понятное сообщение, а оператор видит причину и следующий шаг. Это правило примера, а не требование банка или ЮKassa.
Если причина показывает, что разрешение на автоплатёж отозвано, нельзя продолжать списания с тем же сохранённым методом. Если провайдер вернул финальный неуспешный статус, новый платёж создают как новую операцию по документированному сценарию, а не пытаются изменить завершённый объект.
Учебный пример: путь от входных данных до результата
Исходные данные: подписка SUB-2026-0042, стоимость 990,00 RUB, фиксированный период 30 дней, часовая зона UTC. На старте доступ действует до 2026-10-31T23:59:59Z. Все идентификаторы, даты, суммы и правила ниже условны; это синтетический учебный пример, а не клиентский кейс и не результат живого теста.
При подтверждении pay_demo_001 обработчик сверяет подписку, сумму, валюту и статус. Затем один раз прибавляет 30 дней: доступ действует до 2026-11-30T23:59:59Z. Повторное уведомление с тем же payment_id на результат не влияет.
Дальше показаны две независимые ветви от общей исходной модели. В ветви отмены пользователь выключает будущее продление и сохраняет оплаченный доступ. В отдельной ветви отказа система создаёт следующий платёж, получает отказ и применяет условное правило ожидания. Эти события не происходят последовательно в одной подписке.
| Событие | Статус платежа | Доступ до | Следующее действие | Идемпотентный ключ |
|---|---|---|---|---|
| Первичное подтверждение | succeeded | 2026-10-31 23:59:59 UTC | Запланировать продление | first:SUB-2026-0042:2026-10-01 |
Продление pay_demo_001 | succeeded | 2026-11-30 23:59:59 UTC | Сохранить результат | renew:SUB-2026-0042:2026-11-01 |
Повторный webhook pay_demo_001 | succeeded | 2026-11-30 23:59:59 UTC | Ничего не менять | webhook:pay_demo_001 |
| Отмена будущего продления | Без нового платежа | 2026-11-30 23:59:59 UTC | Не создавать следующий платёж | cancel:SUB-2026-0042:2026-11-10 |
Отказ pay_demo_002 | declined | 2026-12-03 23:59:59 UTC | Перевести в grace, выполнить не более двух повторов | retry:pay_demo_002:0 |
| Два повтора неуспешны | declined | 2026-12-03 23:59:59 UTC | Перевести в past_due, остановить попытки, передать человеку | retry:pay_demo_002:2 |
Если таблица не помещается, прокрутите её вправо. С клавиатуры используйте стрелки.
declined в таблице — понятная метка результата учебного процесса, а не заявление о точном статусе объекта конкретного API. Дата 2026-12-03 в ветви отказа — граница условного grace-периода, а не новый оплаченный срок. В этой ветви повторы назначены на 1 и 3 декабря; после второго неуспешного повтора автоматическое списание останавливается.
Главный вывод примера: событие платежа и изменение доступа связываются через уникальный payment_id и транзакционную запись результата. Поэтому повторная доставка webhook не превращается в лишние 30 дней.

Как проверить результат перед запуском
Проверка должна охватывать обычный путь и исключения. Сообщение пользователю или возврат из redirect не заменяют проверку объекта платежа.
| Ситуация | Ожидаемый результат | Сигнал ошибки | Действие человека |
|---|---|---|---|
| Подтверждённый платёж | Сумма, валюта и подписка совпали; доступ продлён один раз | Дата не изменилась или изменилась дважды | Сверить журнал платежа и транзакцию биллинга |
| Повтор одного webhook | Сохранён прежний результат, срок не увеличился | Появился второй период | Остановить обработчик и проверить уникальность payment_id |
| Возврат через redirect без подтверждённого статуса | Доступ не выдан до проверки объекта | Доступ открыт по факту перехода пользователя | Закрыть ошибочно выданный доступ по согласованной процедуре и исправить условие |
| Не совпали сумма или валюта | Доступ не меняется, событие уходит на разбор | Биллинг принял 990,00 в другой валюте или иную сумму | Проверить тариф, запрос и объект платежа |
| Отмена продления | Следующий платёж не создаётся, оплаченный доступ следует принятому правилу | После отмены появилась новая команда списания | Остановить расписание и разобрать источник команды |
| Отказ банка | Срабатывает ограниченный сценарий повторов и уведомление | Попытки продолжаются сверх лимита | Отключить автоматические повторы и проверить состояние подписки |
| Запрос возврата | Создана отдельная операция только после проверки правил | Отмена подписки автоматически выдала обещание возврата | Передать решение уполномоченному специалисту заказчика |
Если таблица не помещается, прокрутите её вправо. С клавиатуры используйте стрелки.
Перед запуском также проверяют недоступность API, задержку и повторную доставку webhook, одновременную отмену и продление, истечение сохранённого метода и ручное исправление ошибочного состояния. Для каждого сценария заранее фиксируют вход, ожидаемый результат, наблюдаемый сигнал ошибки и ответственного.
Сроки доступа, основания отмены и правила возврата утверждает заказчик с участием профильного специалиста. Эта статья описывает техническую модель и не является юридической, бухгалтерской или отраслевой консультацией.
Что согласовать для внедрения
Сначала стоит проверить готовые возможности платёжного провайдера и уже используемой системы подписок. Готовый инструмент подходит, если он поддерживает нужный цикл, согласие, отмену, уведомления, доступные способы оплаты и обработку повторов. Собственная интеграция нужна, когда требуется связать платёжный объект с внутренней моделью доступа, особыми состояниями или действиями оператора.
Совместимость, тариф, права API и доступность конкретных функций проверяют отдельно для выбранного аккаунта и способа оплаты. Документация вендора подтверждает описанные возможности API, но не доказывает готовую интеграцию, партнёрство или выполненный проект Switch On AI.
Switch On AI может разработать ИИ-помощника, бота или обычную интеграцию для операции «продление и отмена подписки синхронизированы с платежами и доступом» после проверки данных и API. В этом сценарии основой обычно служит детерминированная интеграция. Бот может сообщать статус и передавать исключение человеку, а ИИ-помощник нужен только для согласованных задач со свободным текстом — он не должен самостоятельно подтверждать оплату.
На странице разработки чат-ботов и подключений описано, как отделить ответ пользователю от фактического результата в рабочей системе. Смежный материал о выдаче материалов через Telegram поможет разобрать канал доставки, но не заменяет платёжный биллинг.
Для прототипа достаточно выбрать одну операцию: подтверждённое продление, отмену или обработку отказа. Затем согласовать входные данные, состояния, контрольный пример и действия человека. Правила бухгалтерского, юридического и отраслевого учёта задаёт и проверяет специалист заказчика; работа с 1С в этот объём не входит.
Следующий шаг — обсудить жизненный цикл подписки и платёжного провайдера: описать одну операцию и согласовать прототип. Прототип проверяет понимание сценария, но не равен полному внедрению и не обещает заранее заданный эффект или срок.
Вопросы по этой задаче
Рекуррентный платёж и подписка — одно и то же?
Нет. Рекуррентный платёж — повторная платёжная операция, а подписка — бизнес-модель с периодом, состоянием, правилами отмены и сроком доступа. Платёжный провайдер обрабатывает деньги, а собственный биллинг связывает результат платежа с подпиской.
Что делать при отказе банка?
Проверить статус и причину в объекте платежа, не продлевать доступ как оплаченный и применить заранее согласованный ограниченный сценарий. Например, временно сохранить доступ, выполнить не более заданного числа повторов, уведомить пользователя и передать исключение человеку.
Как отменить продление без потери оплаченного доступа?
Разделить отмену будущих списаний и окончание текущего периода. Биллинг прекращает создавать новые платежи, но сохраняет access_until уже оплаченного периода. Возврат оформляется отдельно по правилам заказчика и возможностям провайдера.
