Перенос подписок нельзя свести к копированию идентификаторов из одной таблицы в другую. Платёжный токен обычно принадлежит конкретному провайдеру или мерчанту, а правила его передачи зависят от договора и способа токенизации. Дополнительно нужно согласовать статусы, календарь продлений, чеки, уведомления и возвраты.
Начните с инвентаризации: число активных подписок, валюты, тарифы, даты следующего списания, пробные периоды, задолженности и типы платёжных методов. До запуска получите от обоих провайдеров подтверждённую процедуру миграции токенов и юридические условия работы с согласием клиента.
Что проверить в первую очередь
Для проблемы «активные подписки нужно перенести между платёжными провайдерами» сначала зафиксируйте один воспроизводимый пример: точное время, идентификатор объекта, пользователя или операции, входные данные, версию приложения и фактический результат. Отдельно запишите ожидаемое поведение: каждая подписка имеет одного активного владельца списания, клиент заранее понимает изменения, а дата и сумма следующего платежа сохраняются или меняются только по явному правилу. Это не формальность. Без исходной точки легко принять временное совпадение за исправление, изменить сразу несколько условий и потерять возможность доказать настоящую причину сбоя.
Проверку начинайте с чтения состояния и журналов. Не запускайте массовый перерасчёт, повторную отправку, удаление записей или изменение прав на рабочей системе, пока не подготовлены резервная копия и способ отката. Секреты, токены, персональные данные и содержимое заказов в диагностические выгрузки не включайте.
- Разделите активные, приостановленные, отменённые, просроченные и пробные подписки.
- Уточните, может ли новый провайдер импортировать токены напрямую и кто выполняет защищённую передачу.
- Сверьте часовой пояс, валюту, период тарифа, налог и дату следующего списания.
- Проверьте открытые возвраты, dispute и уже созданные invoice у старого провайдера.
- Определите момент, после которого старый контур больше не инициирует новые списания.
Почему возникает проблема
Видимый симптом обычно находится в конце цепочки. Пользователь видит неверный статус или отказ, хотя первичная ошибка могла произойти в API, фоновой задаче, кеше, очереди, внешнем сервисе либо при проверке доступа. Основной риск этого сценария: двойное списание, пропуск продления, потеря доступа клиента или использование платёжного токена вне разрешённого сценария. Поэтому исправление только интерфейса или ручная правка итоговой записи часто скрывает проблему, но не устраняет её.
Разбирайте события по хронологии и ищите первую точку, где фактические данные перестают соответствовать бизнес-правилу. В распределённой системе одинаково важны успешный ответ, повтор запроса, задержка события, параллельное выполнение и восстановление после временного отказа.
- Оба планировщика остаются активными во время перехода и списывают один период дважды.
- Импортированный токен не поддерживает off-session платёж или требует нового подтверждения клиента.
- Статус past_due ошибочно превращается в active при загрузке.
- Новый календарь считает период от даты миграции, а не от оплаченной даты продления.
- Webhook двух провайдеров записываются в одну подписку без указания источника и поколения миграции.
Пошаговая диагностика
Создайте безопасный тестовый сценарий, максимально похожий на проблемный, но не затрагивающий реальные списания, рассылки и клиентские данные. Присвойте операции единый correlation ID и проследите его через входящий запрос, бизнес-логику, базу, очередь и внешние интеграции. Для каждого этапа фиксируйте вход, результат, код ответа, время выполнения и номер версии записи.
Сначала подтвердите сам факт расхождения, затем последовательно исключайте уровни. Сравните рабочий и ошибочный случаи по одним и тем же полям. Проверьте часовой пояс, формат идентификаторов, порядок событий, права сервисной учётной записи и актуальность конфигурации на каждом экземпляре приложения. Если результат зависит от повторного запроса, задержки или конкретного узла, это важная часть причины, а не случайный шум.
- Постройте таблицу соответствия old subscription ID, new subscription ID, customer ID и payment token reference.
- Сверьте ближайшие две даты списания и уже оплаченный период для каждой группы тарифов.
- Проверьте тестовый импорт токенов и реальный ответ о возможности последующего рекуррентного платежа.
- Проследите webhook success, failed, refund и chargeback от обоих источников.
- Найдите подписки, у которых одновременно существуют активные расписания у двух провайдеров.
Как организовать управляемую миграцию подписок
Для каждой подписки нужен явный migration state: подготовлена, токен импортирован, проверена, переключена, старое расписание закрыто или требуется действие клиента. Источник, который имеет право инициировать следующее списание, должен определяться однозначно.
Надёжная реализация хранит бизнес-состояние явно и не пытается восстановить его только по экрану, случайному логу или последнему webhook. У каждого значимого действия должен быть стабильный идентификатор, понятный владелец, версия правила и проверяемый переход статуса. Повторная доставка одного события не должна создавать второе действие, а запоздавшее событие не должно возвращать объект в невозможное состояние.
- Каноническая подписка хранится в вашей системе, а идентификаторы провайдеров являются привязанными внешними ссылками.
- Переход выполняется пакетами с контрольной группой и отдельным отчётом по каждой строке.
- Ключ идемпотентности строится из подписки и оплачиваемого периода, а не из попытки конкретного шлюза.
- Старые webhook принимаются для возвратов и dispute, но не возобновляют закрытое расписание.
- Подписки без переносимого токена переводятся в прозрачный сценарий повторной привязки карты.
Как исправить проблему
Исправление разделите на небольшие обратимые изменения. Сначала устраните подтверждённую первопричину, затем восстановите повреждённые данные отдельной контролируемой процедурой. Не смешивайте выпуск нового кода и массовую коррекцию истории в одном непрозрачном запуске: для них нужны разные отчёты, критерии успеха и планы отката.
Если затронуты существующие записи, сначала сформируйте dry-run: список объектов, старое значение, предлагаемое новое значение и основание для изменения. Обновление должно быть идемпотентным, ограниченным точной выборкой и сопровождаться аудитом. Для финансовых данных, прав доступа и персональной информации предпочтительны компенсирующие записи, а не переписывание истории.
- Добавьте migration state и блокировку конкурентного запуска двух планировщиков.
- Переносите токены только по официальному защищённому каналу провайдеров, не через CSV и не через журналы.
- Сохраните исходную дату продления и версию тарифа либо заранее уведомите клиента об изменении.
- Разделите обработчики webhook по provider ID и проверяйте подпись до изменения статуса.
- Подготовьте повторную авторизацию для неподдерживаемых платёжных методов без преждевременного отключения доступа.
Безопасный порядок внедрения
- Сохраните конфигурацию, связанные записи и необходимые журналы; отдельно проверьте, что резервную копию действительно можно восстановить.
- Воспроизведите проблему на тестовом объекте и сохраните результат до изменения, чтобы после выпуска сравнить одинаковые сценарии.
- Внесите минимальное изменение под системой контроля версий, опишите причину, ожидаемый эффект, ограничения и точный способ отката.
- Прогоните нормальный сценарий, ошибочный ввод, повтор одного запроса, два параллельных запроса и временную недоступность зависимости.
- Выпустите изменение на ограниченную долю трафика или один процесс, если архитектура это позволяет, и сравните метрики со старой версией.
- Только после стабильного наблюдения выполните контролируемое исправление исторических данных и сохраните итоговый отчёт.
Как проверить результат
Один успешный пример недостаточен. Проверьте основную операцию повторно, крайние значения, одновременные действия, перезапуск процесса и восстановление после краткого сбоя сети. Результат подтверждайте не только экраном пользователя, но и состоянием базы, очереди, внешнего сервиса и журналом аудита. Особое внимание уделите тому, что система делает при повторной доставке уже обработанного события.
Критерии приёмки сформулируйте до выпуска. Каждый пункт должен давать однозначный ответ «выполнено» или «не выполнено», а не субъективную оценку. Если тест невозможно повторить автоматически, оставьте короткий регрессионный чек-лист с тестовыми данными и ожидаемыми статусами.
- Контрольная подписка продлевается новым провайдером ровно один раз и на правильную сумму.
- Старая система после cutover не создаёт новый charge, но корректно сообщает о позднем возврате.
- Неуспешный импорт оставляет подписку в прежнем рабочем контуре.
- Повтор запуска миграции не создаёт вторую подписку и не меняет уже подтверждённую дату.
- Отмена, пауза, смена тарифа и возврат во время перехода дают согласованные статусы.
Типичные ошибки при исправлении
- Копировать необратимые платёжные данные самостоятельно без процедуры провайдера.
- Переключать все подписки одним запуском без контрольной группы и сверки.
- Обнулять paid_until и начинать период с даты миграции.
- Считать импорт токена гарантией будущего списания без теста возможностей.
- Отключать старые webhook до завершения возвратов и chargeback.
Опаснее всего исправление, которое убирает заметный симптом ценой отключения проверки, ослабления прав или потери аудита. Такое изменение может сделать интерфейс «зелёным», но увеличить ущерб при следующем сбое. Если временный обход всё же необходим, ограничьте его срок, пользователей и область действия, добавьте мониторинг и заранее назначьте дату удаления.
Как предотвратить повторение
Профилактика строится вокруг явных контрактов, идемпотентных обработчиков, наблюдаемости и повторяемых релизов. Система должна не только корректно работать сейчас, но и быстро показывать нарушение правила после обновления, роста нагрузки или отказа интеграции. Ошибку, которая уже привела к потере времени, денег, данных или заявок, стоит закрепить автоматическим тестом.
Настройте мониторинг полного пользовательского пути, а не только доступности отдельных серверов. Техническая метрика должна быть связана с бизнес-результатом: заказ завершён, доступ выдан, файл восстановлен, событие обработано один раз, данные изолированы. Порог оповещения задавайте по нормальному профилю нагрузки и проверяйте, что уведомление содержит достаточно контекста для первого решения.
- Количество подписок на каждом migration state и возраст незавершённого перехода.
- Двойные списания и совпадение периода у charge разных провайдеров.
- Доля токенов, требующих повторной привязки или подтверждения.
- Успешность первого продления после миграции относительно контрольной группы.
- Расхождение между каноническим доступом и состоянием подписки у провайдера.
Что подготовить для технического разбора
- Короткое описание ожидаемого и фактического поведения с точной последовательностью действий.
- Время возникновения, идентификатор тестового объекта и версии всех затронутых компонентов.
- Обезличенные фрагменты журналов до и после ошибки с единым correlation ID.
- Список последних изменений, результаты уже выполненных проверок и условия, при которых симптом исчезает.
- Безопасный доступ к тестовой среде либо минимальный пример, не содержащий паролей, токенов и персональных данных.
Частые вопросы
Можно ли перенести токены карт самостоятельно?
Обычно нет. Передача выполняется провайдерами по согласованной защищённой процедуре и зависит от модели токенизации и договора.
Нужно ли просить клиента снова вводить карту?
Если токен нельзя перенести или новое списание требует подтверждения, нужен понятный сценарий повторной привязки.
Как избежать двойного списания?
Хранить одного владельца следующего периода, использовать общий ключ идемпотентности и проверять отсутствие активного расписания у старого провайдера.
Когда нужна помощь специалиста
Если требуется перенести действующие подписки, я могу подготовить карту статусов, процедуру cutover, идемпотентность, обработку webhook и отчёт сверки. Для оценки нужны обезличенная выборка подписок, правила тарифов и документация обоих платёжных провайдеров.