# n8n-nodes-zalo-gemazo

Community node n8n tích hợp Zalo theo **hai luồng**:

| Luồng | API | Dùng khi |
|-------|-----|----------|
| **Zalo Bot** (khuyến nghị doanh nghiệp) | [Zalo Bot Platform](https://bot.zapps.me/docs) — token chính thức | Chatbot, auto-reply, không cần tài khoản cá nhân |
| **Zalo cá nhân** | [zca-js](https://github.com/RFS-ADRENO/zca-js) — không chính thức | Tự động hóa tài khoản Zalo Web đầy đủ tính năng |

> **Cảnh báo (cá nhân):** API không chính thức, mô phỏng Zalo Web. Có thể vi phạm điều khoản Zalo và dẫn đến khóa tài khoản. Nên dùng tài khoản phụ để thử nghiệm.

## Cài đặt

### Community Nodes (khuyến nghị)

1. Mở n8n → **Settings** → **Community Nodes**
2. Cài package: `n8n-nodes-zalo-gemazo`
3. Tải lại editor

### Cài thủ công

```bash
cd ~/.n8n/nodes
npm install n8n-nodes-zalo-gemazo
```

## Zalo Bot (API chính thức)

### 2 node Bot

| Node | Mô tả |
|------|--------|
| **Zalo Bot Event Trigger** | Nhận tin nhắn qua webhook (tự đăng ký khi activate) |
| **Zalo Bot Tương Tác** | Gửi tin nhắn, ảnh, sticker |

### Tạo bot và credential

1. Mở app **Zalo** → tìm OA **Zalo Bot Manager** → **Tạo bot**
2. Nhập tên bot (bắt đầu bằng `Bot`, ví dụ `Bot MyShop`)
3. Zalo gửi **Bot Token** dạng `{bot_id}:{secret_key}`
4. Trong n8n: credential **Zalo Bot**:
   - **Bot Token**: dán toàn bộ chuỗi token
   - **Webhook Secret Token** (tùy chọn): chỉ cần nếu cấu hình webhook **thủ công** trên Zalo Bot Manager

### Hai cách cấu hình webhook

**Cách A — n8n tự đăng ký (khuyến nghị)**

1. Credential: chỉ điền Bot Token
2. **Zalo Bot Event Trigger** → bật **Tự Đăng Ký Webhook**
3. **Activate** workflow → n8n tự gọi `setWebhook`
4. Không cần điền Webhook trên Zalo Bot Manager

**Cách B — cấu hình tay trên Zalo Bot Manager**

1. **Activate** workflow trước → copy **Production Webhook URL** từ node trigger (dạng `/webhook/...`, **không** dùng `/webhook-test/`)
2. Trên Zalo Bot Manager: dán Webhook URL + Secret Token → **Lưu thay đổi**
3. Credential n8n: dán **cùng Secret Token** vào field **Webhook Secret Token**
4. Node trigger: **tắt** **Tự Đăng Ký Webhook**

> HTTP được Zalo chấp nhận (`http://` hoặc `https://`). Cần IP public + mở port (vd. 5678) để Zalo gọi được vào.

### Workflow mẫu Bot

```
Zalo Bot Event Trigger (Text Message)
  → Zalo Bot Tương Tác (Send Message)
       chatId: {{ $json.message.chat.id }}
       text: Xin chào {{ $json.message.from.display_name }}!
```

**Expression hữu ích:**

| Expression | Mô tả |
|------------|--------|
| `{{ $json.message.chat.id }}` | Chat ID để trả lời |
| `{{ $json.message.text }}` | Nội dung tin nhắn |
| `{{ $json.event_name }}` | Loại sự kiện |

### Yêu cầu và lưu ý Bot

- Webhook URL phải **truy cập được từ internet** (http hoặc https)
- Một bot chỉ gắn **một webhook** — workflow activate sau ghi đè workflow trước
- **Secret Token** trên Zalo phải **trùng** với credential n8n (hoặc để trống để n8n tự sinh)
- **Cloudflare:** Zalo gửi webhook với `User-Agent: Java/1.8.0_192` — có thể bị chặn. Tạo rule WAF skip cho path chứa `/webhook`

### Khắc phục “đã set nhưng không nhận tin”

| Nguyên nhân | Cách xử lý |
|-------------|-----------|
| Secret Token không khớp | Dán cùng secret vào credential **Webhook Secret Token** |
| Dùng `/webhook-test/` | Activate workflow, dùng URL `/webhook/...` (production) |
| Port chưa mở | Mở firewall port n8n (vd. 5678) cho IP public |
| Token cũ sau Reset | Cập nhật Bot Token mới vào credential n8n |
| Cấu hình tay + tự đăng ký | Tắt **Tự Đăng Ký Webhook** nếu đã set trên Zalo |

### Sắp có (Bot)

- `getUpdates` (polling, không cần HTTPS)
- `sendChatAction` (typing indicator)
- Quản lý webhook thủ công

---

## Zalo cá nhân — 3 node chính

| Node | Mô tả |
|------|--------|
| **Zalo Login QR** | Đăng nhập QR, tự lưu credential |
| **Zalo Event Trigger** | Lắng nghe tin nhắn, reaction, thu hồi, sự kiện nhóm |
| **Zalo Tương Tác** | Gửi tin / quản lý bạn bè, nhóm, tài khoản, tool |

### Zalo Tương Tác — Resource

| Resource | Ví dụ |
|----------|--------|
| **Message** | Gửi tin nhắn, sticker, voice (nhiều ảnh) |
| **Get** | Bạn bè, nhóm, user info, sticker |
| **Friend** | Kết bạn, chặn, alias, profile |
| **Group** | Tạo/sửa nhóm, poll, ghi chú |
| **Account** | Thông tin tài khoản, pin, test credential |
| **Tool** | Xóa tin, reaction, typing, danh thiếp |
| **Custom API Call** | Gọi method zca-js tùy ý |

### Zalo Event Trigger — Listen Events

Chọn một hoặc nhiều: **Message**, **Reaction**, **Undo**, **Group Event**.

Output có field `event` (`message`, `reaction`, `undo`, `group_event`).

## So sánh Bot vs Cá nhân

| | Zalo Bot | Zalo cá nhân |
|---|----------|--------------|
| API | Chính thức | Không chính thức |
| Credential | Bot Token | Cookie + IMEI + UA |
| Trigger | Webhook HTTPS | WebSocket |
| Rủi ro khóa TK | Thấp | Cao |
| Tính năng | Chat bot cơ bản | Đầy đủ (nhóm, poll, reaction…) |

## Migration 0.10.0 — Portal khách hàng + Trial bắt buộc đăng nhập

- **Trial:** phải **đăng ký/đăng nhập** tại `/portal` trước khi kích hoạt (`/portal/trial?installationId=...`)
- **Pro:** mua qua `/portal/buy` — admin duyệt đơn (API thanh toán sẽ tích hợp sau)
- Quản lý license, xem key tại `/portal`
- `POST /v1/trial` public → **401** (dùng `POST /api/customer/trial`)
- Env `ZALO_LICENSE_KEY*` chỉ còn **override nội bộ/dev**

```bash
npm install n8n-nodes-zalo-gemazo@0.10.0
# Deploy Worker + migration D1 0005 trước
# restart n8n
```

Portal: https://zalo-license-worker.hygge.workers.dev/portal/login

---

## Migration 0.9.0 — License theo tài khoản Zalo/Bot

Phiên bản **0.9.0** gắn license/trial theo **danh tính Zalo** (cá nhân: `zaloUserId`, Bot: `botId`):

- Cùng credential Zalo/Bot dùng được trên **mọi workflow** và **mọi thiết bị**
- Trial **Personal** và **Bot** tách riêng — mỗi tài khoản trial 1 lần
- Đổi sang Zalo/Bot khác: trial mới (nếu chưa trial) hoặc **reclaim** key cũ
- Pro: **rebind** sang Zalo/Bot mới không giới hạn
- Static data: `zaloLicense.personal` và `zaloLicense.bot` (tự migrate từ format cũ)

```bash
npm install n8n-nodes-zalo-gemazo@0.9.0
# restart n8n
# Deploy Worker + migration D1 0004 trước khi dùng
```

Env Pro (tùy chọn tách dòng):

```bash
ZALO_LICENSE_KEY_PERSONAL=ZLG-...
ZALO_LICENSE_KEY_BOT=ZLG-...
# hoặc ZALO_LICENSE_KEY cho cả hai
```

---

## Migration 0.8.1 — Trial/license theo workflow

Phiên bản **0.8.1** sửa cách tính activation: **1 workflow = 1 license slot**.

- Mọi node Zalo trong cùng workflow dùng chung `installationId`/`instanceId`
- Workflow thứ 2 được tính là slot mới và cần đăng ký trial/license riêng
- Tránh lỗi `Đã vượt số instance cho phép` khi dùng nhiều node trong cùng workflow

```bash
npm install n8n-nodes-zalo-gemazo@0.8.1
# restart n8n
```

---

## Migration 0.8.0 — Cache license 24h, tốc độ nhanh hơn

Phiên bản **0.8.0** tối ưu license check:

- **Cache 24h** trong workflow static data — lần chạy sau không gọi API (0ms network)
- Lần đầu: `POST /v1/activate`; lần sau (trong 24h): skip hoặc `POST /v1/validate` + JWT
- **Bot webhook** không check license mỗi tin — chỉ khi activate workflow
- Trang public không còn link Admin

```bash
npm install n8n-nodes-zalo-gemazo@0.8.0
# restart n8n
```

> Thu hồi key trên admin có hiệu lực chậm tối đa 24h. Khi có cache hợp lệ, node vẫn chạy nếu API tạm down.

---

## Migration 0.7.3 — License không cần credential

Credential **Zalo License** đã **gỡ hoàn toàn**. License tự quản lý qua backend + workflow static data — không còn mục "Set up credential" trên node.

### Trial

1. Chạy node Zalo lần đầu → mở link đăng ký từ lỗi
2. Điền form web → **chạy lại node** — license tự kích hoạt

Hướng dẫn: **https://zalo-license-worker.hygge.workers.dev/register**

### Pro

Đặt biến môi trường trên n8n:

```bash
ZALO_LICENSE_KEY=ZLG-XXXXX-XXXXX
```

```bash
npm install n8n-nodes-zalo-gemazo@0.7.3
# restart n8n
```

---

## Migration 0.7.1 (Trial qua trang đăng ký web)

Phiên bản **0.7.1–0.7.2** yêu cầu đăng ký Trial trên web. *(0.7.3 gỡ credential Zalo License.)*

---

## Migration 0.7.0 (superseded by 0.7.1)

Phiên bản **0.7.0** thay đổi cách nhận Trial: **không dùng email** (tránh spoof), trial được cấp tự động khi chạy **Zalo Login QR** lần đầu. *(Luồng này đã thay bằng 0.7.1 — đăng ký web.)*

---

## Migration 0.6.0 (breaking — bắt buộc License Key)

Phiên bản **0.6.0** yêu cầu credential **Zalo License** trên **cả 5 node**. *(Trial qua email đã thay bằng 0.7.0.)*

---

## Migration 0.5.0 (breaking change)

Phiên bản **0.5.x** gộp toàn bộ node legacy vào **5 node public**. Workflow cũ dùng node ẩn hoặc typeVersion cũ cần migrate thủ công.

### Cài đặt trên VPS

```bash
npm install n8n-nodes-zalo-gemazo@0.5.2
npm ls n8n-nodes-zalo-gemazo
# restart n8n (bắt buộc)
# Mở từng workflow → Update node → Save
```

### Bảng thay node

| Node cũ (sẽ lỗi sau 0.5.0) | Thay bằng |
|----------------------------|-----------|
| `zaloGroup` | Zalo Tương Tác → Resource **Group** |
| `zaloUser` / `zaloAccount` | Resource **Get** / **Friend** / **Account** |
| `zaloMessageTrigger` | Zalo Event Trigger → Listen **Message** |
| `zaloReactionTrigger` | Zalo Event Trigger → Listen **Reaction** |
| `zaloUndoTrigger` | Zalo Event Trigger → Listen **Undo** |
| `zaloGroupEventTrigger` | Zalo Event Trigger → Listen **Group Event** |
| Zalo Tương Tác typeVersion 1–11 | **Update node** → v12, cấu hình lại Resource/Operation |
| Zalo Event Trigger v1 | **Update node** → v2 |
| Zalo Bot nodes v1 | **Update node** → v2 |

### Version mới

| Node | Version |
|------|---------|
| Zalo Tương Tác | **12 only** |
| Zalo Event Trigger | **2 only** |
| Zalo Login QR | 1 |
| Zalo Bot Tương Tác | **2 only** |
| Zalo Bot Event Trigger | **2 only** |

## Chuyển từ node cũ (trước 0.5.0)

| Node cũ | Thay bằng |
|---------|-----------|
| Zalo Message | Zalo Tương Tác → Resource **Message** |
| Zalo User | Resource **Friend** / **Get** |
| Zalo Group | Resource **Group** |
| Zalo Account | Resource **Account** |
| Zalo Sticker | Resource **Get** |
| Zalo Poll / Note | Resource **Group** |
| Zalo Message Trigger | Zalo Event Trigger → **Message** |
| Zalo Reaction Trigger | Zalo Event Trigger → **Reaction** |
| Zalo Undo Trigger | Zalo Event Trigger → **Undo** |
| Zalo Group Event Trigger | Zalo Event Trigger → **Group Event** |

Sau 0.5.0, node legacy **không còn trong package** — workflow chưa migrate sẽ hiện "unknown node".

## Credential `zaloApi` (cá nhân)

| Field | Mô tả |
|-------|--------|
| Cookie | JSON cookie từ Zalo Web hoặc **Zalo Login QR** |
| IMEI | `localStorage.getItem('z_uuid')` trên chat.zalo.me |
| User Agent | `navigator.userAgent` từ trình duyệt |
| Proxy | Tùy chọn |

## Workflow mẫu (cá nhân)

1. **Zalo Login QR** → quét QR → credential `Zalo - Tên (SĐT)`
2. **Zalo Event Trigger** → Listen **Message** → test event
3. **Zalo Tương Tác** → Resource **Message** → Gửi tin nhắn
   - `User/Group Id`: `={{ $json.threadId }}`
   - `Attachments`: `={{ $json.imageUrls.join(",") }}` (album)

## Phát triển

```bash
npm install
npm run build
npm run lint
```

## License

MIT — xem [LICENSE](LICENSE).
