Коротко
Подписка — это автоматическое выставление счетов по расписанию. Деньги со счёта покупателя сами не уходят: каждую оплату он подтверждает в Kaspi сам. Поэтому «подписка не работает» означает две разные вещи — счёт вообще не создался или счёт создался, но покупатель его не оплатил. Начните с полей lastRunStatus и lastError: ответ обычно именно там.
Симптом → причина → решение
| Симптом | Причина | Решение |
|---|---|---|
| Счёт вообще не появился | Подписка в статусе paused или closed | Проверьте статус, при необходимости сделайте resume |
| Время пришло, счёта нет | Следующий запуск назначен на другое время | Посмотрите время следующего запуска |
| Счёт появился с опозданием | Идёт лестница ретраев | Проверьте значения retryDelaysMin |
| Один запуск пропущен полностью | misfirePolicy: skip | Поставьте политику run_once |
В lastError ошибка привязки Kaspi | Сессия кассира оборвалась | Переподключите: Кассир Kaspi не подключается |
В lastError лимит тарифа | Кончился месячный лимит | Достигнут лимит |
| Счета выставляются, денег нет | Покупатели не оплачивают | Это не ошибка, оплата на стороне покупателя |
Что читать в первую очередь
У самой подписки есть три поля для диагностики:
| Поле | Что показывает |
|---|---|
lastRunStatus | Результат последнего запуска |
lastError | Если неудачно — конкретный код ошибки |
failedRuns | Сколько запусков подряд оказались неудачными |
Код в lastError объясняет всё остальное. Например kaspi_session_expired — проблема в кассире, tariff_limit_reached — в тарифе, invalid_phone — в данных покупателя.
Шесть проверок
1. Статус подписки
Статусов три: active, paused, closed.
paused— приостановлена. Запуски не идут. Включается черезPOST /subscriptions/{id}/resume.closed— завершена или остановлена. Её нельзя включить обратно, нужно создать новую (иначе придётsubscription_closed).
Подписка может стать closed сама, если исчерпано заданное максимальное число запусков.
2. Время следующего запуска
В расписании два параметра: интервал (day, week, month) и кратность every. Например month + every: 2 — раз в два месяца.
Частое недоразумение: ожидание, что счёт появится сразу в момент создания подписки. Расписание отсчитывается от времени первого запуска, а он может быть не сегодня. Время следующего запуска смотрите в карточке подписки или в ответе GET /subscriptions/{id}.
3. Лестница ретраев
Если запуск оказался неудачным, подписка не останавливается сразу — она пробует ещё раз по лестнице ретраев. По умолчанию retryDelaysMin: [15, 60, 360] минут: через 15 минут, потом через час, потом через шесть часов. Максимум 5 значений.
Пока лестница не пройдена, со стороны кажется, что счёт просто не выставляется. В это время lastError уже заполнен — причину читайте оттуда.
Когда лестница закончилась, этот запуск отбрасывается, но расписание продолжается: следующий плановый запуск пойдёт в своё время. Счётчик failedRuns при этом растёт.
4. Политика пропуска
Если момент запуска по какой-то причине был пропущен, что делать дальше, решает misfirePolicy:
| Значение | Что происходит |
|---|---|
run_once (по умолчанию) | Пропущенный запуск выполняется один раз позже |
skip | Пропущенный запуск не выполняется вовсе |
misfireAfterMin — через сколько минут запуск считается пропущенным, по умолчанию 1440 (сутки).
Если у вас стоит skip, пропущенный счёт не появится вообще — это не сбой, так настроено.
Чтобы отправить пропущенный запуск вручную: POST /subscriptions/{id}/resume с телом { "catchUp": true }.
5. Активен ли кассир
Подписка запоминает, через какого кассира она создана. Если привязка Kaspi у этого кассира оборвалась, запуск не сможет создать счёт.
Сценарий встречается часто: кто-то заходит с номера кассира в приложение Kaspi Pay, сессия обрывается, а подписка молча пишет ошибку в lastError. Проверка: кабинет → раздел Kaspi, активна ли привязка. Подробнее: Кассир Kaspi не подключается.
6. Лимит тарифа
Когда месячный лимит исчерпан, подписка тоже не может создать новый счёт — он считается как обычный. В lastError будет tariff_limit_reached.
Если подписок много, заложите их месячный объём заранее при выборе тарифа: Какой тариф выбрать.
Что чаще всего понимают неправильно
Подписка не забирает деньги со счёта покупателя сама. Она только выставляет счёт, покупатель видит его в Kaspi и подтверждает оплату сам. Отсюда следует:
- Если счёт выставлен, а покупатель не платит — подписка работает правильно
- Лестница ретраев неплательщика не спасёт: она рассчитана на случай, когда счёт не создался, а не когда он не оплачен
- Напоминать о неоплаченной подписке нужно со своей стороны
Подробнее: Бизнес по подписке.
Вопросы и ответы
Если остановить подписку, пропадут ли уже выставленные счета? Нет. Ранее созданные счета живут своей жизнью: будут оплачены, отменены или истекут.
Можно ли изменить лестницу ретраев? Да, через поле retryDelaysMin, максимум 5 значений. По умолчанию [15, 60, 360] минут.
Можно ли отправить пропущенный запуск вручную? Да: POST /subscriptions/{id}/resume с телом { "catchUp": true }.
Можно ли включить подписку со статусом closed? Нет, придёт ошибка subscription_closed. Создайте новую подписку.
Можно ли поменять кассира, через которого идёт подписка? Подписка запоминает кассира на момент создания. Если кассир меняется, правильнее создать новую подписку.
Где полное описание всех полей? На странице API подписок.