Cách xử lý reaction của tin nhắn bằng webhook hợp nhất
Để xử lý reaction, hãy đăng ký message.reaction, xác minh chữ ký Webhook bằng request body nguyên gốc, rồi dùng data.message.target_message_id làm ID của tin nhắn được reaction. Emoji nằm trong data.event.reaction; chuỗi rỗng có nghĩa là reaction đã bị gỡ. Trước khi cập nhật trạng thái, cần loại bản giao trùng bằng ID sự kiện ở cấp cao nhất.
Điểm chính
data.message.idnhận diện chính reaction, không phải tin nhắn gốc.data.message.target_message_idnhận diện tin nhắn được reaction.data.event.reactionchứa emoji;""có nghĩa là gỡ reaction.- Xác minh
X-Device-Signaturetrước khi parse JSON. - Mức hỗ trợ khác nhau theo nền tảng; tên sự kiện hợp lệ không đảm bảo mọi provider đều phát sự kiện đó.
Đọc payload message.reaction
UnifyPort chuẩn hóa reaction thành sự kiện message.reaction. Một nhóm hỗ trợ dùng chung WhatsApp và Zalo có thể coi 👍 là đã xác nhận, chuyển 👎 sang bước kiểm tra thủ công, hoặc chỉ hiển thị emoji hiện tại trong hộp thư chung. Đó là quy tắc của ứng dụng; sự kiện chỉ mô tả thay đổi vừa xảy ra.
Tham chiếu sự kiện Webhook chuẩn chính thức cung cấp cấu trúc message.reaction sau:
{
"id": "evt_2f9c1a4b7e",
"type": "message.reaction",
"provider": "whatsapp",
"account_id": "acc_8c21d0",
"occurred_at": "2026-06-08T12:35:40Z",
"data": {
"conversation": { "id": "8613912345678", "type": "user" },
"sender": { "id": "8613912345678", "type": "user", "name": "Jordan Lee" },
"message": { "id": "wamid.HBgZ", "target_message_id": "wamid.HBgM" },
"event": { "kind": "message_reaction", "reaction": "👍" }
}
}
Ba ID có ba vai trò khác nhau. data.message.id là bản ghi reaction, data.message.target_message_id trỏ tới tin nhắn gốc, còn id cấp cao nhất nhận diện sự kiện Webhook chuẩn. Trong ví dụ này, cần gắn 👍 với wamid.HBgM, không phải wamid.HBgZ.
Lưu trạng thái hiện tại, không chỉ nối thêm sự kiện
Nhật ký append-only phù hợp cho kiểm tra và chẩn đoán, nhưng giao diện hộp thư thường cần trạng thái hiện tại. Một khóa trạng thái thực tế nên kết hợp:
provideraccount_iddata.conversation.iddata.message.target_message_iddata.sender.id
Khi data.event.reaction không rỗng, lưu emoji hiện tại của người gửi đối với tin nhắn đích. Khi giá trị là chuỗi rỗng, xóa trạng thái tương ứng. Không lưu chuỗi rỗng như một loại reaction mới.
Trước khi cập nhật projection, hãy ghi sự kiện vào queue hoặc cơ sở dữ liệu bền vững và tạo unique constraint cho id cấp cao nhất. Cách này ngăn một lần gửi lại hợp lệ áp dụng thay đổi hai lần. Nếu receiver hiện chỉ nhận tin nhắn đến, hướng dẫn bộ lọc sự kiện Webhook cho biết cách thêm message.reaction mà chưa cần chuyển sang wildcard.
Áp dụng trạng thái bằng Node.js
Đoạn mã cốt lõi dưới đây dùng các field có thật trong API reference. Map chỉ phục vụ minh họa; trong production nên thay bằng bảng cơ sở dữ liệu có transaction và unique constraint.
const event = JSON.parse(rawBody.toString('utf8'));
if (event.type === 'message.reaction') {
const { conversation, sender, message, event: detail } = event.data;
if (!message?.target_message_id || typeof detail?.reaction !== 'string') {
throw new Error('Invalid message.reaction payload');
}
const key = [event.provider, event.account_id, conversation.id,
message.target_message_id, sender.id].join(':');
if (detail.reaction === '') reactionState.delete(key);
else reactionState.set(key, {
emoji: detail.reaction,
reactionMessageId: message.id,
occurredAt: event.occurred_at,
});
}
Chỉ chạy logic này sau khi xác minh chữ ký. Khi endpoint có signing_secret, X-Device-Signature là HMAC-SHA256 dạng hex của <X-Device-Timestamp>.<request body nguyên gốc>. Không parse rồi serialize lại JSON trước khi xác minh. Quy trình đầy đủ nằm trong tài liệu giao Webhook và xác minh chữ ký; thời gian, giao lại và idempotency bền vững được giải thích thêm trong hướng dẫn HMAC và xử lý bản giao lặp an toàn.
Chọn subscription và cách xử lý lỗi
Consumer chỉ xử lý reaction có thể dùng:
{
"subscribed_events": ["message.reaction"]
}
Hộp thư hợp nhất thường đăng ký cả message.received và message.reaction. Chỉ nên dùng "*" cho collector tổng quát đã sẵn sàng nhận mọi sự kiện chuẩn công khai.
Chỉ trả 2xx sau khi đã tiếp nhận bền vững. Từ chối chữ ký không hợp lệ và đưa payload sai cấu trúc vào luồng lỗi có thể quan sát. Trước khi dùng emoji làm tín hiệu phê duyệt duy nhất, hãy kiểm tra ma trận sự kiện Webhook theo provider.
UnifyPort phù hợp ở đâu
UnifyPort cung cấp giao diện không chính thức và chuẩn hóa sự kiện từ các nền tảng được hỗ trợ vào cùng một envelope. Ứng dụng có thể định tuyến theo event.type và tái sử dụng cùng logic trạng thái ở những kết nối có message.reaction.
Chuẩn hóa không tạo ra khả năng mà nền tảng nguồn không có. Nếu reaction là dữ liệu bắt buộc cho kiểm toán, phê duyệt hoặc lưu hồ sơ, hãy xác minh từng nền tảng và chọn API chính thức khi hợp đồng sự kiện của nó phù hợp hơn.
Câu hỏi thường gặp
Field nào nhận diện tin nhắn gốc?
Dùng data.message.target_message_id. data.message.id nhận diện chính reaction.
Làm sao biết reaction đã bị gỡ?
Kiểm tra data.event.reaction. Chuỗi rỗng nghĩa là đã gỡ; chuỗi không rỗng chứa emoji hiện tại.
Có thể loại trùng bằng target_message_id không?
Không. Nhiều người có thể reaction cùng một tin nhắn và một người có thể đổi emoji. Hãy loại bản giao trùng bằng id cấp cao nhất.
Mọi nền tảng đều gửi message.reaction phải không?
Không. Tên sự kiện hợp lệ và mức hỗ trợ thực tế là hai vấn đề khác nhau. Cần kiểm tra ma trận trước khi triển khai.
Bước tiếp theo
Mở tham chiếu tạo Webhook endpoint, thêm message.reaction vào subscribed_events, cấu hình signing_secret, rồi kiểm thử cả thêm và gỡ reaction.
Nguồn
Nguồn chính thức, kiểm tra ngày 20 tháng 8 năm 2026: