Процесс оплаты заказа

API публичной оплаты

Документация для внешних разработчиков: веб-страница оплаты, Telegram Web App, мобильное приложение или любой другой HTTP-клиент.

API позволяет провести прямую оплату через платёжную систему (карта, СБП и т.д.). Списание внутреннего баланса бота через эту форму не поддерживается.

Интерактивная спецификация OpenAPI доступна по адресу {API_BASE}/docs/ (раздел «Оплата (публично)»).


Общие сведения

ПараметрЗначение
МетодPOST для всех запросов
Базовый URL{API_BASE}/v1/payment/order/{действие}
ЗаголовокContent-Type: application/json
Авторизацияне требуется (ни токен бота, ни ключ пользователя)
Лимит120 запросов в минуту с одного IP

Подставьте свой хост API вместо {API_BASE}, например https://api.example.com.

Формат ответа

Успех:

{
  "result": true,
  "data": { ... }
}

Ошибка:

{
  "result": false,
  "message": "текст ошибки"
}

Перед использованием поля data всегда проверяйте result === true.


Идентификатор оплаты (order_id)

В каждом запросе передаются bot_id (число) и order_id (строка).

ФорматЧто оплачиваетсяПримерОткуда взять
o-{число}Заказ магазинаo-123321Ссылка на оплату, API магазина
c-{число}Заказ корзиныc-456После оформления заказа из корзины
p-{число}Платёж по сообщению бота (тип «Оплата»)p-789Сценарий бота / ссылка вида p-{номер}

Условия доступа:

  • заказ с таким номером существует;
  • bot_id совпадает с ботом, к которому относится заказ;
  • заказ ожидает оплаты (см. раздел «Статус заказа»).

Статус заказа

Проверка выполняется во всех методах.

Если заказ уже оплачен (или иным образом не ожидает оплату), API вернёт ошибку:

{
  "result": false,
  "message": "Заказ уже оплачен"
}

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

При успешном get-status заказ всегда в состоянии ожидания:

{
  "result": true,
  "data": {
    "status": "wait",
    "order_id": "o-123321",
    "amount": 150000
  }
}

Поле amount — сумма в минимальных единицах валюты (копейки, центы). Для отображения разделите на 100.


Сценарий для интерфейса

sequenceDiagram
    participant UI as Ваш клиент
    participant API as API оплаты

    UI->>API: get-status
    alt result=false (уже оплачен)
        UI->>UI: Экран «Заказ уже оплачен»
    else result=true, status=wait
        UI->>API: get-groups
        UI->>API: get-items (group_id)
        UI->>API: get-pay-data (item_id)
        UI->>UI: Форма / редирект на оплату
        loop Пуллинг после оплаты
            UI->>API: check-pay или get-status
        end
    end

Пошагово

  1. Входные данные — из URL или конфигурации: bot_id, order_id. Без них оплату не начинать.

  2. get-status — первая загрузка страницы. При ошибке «Заказ уже оплачен» — экран успеха, без мастера оплаты.

  3. get-groups — список групп способов оплаты (карты, СБП…). Пользователь выбирает группу → запомните group_id.

  4. get-items — способы оплаты в группе. Для карточек UI используйте поля вроде design.title, design.text_button. Пользователь выбирает способ → item_id.

  5. get-pay-data — экран оплаты. Сервер фиксирует выбранный способ. Смотрите data.dataPay.type (таблица ниже).

  6. После ухода на оплату — периодически вызывайте check-pay или get-status, пока оплата не подтвердится или не истечёт таймаут.

  7. Отмена — по кнопке «Назад» можно вызвать cancel (данные для навигации в ответе).


Методы

Базовый путь: POST /v1/payment/order/{действие}

ДействиеНазначение
get-statusСумма и проверка, что заказ ждёт оплаты
get-groupsГруппы способов оплаты
get-itemsСпособы оплаты в выбранной группе
get-pay-dataДанные для экрана оплаты
set-pay-inputСохранить ввод пользователя (тип оплаты 2)
check-payЗапросить статус у платёжной системы
cancelОтменить сценарий оплаты

POST /v1/payment/order/get-status

Проверить, можно ли начать оплату, и получить сумму.

Тело запроса

ПолеОбяз.ТипОписание
bot_idдаintegerID бота
order_idдаstringo-…, c-… или p-…

Пример

{
  "bot_id": 1,
  "order_id": "o-123321"
}

Успех (data)

ПолеТипОписание
statusstringВсегда "wait" при успехе
order_idstringПереданный идентификатор
amountintegerСумма в минимальных единицах валюты

POST /v1/payment/order/get-groups

Список групп способов оплаты.

Тело запроса — как у get-status.

Успех (data)

ПолеТипОписание
order_idstringИдентификатор оплаты
amountintegerСумма
groupsarrayГруппы

Элемент groups[]

ПолеТипОписание
idintegerID группы (для get-items)
titlestringНазвание
text_choosestringПодсказка при выборе
sortintegerПорядок сортировки

POST /v1/payment/order/get-items

Способы оплаты внутри группы.

Тело запроса

ПолеОбяз.ТипОписание
bot_idдаintegerID бота
order_idдаstringИдентификатор оплаты
group_idдаintegerID группы из get-groups

Пример

{
  "bot_id": 1,
  "order_id": "c-456",
  "group_id": 5
}

Успех (data)

ПолеТипОписание
order_idstringИдентификатор оплаты
amountintegerСумма
itemsarrayСпособы оплаты

