Как обрабатывать отредактированные сообщения 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)
Затем применяйте изменение как идемпотентный переход состояния:
- Проверьте подпись для исходных байтов тела запроса.
- Исключите повторную доставку по идентификатору Webhook-события.
- Найдите запись по
account_id,data.conversation.idиdata.message.id. - Замените текущий текст значением
data.message.text. - Сохраните
occurred_atкак время наблюдения изменения. - Не меняйте время первого получения; при необходимости ведите отдельную внутреннюю историю редакций.
- Возвращайте 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 года:
Превратите интеграцию сообщений в стабильный продуктовый pipeline.
Начните с отправки через единый API, затем возвращайте входящие сообщения в бизнес-систему стандартными событиями.