@warriorteam/redai-zalo-sdk 1.11.1 → 1.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,481 +1,481 @@
1
- # User Management - Hướng Dẫn Sử Dụng
2
-
3
- ## Tổng Quan
4
-
5
- `UserService` cung cấp các công cụ toàn diện để quản lý người dùng Zalo Official Account, bao gồm:
6
-
7
- - 👥 **User Information** - Lấy thông tin chi tiết người dùng
8
- - 📋 **User Lists** - Quản lý danh sách người dùng với phân trang
9
- - 🏷️ **Tag Management** - Gắn và quản lý tags cho users
10
- - 📊 **Custom Info** - Quản lý thông tin tùy chỉnh
11
- - 🔄 **Bulk Operations** - Xử lý hàng loạt users
12
-
13
- **Endpoints sử dụng:**
14
- - User Info: `https://openapi.zalo.me/v3.0/oa/user/detail`
15
- - User List: `https://openapi.zalo.me/v3.0/oa/user/getlist`
16
- - Update User: `https://openapi.zalo.me/v3.0/oa/user/update`
17
- - Custom Info: `https://openapi.zalo.me/v3.0/oa/user/getcustominfo`
18
- - Tags: `https://openapi.zalo.me/v3.0/oa/tag/gettagsofoa`
19
-
20
- ## Khởi Tạo Service
21
-
22
- ```typescript
23
- import { UserService } from "@warriorteam/redai-zalo-sdk";
24
- import { ZaloClient } from "@warriorteam/redai-zalo-sdk";
25
-
26
- const client = new ZaloClient();
27
- const userService = new UserService(client);
28
- ```
29
-
30
- ## Các Phương Thức Chính
31
-
32
- ### 1. Lấy Thông Tin User Chi Tiết
33
-
34
- ```typescript
35
- // Lấy thông tin chi tiết của một user
36
- const userInfo = await userService.getUserInfo(
37
- accessToken,
38
- "user-id-here"
39
- );
40
-
41
- console.log("User Info:", {
42
- userId: userInfo.user_id,
43
- displayName: userInfo.display_name,
44
- avatar: userInfo.avatar,
45
- userGender: userInfo.user_gender,
46
- userAlias: userInfo.user_alias,
47
- isFollower: userInfo.is_follower,
48
- sharedInfo: userInfo.shared_info
49
- });
50
- ```
51
-
52
- **Tham số:**
53
- - `accessToken`: Access token của OA
54
- - `userId`: ID người dùng cần lấy thông tin
55
-
56
- ### 2. Lấy Danh Sách Users
57
-
58
- ```typescript
59
- // Lấy danh sách users với filter
60
- const userList = await userService.getUserList(accessToken, {
61
- offset: 0,
62
- count: 50,
63
- tag_name: "VIP_CUSTOMER", // Lọc theo tag (tùy chọn)
64
- is_follower: true, // Chỉ lấy followers (tùy chọn)
65
- last_interaction_period: "L7D" // Tương tác trong 7 ngày qua
66
- });
67
-
68
- console.log("Total users:", userList.total);
69
- console.log("Count:", userList.count);
70
- console.log("Offset:", userList.offset);
71
-
72
- userList.users.forEach(user => {
73
- console.log(`${user.display_name} - ${user.user_id}`);
74
- });
75
- ```
76
-
77
- **Tham số:**
78
- - `offset`: Vị trí bắt đầu (0-based)
79
- - `count`: Số lượng users mỗi page (tối đa 50)
80
- - `tag_name`: Lọc theo tag (tùy chọn)
81
- - `is_follower`: true/false để lọc followers
82
- - `last_interaction_period`: "TODAY", "YESTERDAY", "L7D", "L30D"
83
-
84
- ### 3. Lấy Tất Cả Users (Auto Pagination)
85
-
86
- ```typescript
87
- // Lấy tất cả users với phân trang tự động
88
- const allUsers = await userService.getAllUsers(accessToken, {
89
- is_follower: true,
90
- tag_name: "PREMIUM"
91
- });
92
-
93
- console.log(`Total users fetched: ${allUsers.length}`);
94
- ```
95
-
96
- **Lưu ý:**
97
- - Zalo giới hạn max offset = 9951 (tương ứng ~10000 users)
98
- - Method này tự động handle pagination và warning khi vượt giới hạn
99
-
100
- ### 4. Lấy Danh Sách User IDs (Tối Ưu)
101
-
102
- ```typescript
103
- // Chỉ lấy user IDs, không lấy thông tin chi tiết (nhanh hơn)
104
- const userIds = await userService.getAllUserIds(accessToken, {
105
- is_follower: true
106
- });
107
-
108
- console.log(`Total user IDs: ${userIds.length}`);
109
- ```
110
-
111
- ### 5. Helper Methods
112
-
113
- ```typescript
114
- // Lấy chỉ followers
115
- const followers = await userService.getFollowers(accessToken, 0, 50);
116
-
117
- // Lấy users theo tag
118
- const vipUsers = await userService.getUsersByTag(accessToken, "VIP", 0, 50);
119
-
120
- // Lấy users theo thời gian tương tác
121
- const recentUsers = await userService.getUsersByInteraction(
122
- accessToken,
123
- "L7D", // 7 ngày qua
124
- 0,
125
- 50
126
- );
127
- ```
128
-
129
- ## User Management Operations
130
-
131
- ### 6. Cập Nhật Thông Tin User
132
-
133
- ```typescript
134
- // Cập nhật thông tin user
135
- const success = await userService.updateUser(accessToken, {
136
- user_id: "user-id-here",
137
- notes: "Customer quan tâm sản phẩm cao cấp",
138
- // Các field khác có thể cập nhật
139
- });
140
-
141
- console.log("Update success:", success);
142
- ```
143
-
144
- ### 7. Xóa Thông Tin User
145
-
146
- ```typescript
147
- // Xóa thông tin user khỏi OA (không ảnh hưởng tài khoản Zalo)
148
- const success = await userService.deleteUserInfo(accessToken, "user-id-here");
149
- console.log("Delete success:", success);
150
- ```
151
-
152
- ### 8. Quản Lý Custom Info
153
-
154
- ```typescript
155
- // Lấy custom info của user
156
- const customInfo = await userService.getUserCustomInfo(accessToken, {
157
- user_id: "user-id-here",
158
- fields_to_export: ["customer_tier", "total_spent"] // Tùy chọn
159
- });
160
-
161
- console.log("Custom Info:", customInfo.custom_info);
162
-
163
- // Cập nhật custom info
164
- const updateSuccess = await userService.updateUserCustomInfo(accessToken, {
165
- user_id: "user-id-here",
166
- custom_info: {
167
- customer_tier: "VIP",
168
- total_spent: "10000000",
169
- last_purchase: "2024-12-01"
170
- }
171
- });
172
- ```
173
-
174
- **Lưu ý:** Cấu trúc `custom_info` phụ thuộc vào thiết lập OA
175
-
176
- ## Tag Management
177
-
178
- ### 9. Quản Lý Tags
179
-
180
- ```typescript
181
- // Lấy danh sách tất cả tags của OA
182
- const tags = await userService.getLabels(accessToken);
183
- console.log("Available tags:", tags);
184
-
185
- // Thêm tag cho user
186
- const addSuccess = await userService.addTagToUser(accessToken, {
187
- user_id: "user-id-here",
188
- tag_name: "VIP_CUSTOMER"
189
- });
190
-
191
- // Xóa tag khỏi user
192
- const removeSuccess = await userService.removeTagFromUser(accessToken, {
193
- user_id: "user-id-here",
194
- tag_name: "OLD_TAG"
195
- });
196
-
197
- // Xóa tag khỏi OA (xóa hoàn toàn)
198
- const deleteSuccess = await userService.deleteLabel(accessToken, "UNUSED_TAG");
199
- ```
200
-
201
- ### 10. Bulk Operations
202
-
203
- ```typescript
204
- // Bulk add tag cho nhiều users
205
- const bulkAddResult = await userService.bulkAddTag(
206
- accessToken,
207
- ["user1", "user2", "user3"],
208
- "FLASH_SALE_2024"
209
- );
210
-
211
- console.log("Success:", bulkAddResult.success);
212
- console.log("Failed:", bulkAddResult.failed);
213
-
214
- // Bulk remove tag
215
- const bulkRemoveResult = await userService.bulkRemoveTag(
216
- accessToken,
217
- ["user1", "user2", "user3"],
218
- "OLD_CAMPAIGN"
219
- );
220
- ```
221
-
222
- ## API Methods Summary
223
-
224
- | Method | Description | Parameters |
225
- |--------|-------------|------------|
226
- | `getUserInfo` | Lấy thông tin chi tiết user | `accessToken`, `userId` |
227
- | `getUserList` | Lấy danh sách users với pagination | `accessToken`, `request` |
228
- | `getAllUsers` | Lấy tất cả users (auto pagination) | `accessToken`, `filters?` |
229
- | `getAllUserIds` | Lấy tất cả user IDs (tối ưu) | `accessToken`, `filters?` |
230
- | `updateUser` | Cập nhật thông tin user | `accessToken`, `request` |
231
- | `deleteUserInfo` | Xóa thông tin user | `accessToken`, `userId` |
232
- | `getUserCustomInfo` | Lấy custom info | `accessToken`, `request` |
233
- | `updateUserCustomInfo` | Cập nhật custom info | `accessToken`, `request` |
234
- | `getLabels` | Lấy danh sách tags | `accessToken` |
235
- | `addTagToUser` | Thêm tag cho user | `accessToken`, `request` |
236
- | `removeTagFromUser` | Xóa tag khỏi user | `accessToken`, `request` |
237
- | `deleteLabel` | Xóa tag khỏi OA | `accessToken`, `tagName` |
238
- | `getUsersByTag` | Lấy users theo tag | `accessToken`, `tagName`, `offset?`, `count?` |
239
- | `getFollowers` | Lấy chỉ followers | `accessToken`, `offset?`, `count?` |
240
- | `getUsersByInteraction` | Lấy users theo thời gian tương tác | `accessToken`, `period`, `offset?`, `count?` |
241
- | `bulkAddTag` | Bulk add tag | `accessToken`, `userIds`, `tagName` |
242
- | `bulkRemoveTag` | Bulk remove tag | `accessToken`, `userIds`, `tagName` |
243
-
244
- ## Ví Dụ Thực Tế
245
-
246
- ### 1. Customer Support System
247
-
248
- ```typescript
249
- class CustomerSupportSystem {
250
- constructor(private userService: UserService, private accessToken: string) {}
251
-
252
- async handleNewCustomer(userId: string) {
253
- // Lấy thông tin customer
254
- const userInfo = await this.userService.getUserInfo(this.accessToken, userId);
255
-
256
- // Thêm tag "NEW_CUSTOMER"
257
- await this.userService.addTagToUser(this.accessToken, {
258
- user_id: userId,
259
- tag_name: "NEW_CUSTOMER"
260
- });
261
-
262
- // Cập nhật custom info
263
- await this.userService.updateUserCustomInfo(this.accessToken, {
264
- user_id: userId,
265
- custom_info: {
266
- registration_date: new Date().toISOString(),
267
- customer_tier: "STANDARD",
268
- total_interactions: "1"
269
- }
270
- });
271
-
272
- console.log(`New customer ${userInfo.display_name} processed`);
273
- }
274
-
275
- async promoteToVIP(userId: string) {
276
- // Remove old tags
277
- await this.userService.removeTagFromUser(this.accessToken, {
278
- user_id: userId,
279
- tag_name: "STANDARD"
280
- });
281
-
282
- // Add VIP tag
283
- await this.userService.addTagToUser(this.accessToken, {
284
- user_id: userId,
285
- tag_name: "VIP"
286
- });
287
-
288
- // Update custom info
289
- await this.userService.updateUserCustomInfo(this.accessToken, {
290
- user_id: userId,
291
- custom_info: {
292
- customer_tier: "VIP",
293
- promotion_date: new Date().toISOString()
294
- }
295
- });
296
- }
297
- }
298
-
299
- }
300
- ```
301
-
302
- ### 2. Bulk Campaign System
303
-
304
- ```typescript
305
- class BulkCampaignSystem {
306
- constructor(private userService: UserService, private accessToken: string) {}
307
-
308
- async runSegmentedCampaign(campaignConfig: {
309
- segments: string[];
310
- message: string;
311
- batchSize?: number;
312
- }) {
313
- const results = {
314
- totalSent: 0,
315
- totalFailed: 0,
316
- segmentResults: new Map<string, any>()
317
- };
318
-
319
- for (const segment of campaignConfig.segments) {
320
- console.log(`Processing segment: ${segment}`);
321
-
322
- // Get users by tag
323
- const users = await this.userService.getUsersByTag(
324
- this.accessToken,
325
- segment,
326
- 0,
327
- 1000
328
- );
329
-
330
- // Bulk add campaign tag
331
- const userIds = users.users.map(u => u.user_id);
332
- const bulkResult = await this.userService.bulkAddTag(
333
- this.accessToken,
334
- userIds,
335
- `CAMPAIGN_${Date.now()}`
336
- );
337
-
338
- results.segmentResults.set(segment, {
339
- totalUsers: users.total,
340
- tagged: bulkResult.success.length,
341
- failed: bulkResult.failed.length
342
- });
343
-
344
- results.totalSent += bulkResult.success.length;
345
- results.totalFailed += bulkResult.failed.length;
346
- }
347
-
348
- return results;
349
- }
350
- }
351
- ```
352
-
353
- ## Error Handling
354
-
355
- ```typescript
356
- import { ZaloSDKError } from "@warriorteam/redai-zalo-sdk";
357
-
358
- try {
359
- const userInfo = await userService.getUserInfo(accessToken, "user-id");
360
- console.log("User found:", userInfo.display_name);
361
- } catch (error) {
362
- if (error instanceof ZaloSDKError) {
363
- switch (error.code) {
364
- case -216:
365
- console.error("Access token không hợp lệ");
366
- break;
367
- case -233:
368
- console.error("User không tồn tại hoặc đã unfollow");
369
- break;
370
- case -201:
371
- console.error("Tham số không hợp lệ");
372
- break;
373
- default:
374
- console.error("Lỗi khác:", error.message);
375
- }
376
- } else {
377
- console.error("Unexpected error:", error);
378
- }
379
- }
380
- ```
381
-
382
- ## Giới Hạn API
383
-
384
- ### Zalo API Limits
385
-
386
- 1. **User List Pagination**:
387
- - Max offset: 9951
388
- - Max count per request: 50
389
- - Tối đa ~10000 users có thể lấy được
390
-
391
- 2. **Rate Limiting**:
392
- - Nên có delay giữa các requests
393
- - Sử dụng batch operations khi có thể
394
-
395
- 3. **Custom Info**:
396
- - Cấu trúc phụ thuộc vào thiết lập OA
397
- - Tất cả giá trị đều là string
398
-
399
- ## Best Practices
400
-
401
- ### 1. Performance Optimization
402
-
403
- ```typescript
404
- // ✅ Sử dụng getAllUserIds cho performance tốt hơn
405
- const userIds = await userService.getAllUserIds(accessToken);
406
-
407
- // ✅ Batch operations
408
- const bulkResult = await userService.bulkAddTag(
409
- accessToken,
410
- userIds.slice(0, 100),
411
- "NEW_TAG"
412
- );
413
-
414
- // ✅ Pagination với reasonable page size
415
- const users = await userService.getUserList(accessToken, {
416
- offset: 0,
417
- count: 50 // Không quá 50
418
- });
419
- ```
420
-
421
- ### 2. Error Handling
422
-
423
- ```typescript
424
- // ✅ Validate user ID format
425
- function validateUserId(userId: string): boolean {
426
- return /^[0-9]+$/.test(userId) && userId.length > 0;
427
- }
428
-
429
- // ✅ Safe operations
430
- async function safeGetUser(userId: string) {
431
- if (!validateUserId(userId)) {
432
- throw new Error("Invalid user ID format");
433
- }
434
-
435
- try {
436
- return await userService.getUserInfo(accessToken, userId);
437
- } catch (error) {
438
- if (error.code === -233) {
439
- return null; // User not found
440
- }
441
- throw error;
442
- }
443
- }
444
- ```
445
-
446
- ## Troubleshooting
447
-
448
- ### Common Issues
449
-
450
- **Q: "User not found" error**
451
- ```
452
- A: User có thể đã unfollow OA hoặc chặn OA.
453
- Kiểm tra is_follower field trước.
454
- ```
455
-
456
- **Q: Không lấy được phone number**
457
- ```
458
- A: Phone chỉ có khi user đã share với OA.
459
- Sử dụng request_user_info để yêu cầu.
460
- ```
461
-
462
- **Q: getAllUsers không lấy hết**
463
- ```
464
- A: Zalo giới hạn max offset = 9951.
465
- Chỉ lấy được ~10000 users đầu tiên.
466
- ```
467
-
468
- **Q: Custom info không cập nhật**
469
- ```
470
- A: Kiểm tra cấu trúc custom_info trong OA settings.
471
- Tất cả values phải là string.
472
- ```
473
-
474
- ## Tài Liệu Liên Quan
475
-
476
- - [Zalo Official Account API](https://developers.zalo.me/docs/api/official-account-api)
477
- - [User Management API](https://developers.zalo.me/docs/api/official-account-api/quan-ly-nguoi-dung)
478
- - [Tag Management API](https://developers.zalo.me/docs/api/official-account-api/quan-ly-nhan)
479
- - [Consultation Service](./CONSULTATION_SERVICE.md)
480
- - [Tag Management](./TAG_MANAGEMENT.md)
481
-
1
+ # User Management - Hướng Dẫn Sử Dụng
2
+
3
+ ## Tổng Quan
4
+
5
+ `UserService` cung cấp các công cụ toàn diện để quản lý người dùng Zalo Official Account, bao gồm:
6
+
7
+ - 👥 **User Information** - Lấy thông tin chi tiết người dùng
8
+ - 📋 **User Lists** - Quản lý danh sách người dùng với phân trang
9
+ - 🏷️ **Tag Management** - Gắn và quản lý tags cho users
10
+ - 📊 **Custom Info** - Quản lý thông tin tùy chỉnh
11
+ - 🔄 **Bulk Operations** - Xử lý hàng loạt users
12
+
13
+ **Endpoints sử dụng:**
14
+ - User Info: `https://openapi.zalo.me/v3.0/oa/user/detail`
15
+ - User List: `https://openapi.zalo.me/v3.0/oa/user/getlist`
16
+ - Update User: `https://openapi.zalo.me/v3.0/oa/user/update`
17
+ - Custom Info: `https://openapi.zalo.me/v3.0/oa/user/getcustominfo`
18
+ - Tags: `https://openapi.zalo.me/v3.0/oa/tag/gettagsofoa`
19
+
20
+ ## Khởi Tạo Service
21
+
22
+ ```typescript
23
+ import { UserService } from "@warriorteam/redai-zalo-sdk";
24
+ import { ZaloClient } from "@warriorteam/redai-zalo-sdk";
25
+
26
+ const client = new ZaloClient();
27
+ const userService = new UserService(client);
28
+ ```
29
+
30
+ ## Các Phương Thức Chính
31
+
32
+ ### 1. Lấy Thông Tin User Chi Tiết
33
+
34
+ ```typescript
35
+ // Lấy thông tin chi tiết của một user
36
+ const userInfo = await userService.getUserInfo(
37
+ accessToken,
38
+ "user-id-here"
39
+ );
40
+
41
+ console.log("User Info:", {
42
+ userId: userInfo.user_id,
43
+ displayName: userInfo.display_name,
44
+ avatar: userInfo.avatar,
45
+ userGender: userInfo.user_gender,
46
+ userAlias: userInfo.user_alias,
47
+ isFollower: userInfo.is_follower,
48
+ sharedInfo: userInfo.shared_info
49
+ });
50
+ ```
51
+
52
+ **Tham số:**
53
+ - `accessToken`: Access token của OA
54
+ - `userId`: ID người dùng cần lấy thông tin
55
+
56
+ ### 2. Lấy Danh Sách Users
57
+
58
+ ```typescript
59
+ // Lấy danh sách users với filter
60
+ const userList = await userService.getUserList(accessToken, {
61
+ offset: 0,
62
+ count: 50,
63
+ tag_name: "VIP_CUSTOMER", // Lọc theo tag (tùy chọn)
64
+ is_follower: true, // Chỉ lấy followers (tùy chọn)
65
+ last_interaction_period: "L7D" // Tương tác trong 7 ngày qua
66
+ });
67
+
68
+ console.log("Total users:", userList.total);
69
+ console.log("Count:", userList.count);
70
+ console.log("Offset:", userList.offset);
71
+
72
+ userList.users.forEach(user => {
73
+ console.log(`${user.display_name} - ${user.user_id}`);
74
+ });
75
+ ```
76
+
77
+ **Tham số:**
78
+ - `offset`: Vị trí bắt đầu (0-based)
79
+ - `count`: Số lượng users mỗi page (tối đa 50)
80
+ - `tag_name`: Lọc theo tag (tùy chọn)
81
+ - `is_follower`: true/false để lọc followers
82
+ - `last_interaction_period`: "TODAY", "YESTERDAY", "L7D", "L30D"
83
+
84
+ ### 3. Lấy Tất Cả Users (Auto Pagination)
85
+
86
+ ```typescript
87
+ // Lấy tất cả users với phân trang tự động
88
+ const allUsers = await userService.getAllUsers(accessToken, {
89
+ is_follower: true,
90
+ tag_name: "PREMIUM"
91
+ });
92
+
93
+ console.log(`Total users fetched: ${allUsers.length}`);
94
+ ```
95
+
96
+ **Lưu ý:**
97
+ - Zalo giới hạn max offset = 9951 (tương ứng ~10000 users)
98
+ - Method này tự động handle pagination và warning khi vượt giới hạn
99
+
100
+ ### 4. Lấy Danh Sách User IDs (Tối Ưu)
101
+
102
+ ```typescript
103
+ // Chỉ lấy user IDs, không lấy thông tin chi tiết (nhanh hơn)
104
+ const userIds = await userService.getAllUserIds(accessToken, {
105
+ is_follower: true
106
+ });
107
+
108
+ console.log(`Total user IDs: ${userIds.length}`);
109
+ ```
110
+
111
+ ### 5. Helper Methods
112
+
113
+ ```typescript
114
+ // Lấy chỉ followers
115
+ const followers = await userService.getFollowers(accessToken, 0, 50);
116
+
117
+ // Lấy users theo tag
118
+ const vipUsers = await userService.getUsersByTag(accessToken, "VIP", 0, 50);
119
+
120
+ // Lấy users theo thời gian tương tác
121
+ const recentUsers = await userService.getUsersByInteraction(
122
+ accessToken,
123
+ "L7D", // 7 ngày qua
124
+ 0,
125
+ 50
126
+ );
127
+ ```
128
+
129
+ ## User Management Operations
130
+
131
+ ### 6. Cập Nhật Thông Tin User
132
+
133
+ ```typescript
134
+ // Cập nhật thông tin user
135
+ const success = await userService.updateUser(accessToken, {
136
+ user_id: "user-id-here",
137
+ notes: "Customer quan tâm sản phẩm cao cấp",
138
+ // Các field khác có thể cập nhật
139
+ });
140
+
141
+ console.log("Update success:", success);
142
+ ```
143
+
144
+ ### 7. Xóa Thông Tin User
145
+
146
+ ```typescript
147
+ // Xóa thông tin user khỏi OA (không ảnh hưởng tài khoản Zalo)
148
+ const success = await userService.deleteUserInfo(accessToken, "user-id-here");
149
+ console.log("Delete success:", success);
150
+ ```
151
+
152
+ ### 8. Quản Lý Custom Info
153
+
154
+ ```typescript
155
+ // Lấy custom info của user
156
+ const customInfo = await userService.getUserCustomInfo(accessToken, {
157
+ user_id: "user-id-here",
158
+ fields_to_export: ["customer_tier", "total_spent"] // Tùy chọn
159
+ });
160
+
161
+ console.log("Custom Info:", customInfo.custom_info);
162
+
163
+ // Cập nhật custom info
164
+ const updateSuccess = await userService.updateUserCustomInfo(accessToken, {
165
+ user_id: "user-id-here",
166
+ custom_info: {
167
+ customer_tier: "VIP",
168
+ total_spent: "10000000",
169
+ last_purchase: "2024-12-01"
170
+ }
171
+ });
172
+ ```
173
+
174
+ **Lưu ý:** Cấu trúc `custom_info` phụ thuộc vào thiết lập OA
175
+
176
+ ## Tag Management
177
+
178
+ ### 9. Quản Lý Tags
179
+
180
+ ```typescript
181
+ // Lấy danh sách tất cả tags của OA
182
+ const tags = await userService.getLabels(accessToken);
183
+ console.log("Available tags:", tags);
184
+
185
+ // Thêm tag cho user
186
+ const addSuccess = await userService.addTagToUser(accessToken, {
187
+ user_id: "user-id-here",
188
+ tag_name: "VIP_CUSTOMER"
189
+ });
190
+
191
+ // Xóa tag khỏi user
192
+ const removeSuccess = await userService.removeTagFromUser(accessToken, {
193
+ user_id: "user-id-here",
194
+ tag_name: "OLD_TAG"
195
+ });
196
+
197
+ // Xóa tag khỏi OA (xóa hoàn toàn)
198
+ const deleteSuccess = await userService.deleteLabel(accessToken, "UNUSED_TAG");
199
+ ```
200
+
201
+ ### 10. Bulk Operations
202
+
203
+ ```typescript
204
+ // Bulk add tag cho nhiều users
205
+ const bulkAddResult = await userService.bulkAddTag(
206
+ accessToken,
207
+ ["user1", "user2", "user3"],
208
+ "FLASH_SALE_2024"
209
+ );
210
+
211
+ console.log("Success:", bulkAddResult.success);
212
+ console.log("Failed:", bulkAddResult.failed);
213
+
214
+ // Bulk remove tag
215
+ const bulkRemoveResult = await userService.bulkRemoveTag(
216
+ accessToken,
217
+ ["user1", "user2", "user3"],
218
+ "OLD_CAMPAIGN"
219
+ );
220
+ ```
221
+
222
+ ## API Methods Summary
223
+
224
+ | Method | Description | Parameters |
225
+ |--------|-------------|------------|
226
+ | `getUserInfo` | Lấy thông tin chi tiết user | `accessToken`, `userId` |
227
+ | `getUserList` | Lấy danh sách users với pagination | `accessToken`, `request` |
228
+ | `getAllUsers` | Lấy tất cả users (auto pagination) | `accessToken`, `filters?` |
229
+ | `getAllUserIds` | Lấy tất cả user IDs (tối ưu) | `accessToken`, `filters?` |
230
+ | `updateUser` | Cập nhật thông tin user | `accessToken`, `request` |
231
+ | `deleteUserInfo` | Xóa thông tin user | `accessToken`, `userId` |
232
+ | `getUserCustomInfo` | Lấy custom info | `accessToken`, `request` |
233
+ | `updateUserCustomInfo` | Cập nhật custom info | `accessToken`, `request` |
234
+ | `getLabels` | Lấy danh sách tags | `accessToken` |
235
+ | `addTagToUser` | Thêm tag cho user | `accessToken`, `request` |
236
+ | `removeTagFromUser` | Xóa tag khỏi user | `accessToken`, `request` |
237
+ | `deleteLabel` | Xóa tag khỏi OA | `accessToken`, `tagName` |
238
+ | `getUsersByTag` | Lấy users theo tag | `accessToken`, `tagName`, `offset?`, `count?` |
239
+ | `getFollowers` | Lấy chỉ followers | `accessToken`, `offset?`, `count?` |
240
+ | `getUsersByInteraction` | Lấy users theo thời gian tương tác | `accessToken`, `period`, `offset?`, `count?` |
241
+ | `bulkAddTag` | Bulk add tag | `accessToken`, `userIds`, `tagName` |
242
+ | `bulkRemoveTag` | Bulk remove tag | `accessToken`, `userIds`, `tagName` |
243
+
244
+ ## Ví Dụ Thực Tế
245
+
246
+ ### 1. Customer Support System
247
+
248
+ ```typescript
249
+ class CustomerSupportSystem {
250
+ constructor(private userService: UserService, private accessToken: string) {}
251
+
252
+ async handleNewCustomer(userId: string) {
253
+ // Lấy thông tin customer
254
+ const userInfo = await this.userService.getUserInfo(this.accessToken, userId);
255
+
256
+ // Thêm tag "NEW_CUSTOMER"
257
+ await this.userService.addTagToUser(this.accessToken, {
258
+ user_id: userId,
259
+ tag_name: "NEW_CUSTOMER"
260
+ });
261
+
262
+ // Cập nhật custom info
263
+ await this.userService.updateUserCustomInfo(this.accessToken, {
264
+ user_id: userId,
265
+ custom_info: {
266
+ registration_date: new Date().toISOString(),
267
+ customer_tier: "STANDARD",
268
+ total_interactions: "1"
269
+ }
270
+ });
271
+
272
+ console.log(`New customer ${userInfo.display_name} processed`);
273
+ }
274
+
275
+ async promoteToVIP(userId: string) {
276
+ // Remove old tags
277
+ await this.userService.removeTagFromUser(this.accessToken, {
278
+ user_id: userId,
279
+ tag_name: "STANDARD"
280
+ });
281
+
282
+ // Add VIP tag
283
+ await this.userService.addTagToUser(this.accessToken, {
284
+ user_id: userId,
285
+ tag_name: "VIP"
286
+ });
287
+
288
+ // Update custom info
289
+ await this.userService.updateUserCustomInfo(this.accessToken, {
290
+ user_id: userId,
291
+ custom_info: {
292
+ customer_tier: "VIP",
293
+ promotion_date: new Date().toISOString()
294
+ }
295
+ });
296
+ }
297
+ }
298
+
299
+ }
300
+ ```
301
+
302
+ ### 2. Bulk Campaign System
303
+
304
+ ```typescript
305
+ class BulkCampaignSystem {
306
+ constructor(private userService: UserService, private accessToken: string) {}
307
+
308
+ async runSegmentedCampaign(campaignConfig: {
309
+ segments: string[];
310
+ message: string;
311
+ batchSize?: number;
312
+ }) {
313
+ const results = {
314
+ totalSent: 0,
315
+ totalFailed: 0,
316
+ segmentResults: new Map<string, any>()
317
+ };
318
+
319
+ for (const segment of campaignConfig.segments) {
320
+ console.log(`Processing segment: ${segment}`);
321
+
322
+ // Get users by tag
323
+ const users = await this.userService.getUsersByTag(
324
+ this.accessToken,
325
+ segment,
326
+ 0,
327
+ 1000
328
+ );
329
+
330
+ // Bulk add campaign tag
331
+ const userIds = users.users.map(u => u.user_id);
332
+ const bulkResult = await this.userService.bulkAddTag(
333
+ this.accessToken,
334
+ userIds,
335
+ `CAMPAIGN_${Date.now()}`
336
+ );
337
+
338
+ results.segmentResults.set(segment, {
339
+ totalUsers: users.total,
340
+ tagged: bulkResult.success.length,
341
+ failed: bulkResult.failed.length
342
+ });
343
+
344
+ results.totalSent += bulkResult.success.length;
345
+ results.totalFailed += bulkResult.failed.length;
346
+ }
347
+
348
+ return results;
349
+ }
350
+ }
351
+ ```
352
+
353
+ ## Error Handling
354
+
355
+ ```typescript
356
+ import { ZaloSDKError } from "@warriorteam/redai-zalo-sdk";
357
+
358
+ try {
359
+ const userInfo = await userService.getUserInfo(accessToken, "user-id");
360
+ console.log("User found:", userInfo.display_name);
361
+ } catch (error) {
362
+ if (error instanceof ZaloSDKError) {
363
+ switch (error.code) {
364
+ case -216:
365
+ console.error("Access token không hợp lệ");
366
+ break;
367
+ case -233:
368
+ console.error("User không tồn tại hoặc đã unfollow");
369
+ break;
370
+ case -201:
371
+ console.error("Tham số không hợp lệ");
372
+ break;
373
+ default:
374
+ console.error("Lỗi khác:", error.message);
375
+ }
376
+ } else {
377
+ console.error("Unexpected error:", error);
378
+ }
379
+ }
380
+ ```
381
+
382
+ ## Giới Hạn API
383
+
384
+ ### Zalo API Limits
385
+
386
+ 1. **User List Pagination**:
387
+ - Max offset: 9951
388
+ - Max count per request: 50
389
+ - Tối đa ~10000 users có thể lấy được
390
+
391
+ 2. **Rate Limiting**:
392
+ - Nên có delay giữa các requests
393
+ - Sử dụng batch operations khi có thể
394
+
395
+ 3. **Custom Info**:
396
+ - Cấu trúc phụ thuộc vào thiết lập OA
397
+ - Tất cả giá trị đều là string
398
+
399
+ ## Best Practices
400
+
401
+ ### 1. Performance Optimization
402
+
403
+ ```typescript
404
+ // ✅ Sử dụng getAllUserIds cho performance tốt hơn
405
+ const userIds = await userService.getAllUserIds(accessToken);
406
+
407
+ // ✅ Batch operations
408
+ const bulkResult = await userService.bulkAddTag(
409
+ accessToken,
410
+ userIds.slice(0, 100),
411
+ "NEW_TAG"
412
+ );
413
+
414
+ // ✅ Pagination với reasonable page size
415
+ const users = await userService.getUserList(accessToken, {
416
+ offset: 0,
417
+ count: 50 // Không quá 50
418
+ });
419
+ ```
420
+
421
+ ### 2. Error Handling
422
+
423
+ ```typescript
424
+ // ✅ Validate user ID format
425
+ function validateUserId(userId: string): boolean {
426
+ return /^[0-9]+$/.test(userId) && userId.length > 0;
427
+ }
428
+
429
+ // ✅ Safe operations
430
+ async function safeGetUser(userId: string) {
431
+ if (!validateUserId(userId)) {
432
+ throw new Error("Invalid user ID format");
433
+ }
434
+
435
+ try {
436
+ return await userService.getUserInfo(accessToken, userId);
437
+ } catch (error) {
438
+ if (error.code === -233) {
439
+ return null; // User not found
440
+ }
441
+ throw error;
442
+ }
443
+ }
444
+ ```
445
+
446
+ ## Troubleshooting
447
+
448
+ ### Common Issues
449
+
450
+ **Q: "User not found" error**
451
+ ```
452
+ A: User có thể đã unfollow OA hoặc chặn OA.
453
+ Kiểm tra is_follower field trước.
454
+ ```
455
+
456
+ **Q: Không lấy được phone number**
457
+ ```
458
+ A: Phone chỉ có khi user đã share với OA.
459
+ Sử dụng request_user_info để yêu cầu.
460
+ ```
461
+
462
+ **Q: getAllUsers không lấy hết**
463
+ ```
464
+ A: Zalo giới hạn max offset = 9951.
465
+ Chỉ lấy được ~10000 users đầu tiên.
466
+ ```
467
+
468
+ **Q: Custom info không cập nhật**
469
+ ```
470
+ A: Kiểm tra cấu trúc custom_info trong OA settings.
471
+ Tất cả values phải là string.
472
+ ```
473
+
474
+ ## Tài Liệu Liên Quan
475
+
476
+ - [Zalo Official Account API](https://developers.zalo.me/docs/api/official-account-api)
477
+ - [User Management API](https://developers.zalo.me/docs/api/official-account-api/quan-ly-nguoi-dung)
478
+ - [Tag Management API](https://developers.zalo.me/docs/api/official-account-api/quan-ly-nhan)
479
+ - [Consultation Service](./CONSULTATION_SERVICE.md)
480
+ - [Tag Management](./TAG_MANAGEMENT.md)
481
+