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

Xử lý xác nhận đã nhận và đã đọc theo lô với UnifyPort

Một sự kiện xác nhận đã nhận hoặc đã đọc của UnifyPort có thể áp dụng cho nhiều tin nhắn. Khi có trường theo lô, hãy xử lý mọi ID trong data.message.ids; với xác nhận một tin nhắn, dùng data.message.id. Lưu xác nhận riêng với nội dung để không mất dữ liệu khi xác nhận đến trước. Yêu cầu gửi được chấp nhận, xác nhận từ người nhận và trạng thái đã đọc trong hộp thư của nhóm là ba loại bằng chứng khác nhau.

Điểm chính

  • Đối chiếu trong phạm vi workspace, nhà cung cấp, tài khoản nhắn tin và cuộc hội thoại, không chỉ theo ID tin nhắn.
  • Lưu thời gian do nhà cung cấp báo riêng với thời gian webhook đến.
  • Xác nhận đã nhận đến muộn không được xóa bằng chứng đã đọc.
  • Chưa có xác nhận nghĩa là chưa biết, không phải căn cứ để gửi lại.

Kiểm tra phạm vi lô trước khi đổi trạng thái hiển thị

Đặc tả sự kiện chuẩn định nghĩa message.delivered là tin nhắn đã đến thiết bị của người nhận, còn message.read là xác nhận người nhận đã đọc. Trường theo lô là data.message.ids. Chỉ cập nhật id đơn lẻ sẽ bỏ sót phần còn lại.

Bằng chứngXác nhận điều gìKhông xác nhận điều gì
Phản hồi gửi có status: acceptedYêu cầu đã được tiếp nhậnĐã đến thiết bị hoặc đã đọc
message.deliveredCác tin nhắn được chỉ định đã đến thiết bịNgười nhận đã đọc
message.readCác tin nhắn được chỉ định đã được đọcYêu cầu hỗ trợ đã giải quyết hoặc cả nhóm đã đọc
Trạng thái đọc cục bộ của hội thoạiTrạng thái danh sách chat của tài khoản kết nốiXác nhận từ người nhận

Hàng cuối thuộc quy trình đồng bộ đã đọc/chưa đọc trong hộp thư chung. Đừng gọi thao tác đánh dấu hội thoại đã đọc để sửa việc thiếu xác nhận cho tin nhắn gửi đi.

Ví dụ rút gọn dưới đây dùng các trường trong tài liệu message.read. Đây là minh họa, không phải sự kiện thu thập từ khách hàng:

{
  "id": "evt_2f9c1a4b7e",
  "type": "message.read",
  "provider": "whatsapp",
  "account_id": "acc_8c21d0",
  "occurred_at": "2026-06-08T12:35:10Z",
  "data": {
    "conversation": { "id": "8613912345678", "type": "user" },
    "sender": { "id": "8613912345678", "type": "user" },
    "message": {
      "id": "wamid.HBgM",
      "ids": ["wamid.HBgM", "wamid.HBgN"],
      "read_at": "2026-06-08T12:35:10Z"
    }
  }
}

Xác nhận áp dụng cho hai tin nhắn được liệt kê. Nó không chứng minh mọi tin nhắn trước đó đều đã đọc. Ngay cả khi ID trông như số, cũng không được suy ra một khoảng liên tục.

Lưu bằng chứng trước khi tạo nhãn trạng thái

Thiết kế đề xuất gồm hai lớp: bản ghi sự kiện đã xác minh được lưu bền vững và bảng trạng thái xác nhận theo từng tin nhắn. Đây là thiết kế lưu trữ của ứng dụng, không phải trường bổ sung của UnifyPort.

  1. Thêm cả hai tên sự kiện xác nhận vào danh sách đăng ký, đồng thời giữ các sự kiện cần thiết khác và cấu hình chữ ký.
  2. Theo đặc tả phân phối webhook, dùng signing_secret kiểm tra HMAC-SHA256 của timestamp, dấu chấm và raw body. Kiểm tra cả độ mới của timestamp đã ký.
  3. Lưu bền vững sự kiện đã xác minh trước khi trả 2xx. Ghi sự kiện và tác vụ bền vững một cách nguyên tử; hoặc cập nhật bảng trạng thái và bản ghi chống trùng trong cùng giao dịch.
  4. Tách lô thành các bản ghi quan sát theo tin nhắn. Giữ ngữ cảnh workspace, provider, account_id, data.conversation.id, ID sự kiện và danh tính người gửi nếu có.
  5. Lưu riêng occurred_at, read_at hoặc delivered_at do nhà cung cấp báo và thời gian ứng dụng nhận được sự kiện. Thời gian xác nhận cũng được sao chép sang trường cùng tên ở cấp data. Nếu thiếu thời gian, giữ là chưa biết; không dùng thời gian đến để thay cho thời gian của nhà cung cấp.

