Процесс оформления и оплаты заказа

API публичного магазина (shoppublic)

Документация для внешних клиентов: сайт, Telegram Web App, мобильное приложение. Хост API: api.bot-t.com. Создание заказа — анонимно (https://api.bot-t.com/v1/shoppublic/order/create) или для пользователя бота (https://api.bot-t.com/v1/shoppublic/order/create-user + secret_user_key). Выдача после оплаты: https://api.bot-t.com/v1/shoppublic/order/get-product + orderKey или https://api.bot-t.com/v1/shoppublic/order/get-product-user + secret_user_key.


Полная документация API на сайте: Getting Started. См. также: процесс оплаты заказа, заказы магазина (владелец).


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

ПараметрЗначение
МетодPOST для всех запросов
Хост APIapi.bot-t.com (всегда этот домен)
Базовый URLhttps://api.bot-t.com/v1/shoppublic/{контроллер}/{действие}
ЗаголовокContent-Type: application/json
Тип ботаSHOP или SHOP_CART (для корзины см. оформление через корзину)
Лимит (общий)120 запросов в минуту с IP
Лимит order/create1/мин, 10/час, 100/сутки с IP

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

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

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


Авторизация по категориям методов

КатегорияОбязательные поляТокен бота
Магазин, витринаbot_idне нужен
Заказы (create, get-product)bot_id; для выдачи — order_id, order_key / orderKeyне нужен
Заказы (create-user, get-product-user)bot_id, user_id, secret_user_key; для выдачи — order_idне нужен
Промокодыbot_id, user_id, secret_user_keyне нужен
Засчитать оплату / товар для CRMshop/order/* + токен ботатолько backend, не веб — см. API владельца

user_id — это bots_bot_user.id, не Telegram ID. secret_user_key берётся из API пользователя бота (например POST https://api.bot-t.com/v1/bot/user/view-by-telegram-id).

Важно: для гостевого заказа (create) выдача только через https://api.bot-t.com/v1/shoppublic/order/get-product + orderKey. Для Web App (create-user) можно также https://api.bot-t.com/v1/shoppublic/order/get-product-user с теми же user_id и secret_user_key (без сохранения orderKey). Подробнее — выдача товара.


Каталог методов

Публичный магазин — магазин

POST https://api.bot-t.com/v1/shoppublic/shop/info

ПолеОбяз.Описание
bot_idдаID бота

Ответ data: { "help": string, "rules": string } — тексты справки и правил.


Публичный магазин — витрина

Базовый префикс: POST https://api.bot-t.com/v1/shoppublic/category/

ДействиеНазначение
viewДочерние категории и товары для витрины (category_id=0 — корень)
getОдна категория/товар по category_id (полный ShopCategoryDto)
allsПлоский список всех категорий (мини-DTO)
allHTML-текст витрины (как в боте)

view

ПолеОбяз.Описание
bot_idдаID бота
category_idнет0 или не передан — корень; для папки (type=0) обязателен ID папки

get

ПолеОбяз.Описание
bot_idдаID бота
category_idдаID категории или товара

Ошибка method supported only type = 0 — для view передана категория не-папки (нужен товар или корень).


Публичный магазин — промокоды

Базовый префикс: POST https://api.bot-t.com/v1/shoppublic/coupon/

Требуют bot_id, user_id, secret_user_key.

ДействиеНазначение
find-activeАктивный промокод пользователя в магазине
activatedАктивировать по строке code
deactivatedСнять активный промокод

Промокод применяется при расчёте заказа в боте; для анонимного order/create сценарий купонов на сайте обычно не используется (создание заказа без user_id).


Публичный магазин — заказы

Базовый префикс: POST https://api.bot-t.com/v1/shoppublic/order/

ДействиеНазначение
createСоздать заказ без пользователя (гостевой сайт)
create-userСоздать заказ для пользователя бота (Web App, авторизованный покупатель)
get-productВыдача товара после оплаты (order_id + orderKey)
get-product-userВыдача товара для заказа пользователя (order_id + user_id + secret_user_key)

Полный сценарий: от витрины до товара

sequenceDiagram
    participant UI as Ваш клиент
    participant SP as shoppublic
    participant Pay as payment/order
    participant Ext as Внешняя оплата / ЛК

    UI->>SP: shop/info, category/view
    UI->>SP: order/create
    Note over UI: Сохранить id, orderKey, amount
    alt Встроенная оплата BOT-T
        UI->>Pay: get-status (order_id=o-{id})
        UI->>Pay: get-groups → get-items → get-pay-data
        UI->>Pay: check-pay / webhook
    else Внешняя оплата
        Ext->>Ext: Свой платёжный шлюз
        Ext->>Ext: success-order или webhook BOT-T
    end
    UI->>SP: order/get-product
    UI->>UI: Показать product[]

Пошагово

  1. Витринаcategory/view / category/get, при необходимости shop/info.
  2. Создание заказаorder/create (гость) или order/create-user (есть user_id + secret_user_key из Web App).
  3. Сохранить из ответа: data.id, data.orderKey, data.amount, data.status (ожидается 0 — WAIT).
  4. Оплата — один из вариантов ниже.
  5. Выдачаorder/get-product (или get-product-user для Web App) после статуса ACTIVE (1).
  6. Показать пользователю массив { id, product }[].

Какой метод создания выбрать

СитуацияМетод
Сайт без входа, гостевая покупкаorder/create
Telegram Web App, есть user_id и secret_user_keyorder/create-user
Магазин с корзинойshopcart/order/create, не shoppublic

Создание заказа

Тело запроса

ПолеОбяз.ТипОписание
bot_idдаintegerID бота
category_idдаintegerID товара (категории с товаром)
countнетintegerКоличество, ≥ 1, по умолчанию 1

Пример

{
  "bot_id": 1,
  "category_id": 42,
  "count": 1
}

Успех (data) — объект заказа ShopOrderDto плюс:

ПолеОписание
orderKeyСекрет выдачи: HMAC-SHA256(order_id, токен_бота). Сохраните на клиенте (localStorage, сессия, QR). Без него get-product недоступен.

Ограничения

  • Категории типа «Подарок» и «Подарок файлом» — ошибка: недоступны для анонимного заказа.
  • user_id в заказе будет null (анонимная покупка).
  • Статус после создания: WAIT (0) — ожидает оплаты, товар забронирован.

Поле product в ответе create

До оплаты часто product.type = "pay" и product.data — ссылка/deep-link на оплату, а не сам товар. Содержимое купленных позиций — только через get-product после оплаты.

Ссылка на оплату в Telegram

https://t.me/{username_бота}?start=o_{order_id}

Идентификатор для API оплаты

o-{order_id}

Пример: заказ 1001o-1001.


Варианты оплаты

1. Встроенные способы BOT-T (рекомендуется для сайта)

Публичный API оплаты: POST https://api.bot-t.com/v1/payment/order/{действие} (см. процесс оплаты заказа, методы: статус, данные для оплаты, проверить оплату).

ПараметрЗначение для заказа магазина
bot_idID бота
order_ido-{id} — ID из order/create

Цепочка: get-statusget-groupsget-itemsget-pay-data → (при type 2: set-pay-input) → check-pay или polling get-status.

После успешного webhook/проверки заказ переходит в ACTIVE, можно вызывать get-product.

Списание внутреннего баланса бота через этот публичный API оплаты не поддерживается (только платёжные системы).

2. Внешняя оплата с засчитыванием в BOT-T

Если оплата проходит вне формы payment/order (свой эквайринг, банк, крипта, ручной перевод):

СпособКто вызываетAPI
Webhook платёжной системыBOT-T (автоматически)Настроенный URL платёжки в ЛК; формат order_id: {code}-{order_id}-{item_id}
Ручное подтверждениеТолько ваш backendPOST https://api.bot-t.com/v1/shop/order/success-order с токеном бота — см. раздел ниже
Модуль веб-магазинаВаш backend модуляPOST https://api.bot-t.com/v1/module/shop/order-create + своя логика оплаты (другой сценарий, с привязкой пользователя)

Для анонимного заказа shoppublic уведомление в Telegram может быть недоступно (Нет telegram_id для заказа при send-message) — выдача покупателю на сайте через https://api.bot-t.com/v1/shoppublic/order/get-product.

3. Сравнение

Встроенная (payment/order)Внешняя + success-order / webhook
Авторизация клиентатолько bot_idwebhook — сервер; success-order — токен владельца
UI оплатыBOT-T (карты, СБП, …)Ваш
Подтверждениеcheck-pay, webhooksuccess-order или webhook
order_id в оплатеo-{id}тот же в webhook

API владельца: токен бота (только сервер)

Префикс: POST https://api.bot-t.com/v1/shop/order/ — это приватный API владельца магазина, не публичный shoppublic.

Документация на сайте: заказы магазина, Getting Started — ключи.

⚠️ Нельзя вызывать из веба (браузера)

ЗапрещеноПочему
JavaScript на странице сайта, Telegram Web App, мобильное приложениеВ query попадает токен бота или secretKey — полный доступ к магазину и заказам
Прокси «через свой API без проверки» с токеном в открытом конфиге фронтаТокен утечёт в DevTools, исходниках, логах

Разрешено: ваш backend (PHP, Node, cron), сервер интеграции, webhook-обработчик на VPS. Токен храните в переменных окружения / секретах сервера.

Публичная витрина и покупатель используют только shoppublic + payment/order + orderKey. Токен бота к ним не подмешивайте.

Авторизация

ПараметрГдеОписание
bot_idтело JSONID бота
botToken или tokenquery (рекомендуется) или телоТокен бота из ЛК
secretKeyqueryСекретный ключ бота (альтернатива токену)

Достаточно одного способа: botToken или secretKey.

Пример URL:

POST https://api.bot-t.com/v1/shop/order/success-order?botToken=123456789:ABC...
Content-Type: application/json

{"bot_id": 1, "order_id": 1001}

Засчитать оплату и выдать товар

Подтверждает оплату вручную (как кнопка в ЛК): WAITACTIVE, списывает товар со склада, фиксирует выданные строки в заказе.

Тело

ПолеОбяз.Описание
bot_idдаID бота
order_idдаЧисловой ID заказа из https://api.bot-t.com/v1/shoppublic/order/create (data.id)

Пример

{
  "bot_id": 1,
  "order_id": 1001
}

Поведение

  • Только заказ в статусе WAIT (0). Иначе: Заказ уже оплачен.
  • После успеха заказ ACTIVE (1) — можно отдавать товар покупателю.
  • Для категории «Услуга» статус может стать WAIT_USER (6) — уточняйте status в ответе.

Типовой сценарий (внешняя оплата)

sequenceDiagram
    participant Site as Сайт (публично)
    participant Backend as Ваш сервер
    participant API as API BOT-T

    Site->>API: shoppublic/order/create
    Site->>Site: Оплата у вас (эквайринг)
    Site->>Backend: Webhook «оплачено», order_id
    Backend->>API: shop/order/success-order?botToken=...
    Note over Site: Покупателю — get-product + orderKey
    Backend->>API: shop/order/view?botToken=... (опционально)
  1. Сайт создаёт заказ через https://api.bot-t.com/v1/shoppublic/order/create (без токена).
  2. После подтверждения оплаты ваш сервер вызывает https://api.bot-t.com/v1/shop/order/success-order.
  3. Покупателю на сайте отдайте товар через https://api.bot-t.com/v1/shoppublic/order/get-product (order_id + orderKey из шага 1).

Получить содержимое товара по токену бота

Возвращает заказ, в том числе выданный товар в поле product (строка, несколько позиций через перевод строки).

Тело: bot_id, order_id.

Когда использовать

  • Проверка на backend после success-order.
  • CRM, админка, своя выдача (email, API партнёра) — не отдавайте ответ view напрямую в браузер покупателю (там же чувствительные данные заказа).

Фрагмент ответа (status = 1)

{
  "id": 1001,
  "status": 1,
  "product": "ключ-строка-1\nключ-строка-2",
  "price": {
    "sum": "150.00 ₽",
    "balance_type_id": "API",
    "currency": "RUB"
  },
  "telegram_id": null,
  "coupon": null
}
ПолеОписание
productВыданные строки товара (пусто или ссылка на оплату, пока заказ не оплачен)
status0 — ещё ждёт оплату; 1 и выше — оплачен / в обработке

Дополнительно: find-by-shop-product — поиск заказа по точному тексту выданной строки (тоже только с токеном бота, только с сервера).

shop/order vs shoppublic: что кому

ЗадачаМетодАвторизацияОткуда вызывать
Засчитать оплатуhttps://api.bot-t.com/v1/shop/order/success-orderтокен ботаТолько сервер
Товар для backend / CRMhttps://api.bot-t.com/v1/shop/order/viewтокен ботаТолько сервер
Товар для покупателя (гость)https://api.bot-t.com/v1/shoppublic/order/get-productorderKeyСайт без пользователя бота
Товар для покупателя (Web App)https://api.bot-t.com/v1/shoppublic/order/get-product-usersecret_user_keyWeb App с user_id
Товар для покупателя (универсально)https://api.bot-t.com/v1/shoppublic/order/get-productorderKeyГость и Web App, если сохранён orderKey

Формат товара различается: view — одна строка product с \n; get-product — массив { id, product }[].

Пример (PHP, server-side)

<?php

const BOT_ID = 1;
const BOT_TOKEN = '123456789:ABC...'; // только на сервере, не в JS

function shopOwnerRequest(string $action, array $body): array
{
    $url = 'https://api.bot-t.com/v1/shop/order/' . $action
        . '?botToken=' . urlencode(BOT_TOKEN);

    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
        CURLOPT_POSTFIELDS => json_encode(array_merge(['bot_id' => BOT_ID], $body)),
    ]);
    $raw = curl_exec($ch);
    curl_close($ch);
    $data = json_decode($raw, true);
    if (!is_array($data) || empty($data['result'])) {
        throw new RuntimeException($data['message'] ?? 'API error');
    }
    return $data['data'];
}

// После webhook вашего эквайринга:
$orderId = 1001;
shopOwnerRequest('success-order', ['order_id' => $orderId]);

$order = shopOwnerRequest('view', ['order_id' => $orderId]);
// $order['product'] — строки товара для логов/CRM
// Покупателю на фронте — https://api.bot-t.com/v1/shoppublic/order/get-product + orderKey

Выдача товара после оплаты (покупатель на сайте)

Условия

  • Заказ существует в магазине бота (bot_id).
  • orderKey совпадает с HMAC от order_id и токена бота (из create).
  • Статус заказа ACTIVE (1). Иначе ответ: not found (без раскрытия причины).

Тело запроса

ПолеОбяз.Описание
bot_idдаID бота
order_idдаID заказа (число)
order_keyда*Секрет из create
orderKeyда*Устаревший alias для order_key

Пример

{
  "bot_id": 1,
  "order_id": 1001,
  "order_key": "a1b2c3..."
}

Успех (data) — массив:

[
  { "id": 501, "product": "строка-товара-или-ключ" },
  { "id": 502, "product": "вторая-строка" }
]

При count > 1 или нескольких позициях — несколько элементов.

Выдача для заказа, созданного через create-user (или любого заказа этого пользователя в магазине бота).

Условия (как у get-product):

  • заказ в статусе ACTIVE (1);
  • order_id принадлежит магазину бота;
  • заказ привязан к переданному user_id / secret_user_key (not access — чужой заказ).

Тело:

ПолеОбяз.Описание
bot_idдаID бота
user_idдаbots_bot_user.id
secret_user_keyдаКлюч пользователя бота
order_idдаID заказа

Ответ data: тот же массив { id, product }[], что у get-product.

Когда использовать: Web App уже знает user_id и secret_user_key, а orderKey на клиенте не сохраняли — можно запросить товар без HMAC-ключа.


Проверка: выдача по secret_user_key

ВопросОтвет
Есть ли в shoppublic метод с secret_user_key для товара оплаченного заказа?ДаPOST https://api.bot-t.com/v1/shoppublic/order/get-product-user
Как получить товар без orderKey?get-product-user: bot_id, user_id, secret_user_key, order_id
Как для гостевого заказа?Только get-product + orderKey из create
Нужен ли secret_user_key для get-product?Нет (только orderKey)

Связанные API:

APIКогда использовать
shoppublic/order/create-userWeb App: заказ с user_id + secret_user_key (этот метод)
shopdigital/order-public/getЦифровой магазин — другой тип бота
shopcart/order/getМагазин с корзиной
shop/order/viewCRM / backend с токеном бота, не для браузера покупателя

Статусы заказа (кратко)

IDКодДля интеграции
0WAITПосле create; можно оплачивать
1ACTIVEМожно вызывать get-product
6WAIT_USERУслуга после оплаты (товар может отличаться)

Полная таблица статусов и методов владельца: заказы магазина на сайте документации.


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

messageПричина
category_id not foundНе передан category_id
not foundЧужая категория/заказ, неверный orderKey, заказ не ACTIVE
not accessget-product-user: заказ другого пользователя
Категория данного типа недоступна для анонимного заказаПодарок / подарок файлом
count must be >= 1Некорректное количество
Неверный тип ботаБот не SHOP / SHOP_CART
Бот не связан с магазиномНет model_id магазина
Not found secret_user_keycreate-user / get-product-user / промокоды без secret_user_key
HTTP 429Лимит на order/create, order/create-user (и те же окна на OrderUserController)

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

  • Витрина: category/view / get, тексты: shop/info.
  • order/create или order/create-user → сохранить id, orderKey, сумму (amount в копейках).
  • Оплата: payment/order с order_id=o-{id} или внешняя + success-order на сервере (не из браузера) / webhook.
  • После оплаты: polling payment/order/get-status или ожидание webhook.
  • Выдача: order/get-product + orderKey (гость); для Web App — get-product-user или get-product + orderKey.
  • Промокоды (опционально): только с user_id + secret_user_key.

Примеры кода

Общий сценарий: создать заказ → оплатить (o-{id}) → get-product.
Все запросы идут на https://api.bot-t.com. Подставьте свои: BOT_ID, category_id, для Web App — USER_ID и SECRET_USER_KEY.


PHP

<?php

const BOT_ID = 1;

function shopPublicPost(string $url, array $body): array
{
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
        CURLOPT_POSTFIELDS => json_encode($body),
    ]);
    $raw = curl_exec($ch);
    curl_close($ch);
    $data = json_decode($raw, true);
    if (!is_array($data) || empty($data['result'])) {
        throw new RuntimeException($data['message'] ?? 'API error');
    }
    return $data['data'];
}

// 1a. Гостевой заказ
$order = shopPublicPost('https://api.bot-t.com/v1/shoppublic/order/create', [
    'bot_id' => BOT_ID,
    'category_id' => 42,
    'count' => 1,
]);

// 1b. Заказ пользователя Web App
// $order = shopPublicPost('https://api.bot-t.com/v1/shoppublic/order/create-user', [
//     'bot_id' => BOT_ID,
//     'user_id' => 555,
//     'secret_user_key' => '...',
//     'category_id' => 42,
//     'count' => 1,
// ]);

$orderId = $order['id'];
$orderKey = $order['orderKey'];

// 2. Оплата: POST https://api.bot-t.com/v1/payment/order/... с order_id = 'o-' . $orderId
// https://bott.readme.io/reference/процесс-оплаты-заказа

// 3. После оплаты (status ACTIVE)
$lines = shopPublicPost('https://api.bot-t.com/v1/shoppublic/order/get-product', [
    'bot_id' => BOT_ID,
    'order_id' => $orderId,
    'order_key' => $orderKey,
]);

JavaScript (Node.js 18+, fetch)

const BOT_ID = 1;

async function shopPublicPost(url, body) {
  const response = await fetch(url, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
  });

  const json = await response.json();
  if (!json.result) {
    throw new Error(json.message || 'API error');
  }
  return json.data;
}

async function buyFlowGuest() {
  const order = await shopPublicPost('https://api.bot-t.com/v1/shoppublic/order/create', {
    bot_id: BOT_ID,
    category_id: 42,
    count: 1,
  });

  const orderId = order.id;
  const orderKey = order.orderKey;
  const paymentOrderId = `o-${orderId}`;

  console.log('Создан заказ', orderId, 'оплата:', paymentOrderId);
  // await paymentFlow(paymentOrderId); — см. payment/order API

  const products = await shopPublicPost('https://api.bot-t.com/v1/shoppublic/order/get-product', {
    bot_id: BOT_ID,
    order_id: orderId,
    order_key: orderKey,
  });

  console.log('Товар:', products);
  return products;
}

async function buyFlowWebApp(userId, secretUserKey) {
  const order = await shopPublicPost('https://api.bot-t.com/v1/shoppublic/order/create-user', {
    bot_id: BOT_ID,
    user_id: userId,
    secret_user_key: secretUserKey,
    category_id: 42,
    count: 1,
  });

  const orderId = order.id;
  // ... оплата o-{orderId}, затем выдача:
  return shopPublicPost('https://api.bot-t.com/v1/shoppublic/order/get-product-user', {
    bot_id: BOT_ID,
    user_id: userId,
    secret_user_key: secretUserKey,
    order_id: orderId,
  });
  // альтернатива: get-product + order.orderKey (если ключ сохранён на клиенте)
}

buyFlowGuest().catch(console.error);
// buyFlowWebApp(555, 'secret-from-bot-user-api').catch(console.error);

Браузер (Telegram Web App): тот же fetch, но для create-user нужны user_id и secret_user_key из initData/вашего backend. Не вызывайте shop/order/success-order с токеном бота из клиентского JS — только с сервера.


Python 3

import requests

BOT_ID = 1


def shop_public_post(url: str, body: dict) -> dict:
    response = requests.post(
        url,
        json=body,
        headers={'Content-Type': 'application/json'},
        timeout=30,
    )
    response.raise_for_status()
    data = response.json()
    if not data.get('result'):
        raise RuntimeError(data.get('message', 'API error'))
    return data['data']


def buy_flow_guest() -> list:
    order = shop_public_post('https://api.bot-t.com/v1/shoppublic/order/create', {
        'bot_id': BOT_ID,
        'category_id': 42,
        'count': 1,
    })

    order_id = order['id']
    order_key = order['orderKey']
    payment_order_id = f'o-{order_id}'

    print('Создан заказ', order_id, 'оплата:', payment_order_id)
    # payment_flow(payment_order_id)  # см. https://api.bot-t.com/v1/payment/order/

    return shop_public_post('https://api.bot-t.com/v1/shoppublic/order/get-product', {
        'bot_id': BOT_ID,
        'order_id': order_id,
        'order_key': order_key,
    })


def buy_flow_web_app(user_id: int, secret_user_key: str) -> list:
    order = shop_public_post('https://api.bot-t.com/v1/shoppublic/order/create-user', {
        'bot_id': BOT_ID,
        'user_id': user_id,
        'secret_user_key': secret_user_key,
        'category_id': 42,
        'count': 1,
    })

    return shop_public_post('https://api.bot-t.com/v1/shoppublic/order/get-product-user', {
        'bot_id': BOT_ID,
        'user_id': user_id,
        'secret_user_key': secret_user_key,
        'order_id': order['id'],
    })
    # альтернатива: get-product + order['orderKey']


if __name__ == '__main__':
    products = buy_flow_guest()
    print('Товар:', products)

    # products = buy_flow_web_app(555, 'secret-from-bot-user-api')
    # print('Товар (Web App):', products)

Требуется пакет requests: pip install requests.