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

Как обрабатывать отредактированные сообщения LINE через Webhook message.updated

12 августа 2026 года LINE добавил в Messaging API событие редактирования. Когда пользователь изменяет ранее отправленный текст в поддерживаемом групповом чате с LINE Official Account, LINE может отправить Webhook messageEdited. Общая входящая очередь должна обновить исходное сообщение, а не добавить второе. В UnifyPort этому соответствует стандартное событие message.updated, связанное с исходным data.message.id.

Главное

  • В LINE событие называется messageEdited, а в нормализованной схеме UnifyPort — message.updated.
  • Исходное сообщение следует искать по сочетанию messaging account, диалога и data.message.id.
  • Редактирование — это изменение состояния, а не новое входящее сообщение.
  • Перед разбором JSON необходимо проверить подпись HMAC-SHA256.
  • Возможность получить изменение LINE не означает, что через UnifyPort можно инициировать редактирование сообщения LINE.

Что изменилось в групповых чатах LINE

На официальной странице новостей Messaging API LINE зафиксировано обновление от 12 августа 2026 года: пользователи получили возможность редактировать сообщения в групповых чатах с LINE Official Account, а среди объектов Webhook появился messageEdited. В актуальном справочнике Messaging API Edit event также указан среди объектов событий Webhook.

Изменение важно для общих входящих очередей, истории CRM, поисковых индексов и контекста для AI. Если клиент исправил номер заказа, адрес или вопрос, а система продолжает использовать старый текст, последующая автоматизация работает с устаревшими данными. Если же вставить исправленный текст как новое сообщение, счетчики задвоятся, а лента перестанет соответствовать LINE.

Правильная модель — изменение состояния одного сообщения провайдера.

Соответствие LINE messageEdited и UnifyPort message.updated

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

{
  "id": "evt_7f42c18a9d",
  "type": "message.updated",
  "provider": "line",
  "account_id": "acc_8c21d0",
  "occurred_at": "2026-08-22T09:15:30Z",
  "data": {
    "conversation": {
      "id": "c8f2a4d91e",
      "type": "group",
      "title": "Поддержка заказов"
    },
    "sender": {
      "id": "u71b9d420f",
      "type": "user",
      "name": "Jordan Lee"
    },
    "message": {
      "id": "551842037194",
      "text": "Исправление: номер заказа A1234.",
      "direction": "inbound",
      "sent_at": "2026-08-22T09:12:04Z"
    },
    "event": {
      "kind": "message_updated"
    }
  }
}

У двух идентификаторов разные задачи:

  • Верхнеуровневый id обозначает событие Webhook и помогает исключить повторную доставку.
  • data.message.id обозначает исходное сообщение, содержание которого изменилось.

Актуальная поддержка по провайдерам указана в матрице стандартных событий Webhook. В ней LINE поддерживает message.updated, однако доступность отдельных полей может зависеть от исходного аккаунта и развертывания.

Как применить изменение без дубликата

Не считайте идентификатор сообщения глобально уникальным. Используйте составной ключ:

(account_id, conversation_id, provider_message_id)

Затем применяйте изменение как идемпотентный переход состояния:

  1. Проверьте подпись для исходных байтов тела запроса.
  2. Исключите повторную доставку по идентификатору Webhook-события.
  3. Найдите запись по account_id, data.conversation.id и data.message.id.
  4. Замените текущий текст значением data.message.text.
  5. Сохраните occurred_at как время наблюдения изменения.
  6. Не меняйте время первого получения; при необходимости ведите отдельную внутреннюю историю редакций.
  7. Возвращайте 2xx только после успешной надежной записи.

Ниже приведен компактный обработчик Express. Методы базы данных оставлены абстрактными, чтобы подчеркнуть реальный контракт события.

import crypto from 'crypto';
import express from 'express';

const app = express();
const secret = process.env.WEBHOOK_SIGNING_SECRET;

app.post('/webhook', express.raw({ type: 'application/json' }), async (req, res) => {
  const timestamp = req.get('X-Device-Timestamp') || '';
  const signature = req.get('X-Device-Signature') || '';
  const expected = crypto.createHmac('sha256', secret)
    .update(timestamp + '.')
    .update(req.body)
    .digest('hex');

  const valid = signature.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
  if (!valid) return res.sendStatus(401);

  const event = JSON.parse(req.body.toString('utf8'));
  if (await db.hasWebhookEvent(event.id)) return res.sendStatus(200);

  if (event.type === 'message.updated') {
    await db.applyMessageEdit({
      accountId: event.account_id,
      conversationId: event.data.conversation.id,
      messageId: event.data.message.id,
      text: event.data.message.text,
      editedAt: event.occurred_at
    });
  }

  await db.rememberWebhookEvent(event.id);
  return res.sendStatus(200);
});

Точная строка подписи, условия повторной доставки и ограничения порядка описаны в руководстве по доставке и подписи Webhook. Дополнительные рекомендации по временным меткам и идемпотентности есть в руководстве по защите HMAC Webhook от повторных запросов.

Если исходное сообщение отсутствует или события пришли не по порядку

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

Поместите обновление во временную pending-таблицу с составным ключом сообщения. Когда придет исходное message.received, примените ожидающий текст до отображения записи. Если исходное сообщение так и не появится, пометьте данные как неполное наблюдение редактирования для проверки оператором, а не представляйте их как полноценное сообщение.

Та же модель состояния подходит для реакций. В статье Как обрабатывать реакции на сообщения в едином Webhook показана разница между событием и состоянием сообщения, которое оно меняет.

Где подходит UnifyPort и каковы ограничения

UnifyPort полезен небольшой команде, которая получает LINE вместе с WhatsApp, Telegram, TikTok, Zalo или X и хочет использовать один подписанный контракт событий. Неофициальный интерфейс сокращает число платформенных парсеров, а обработчик может ветвиться по message.updated.

Если приложение построено вокруг LINE Official Account и ему нужны специфические возможности LINE или исходный Payload провайдера, официальный Messaging API будет более подходящим выбором. Важно учитывать и текущую границу действий: UnifyPort нормализует входящие обновления сообщений LINE, но исходящее действие POST /v1/messages/edit для LINE сейчас не поддерживается. Получение изменения и инициирование изменения — разные возможности.

Частые вопросы

Что такое LINE messageEdited?

Это официальное событие Webhook Messaging API для поддерживаемого редактирования сообщения. LINE объявил его для групповых чатов с LINE Official Account 12 августа 2026 года.

На какое событие подписываться в UnifyPort?

Подпишитесь на message.updated. Если Endpoint осознанно получает все публичные стандартные события, можно использовать "*"; для точного производственного фильтра указывайте полное имя события.

Нужно ли создавать новую запись во входящей очереди?

Нет. Найдите исходное сообщение по data.message.id и обновите его текущее содержание. Историю редакций при необходимости храните отдельно.

Можно ли отредактировать сообщение LINE через UnifyPort?

Сейчас нет. В текущей матрице действий провайдеров исходящее редактирование для LINE не поддерживается. Эта инструкция посвящена получению и применению изменений.

Следующий шаг

Проверьте матрицу Webhook-событий по провайдерам, добавьте message.updated в подписку и протестируйте идемпотентное обновление и неправильный порядок событий до включения функции в рабочей очереди.

Официальные источники

Проверено 22 августа 2026 года:

UnifyPort API

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

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