Перейти до вмісту

Вебхуки

MoreLogin може надсилати JSON-подію методом POST на ваш HTTPS-ендпоінт відразу після того, як операція з хмарним телефоном або хмарним браузером досягла підсумкового результату, тому опитувати результат більше не потрібно. На команду зберігається один URL зворотного виклику, і Local API та Open API пишуть в один і той самий запис.

Налаштування URL зворотного виклику

Обидва контури надають ту саму операцію. Open API:

curl -X POST "https://api.morelogin.com/webhook/config" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "callbackUrl": "https://example.com/morelogin/webhook",
    "enabled": true
  }'

Local API:

curl -X POST "http://127.0.0.1:40000/api/webhook/config" \
  -H "Content-Type: application/json" \
  -d '{
    "callbackUrl": "https://example.com/morelogin/webhook",
    "enabled": true
  }'

Маршрут Local API обслуговує настільний клієнт, тому потрібен клієнт MoreLogin v2.66.0 або новіший. Ендпоінт Open API від клієнта не залежить.

teamId ніколи не читається із запиту. Кожен виклик налаштовує команду із серверного контексту, тому спрямувати події іншої команди на свій ендпоінт не вийде.

URL має бути HTTPS, довжиною від 1 до 1024 символів, з іменем хоста, без даних користувача, без фрагмента та з коректним портом. Усі адреси, у які він розв'язується, повинні маршрутизуватися в інтернеті: діапазони localhost, приватні, link-local, CGNAT, метаданих хмари, зарезервовані протоколом, документаційні та 6to4 відхиляються з кодом 41001. Та сама перевірка повторюється в момент, коли доставка відкриває з'єднання, тому імʼя хоста, яке згодом розв'яжеться у приватний діапазон, призведе до невдачі цієї доставки, а не до звернення у вашу мережу.

Збереження — це upsert за командою, тому надіслати те саме тіло двічі безпечно.

Вимкнення доставки

enabled: false зберігає URL і припиняє створення нових подій. Уже поставлені в чергу події скасовуються по одній, у той момент, коли кожну з них має бути авторизовано, і лише поки конфігурація все ще вимкнена — тому при швидкому повторному ввімкненні події з черги продовжать доставлятися, а не будуть відкинуті.

Як виглядає доставка

Кожна доставка — це POST із такими заголовками:

ЗаголовокЗначення
Content-Typeapplication/json
User-AgentMoreLogin-Webhook/1.0
X-Webhook-Event-IdТе саме, що eventId у тілі
X-Webhook-Event-TypeТе саме, що eventType у тілі

Два заголовки X-Webhook-* навмисно дублюють поля тіла, щоб маршрутизатор або черга могли розподіляти запити за ними без розбору JSON.

{
  "eventId": "c7f3a2b10d8e4f6a9c1b2d3e4f5a6b7c",
  "eventType": "cloud_phone.power_off",
  "eventTime": "1787241600000",
  "data": {
    "teamId": "10001",
    "cloudPhoneId": "20001",
    "reason": "MONEY_SAVING"
  },
  "result": {
    "success": true,
    "code": "0",
    "message": null
  }
}
ПолеОпис
eventIdУнікальний ID події. Повтори та внутрішні відтворення тієї самої події використовують його повторно, тому це ключ ідемпотентності
eventTypeСтабільна назва події з таблиці нижче
eventTimeКоли настав підсумковий результат, у мілісекундах епохи Unix. Передається рядком
data.teamIdКоманда, якій належить ресурс. Передається рядком
data.cloudPhoneIdХмарний телефон, до якого стосується подія. Передається рядком
data.cloudBrowserIdПрофіль хмарного браузера, до якого стосується подія. Передається рядком
data.runIdЕкземпляр запуску хмарного браузера, до якого стосується подія
data.reasonЛише у cloud_phone.power_off та cloud_browser.stop
result.successЧи завершилася операція успішно
result.code0 у разі успіху; інакше стабільний бізнес-код помилки, що не залежить від мови
result.messagenull у разі успіху; інакше пояснення мовою команди з переходом на en-US

Усі числові ідентифікатори та eventTime надходять рядками JSON, як і в решті API — див. Загальний формат відповіді. Розбирайте їх як рядки, а не як числа, інакше втратите точність на 64-бітних ID.

Події

eventTypeПідсумковий результат, про який повідомляється
cloud_phone.power_onУвімкнення вдалося або не вдалося
cloud_phone.power_offВимкнення вдалося. Невдале вимкнення події не створює
cloud_phone.restartПерезапуск удався або не вдався
cloud_phone.resetСкидання вдалося або не вдалося
cloud_phone.new_machineНовий пристрій одним клацанням удався або не вдався
cloud_browser.startЗапуск хмарного браузера вдався або не вдався
cloud_browser.stopКожна спроба зупинки хмарного браузера, успішна чи ні

