Тарифы и оплата

Просмотр доступных тарифов, создание и сопровождение платежа, история платежей. Платежи обрабатываются через AffiCat Pay. Подробнее о тарифах, продлении и льготном периоде — в разделе Оплата и тарифы.

Все эндпоинты этого раздела требуют авторизации (ваш API-ключ, см. Профиль и API-ключ). Эндпоинты оплаты работают без активной подписки — лапснувший аккаунт может оплатить тариф.

Каждый ответ — это HTTP 200 с Content-Type: application/json. Успех или ошибка определяются полем status в теле, а не HTTP-кодом. Ошибка всегда приходит в виде {"status":"error","error":"<код>"}. Поля времени — целые Unix-секунды (0, если не задано), а не строки с датой.


Список тарифов

GET /api/tariff/list.json

Возвращает все активные тарифы в порядке, заданном администратором. Каждая карточка дополнена предпросмотром начисления (proration): сколько дней даст покупка именно этого тарифа прямо сейчас с учётом остатка текущей подписки.

{
  "status": "ok",
  "data": [
    {
      "id": 1,
      "code": "kitten",
      "name": "Котёнок",
      "campaigns": 1,
      "price_usd": 0,
      "price_rub": 0,
      "days": 30,
      "broadcasts": false,
      "broadcasts_day": 0,
      "screens": false,
      "crm": false,
      "operators": 0,
      "until": 1748692800,
      "get_days": 30,
      "credit_days": 0
    },
    {
      "id": 2,
      "code": "cat",
      "name": "Котик",
      "campaigns": 15,
      "price_usd": 24,
      "price_rub": 2400,
      "days": 30,
      "broadcasts": true,
      "broadcasts_day": 1350,
      "screens": true,
      "crm": false,
      "operators": 0,
      "until": 1751284800,
      "get_days": 33,
      "credit_days": 3
    },
    {
      "id": 5,
      "code": "cattery",
      "name": "Котомник",
      "campaigns": 100,
      "price_usd": 135,
      "price_rub": 13500,
      "days": 30,
      "broadcasts": true,
      "broadcasts_day": 13500,
      "screens": true,
      "crm": true,
      "operators": 15,
      "until": 1751284800,
      "get_days": 31,
      "credit_days": 1
    }
  ]
}

data — это массив (пустой [], если тарифов нет).

ПолеЗначение
idЧисловой идентификатор тарифа. Именно его передают в tariff/buy
codeМашинный код тарифа
nameНазвание тарифа, локализованное по языку пользователя. Английское название отдаётся, только если язык — en и в тарифе заполнено английское поле; иначе возвращается русское название (русский — язык по умолчанию)
campaignsЛимит кампаний; -1 — без ограничения
price_usdЦена в долларах USD
price_rubЦена в рублях RUB
daysСрок подписки в днях
broadcastsДоступны ли рассылки
broadcasts_dayДневной лимит сообщений рассылок (0, если рассылки недоступны)
screensДоступны ли мультиэкранные приветствия
crmДоступен ли CRM-чат операторов
operatorsКоличество мест операторов CRM (0, если CRM недоступна)
untilПредполагаемая дата окончания подписки, если купить тариф сейчас (Unix-время)
get_daysСколько всего дней даст покупка с учётом остатка текущей подписки
credit_daysСколько из них зачтено из остатка текущей подписки (proration)
ОшибкаЗначение
dbОшибка базы данных

Купить тариф

POST /api/tariff/buy.json

Создаёт платёж по тарифу. Платный тариф создаёт счёт в AffiCat Pay и возвращает URL страницы оплаты — перенаправьте на него пользователя. Бесплатный тариф (цена 0 в обеих валютах) активируется мгновенно, без обращения к шлюзу, и URL не возвращается.

ПараметрОбязательныйОписание
tariffЧисловой идентификатор тарифа — поле id из списка тарифов. Это число, а не машинный код

Платный тариф — ответ содержит pay_id и url страницы оплаты:

{
  "status": "ok",
  "pay_id": 55,
  "url": "https://core.affi.cat/pay/abc123"
}

Бесплатный тариф — счёт сразу помечается оплаченным, URL не нужен:

{
  "status": "ok",
  "pay_id": 56,
  "free": true,
  "paid": true
}

url — это непрозрачная ссылка на страницу оплаты, которую вернул шлюз; конкретный хост может отличаться, не зашивайте его жёстко.

После оплаты подписка продлевается автоматически после подтверждения оплаты шлюзом. Оплата также может быть подтверждена через pay/check, когда пользователь возвращается со страницы оплаты — оба пути идемпотентны.

