Spec nghiệp vụ — Node Đa kênh: Zalo cá nhân
Phiên bản: 2.0 · Cập nhật: 01/10/2026
Đối tượng sử dụng: BA, Product, Designer, QA và đội phát triển.
Thiết kế tham chiếu: https://www.figma.com/design/ATYdUgiA22OXRB23kb0ipK?node-id=51156-51586
1. Mục tiêu và phạm vi
Node Đa kênh hỗ trợ một hành động cấp cao: Kết bạn, gửi tin nhắn & liên kết khách hàng qua Zalo cá nhân. Trong Cài đặt, người dùng tick một hoặc nhiều thao tác để thực hiện trong cùng node.
Phạm vi phiên bản này: tài khoản Zalo cá nhân đã kết nối; lời mời kết bạn; tin nhắn văn bản đầu tiên; tin nhắn văn bản vào thread cá nhân/nhóm đã có; liên kết thread với liên hệ CRM.
Các thay đổi đã chốt theo trao đổi và thiết kế
- Tên node là Đa kênh; chỉ hỗ trợ Zalo cá nhân trong hành động này.
- Ba tab: Hành động, Cài đặt, Đầu ra. Không có tab Auth.
- Một ô tài khoản Zalo: chọn tài khoản cụ thể hoặc biến user từ bước trước để xác định tài khoản Zalo được liên kết với user.
- Bốn thao tác dạng checkbox, không có khung viền riêng bao quanh.
- Bỏ Nguồn hội thoại và Nguồn liên hệ cùng các dropdown nguồn.
- Thêm ô
thread_id: chọn thread chat hoặc nhập SĐT để tự tìm thread phù hợp. - Giữ ô Người nhận; điền một trong hai ô Người nhận hoặc Thread ID.
- Khi tick liên kết, giữ ô Liên hệ cần liên kết, nhận contact ID hoặc biến contact ID.
- Chèn biến bằng icon dấu cộng; có Tin nhắn nhanh ở phần tin nhắn đầu tiên.
- Không có nút Lưu riêng của node, trường mục đích gửi tin hoặc các khối information màu xanh. Việc lưu dùng cơ chế của editor hiện tại.
- Đầu ra hiển thị danh sách tên biến kèm icon kiểu dữ liệu theo mẫu Figma.
Các quy tắc chi tiết chưa được người dùng chốt trực tiếp được ghi là đề xuất mặc định trong mục 10. Tài liệu này mô tả yêu cầu, không khẳng định chức năng đã triển khai hoặc tên trường đã khớp API hiện tại.
2. Tổ chức giao diện
| Tab | Nội dung |
|---|---|
| Hành động | Một lựa chọn: Kết bạn, gửi tin nhắn & liên kết khách hàng qua Zalo cá nhân |
| Cài đặt | Tài khoản Zalo; Người nhận; Thread ID; bốn checkbox và cấu hình tương ứng |
| Đầu ra | Các biến chung và biến kết quả của thao tác được tick; mỗi dòng có icon kiểu dữ liệu và tên biến |
Trường cấu hình chung
| Trường | Giá trị và tương tác | Bắt buộc |
|---|---|---|
| Tài khoản Zalo | Chọn tài khoản Zalo cá nhân hoặc chọn biến user ID từ bước trước. Chưa chọn: placeholder màu nhạt theo design system. Đã chọn: avatar + tên Zalo hoặc biến user | Có |
| Người nhận | SĐT trực tiếp hoặc biến trả về SĐT, ví dụ `` | Một trong hai ô Người nhận/Thread ID |
Thread ID (thread_id) |
Combobox cho chọn thread chat, nhập SĐT hoặc chọn biến trả về ID thread/SĐT | Một trong hai ô Người nhận/Thread ID |
| Thao tác | Tick Gửi lời mời kết bạn / Gửi tin nhắn Zalo đầu tiên / Gửi tin vào hội thoại / Liên kết liên hệ | Ít nhất một |
Không suy luận đầu vào Người nhận là contact ID. Nếu có contact từ node trước, sử dụng thuộc tính SĐT của contact tại ô này. Contact ID phục vụ liên kết được nhập riêng tại Liên hệ cần liên kết.
Chi tiết ô Thread ID
- Placeholder: Chọn thread chat hoặc nhập số điện thoại.
- Chọn thread: lưu ID thread nội bộ; hiển thị tên hội thoại, loại Cá nhân/Nhóm, tài khoản Zalo. ID thật vẫn có thể xem khi cần.
- Nhập SĐT: hiển thị SĐT; tự tra cứu thread thuộc tài khoản Zalo đã chọn. Nếu tìm thấy duy nhất một kết quả, hiển thị thread đã resolve.
- Chọn biến: hiển thị biến, ví dụ
hoặc; resolve khi node chạy. Không báo lỗi không tìm thấy chỉ vì chưa có dữ liệu runtime. - Không thêm dropdown Nguồn. Chọn thread từ picker xác định giá trị là ID; SĐT nhập tự do được nhận diện theo định dạng điện thoại. Biến lấy kiểu dữ liệu từ output node trước; nếu kiểu chưa rõ, kiểm tra khi thực thi.
- Không diễn giải một thread ID chỉ gồm chữ số thành SĐT khi nó đến từ lựa chọn thread hoặc biến có kiểu thread ID.
- Đổi tài khoản Zalo: bỏ thread chọn cứng thuộc tài khoản cũ; với SĐT thì tìm lại trong tài khoản mới; với biến thì xác minh lại khi chạy.
- Đề xuất trạng thái UI: trống, đang tìm, tìm thấy, không tìm thấy, nhiều kết quả, không có quyền/mất kết nối.
3. Quy tắc xác định thread từ SĐT
- Resolve và kiểm tra tài khoản Zalo trước khi tìm thread.
- Chuẩn hóa SĐT theo quy tắc chung của hệ thống; các dạng tương đương như
0901234678và+84901234678phải được đối chiếu nhất quán. - Tìm trong đúng workspace, đúng tài khoản Zalo và phạm vi hội thoại người dùng được phép truy cập.
- Đối chiếu SĐT với hồ sơ người tham gia đã xác minh hoặc mapping SĐT ↔ Zalo UID. Không tìm theo chuỗi SĐT xuất hiện trong nội dung tin nhắn, tên nhóm hay ghi chú.
- Tìm bằng SĐT chỉ resolve thread cá nhân của người đó. Chat nhóm phải chọn trực tiếp hoặc dùng biến thread ID.
- Không yêu cầu thread đã liên kết contact để được tìm thấy. Có Zalo UID cũng chưa đồng nghĩa đã có thread nội bộ.
| Kết quả | Hành vi đề xuất |
|---|---|
| Một thread phù hợp | Dùng ID thread nội bộ để thực thi các thao tác phụ thuộc thread |
| Không có thread | Báo Không tìm thấy hội thoại phù hợp. Không tự tạo thread hoặc chuyển sang gửi tin đầu tiên từ ô Thread ID |
| Nhiều thread phù hợp | Cấu hình bằng SĐT cố định: hiển thị danh sách để chọn một thread. Dữ liệu runtime: trả lỗi mơ hồ; không tự lấy kết quả đầu tiên |
| Thread thuộc tài khoản khác | Không tự đổi tài khoản; báo không khớp tài khoản |
| SĐT không hợp lệ | Báo lỗi định dạng; chưa thực hiện hành động |
| Thiếu mapping đủ tin cậy | Báo chưa xác định được thread; không đoán từ lịch sử tin nhắn |
Người muốn kết bạn/gửi tin lần đầu khi chưa có thread sử dụng ô Người nhận. Người đã có thread sử dụng ô Thread ID. Hai đường nhập phục vụ hai tình huống khác nhau.
4. Quy tắc đầu vào và hiển thị form
| Tình huống | Hành vi |
|---|---|
| Cả hai ô Người nhận và Thread ID trống | Báo cần điền một trong hai ô |
| Cả hai ô có giá trị | Báo chỉ chọn một cách xác định người nhận/hội thoại; không ưu tiên ngầm một ô |
| Thread cá nhân + kết bạn/tin đầu tiên | Lấy người nhận từ danh tính của thread, không lấy SĐT bất kỳ trong tin nhắn |
| Thread nhóm + kết bạn/tin đầu tiên | Không cho thực hiện hai thao tác này; đề nghị chọn thread cá nhân hoặc bỏ tick |
| Người nhận + gửi vào hội thoại | Tìm thread cá nhân hiện có; nếu tin đầu tiên vừa tạo/resolve thread, dùng thread đó |
| Người nhận + liên kết | Resolve thread tương ứng; chỉ liên kết sau khi có ID thread nội bộ và danh tính phù hợp |
| Liên kết được tick | Hiển thị Liên hệ cần liên kết; bắt buộc contact ID hoặc biến contact ID |
| Một thao tác không được tick | Ẩn phần điền tương ứng; không thực thi và không yêu cầu dữ liệu của thao tác đó |
Validation áp dụng ở cấu hình đối với giá trị cố định và được kiểm tra lại khi thực thi đối với biến.
5. Bốn thao tác
5.1. Gửi lời mời kết bạn
- Hiển thị checkbox và textarea lời giới thiệu, có icon dấu cộng để chèn biến.
- Resolve người nhận từ Người nhận hoặc từ thread cá nhân đã xác định.
- Đã là bạn hoặc lời mời đang chờ: bỏ qua; đây không phải lỗi.
- Gửi thành công chỉ có nghĩa đã gửi lời mời, không có nghĩa khách đã chấp nhận.
- Nếu không kiểm tra được quan hệ, trả lỗi; không mặc định coi là chưa kết bạn.
- Không tự chấp nhận lời mời do người nhận gửi đến trong phạm vi này.
5.2. Gửi tin nhắn Zalo đầu tiên
- Hiển thị textarea, Tin nhắn nhanh và icon dấu cộng để chèn biến.
- Nội dung bắt buộc khi tick; không có trường Mục đích gửi tin.
- Gửi nếu đáp ứng điều kiện của kênh. Nếu bị từ chối do chưa là bạn, trả kết quả thất bại; không tự chờ vô thời hạn.
- Theo giao diện hiện tại, không có cấu hình Điều kiện gửi/Thời hạn chờ; không đưa lại hai trường này vào phiên bản này.
- Đề xuất chống gửi lời chào lặp theo tài khoản Zalo + người nhận trên phạm vi workspace; không dùng mã mục đích do người cấu hình nhập.
- Nếu đã ghi nhận gửi thành công trước đó, trả
skipped; không gửi lại khi retry. - Sau gửi, resolve thread nội bộ để các thao tác tiếp theo dùng. Nếu chưa đồng bộ thread, ghi nhận tin đã gửi; không gửi lại chỉ để tạo thread.
- Cần thống nhất phạm vi “tin đầu tiên” tại mục 10 trước triển khai.
5.3. Gửi tin vào hội thoại
- Hiển thị checkbox, textarea Nội dung tin nhắn và icon chèn biến. Bỏ các ô Nguồn hội thoại/Giá trị cũ.
- Nội dung bắt buộc khi tick. Dùng thread đã resolve từ cấu hình chung.
- Hỗ trợ thread cá nhân và nhóm. Với nhóm, tài khoản gửi phải còn quyền gửi tin trong nhóm.
- Nếu vừa thực hiện tin đầu tiên qua đường Người nhận, sử dụng thread của người nhận đó sau khi resolve thành công.
- Không có thread thì trả lỗi; không tự đổi thành thao tác Gửi tin nhắn Zalo đầu tiên.
- Được gửi nhiều lần trong các lần chạy nghiệp vụ khác nhau; chỉ chống trùng do retry cùng lần thực thi.
- Nếu tick cả tin đầu tiên và gửi vào hội thoại, hai nội dung là hai tin riêng, gửi theo thứ tự; UI không gộp thành một tin.
5.4. Liên kết liên hệ
- Hiển thị Liên hệ cần liên kết, chọn một liên hệ CRM hoặc biến contact ID. Bỏ Nguồn liên hệ, Nguồn hội thoại và ô giá trị nguồn cũ.
- Dùng thread đã xác định từ cấu hình chung; không chọn thêm thread ở thao tác này.
- Contact phải tồn tại trong workspace và người dùng có quyền thao tác.
- Thread cá nhân: xác minh danh tính người nhận phù hợp với contact trước khi liên kết.
- Thread nhóm: chỉ cho liên kết khi danh tính contact được xác minh là thành viên của nhóm được chọn; không coi SĐT trong tin nhắn là bằng chứng.
- Chưa gắn contact: tạo liên kết. Đã gắn đúng contact:
skippedvới lý doALREADY_LINKED. - Đã gắn contact khác: báo
CONTACT_LINK_CONFLICT; không tự thay thế. - Contact không tồn tại: báo lỗi; không tự tạo contact.
- Thiếu dữ liệu xác minh: báo chưa đủ dữ liệu, không ghi liên kết.
6. Thứ tự và kết quả thực thi
Thứ tự cố định cho các thao tác được tick:
- Gửi lời mời kết bạn.
- Gửi tin nhắn Zalo đầu tiên.
- Gửi tin vào hội thoại.
- Liên kết liên hệ.
Trước thao tác đầu tiên, kiểm tra tài khoản, quyền và dữ liệu cố định có thể xác minh. Các điều kiện phụ thuộc kết quả trước, như thread vừa được đồng bộ, được kiểm tra tại thời điểm cần sử dụng.
- Đề xuất mặc định dừng các thao tác còn lại nếu một thao tác thất bại; thao tác bỏ qua do đã thực hiện không làm dừng chuỗi.
- Kết quả thao tác đã thành công không bị xóa hoặc gửi lại nếu thao tác sau thất bại.
- Retry chỉ xử lý phần chưa hoàn tất và có thể thử lại an toàn; không lặp lời mời/tin đã thành công.
- Timeout sau khi gửi mà chưa biết kết quả:
unknown; cần đối soát trước khi gửi lại. - Khi tin đầu tiên đã gửi nhưng thread chưa đồng bộ, giữ kết quả gửi và chỉ thử resolve thread lại; nếu vẫn chưa có thì các thao tác phụ thuộc thread chưa được thực hiện.
- Áp dụng giới hạn gửi của hệ thống/kênh theo tài khoản; tài liệu không đặt ra số lượt cố định của Zalo.
7. Đầu ra của node
Tên biến dưới đây là contract nghiệp vụ đề xuất để BA và đội phát triển thống nhất. ID đều biểu diễn kiểu string; thread_id là ID thread nội bộ, không phải SĐT hoặc Zalo UID.
| Biến | Kiểu | Ý nghĩa |
|---|---|---|
status |
String | success, partial_success, failed, skipped, unknown |
zalo_account_id |
String | Tài khoản Zalo thực tế đã sử dụng |
recipient_id |
String / null | Zalo UID người nhận; null nếu không có người nhận cá nhân |
thread_id |
String / null | Thread nội bộ được chọn hoặc tìm thấy |
contact_id |
String / null | Liên hệ dùng cho thao tác liên kết, không suy ra từ SĐT một cách mơ hồ |
friend_request.status |
String | success, skipped, failed, not_executed, unknown |
friend_request.id |
String / null | ID lời mời nếu kênh trả về; không tự tạo ID giả |
first_message.status |
String | Kết quả tin nhắn đầu tiên |
first_message.id |
String / null | ID tin nhắn đầu tiên |
message.status |
String | Kết quả gửi tin vào hội thoại |
message.id |
String / null | ID tin nhắn gửi vào hội thoại |
contact_link.status |
String | Kết quả liên kết liên hệ |
error_code |
String / null | Mã lỗi hoặc mã cần đối soát khiến node chưa hoàn tất |
error_message |
String / null | Diễn giải dễ hiểu về lỗi/kết quả chưa xác định |
Quy tắc output:
- Tab Đầu ra thể hiện các biến chung và nhóm của thao tác được tick. Runtime giữ schema ổn định: thao tác không tick hoặc chưa đến lượt có trạng thái
not_executed, các ID chưa có trả null. success: toàn bộ thao tác được tick đã thành công hoặc bỏ qua hợp lệ, có ít nhất một thao tác thành công.skipped: tất cả thao tác được tick đều được bỏ qua hợp lệ.failed: có lỗi và chưa có thao tác nào thành công.partial_success: có thao tác thành công trước khi xảy ra lỗi ở thao tác sau.unknown: có kết quả gửi chưa xác định; kết quả đã biết của từng thao tác vẫn được giữ.- ID tin nhắn và trạng thái thành công không chứng minh người nhận đã đọc tin.
- Thiết kế đầu ra cũ đang có
conversation_id: spec này thống nhất đổi thànhthread_id. Nếu hệ thống cần tương thích tên cũ, mapping là công việc kỹ thuật, không tạo hai trường nhập cho người dùng.
8. Thông báo và mã lỗi đề xuất
| Mã | Thông báo |
|---|---|
TARGET_REQUIRED |
Điền Người nhận hoặc Thread ID. |
TARGET_INPUT_CONFLICT |
Chỉ điền một trong hai trường Người nhận hoặc Thread ID. |
INVALID_PHONE |
Số điện thoại không hợp lệ. |
ACCOUNT_NOT_RESOLVED |
Chưa xác định được tài khoản Zalo từ user đã chọn. |
ACCOUNT_UNAVAILABLE |
Tài khoản Zalo không sẵn sàng để thực hiện hành động. |
THREAD_NOT_FOUND |
Không tìm thấy hội thoại phù hợp trong tài khoản Zalo này. |
THREAD_AMBIGUOUS |
Tìm thấy nhiều hội thoại. Hãy chọn thread cụ thể. |
ACCOUNT_THREAD_MISMATCH |
Hội thoại không thuộc tài khoản Zalo đã chọn. |
THREAD_ACCESS_DENIED |
Không có quyền truy cập hoặc gửi tin vào hội thoại. |
PERSONAL_THREAD_REQUIRED |
Kết bạn và gửi tin nhắn đầu tiên chỉ áp dụng cho người nhận cá nhân. |
THREAD_NOT_SYNCED |
Tin đã gửi nhưng hội thoại chưa đồng bộ; chưa thể thực hiện thao tác cần thread. |
CONTACT_REQUIRED |
Chọn liên hệ cần liên kết. |
CONTACT_NOT_FOUND |
Không tìm thấy liên hệ phù hợp. |
IDENTITY_NOT_VERIFIED |
Chưa đủ thông tin xác minh liên hệ và hội thoại. |
CONTACT_LINK_CONFLICT |
Hội thoại đã liên kết với liên hệ khác. |
SEND_OUTCOME_UNKNOWN |
Chưa xác định được kết quả gửi; cần đối soát trước khi thử lại. |
ALREADY_FRIEND, FRIEND_REQUEST_PENDING, FIRST_MESSAGE_ALREADY_SENT và ALREADY_LINKED là lý do bỏ qua hợp lệ, không phải lỗi làm dừng node. Nhật ký thực thi lưu lý do theo thao tác.
9. Tiêu chí nghiệm thu
| ID | Tình huống | Kết quả mong đợi |
|---|---|---|
| AC01 | Mở node | Tên Đa kênh; ba tab; không có Auth hoặc nút Lưu riêng |
| AC02 | Chọn tài khoản cụ thể/biến user | Hiển thị avatar + tên hoặc biến; runtime resolve đúng tài khoản |
| AC03 | Chưa tick/tick/bỏ tick thao tác | Chỉ hiển thị và yêu cầu nội dung tương ứng; không có dropdown nguồn cũ |
| AC04 | Chọn thread trực tiếp | Hiển thị tên/loại/tài khoản; thực thi trên đúng ID thread |
| AC05 | Thread ID nhập SĐT, có một thread | Tự tìm đúng thread trong tài khoản và workspace đã chọn |
| AC06 | Nhập dạng SĐT tương đương | Chuẩn hóa và resolve cùng người nhận/thread |
| AC07 | Cùng SĐT tồn tại ở tài khoản/workspace khác | Không lấy thread ngoài phạm vi |
| AC08 | Không có/nhiều thread khi resolve SĐT | Báo trạng thái tương ứng; không tạo thread hoặc tự chọn kết quả đầu tiên |
| AC09 | Chỉ có SĐT trong tin nhắn hoặc thành viên nhóm | Không tự coi đó là thread cá nhân phù hợp |
| AC10 | Thread ID đến từ biến; ID chỉ gồm số | Giữ kiểu thread ID, không diễn giải nhầm thành SĐT |
| AC11 | Cả hai ô trống/cùng có giá trị | Chặn thực thi và báo lỗi đầu vào tương ứng |
| AC12 | Thread nhóm + kết bạn/tin đầu tiên | Chặn tổ hợp không hợp lệ; gửi tin nhóm vẫn dùng được khi có quyền |
| AC13 | Đã là bạn/đang chờ lời mời | Không gửi lại lời mời; trả skipped và lý do |
| AC14 | Retry tin đầu tiên đã thành công | Không gửi lại; giữ ID và kết quả cũ |
| AC15 | Tin đầu tiên thành công nhưng thread chưa đồng bộ | Không gửi lại; thao tác phụ thuộc thread chưa được thực hiện |
| AC16 | Tick hai thao tác gửi tin | Gửi hai nội dung theo thứ tự khi đủ điều kiện; ghi hai kết quả riêng |
| AC17 | Liên kết đúng contact/đã gắn contact khác | Bỏ qua hợp lệ hoặc báo xung đột; không thay thế ngầm |
| AC18 | Liên kết thất bại sau khi đã gửi | Giữ kết quả gửi; retry không gửi trùng |
| AC19 | Đổi tài khoản sau khi chọn thread | Xóa lựa chọn không còn phù hợp hoặc resolve lại theo SĐT/biến |
| AC20 | Timeout kết quả gửi chưa xác định | Trả unknown; không tự gửi lại |
| AC21 | Xem Đầu ra | Icon kiểu dữ liệu + tên biến; có thread_id; ID chưa resolve là null |
10. Các giả định cần chốt trước triển khai
Không chặn việc review spec; đây là những quy tắc mặc định được đề xuất vì yêu cầu hiện tại chưa quyết định chi tiết.
| Vấn đề | Đề xuất mặc định trong spec |
|---|---|
| User được liên kết nhiều tài khoản Zalo | Dùng tài khoản mặc định cho automation; chưa có mặc định thì báo chưa resolve, không chọn ngẫu nhiên |
| Thread ID nhập SĐT nhưng chưa có thread | Báo không tìm thấy; sử dụng đường Người nhận để kết bạn/gửi tin đầu tiên |
| Nhiều thread cá nhân phù hợp | Yêu cầu chọn rõ hoặc trả lỗi runtime; không lấy thread mới nhất/đầu tiên ngầm |
| Định nghĩa tin nhắn đầu tiên | Một lần gửi lời chào automation thành công theo tài khoản + người nhận trên workspace; chưa đồng nhất với toàn bộ lịch sử tin nhắn thủ công |
| Chưa là bạn nhưng tick gửi tin đầu tiên | Thực hiện theo khả năng kênh; không có cơ chế chờ thành bạn trong giao diện hiện tại |
| Một thao tác thất bại | Dừng thao tác còn lại; bảo toàn kết quả đã thành công |
| Liên kết nhóm và số contact/thread | Giữ một contact/thread, yêu cầu xác minh thành viên; hỗ trợ nhiều contact/nhóm là phạm vi riêng |
| Thread chưa đồng bộ sau tin đầu tiên | Chỉ thử resolve lại có giới hạn, không gửi lại tin; thời gian/số lần theo quy tắc đồng bộ hiện có của hệ thống |
11. Ghi chú bàn giao
Tài liệu này thay thế đề xuất cũ có sáu tab, một node/một thao tác và dropdown Nguồn hội thoại/Nguồn liên hệ. Không dùng các phần đó để triển khai phiên bản mới.
Thiết kế Figma hiện tại đã thể hiện ô Thread ID và Liên hệ cần liên kết. Việc thread picker cho nhập SĐT, trạng thái tìm kiếm và đổi đầu ra từ conversation_id sang thread_id cần được đối chiếu khi bàn giao UI. Spec này không tự thay đổi Figma hoặc khẳng định runtime đã hỗ trợ các quy tắc mới.