← Все статьи
Руководство

LINE Webhook: Verify не проходит? Обработайте пустой events

При проверке Webhook URL LINE отправляет HTTP POST с пустым массивом events. Получатель должен проверить подпись и вернуть 200, не пытаясь прочитать сообщение или отправить ответ. Если обработчик предполагает, что events[0] существует всегда, Verify может завершиться ошибкой даже при исправной обработке обычных сообщений. Обратное тоже верно: успешный Verify не доказывает, что реальные сообщения доходят до очереди или рабочего интерфейса поддержки.

Главное

  • Подлинный запрос с events: [] — это проверка связи, а не потерянное сообщение.
  • Проверяйте x-line-signature по исходному телу с помощью channel secret до разбора JSON.
  • Связность и бизнес-обработку нужно тестировать отдельно.
  • Не смешивайте нативный webhook LINE с нормализованными событиями UnifyPort.

Что отправляет кнопка Verify

Официальное руководство по проверке Webhook URL описывает два способа: API тестирования webhook и кнопку Verify в LINE Developers Console. Оба проверяют возможность связи LINE с получателем. На проверочный запрос без события LINE предписывает вернуть 200.

Ниже показано тело из примера проверки подписи LINE. Это не сообщение клиента:

{"destination":"U8e742f61d673b39c7fff3cecb7536ef0","events":[]}

Здесь нет объекта события с сообщением, отправителем или токеном ответа. Не создавайте клиента по destination, не придумывайте идентификатор сообщения и не ставьте автоматический ответ в очередь. При необходимости учитывайте проверки связи отдельно от клиентского трафика.

Прежде чем менять URL, выясните, какой компонент им управляет. Если к официальному аккаунту подключено несколько инструментов, используйте чек-лист совместного использования webhook. Ошибка парсера — не повод случайно перенаправить трафик с исправного получателя.

Сначала подпись, затем пустой массив

В руководстве LINE по проверке подписи указан HMAC-SHA256 от полученного тела: ключом служит channel secret, подпись представляется в Base64. Это не channel access token, используемый для исходящих API-вызовов.

Сохраните исходные байты. Разбор JSON с последующей сериализацией может изменить пробелы или экранирование и нарушить проверку подписи. Пустой events не освобождает от аутентификации: такой же JSON может отправить посторонний клиент.

Этот пример функции Node.js проверяет и разбирает нативный запрос LINE. rawBody должен быть исходным Buffer от HTTP-фреймворка, а channelSecret — значением из серверного хранилища секретов. Это не готовый сервер и не реализация постоянной очереди.

import { createHmac, timingSafeEqual } from 'node:crypto';

export function readLineEvents(rawBody, signature, channelSecret) {
  if (!Buffer.isBuffer(rawBody) || !channelSecret) {
    throw new Error('Raw body and channel secret are required');
  }
  const expected = createHmac('sha256', channelSecret)
    .update(rawBody)
    .digest('base64');
  const supplied = Buffer.from(signature ?? '', 'utf8');
  const calculated = Buffer.from(expected, 'utf8');
  if (supplied.length !== calculated.length ||
      !timingSafeEqual(supplied, calculated)) {
    return { status: 401 };
  }
  try {
    const payload = JSON.parse(rawBody.toString('utf8'));
    if (!payload || !Array.isArray(payload.events)) {
      return { status: 400 };
    }
    return { status: 200, events: payload.events };
  } catch {
    return { status: 400 };
  }
}

Ветки 400 и 401 — защитные решения этого примера, а не коды ошибок LINE API. Встройте функцию в обработчик следующим образом:

  1. Передайте заголовок x-line-signature и неизменённое тело.
  2. Отклоняйте некорректные запросы без создания бизнес-задач.
  3. Если проверка успешна и events.length === 0, сразу верните HTTP 200.
  4. Если события есть, сначала надёжно сохраните их, затем подтвердите приём. Длительные операции выполняйте асинхронно. При сбое сохранения нельзя отправлять 200 только потому, что функция вернула такой статус.

