agentsclimarketplace

Creating zalo oa chatbot

Skill duongxthanh/claude-zalo-skills/skills/creating-zalo-oa-chatbot

Use when a chatbot/app needs to SEND Zalo Official Account (OA) messages to a user — handoff notifications, alerts, customer-service replies. Dùng khi cần cho chatbot gửi tin nhắn qua Zalo OA (thông báo handoff, nhắc lịch, trả lời CSKH). Guides creating a dedicated Zalo app, authorizing the OA, the OAuth code→token exchange, and wiring a token-manager that survives refresh_token rotation (crash sau ~25h nếu làm sai).From its SKILL.md

Install
npx -y skills add duongxthanh/claude-zalo-skills --skill creating-zalo-oa-chatbot

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

8.0 KB, ~2.5k tokens by cl100k_base, as published. Nobody here has run it

Tích hợp Zalo OA vào chatbot (gửi tin từ app/script)

Tổng quan

Cho chatbot/script gửi tin nhắn qua Official Account (OA) của Zalo tới một người dùng — ví dụ agent gặp ca ngoài phạm vi thì handoff: bắn tóm tắt vào Zalo của nhân viên. Skill này đi từ tạo app Zalo riêng → cấp quyền OA → đổi OAuth code lấy token → wire helper gửi tin, kết thúc bằng 1 tin test gửi thật.

CS message vs ZNS. Skill này dùng /message/cs (Customer Service) — chỉ gửi được cho người đã nhắn OA trong cửa sổ CS (Zalo giới hạn ~48h kể từ tin cuối của họ). Handoff nội bộ (gửi cho nhân viên chủ động nhắn OA) hợp với CS. Muốn gửi chủ động cho khách bất kỳ (nhắc lịch, marketing) → cần ZNS template trả phí, cơ chế khác.

Điểm cốt lõi khiến việc này dễ hỏng: refresh_token XOAY

Zalo xoay refresh_token MỖI lần bạn refresh access_token — token cũ vô hiệu ngay. access_token sống ~25h (expires_in≈90000). Hệ quả:

  • Không lưu lại refresh_token mới ⇒ sau 25h app crash, không gửi được tin.
  • Mỗi chatbot/app một Zalo app RIÊNG. Hai app/tiến trình xoay cùng một refresh_token sẽ vô hiệu token của nhau. Tách app = token độc lập, không đạp lên nhau.

zalo_oa.py (kèm skill) lo hết: cache access_token theo hạn, chỉ refresh khi hết hạn, và ghi đè refresh_token đã xoay trở lại file config.

Quy trình (làm 1 lần để lấy token)

1. Tạo app riêng + kích hoạt

developers.zalo.meTạo ứng dụng → đặt tên, chọn danh mục. Ghi lại App ID (công khai) và App Secret (BÍ MẬT — không commit). Vào Thông tin ứng dụng, điền Điện thoại + Email liên hệ để app chuyển "Đang hoạt động" (chưa kích hoạt thì không cấp quyền OA được).

2. Xác thực domain của redirect_uri