Đoạn JavaScript này chỉ lấy phạm vi tin nhắn từ sự kiện đã xác minh chữ ký. Nó không phải bộ tiếp nhận hay triển khai cơ sở dữ liệu hoàn chỉnh:

function receiptMessageIds(event) {
  if (!['message.delivered', 'message.read'].includes(event.type)) return [];
  const message = event.data?.message;
  const ids = message?.ids === undefined ? [message?.id] : message.ids;
  if (!Array.isArray(ids) || ids.length === 0 ||
      ids.some(id => typeof id !== 'string' || id.length === 0)) {
    throw new Error('Receipt scope needs review');
  }
  return [...new Set(ids)];
}

Đừng âm thầm chuyển sang ID đơn khi dữ liệu lô không hợp lệ. Giữ sự kiện để điều tra thay vì cập nhật theo phạm vi phỏng đoán.

Hợp nhất mà không tự tạo bằng chứng

Giữ quan sát đã nhận và đã đọc độc lập. Nếu xác nhận đã đọc đến trước xác nhận đã nhận, có thể hiển thị “đã ghi nhận đọc” mà không tự tạo delivered_at. Sự kiện đã nhận đến sau chỉ bổ sung bằng chứng, không được hạ nhãn về “đã nhận”. Sự kiện lặp lại cũng không được tạo thông báo trùng.

Nếu chưa có nội dung tin nhắn, giữ xác nhận theo danh tính tin nhắn có đầy đủ phạm vi rồi liên kết khi bản ghi tương ứng xuất hiện. Không tạo tin nhắn đến hoặc tăng số lượng trong hộp thư chỉ từ xác nhận. Dùng occurred_at và ID sự kiện để có thứ tự xử lý xác định, nhưng không áp dụng quy tắc lấy trạng thái đến cuối cùng ghi đè mọi thứ.

Khi gửi, lưu message_id và provider_ref trong phản hồi cùng thao tác nội bộ. Trước khi nối xác nhận, xác định mã nào tương ứng với tin nhắn của nhà cung cấp đã quan sát; các trường khác tên không bảo đảm luôn có giá trị bằng nhau. Xác nhận không khớp phải vào hàng đợi đối soát, không gắn vào tin nhắn gần nhất về thời gian. Giữ danh tính người gửi có sẵn, nhưng không biến một quan sát thành “mọi người đã đọc”.

Hướng dẫn xử lý lỗi gửi media giải quyết nguồn tệp và bước tiếp nhận yêu cầu. Xác nhận thuộc một lớp khác. Timeout hoặc thiếu xác nhận không được tự động kích hoạt lần gửi mới.

Giới hạn hỗ trợ và các ca kiểm thử

UnifyPort là giao diện không chính thức. Ma trận sự kiện theo nhà cung cấp mô tả khả năng ánh xạ của bộ phân tích, không bảo đảm mọi tài khoản hay môi trường đều phát xác nhận. Với hộp thư kết hợp WhatsApp và Zalo, cũng như khi thêm LINE, cần kiểm tra từng nhà cung cấp trước khi cam kết hiển thị trạng thái đã nhận. Cùng một cấu trúc sự kiện không có nghĩa mọi kênh đều phát cùng loại xác nhận.

Không có xác nhận không chứng minh tin chưa đọc, gửi thất bại hoặc bị chặn. Việc phát lại payload đã bỏ lỡ cũng không được bảo đảm.

Các ca nên thử: lô gồm hai tin nhắn, xác nhận đơn, sự kiện trùng, đã đọc đến trước đã nhận, xác nhận đến trước nội dung, cùng ID ở hai tài khoản, dữ liệu lô không hợp lệ và không có xác nhận. Kiểm tra chỉ những ID được liệt kê rõ ràng mới thay đổi và không ca nào tự gửi lại. Đây là kế hoạch kiểm thử, không phải kết quả đã thực hiện.

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

Nên xử lý id hay ids?

Dùng ids nếu có lô hợp lệ và không rỗng. Nếu không, dùng id đơn. Phạm vi không hợp lệ cần được điều tra.

Có thể điền delivered_at từ xác nhận đã đọc không?

Không. Hiển thị bằng chứng đã đọc, nhưng không tự tạo thời gian giao nhận của nhà cung cấp.

Thiếu xác nhận có nghĩa gửi thất bại không?

Không thể kết luận chỉ từ điều đó. Giữ trạng thái xác nhận là chưa biết rồi kiểm tra hỗ trợ, đăng ký sự kiện, luồng tiếp nhận và đối chiếu ID.

Bước tiếp theo và nguồn tham khảo

Bắt đầu với tài liệu xác nhận đã nhận, triển khai nơi lưu quan sát có phạm vi rõ ràng trước khi thêm nhãn trạng thái vào giao diện.

Tài liệu sản phẩm được kiểm tra ngày 2026-11-06:

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.