Поток установки (Flow A)
Это сценарий для интеграции в маркетплейсе. Он начинается внутри Bito: клиент открывает Интеграция → Интеграция, находит вашу интеграцию в маркетплейсе и нажимает кнопку установки (Установить бесплатно или Внешняя оплата). После этого Bito сам отправляет код авторизации на ваш сервер. Браузер клиента в этом не участвует, поэтому вам нужна не страница обратного вызова, а эндпоинт.
Клиент (в Bito) Bito Ваш сервер
| | |
| 1. нажимает «Установить»| |
|------------------------->| |
| | 2. POST на redirect_uri |
| | { code, client_id, |
| | account_id } |
| |--------------------------->|
| | |
| | 3. POST /auth/oauth/token |
| |<---------------------------|
| | { access_token, |
| | refresh_token } |
| |--------------------------->|
| | |
| 4. пользуется интеграцией |1. Клиент устанавливает интеграцию
Реализовывать нечего. Кнопка Установить появляется у всех клиентов, как только интеграция становится PUBLIC; пока она PRIVATE, её видит только ваш аккаунт — это и нужно во время разработки.
2. Bito отправляет код на ваш redirect_uri
Bito шлёт POST — не редирект — на redirect_uri, указанный при создании интеграции.
Запрос, который отправляет Bito
POST https://your-app.example.com/bito/install
Content-Type: application/json
X-Bito-Signature: t=1736937000,v1=6b1f0a...c94e
{
"code": "abc123def456",
"client_id": "69c50a2d50f7b939923a469b",
"account_id": "507f1f77bcf86cd799439011"
}| Поле | Описание |
|---|---|
code | Код авторизации. Одноразовый, живёт 20 минут. |
client_id | Ваш OAuth client id — проверьте, что он ваш, прежде чем что-то делать. |
account_id | Аккаунт клиента, который вас установил. Сохраните: по нему вы различаете своих клиентов. |
X-Bito-Signature | Подпись запроса — см. ниже. |
Проверьте, что запрос действительно пришёл от Bito
Этот POST подписан вашим client_secret. Этот секрет знаете только вы и Bito, поэтому совпавшая подпись доказывает подлинность запроса, и третья сторона не сможет подделать установку.
- Формат заголовка:
X-Bito-Signature: t=<unix-секунды>,v1=<hex> v1 = HMAC_SHA256(client_secret, "{t}.{raw_body}")— вычисляется по байтам исходного тела запроса. Не сериализуйте JSON заново.- Пересчитайте
v1и сравните с заголовком за константное время; при несовпадении отклоняйте запрос. - Отклоняйте запросы, где
tотличается от текущего времени более чем на ~5 минут — это защищает от повторной отправки (replay). - Также убедитесь, что
client_idиaccount_idсоответствуют ожидаемому клиенту.
Пример (Node.js)
const crypto = require('crypto');
function verifyBitoSignature(rawBody, headers, clientSecret, now = Date.now()) {
const m = /t=(\d+),v1=([a-f0-9]+)/.exec(headers['x-bito-signature'] || '');
if (!m) return false;
const [, t, v1] = m;
if (Math.abs(now / 1000 - Number(t)) > 5 * 60) return false; // stale / replay
const expected = crypto
.createHmac('sha256', clientSecret)
.update(t + '.' + rawBody)
.digest('hex');
const a = Buffer.from(expected, 'hex');
const b = Buffer.from(v1, 'hex');
return a.length === b.length && crypto.timingSafeEqual(a, b);
}WARNING
Отвечайте 2xx быстро, а обмен кода на токены при необходимости делайте в фоне. Bito не повторяет этот запрос.
3. Обменяйте код на токены
В течение 20 минут вызовите эндпоинт обмена — только с сервера, потому что запрос содержит ваш client_secret.
См. Работа с токенами → Обмен кода авторизации.
4. Сохраните токены рядом с аккаунтом
Храните access_token, refresh_token и account_id вместе. Один клиент — одна пара токенов. Когда access-токен истечёт, обновите его.
TIP
Реализуйте также хук удаления, чтобы удалять данные клиента, когда он отключает вашу интеграцию.