Події хмарного телефона містять teamId та cloudPhoneId. Події хмарного браузера містять teamId, cloudBrowserId і runId.

Увімкнення, перезапуск, скидання та створення нового пристрою одним клацанням повідомляють success: true лише після того, як зворотний виклик сервісу був успішним і локальна синхронізація зафіксована. Помилка списання коштів або асинхронна перевірка проксі, яка завершилася невдало та довела до кінця своє очищення, повідомляють про невдале увімкнення і не створюють додатково подію вимкнення. Відкладені задачі, наприклад встановлення попередньо визначених застосунків або видалення застарілих файлів, результат не змінюють.

Якщо вимкнення перервало завантаження, ця спроба не створює події увімкнення; успішне вимкнення згодом усе одно створить власне cloud_phone.power_off.

Причини зупинки

cloud_phone.power_off додає data.reason:

ЗначенняСенс
NORMALЗвичайне вимкнення
MONEY_SAVINGРежим економії коштів
OTHERЗаборгованість, завершення терміну, обслуговування або інша причина

cloud_browser.stop додає data.reason:

ЗначенняСенс
NORMALЗвичайне закриття
MONEY_SAVINGРежим економії коштів
ENERGY_SAVINGРежим енергозбереження
BROWSER_EXITEDБраузер завершився неочікувано
OTHERБудь-яка інша причина

Внутрішня помилка архівування змінює лише result і ніколи не перезаписує reason, зафіксований на початку зупинки.

Доставка, повтори та порядок

Будь-який 2xx вважається доставкою. Будь-який інший статус, а також тайм-аути з'єднання та читання і мережеві помилки вважаються невдачею. Тайм-аут з'єднання — 5 секунд, тайм-аут читання — 30 секунд.

Невдала доставка повторюється не більше 6 разів: через 10 секунд, 30 секунд, 60 секунд, 3 хвилини, 10 хвилин і 30 хвилин. Це не більше 7 запитів на одну подію. Після невдачі шостого повтору подія перестає повторюватися автоматично.

Події одного хмарного телефона або одного хмарного браузера доставляються в порядку створення, по одній. Різні ресурси доставляються паралельно, тому не покладайтеся на якийсь порядок між ними.

Повтори однієї події завжди використовують ті самі eventId, eventTime і тіло. У межових мережевих або відновлювальних ситуаціях та сама подія може бути доставлена кілька разів із незмінними значеннями, тому дедуплікуйте за eventId.

Для зупинок хмарного браузера одна спроба зупинки дає рівно одну подію. Подальший повтор вручну, примусове звільнення вручну або примусове звільнення, ініційоване системою, — це нова операція, яка отримує новий eventId. Дві спроби ніколи не об'єднуються в одну подію.

Операції хмарного телефона визначаються за ID задачі сервісу, traceId або стабільною бізнес-позначкою часу. Коли жодного з них немає, сервіс генерує UUID і вважає поточний підсумковий зворотний виклик новою операцією, тому ви отримуєте новий eventId, а дві різні операції не зливаються в одну.

Реалізація отримувача

Повертайте 2xx відразу після того, як зберегли подію, а реальну роботу виконуйте асинхронно. Тіло відповіді ігнорується, а повільний обробник витратить ваші 30 секунд на читання і відправить подію до розкладу повторів, хоча ви її вже отримали.

Дедуплікуйте за eventId. Вважайте повтор уже обробленим, а не відтворюйте побічні ефекти знову.

Не вважайте корисне навантаження довіреним вводом лише тому, що воно надійшло на ваш ендпоінт. У цьому випуску зворотні виклики не підписуються, тому надіслати запит може будь-хто, хто дізнався ваш URL. Використовуйте URL, який важко вгадати, і перш ніж виконувати щось дороге, підтвердьте стан через API — наприклад POST /cloudphone/info для хмарного телефона або POST /cloudbrowser/page для запуску хмарного браузера.

result.code використовує ті самі бізнес-коди, що й синхронний API, тому невдачу можна знайти в Коди помилок. result.message — читабельний для людини рядок, формулювання та мова якого можуть змінюватися; розгалужуйтеся за result.success і result.code, але ніколи за result.message.

Машинно-читний контракт кожної події, включно зі схемами та прикладами по подіях, публікується разом зі специфікацією спільних ресурсів: Shared Resources Open API.