developers.zalo.me/app/<APP_ID>/verify-domain → thêm domain sẽ nhận code (vd https://your-bot.example.com). Verify bằng 1 trong 3: DNS TXT zalo-platform-site-verification=<token>, hoặc file HTML ở root, hoặc <meta name="zalo-platform-site-verification" content="<token>"> ở trang chủ. Chưa verify domain thì bước 3 không lưu được.

3. Khai Callback Url ở OA (chỗ hay nhầm nhất)

Vào Official Account → Thiết lập chung (/app/<APP_ID>/oa/settings) → điền "Official Account Callback Url" = đúng redirect_uri (domain vừa verify) → Cập nhật. Zalo sẽ tự sinh sẵn "Đường dẫn yêu cầu cấp quyền" khớp redirect_uri này.

ĐỪNG tự chế URL oauth.zaloapp.com/v4/oa/permission?...redirect_uri=... rồi mở thẳng — sẽ dính -14003 Invalid redirect uri. redirect_uri phải được khai TRƯỚC ở field "Official Account Callback Url" thì Zalo mới chấp nhận. (Subdomain nền tảng free như *.onrender.com vẫn dùng được một khi đã verify domain + khai đúng field này.)

⚠️ ĐỪNG bấm "Liên kết với Official Account" ở trang /oa/manage. Đó là cơ chế độc quyền 1 OA ↔ 1 app (cho Zalo Login user_id_by_app) — bấm sẽ tự hủy liên kết OA khỏi app khác đang dùng, phá setup đó. Handoff chỉ cần "cấp quyền" (không độc quyền, 1 OA cấp quyền cho nhiều app được).

4. Lấy code rồi đổi lấy token

Mở "Đường dẫn yêu cầu cấp quyền" (Zalo sinh ở bước 3) trên Chrome đã đăng nhập admin OA → tick đồng ý điều khoản → Cấp quyền. Trình duyệt redirect về redirect_uri?oa_id=...&code=XXXX → copy code (ngắn hạn, đổi ngay). Điền .zalo-config (xem dưới) rồi:

python3 zalo_oa.py path/to/.zalo-config exchange-code "XXXX"

Helper đổi code → access_token + refresh_token và lưu refresh_token vào config. Xong seed — từ đây helper tự xoay.

5. Lấy user_id người nhận

user_idtheo từng OA (OA-scoped), không phải số điện thoại. Người nhận (vd nhân viên) nhắn cho OA 1 tin (từ Zalo cá nhân của họ) để mở cửa sổ CS → rồi:

python3 zalo_oa.py path/to/.zalo-config recent

Đọc from_id của họ trong danh sách (listrecentchat, tối đa 10 hội thoại gần nhất, src=1 là user gửi). Bỏ vào ZALO_HANDOFF_USER_ID.

Config & wiring

Config<project>/config/.zalo-config (copy từ .zalo-config.example):

ZALO_APP_ID=1234567890
ZALO_APP_SECRET=xxxxxxxx
ZALO_OA_ID=9876543210
ZALO_REFRESH_TOKEN=          # helper tự điền sau exchange-code, rồi tự xoay
ZALO_HANDOFF_USER_ID=        # user_id lấy ở bước 5

Gitignore secret — thêm vào <project>/.gitignore: **/.zalo-config (chỉ commit file .example). Xác nhận đã ignore trước khi commit.

Wire vào chatbot — copy zalo_oa.py vào project, build đường dẫn config tuyệt đối từ __file__ (cron/chạy từ thư mục con sẽ không miss config):

from pathlib import Path
from zalo_oa import ZaloOA

CFG = Path(__file__).resolve().parent / "config" / ".zalo-config"
oa = ZaloOA(str(CFG))
oa.send(user_id, "🔔 Có khách cần tư vấn — anh/chị vào chốt giúp nhé.")
# Handoff mặc định: oa.send(oa.cfg["ZALO_HANDOFF_USER_ID"], text)

Verify — gửi thử: python3 zalo_oa.py config/.zalo-config send - "test handoff".

Quick reference

CầnCách
App mớidevelopers.zalo.me → Tạo ứng dụng → App ID + Secret
redirect_uri hợp lệverify-domain → khai ở OA → Thiết lập chung → Official Account Callback Url
Lấy codemở "Đường dẫn yêu cầu cấp quyền" (Zalo sinh) trên Chrome, admin OA cấp quyền
code → tokenzalo_oa.py <cfg> exchange-code <CODE> (grant_type=authorization_code)
access_token hết hạnhelper tự refresh + xoay refresh_token (grant_type=refresh_token, header secret_key)
Gửi tinPOST openapi.zalo.me/v3.0/oa/message/cs, header access_token
Lấy user_idngười nhận nhắn OA trước → zalo_oa.py <cfg> recent (listrecentchat)

Lỗi thường gặp

  • -14003 Invalid redirect uri → redirect_uri chưa khai ở "Official Account Callback Url", hoặc chưa verify domain. Đừng tự ghép URL permission bằng tay.
  • App crash sau ~25h / -124 invalid access token → không persist refresh_token đã xoay. Dùng helper này (ghi đè token vào config). Đừng để 2 tiến trình cùng xoay 1 refresh_token.
  • Bấm nhầm "Liên kết OA" → hủy liên kết OA khỏi app khác. Chỉ dùng "cấp quyền".
  • -32 / ngoài cửa sổ CS → người nhận chưa nhắn OA gần đây. Bảo họ nhắn OA 1 tin trước; hoặc chuyển sang ZNS nếu cần chủ động.
  • Không thấy người cần lấy user_id trong recent → họ chưa gửi tin (chỉ "Quan tâm" OA không đủ), hoặc đã trôi quá 10 hội thoại gần nhất.
  • Commit nhầm secret/token → gitignore .zalo-config TRƯỚC. App Secret + refresh_token không bao giờ vào repo/log/chat.
  • Chạy exchange-code với code cũcode ngắn hạn, hết hạn nhanh. Lấy xong đổi ngay.

What ships with it: 3 files

16.5 KB alongside SKILL.md, 2 of them executable

Keep looking

Skills are one crate of 326,750. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.