Каждый элемент items[] — публичное описание способа (название, текст кнопки, оформление). Секретные ключи платёжных систем не передаются.


POST /v1/payment/order/get-pay-data

Данные для экрана оплаты после выбора способа.

Тело запроса

ПолеОбяз.ТипОписание
bot_idдаintegerID бота
order_idдаstringИдентификатор оплаты
item_idнетintegerID способа из get-items

Пример

{
  "bot_id": 1,
  "order_id": "p-789",
  "item_id": 42
}

Успех (data) — основные поля

ПолеТипОписание
statusstring"wait"
idstring/integerВнутренний ID для отображения
amountintegerСумма
button_cancel_paystring | nullТекст кнопки отмены
button_check_paystring | nullТекст кнопки «Проверить оплату»
userContactsnullВ веб-API всегда null
itemobjectВыбранный способ оплаты
dataPayobject | nullИнструкции для UI (см. ниже)

Ошибка: если способ требует email/телефон для чека — result: false с текстом о выборе другого способа или оплате в Telegram-боте.


POST /v1/payment/order/set-pay-input

Нужен, когда dataPay.type === 2: пользователь вводит текст (номер карты отправителя, комментарий и т.п.).

Тело запроса

ПолеОбяз.ТипОписание
bot_idдаintegerID бота
order_idдаstringИдентификатор оплаты
item_idдаintegerID способа оплаты
input_valueда*stringВведённый текст
textнетstringАльias для input_value (устаревший)

* Обязателен input_value или text.

Пример

{
  "bot_id": 1,
  "order_id": "o-123321",
  "item_id": 42,
  "input_value": "текст от пользователя"
}

Успех (data)

{
  "saved": true,
  "message": "Данные сохранены. Вызовите get-pay-data с тем же item_id."
}

После успеха снова вызовите get-pay-data с тем же item_id.


POST /v1/payment/order/check-pay

Проверить у платёжной системы, прошла ли оплата (аналог кнопки «Проверить оплату» в боте).

Тело запроса — как у get-status.

Успех (data)

ПолеТипОписание
payment_foundbooleantrue — оплата найдена
payment_urlstringОпционально: ссылка для повторной оплаты (отдельные платёжки)

Если payment_found === true, можно показать экран успеха или снова вызвать get-status (ожидается ошибка «Заказ уже оплачен» после обработки webhook).


POST /v1/payment/order/cancel

Отменить сценарий оплаты (кнопка «Назад»).

Тело запроса — как у get-status.

Успех (data)

ПолеТипОписание
redirect_actionstringИдентификатор действия для навигации
redirect_dataobjectДополнительные данные для навигации

Поле dataPay — что показывать пользователю

typeПоведение
0Только текст: показать dataPay.text
1Ссылка: кнопка/ссылка на dataPay.link
2Поле ввода по label_input и rules_inputset-pay-input → снова get-pay-data
3, 4, 8В ответе requires_telegram: true — завершить оплату можно только в Telegram-боте
6Открыть Web App: dataPay.web_app
7, 9На сайте не поддерживается — API вернёт ошибку ещё на этапе get-pay-data

Дополнительные поля dataPay:

ПолеОписание
textПоясняющий текст
linkURL оплаты
web_appURL Telegram Web App
label_inputПодпись поля ввода (type 2)
rules_inputПравила валидации ввода
is_button_checkЕсли true — показывать кнопку проверки оплаты
requires_telegramСпособ нельзя завершить на сайте
requires_telegram_hintТекст подсказки для пользователя
next_actionДля type 2: "set-pay-input"
next_action_hintПодсказка по следующему запросу
qr_image_urlURL QR-кода (если есть)

Если заданы button_check_pay и dataPay.is_button_check === true, по нажатию вызывайте check-pay.


Типовые ошибки

Ситуацияmessage (пример)
Неверный формат order_idДопустимы только o-{id}, c-{id} или p-{id}
Заказ не найденnot found
bot_id не совпадает с ботом заказаnot_access (public_bot)
Заказ уже оплаченЗаказ уже оплачен
Нет настроенных способов оплатыСоздатель бота не настроил ни одного способа оплаты
Способ с чеком (email/телефон)Текст про другой способ или оплату в Telegram
Сумма вне лимитов группыТекст с минимальной/максимальной суммой
Внутренняя ошибка сервераПроизошла внутренняя ошибка

Откуда берётся order_id

ТипКак получить
o-{id}После создания заказа в магазине; часто передаётся в ссылке на страницу оплаты
c-{id}После оформления заказа из корзины (API корзины, метод создания заказа)
p-{id}При переходе пользователя к оплате сообщения бота с типом «Оплата»

Чек-лист интеграции

  • Страница принимает bot_id и order_id из URL или конфигурации.
  • Все запросы: POST, JSON, заголовок Content-Type: application/json.
  • В каждом теле есть bot_id и order_id.
  • Первая загрузка: get-status; обработка «Заказ уже оплачен».
  • Цепочка: get-groupsget-itemsget-pay-data.
  • Рендер по dataPay.type; для type 2: set-pay-inputget-pay-data.
  • Обработка ошибки способа с чеком на get-pay-data.
  • Подсказка про Telegram для requires_telegram.
  • Кнопка «Проверить оплату» → check-pay.
  • Сумма в интерфейсе: amount / 100 (с учётом валюты проекта).