Накопление. Платные тарифы продлеваются от текущей даты окончания, а не от сегодняшнего дня: при досрочном продлении или переходе остаток пересчитывается в дни нового тарифа (см. поля get_days/credit_days). А вот бесплатный тариф ставится от сегодняшнего дня и не накапливается, поэтому он перебил бы ещё действующий платный период — такой переход блокируется (ошибка active, см. ниже).

ОшибкаЗначение
funcПараметр tariff отсутствует, равен 0 или указывает на несуществующий/скрытый тариф
busyПревышен лимит создания счетов (не более 20 за 60 секунд на пользователя)
activeПопытка взять бесплатный тариф, пока действующий платный имеет более 5 дней до окончания. Платные продления/переходы этим правилом не блокируются
payНе удалось создать счёт в AffiCat Pay (зависший счёт помечается неуспешным)
dbОшибка базы данных

Возобновить платёж

POST /api/pay/resume

Заново открывает страницу оплаты для собственного незавершённого (ожидающего) платежа и возвращает её URL. Позволяет завершить брошенный платёж без создания дубликата: шлюз сопоставляет счёт по магазину и uid, поэтому тот же pay_id всегда ведёт на ту же форму.

ПараметрОбязательныйОписание
uidpay_id существующего ожидающего платежа, принадлежащего вам
{
  "status": "ok",
  "pay_id": 55,
  "url": "https://core.affi.cat/pay/abc123"
}
ОшибкаЗначение
funcПараметр uid отсутствует/равен 0, либо платёж относится к бесплатному тарифу, у которого формы оплаты не было
busyПревышен лимит создания счетов (общий с tariff/buy: 20 за 60 секунд)
accessПлатёж не найден или принадлежит другому пользователю
statusПлатёж уже не в статусе ожидания (оплачен, отменён или возвращён) — возобновлять нечего
payНе удалось переоткрыть счёт в AffiCat Pay
dbОшибка базы данных

Отменить платёж

POST /api/pay/cancel

Помечает собственный ожидающий платёж как неуспешный (статус 2) — действие «Отмена» для брошенного счёта на экране оплаты. Неуспешный счёт уже нельзя превратить в оплаченный, поэтому поздний постбэк по отменённому счёту безопасно игнорируется.

ПараметрОбязательныйОписание
uidpay_id собственного ожидающего платежа
{
  "status": "ok",
  "pay_id": 55
}
ОшибкаЗначение
funcПараметр uid отсутствует или равен 0
accessПлатёж не найден, принадлежит другому пользователю или уже не в статусе ожидания
dbОшибка базы данных

Проверить статус платежа

GET /api/pay/check

Pull-подтверждение собственного платежа при возврате со страницы оплаты. Если платёж уже оплачен, возвращает paid: true; иначе опрашивает AffiCat и, если счёт оплачен, принимает его (продлевает подписку). Вызывается автоматически при возврате и идемпотентен с push-постбэком.

ПараметрОбязательныйОписание
uidpay_id собственного платежа (шлюз добавляет его к return URL)
{
  "status": "ok",
  "paid": true
}

paid равно false, если шлюз всё ещё сообщает, что счёт не оплачен.

ОшибкаЗначение
funcПараметр uid отсутствует или равен 0
accessПлатёж не найден или принадлежит другому пользователю
payНе удалось обратиться к AffiCat за статусом счёта
dbОшибка базы данных

История платежей

GET /api/pay/list.json

Возвращает историю ваших платежей, от новых к старым, с постраничной выборкой. Внутренние данные о расчёте (поступившая сумма, валюта, метаданные) не отдаются.

ПараметрОбязательныйОписание
limitРазмер страницы; по умолчанию 50, максимум 200
offsetСмещение от начала; значения меньше 0 приводятся к 0
{
  "status": "ok",
  "data": [
    {
      "id": 55,
      "tariff": 2,
      "usd": 24,
      "rub": 2400,
      "status": 1,
      "created": 1746111600,
      "paid": 1746111720
    }
  ]
}

data — это массив (пустой [], если платежей нет). Поле tariff — это числовой идентификатор тарифа (не код и не название). Поля created и paid — Unix-время в секундах; paid равно 0 для ожидающих и неоплаченных счетов.

statusЗначение
0Ожидает оплаты — счёт создан, оплата не подтверждена
1Оплачен
2Неуспешен или отменён — отклонён шлюзом, отменён пользователем либо брошен
3Возвращён
ОшибкаЗначение
dbОшибка базы данных