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

Lỗi định dạng Telegram: gửi văn bản động an toàn bằng HTML

Nếu tin nhắn Telegram gửi được với nội dung cố định nhưng thất bại khi chèn tên khách hàng hoặc câu trả lời AI, hãy kiểm tra chế độ định dạng trước khi thử lại. Với văn bản thuần, bỏ parse_mode và gửi nội dung gốc. Với HTML, escape giá trị động trước khi đưa vào mẫu do ứng dụng kiểm soát. JSON hợp lệ không có nghĩa là nội dung cũng tuân thủ quy tắc định dạng của Telegram.

Điểm chính

  • Văn bản thuần, HTML và MarkdownV2 cần các cách dựng nội dung khác nhau, không chỉ khác tên chế độ.
  • Giữ nội dung gốc riêng với kết quả đã định dạng; chỉ escape một lần ở bước tạo đầu ra.
  • Phân biệt lỗi định dạng đã xác nhận, giới hạn tốc độ và lần gửi chưa rõ kết quả.
  • Trong UnifyPort, phần mở rộng là provider_data.parse_mode, không phải trường cấp cao nhất như Bot API.

Trước hết, tách riêng lớp định dạng

Tài liệu Telegram Bot API mô tả parse_mode là chế độ phân tích các thực thể văn bản. HTML chỉ hỗ trợ tập thẻ được quy định, không phải trình hiển thị HTML của trình duyệt. Tài liệu cũng phân biệt Markdown cũ với MarkdownV2: đổi chế độ mà không đổi bộ dựng nội dung không phải cách sửa lỗi.

Dùng một cuộc trò chuyện có kiểm soát và văn bản ngắn, không chứa dữ liệu nhạy cảm:

  1. Kiểm tra yêu cầu cuối cùng sau khi SDK hoặc công cụ tự động hóa tuần tự hóa. Cấu hình mặc định có thể tự thêm chế độ định dạng.
  2. Gửi văn bản gốc ngắn, không kèm tùy chọn định dạng. Không tái sử dụng chuỗi đã escape cho HTML hoặc Markdown.
  3. Thêm một mẫu HTML nhỏ chỉ chứa nội dung cố định.
  4. Escape giá trị động theo quy tắc văn bản HTML rồi mới chèn vào mẫu.
  5. Kiểm tra riêng kết quả API và nội dung hiển thị trong ứng dụng.

Nếu văn bản thuần cũng thất bại, hãy kiểm tra lỗi thực tế, người nhận, xác thực và độ dài thay vì mặc định cho rằng bộ phân tích có vấn đề. Nếu đang nhúng lệnh gửi trong phản hồi webhook, hãy đọc so sánh với yêu cầu sendMessage riêng: cách nhúng không cung cấp kết quả gửi để ứng dụng kiểm tra.

Escape giá trị động, không chấp nhận mã đánh dấu tùy ý

Trong chế độ HTML, Telegram yêu cầu thay <, > và & không thuộc thẻ hoặc thực thể bằng HTML entity tương ứng. Ví dụ JavaScript sau chỉ xử lý văn bản chèn giữa các thẻ. Đây không phải bộ làm sạch HTML tổng quát, bộ chuyển đổi Markdown hay bộ kiểm tra thuộc tính URL.

function escapeTelegramHtmlText(value) {
  if (typeof value !== 'string') {
    throw new TypeError('Expected text');
  }
  return value
    .replaceAll('&', '&amp;')
    .replaceAll('<', '&lt;')
    .replaceAll('>', '&gt;');
}

function renderSupportAnswer(customerName, answer) {
  return `<b>${escapeTelegramHtmlText(customerName)}</b>\n` +
    escapeTelegramHtmlText(answer);
}

const rendered = renderSupportAnswer(
  'R&D <Team>',
  'Use x < 5 & keep the original value.'
);

Thay & trước để không escape lại các thực thể được tạo ở bước sau. Mã HTML dự kiến là:

<b>R&amp;D &lt;Team&gt;</b>
Use x &lt; 5 &amp; keep the original value.

Người nhận cần thấy các ký hiệu gốc và tên được in đậm. Cấu trúc thẻ phải do ứng dụng kiểm soát. Thẻ xuất hiện trong tên khách hàng hoặc câu trả lời AI nên tiếp tục là nội dung, không trở thành lệnh định dạng mới.

Đừng escape toàn bộ mẫu sau khi ghép: các thẻ chủ động thêm cũng sẽ hiện thành văn bản. Ngược lại, đừng bỏ escape HTML chỉ vì sau đó có JSON.stringify. Tuần tự hóa JSON và phân tích HTML của Telegram là hai lớp khác nhau.

Nếu cần liên kết, hãy dùng bộ dựng riêng đã được rà soát, có kiểm tra địa chỉ đích và xử lý thuộc tính an toàn. Hàm này cố ý không chèn thuộc tính động. Khi cần thêm kiểu định dạng, mở rộng và kiểm thử theo tập thẻ được Telegram công bố thay vì nhận HTML tùy ý.