LINE рекомендует асинхронную обработку. Хранилище и воркеры остаются ответственностью приложения. Обходите весь массив, а не только первый элемент.

Найдите границу сбоя

НаблюдениеЧто проверить дальше
Запрос не доходит до приложенияНастроенные хост и путь, TLS, маршрутизацию на входе, журналы прокси
Подпись не проходит проверкуПравильность channel secret, сохранность исходных байтов, передачу заголовков
Проверенный пустой запрос вызывает исключениеБезусловное обращение к первому событию, сообщению или токену ответа
Приложение сообщает об успехе, но Verify не проходитСтатус, реально возвращённый публичной точкой входа, и время обработки
Verify проходит, но сообщений в интерфейсе нетСохранение реальных событий, маршрутизацию и выполнение воркера

Не меняйте секреты или владельца webhook только потому, что обработчик сообщений не принимает пустой массив. Если реальные события приходят, но токена ответа нет, это другой вопрос: руководство по режиму LINE standby объясняет право на ответ. У пустого проверочного запроса нет события и, соответственно, его поля mode.

Проверьте связь и сообщения отдельно

Ниже предложены приёмочные тесты, а не результаты уже проведённых испытаний:

  • Корректно подписанный пустой запрос получает 200 и не создаёт сообщение клиента или задачу отправки.
  • Такое же пустое тело без подписи или с неверной подписью отклоняется.
  • Корректно подписанный непустой запрос сохраняется до подтверждения приёма.
  • После успешного Verify контролируемое сообщение, отправленное нужному официальному аккаунту, проходит ожидаемый процесс обработки в поддержке.
  • Ошибка сохранения не считается завершённой обработкой лишь на основании правильной подписи.

Записывайте только необходимую диагностику: результат проверки подписи, число событий, HTTP-статус и время наблюдения. Не помещайте channel secret, токены ответа и тексты клиентов в обычные журналы.

Отделите получатель UnifyPort

Неофициальный интерфейс UnifyPort подключает аккаунт LINE через процесс авторизации LINE. Это не нативная служба проверки webhook официального аккаунта.

В контракте доставки webhook используется X-Device-Signature. При заданном signing_secret подпись представляет собой HMAC-SHA256 от X-Device-Timestamp, точки и исходного тела, закодированный в шестнадцатеричном формате. Нормализованный конверт содержит id, type, provider, account_id, occurred_at и data, а не массив events LINE.

Используйте отдельные маршруты или явно разделённые настройки получателя. Отсутствие нативного events в payload UnifyPort нельзя трактовать как пустой проверочный запрос LINE. Успешный LINE Verify не проверяет доставку UnifyPort, авторизацию аккаунта или обработку нормализованных сообщений. Если требуется именно идентичность LINE Official Account, сохраняйте официальный путь Messaging API.

Вопросы и ответы

events: [] — это ошибка?

Не в запросе проверки Webhook URL LINE. Проверьте подпись и верните 200, не создавая задачу обработки сообщения. Отсутствующий массив или неверный тип поля — не то же самое, что пустой массив.

Почему обычные сообщения работают, а Verify нет?

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

Успешная проверка означает, что бот может отвечать?

Нет. Она проверяет связь с получателем, но не сохранение, выполнение воркеров, возможность ответа или успешность исходящего API-вызова.

Следующий шаг и источники

Для официального аккаунта выполните проверку Webhook URL LINE, затем проследите путь одного реального тестового сообщения. Для независимой интеграции UnifyPort реализуйте её документированный контракт webhook.

Официальные материалы проверены 2026-10-28:

UnifyPort API

Превратите интеграцию сообщений в стабильный продуктовый pipeline.

Начните с отправки через единый API, затем возвращайте входящие сообщения в бизнес-систему стандартными событиями.