← Tất cả bài viết
Hướng dẫn

File media Telegram trong Unified Webhook: ảnh, voice, tài liệu, liên hệ và vị trí

Telegram Bot API chính thức biểu diễn media bằng các field riêng trong Message, chẳng hạn photo, document, voice, contactlocation. Nếu đường nhận của bạn là unified webhook của UnifyPort, bạn không cần đưa từng field Telegram vào model chính của inbox. Hãy lưu envelope message.received trước: text ở data.message.text, media ở data.message.attachments[], contact ở data.message.contact, và tọa độ ở data.message.location.

Tóm tắt nhanh

  • Media message của Telegram không chỉ là “tin nhắn có chữ”; Telegram Bot API chính thức định nghĩa nhiều optional field riêng cho ảnh, tài liệu, voice message, contact và location.
  • UnifyPort chuẩn hóa inbound Telegram content thành cùng envelope message.received dùng cho WhatsApp, LINE, TikTok, Zalo và X. Với đội ngũ Việt Nam, điều này hữu ích khi WhatsApp và Zalo cùng nằm trong luồng hỗ trợ.
  • Media file nằm trong data.message.attachments[], với các field như type, url, mimetype và metadata tùy chọn như kích thước hoặc thời lượng.
  • Luôn xác minh X-Device-Signature bằng raw request body trước khi đọc nội dung, tải file hoặc gửi event sang CRM/AI workflow.
  • Nếu bạn vẫn đang chọn đường nhận Telegram, hãy đọc trước Telegram Bot API Webhook hay Unified Inbound Webhook.

Telegram gửi gì, inbox của bạn nên lưu gì

Message object của Telegram Bot API rất phù hợp cho Telegram bot: code có thể branch theo field riêng của Telegram. Nhưng shared inbox hoặc hàng đợi hỗ trợ đa kênh thường có mục tiêu khác. Bạn muốn nhận Telegram hôm nay, rồi thêm WhatsApp, Zalo, LINE, TikTok hoặc X mà không phải đổi storage contract mỗi lần thêm provider.

Vì vậy bản ghi production đầu tiên nên là standard event envelope của UnifyPort, được mô tả trong Standard event types and payload:

{
  "id": "evt_b1a7c3e5f8",
  "type": "message.received",
  "provider": "telegram",
  "account_id": "acc_8c21d0",
  "occurred_at": "2026-06-08T12:37:00Z",
  "data": {
    "conversation": { "id": "5005", "type": "user" },
    "sender": { "id": "4004", "type": "user", "name": "Jordan Lee" },
    "message": {
      "id": "3003",
      "direction": "inbound",
      "sent_at": "2026-06-08T12:37:00Z",
      "contact": {
        "phone_number": "+8600000000000",
        "first_name": "Demo",
        "last_name": "User",
        "vcard": "BEGIN:VCARD\nVERSION:3.0\nFN:Demo User\nEND:VCARD",
        "user_id": 4004
      }
    },
    "event": { "kind": "message_received" }
  }
}

Nếu nội dung là ảnh, voice note, video hoặc tài liệu, dùng data.message.attachments[]. Nếu người dùng chia sẻ contact, dùng data.message.contact. Nếu họ chia sẻ location, dùng data.message.location với longitudelatitude.

Bảng map lưu trữ cho Telegram media

Nội dung nhận đượcField nên lưuGhi chú
Text hoặc captiondata.message.textKhông phải media message nào cũng có text.
Ảnh, audio, video, tài liệu, filedata.message.attachments[]Mỗi item có type đã chuẩn hóa; media URL có thể tạm thời, nên xử lý hoặc copy theo chính sách lưu trữ của bạn.
Thời lượng voice/audioattachments[].duration_ms nếu cóXem đây là optional field.
Tên tài liệuattachments[].title nếu cóDùng để hiển thị, không dùng làm unique identifier.
Contact được chia sẻdata.message.contactTelegram contact payload có thể có số điện thoại, tên, vCard và user id.
Vị trídata.message.locationLưu { longitude, latitude } riêng, không chỉ nhét vào trường địa chỉ dạng text.
Message identitydata.message.idDùng cho message-level action; dùng top-level id để deduplicate webhook delivery.

Bài này là phần triển khai cụ thể nối tiếp checklist inbound integration bắt đầu từ Webhook. Hãy tạo receiver trước, lưu event đã chuẩn hóa, rồi mới fan out sang search index, CRM, AI triage hoặc worker xử lý file.

Xác minh trước, parse sau

Tài liệu delivery của UnifyPort định nghĩa X-Device-TimestampX-Device-Signature. Khi bật signing_secret, signature là hex HMAC-SHA256 của chuỗi:

<X-Device-Timestamp>.<raw request body>

Tài liệu chính thức Node.js mô tả crypto.createHmac()crypto.timingSafeEqual(), còn tài liệu Express cho biết express.raw() parse payload thành Buffer. Vì vậy receiver nên giữ raw body để xác minh trước khi parse JSON.

import crypto from 'node:crypto';
import express from 'express';

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

if (!signingSecret) throw new Error('WEBHOOK_SIGNING_SECRET is required');

app.post('/webhooks/unifyport', 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', signingSecret)
    .update(timestamp + '.')
    .update(req.body)
    .digest();

  const supplied = /^[0-9a-f]{64}$/i.test(signature)
    ? Buffer.from(signature, 'hex')
    : Buffer.alloc(0);

  if (supplied.length !== expected.length || !crypto.timingSafeEqual(supplied, expected)) {
    return res.sendStatus(401);
  }

  const event = JSON.parse(req.body.toString('utf8'));
  await storeEvent(event.id, event);

  if (event.type !== 'message.received' || event.provider !== 'telegram') {
    return res.sendStatus(202);
  }

  const message = event.data.message;
  for (const attachment of message.attachments ?? []) {
    await mediaQueue.enqueue({
      eventId: event.id,
      messageId: message.id,
      conversationId: event.data.conversation.id,
      type: attachment.type,
      url: attachment.url,
      mimetype: attachment.mimetype,
      title: attachment.title,
      durationMs: attachment.duration_ms,
    });
  }

  if (message.contact) await contactQueue.enqueue(message.contact);
  if (message.location) await geoQueue.enqueue(message.location);

  return res.sendStatus(202);
});

Trong production, thay mediaQueue, contactQueuegeoQueue bằng database hoặc job queue của bạn. Ranh giới quan trọng là event đã xác minh phải được lưu bền vững trước khi chạy các tác vụ chậm như tải media, OCR, AI enrichment hoặc CRM sync. Chi tiết về delivery, retry và signature nằm trong Webhook delivery and signature verification. Nếu inbox cũng xử lý reaction, xem thêm cách xử lý message.reaction bằng webhook hợp nhất.

UnifyPort nằm ở đâu trong kiến trúc

UnifyPort cung cấp giao diện không chính thức để nhận inbound Telegram messages từ messaging account đã kết nối và giao chúng dưới dạng event chuẩn hóa. Bạn vẫn quyết định media được giữ bao lâu, có copy temporary file URL hay không, và worker nào được quyền đọc attachment.

Lợi ích chính là tái sử dụng schema. Receiver đang xử lý ảnh Telegram hôm nay có thể nhận WhatsApp image, LINE photo, Zalo message, TikTok DM hoặc X message sau này mà không biến Telegram Message object thành trung tâm của database.

Giới hạn và trade-offs

Dùng official Bot API khi bạn đang xây Telegram bot identity, bot commands, inline keyboards, BotFather configuration hoặc hành vi đặc thù của bot Telegram. Dùng unified webhook khi công việc là inbound intake cho messaging account sẵn có hoặc hàng đợi đa kênh.

Cũng đừng giả định mọi provider đều có đủ media shape giống Telegram. Bạn có thể chuẩn hóa storage layer, nhưng capability check theo provider vẫn nên nằm ở rìa hệ thống.

FAQ

Ảnh Telegram có được lưu trong data.message.text không?

Không. Text và caption dùng data.message.text; media file dùng data.message.attachments[] với type đã chuẩn hóa.

Một webhook có nhận được contact và location của Telegram không?

Có. Event message.received có thể mang các structured field như data.message.contact hoặc data.message.location khi tin nhắn đến chứa loại nội dung đó.

Có nên tải media xong rồi mới trả 2xx không?

Thường là không. Hãy lưu verified event trước, đưa tác vụ media vào queue, rồi trả 2xx. Tải file chậm không nên chặn acknowledgement.

Đây có giống Telegram Bot API webhook không?

Không. Telegram Bot API webhook nhận Telegram Update objects cho bot token. UnifyPort webhook nhận event đã chuẩn hóa cho messaging account đã kết nối và có thể dùng cùng receiver trên nhiều provider.

Bước tiếp theo

Mở Create webhook endpoint, subscribe message.received, bật signing_secret, rồi kiểm thử text, attachment, contact và location trước khi nối handler vào production workflow.

Sources checked on 2026-09-08

UnifyPort API

Biến tích hợp nhắn tin thành một pipeline sản phẩm ổn định.

Bắt đầu bằng cách gửi qua một API, rồi đưa mọi tin nhắn inbound trở lại hệ thống kinh doanh bằng sự kiện chuẩn.