Đặt tham số đúng theo từng API

Cách tích hợpTrường văn bảnTùy chọn định dạng
Telegram Bot API chính thức, sendMessagetextparse_mode
Gửi văn bản chuẩn hóa của UnifyPortmessage.textprovider_data.parse_mode

Giao diện không chính thức của UnifyPort dùng tài khoản nhắn tin đã kết nối và cấu trúc yêu cầu khác Bot API. Tài liệu gửi văn bản quy định POST /v1/messages, message.text không được rỗng và phần mở rộng parse_mode. Ma trận khả năng gửi giới hạn phần mở rộng này cho Telegram, không cam kết HTML hoạt động trên mọi kênh.

Hàm sau dùng bộ dựng nội dung ở trên. Truyền ID tài khoản thật cùng ID và loại của cuộc trò chuyện đã chọn. Hàm chỉ tạo JSON, không gửi hay thử lại, và không phải báo cáo rằng tích hợp đã được kiểm thử thực tế.

function buildTelegramReply({ accountId, conversation, name, answer }) {
  return {
    account_id: accountId,
    to: { id: conversation.id, type: conversation.type },
    message: {
      type: 'text',
      text: renderSupportAnswer(name, answer)
    },
    provider_data: { parse_mode: 'HTML' }
  };
}

Gửi body qua endpoint trong tài liệu, xác thực bằng X-Api-Key ở máy chủ. Với văn bản thuần, bỏ provider_data.parse_mode và dùng câu trả lời gốc thay cho chuỗi HTML. Không sao chép chat_id, entities hoặc tham số Bot API khác vào body chuẩn hóa nếu chưa có ánh xạ được tài liệu hóa.

Worker chung cho Telegram, Zalo hoặc WhatsApp nên chọn bộ dựng nội dung theo nhà cung cấp. Chung luồng định tuyến không có nghĩa là chung cú pháp định dạng.

Kiểm thử nội dung trước khi thêm cơ chế thử lại

Dùng dữ liệu giả lập, không dùng hội thoại thật của khách hàng:

Dữ liệu kiểm thửĐiều cần xác minh
Tên chứa & và dấu ngoặc nhọn gócKý tự gốc hiển thị đúng; chỉ thẻ do ứng dụng kiểm soát tạo định dạng
Chuỗi nguyên văn &amp; trong nguồnVẫn là nội dung gốc, không bị giải mã ngoài ý muốn
Emoji, nhiều ngôn ngữ và xuống dòngTuần tự hóa và hiển thị không làm hỏng nội dung
Đầu vào rỗng hoặc câu trả lời AI dàiKiểm tra dữ liệu và chính sách độ dài chạy trước khi gửi
Dựng cùng một nguồn hai lầnMỗi lần bắt đầu từ nguồn, không escape lại đầu ra trước

Với nội dung dài, chia nguồn thành các phần có ý nghĩa rồi định dạng riêng từng phần. Không cắt chuỗi HTML đã tạo tại vị trí tùy ý vì có thể cắt giữa thẻ hoặc thực thể. Kiểm tra quy tắc độ dài hiện hành của phương thức đã chọn; ví dụ này không kiểm tra độ dài hay triển khai rich message.

Lỗi định dạng đã xác nhận cần sửa nội dung, không cần vòng lặp chờ rồi gửi lại. Với giới hạn tốc độ, xem hướng dẫn Telegram 429 và hàng đợi gửi. Nếu hết thời gian chờ mà không có phản hồi, giữ trạng thái chưa rõ kết quả. Đừng tự động gửi bản văn bản thuần thay thế vì tin nhắn đầu có thể đã đến nơi.

Câu hỏi thường gặp

JSON hợp lệ có đảm bảo định dạng hợp lệ không?

Không. JSON có thể được phân tích thành công trong khi văn bản bên trong vi phạm quy tắc của chế độ đã chọn.

Có nên chuyển mọi lỗi sang MarkdownV2 không?

Không. MarkdownV2 có quy tắc escape riêng. Hãy chọn chế độ có chủ đích và dùng bộ dựng phù hợp.

Vì sao HTML entity xuất hiện trong tin nhắn văn bản thuần?

Kiểm tra xem bạn có tiếp tục dùng đầu ra đã escape cho HTML sau khi bỏ chế độ phân tích không. Văn bản thuần nên bắt đầu từ nội dung gốc.

Hàm này xử lý được cả tài liệu HTML không?

Không. Nó chỉ escape văn bản động giữa các thẻ đáng tin cậy, không xác minh mã đánh dấu tùy ý, thuộc tính, liên kết hay độ dài tin nhắn.

Bước tiếp theo và nguồn

Tách bộ dựng văn bản thuần khỏi HTML, rồi kiểm thử trong một cuộc trò chuyện Telegram có kiểm soát. Với tài khoản đã kết nối, hãy dựa trên đặc tả gửi văn bản UnifyPort.

Nguồn được kiểm tra ngày 2026-10-21:

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.