@warriorteam/redai-zalo-sdk 1.17.5 → 1.19.0
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.
- package/CHANGELOG.md +161 -0
- package/dist/services/consultation.service.d.ts +167 -0
- package/dist/services/consultation.service.d.ts.map +1 -1
- package/dist/services/consultation.service.js +274 -0
- package/dist/services/consultation.service.js.map +1 -1
- package/dist/services/group-message.service.d.ts +200 -0
- package/dist/services/group-message.service.d.ts.map +1 -1
- package/dist/services/group-message.service.js +331 -0
- package/dist/services/group-message.service.js.map +1 -1
- package/docs/group-message-list-api.md +332 -0
- package/docs/message-sequence-api.md +464 -0
- package/examples/group-message-list.ts +288 -0
- package/examples/send-message-sequence.ts +200 -0
- package/package.json +16 -3
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
# API Gửi Chuỗi Tin Nhắn Tư Vấn
|
|
2
|
+
|
|
3
|
+
API này cho phép gửi một chuỗi tin nhắn tư vấn tới một người dùng với khả năng delay tùy chỉnh giữa các tin nhắn.
|
|
4
|
+
|
|
5
|
+
## Tính năng
|
|
6
|
+
|
|
7
|
+
- ✅ Hỗ trợ tất cả các loại tin nhắn: `text`, `image`, `gif`, `file`, `sticker`, `request_user_info`
|
|
8
|
+
- ✅ Delay tùy chỉnh cho từng tin nhắn
|
|
9
|
+
- ✅ Delay mặc định cho toàn bộ chuỗi tin nhắn
|
|
10
|
+
- ✅ Xử lý lỗi chi tiết cho từng tin nhắn
|
|
11
|
+
- ✅ Thống kê kết quả gửi tin nhắn
|
|
12
|
+
- ✅ Ghi log thời gian thực hiện
|
|
13
|
+
|
|
14
|
+
## Cách sử dụng
|
|
15
|
+
|
|
16
|
+
### 1. Import các interface và service
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import {
|
|
20
|
+
ConsultationService,
|
|
21
|
+
MessageItem,
|
|
22
|
+
SendMessageSequenceRequest
|
|
23
|
+
} from "../src/services/consultation.service";
|
|
24
|
+
import { ZaloClient } from "../src/clients/zalo-client";
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### 2. Khởi tạo service
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
const zaloClient = new ZaloClient();
|
|
31
|
+
const consultationService = new ConsultationService(zaloClient);
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 3. Định nghĩa chuỗi tin nhắn
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
const messages: MessageItem[] = [
|
|
38
|
+
{
|
|
39
|
+
type: "text",
|
|
40
|
+
text: "Xin chào! 👋",
|
|
41
|
+
delay: 2000, // Delay 2 giây sau tin nhắn này
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
type: "image",
|
|
45
|
+
imageUrl: "https://example.com/image.jpg",
|
|
46
|
+
text: "Hình ảnh minh họa",
|
|
47
|
+
delay: 1500,
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
type: "sticker",
|
|
51
|
+
stickerAttachmentId: "STICKER_ID",
|
|
52
|
+
},
|
|
53
|
+
];
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 4. Gửi chuỗi tin nhắn
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
const request: SendMessageSequenceRequest = {
|
|
60
|
+
accessToken: "YOUR_ACCESS_TOKEN",
|
|
61
|
+
userId: "USER_ID",
|
|
62
|
+
messages,
|
|
63
|
+
defaultDelay: 1000, // Delay mặc định 1 giây
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
const result = await consultationService.sendMessageSequence(request);
|
|
68
|
+
console.log(`Thành công: ${result.successCount}/${messages.length}`);
|
|
69
|
+
} catch (error) {
|
|
70
|
+
console.error("Lỗi:", error);
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Các loại tin nhắn được hỗ trợ
|
|
75
|
+
|
|
76
|
+
### 1. Text Message
|
|
77
|
+
```typescript
|
|
78
|
+
{
|
|
79
|
+
type: "text",
|
|
80
|
+
text: "Nội dung tin nhắn",
|
|
81
|
+
delay: 1000, // Optional
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 2. Image Message
|
|
86
|
+
```typescript
|
|
87
|
+
// Sử dụng URL
|
|
88
|
+
{
|
|
89
|
+
type: "image",
|
|
90
|
+
imageUrl: "https://example.com/image.jpg",
|
|
91
|
+
text: "Caption cho ảnh", // Optional
|
|
92
|
+
delay: 1500,
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Hoặc sử dụng attachment ID
|
|
96
|
+
{
|
|
97
|
+
type: "image",
|
|
98
|
+
attachmentId: "ATTACHMENT_ID",
|
|
99
|
+
text: "Caption cho ảnh", // Optional
|
|
100
|
+
delay: 1500,
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### 3. GIF Message
|
|
105
|
+
```typescript
|
|
106
|
+
{
|
|
107
|
+
type: "gif",
|
|
108
|
+
gifUrl: "https://example.com/animation.gif",
|
|
109
|
+
width: 300, // Bắt buộc
|
|
110
|
+
height: 200, // Bắt buộc
|
|
111
|
+
text: "Caption cho GIF", // Optional
|
|
112
|
+
delay: 2000,
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### 4. File Message
|
|
117
|
+
```typescript
|
|
118
|
+
{
|
|
119
|
+
type: "file",
|
|
120
|
+
fileToken: "FILE_TOKEN_FROM_UPLOAD_API", // Bắt buộc
|
|
121
|
+
delay: 1000,
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### 5. Sticker Message
|
|
126
|
+
```typescript
|
|
127
|
+
{
|
|
128
|
+
type: "sticker",
|
|
129
|
+
stickerAttachmentId: "STICKER_ID", // Bắt buộc
|
|
130
|
+
delay: 500,
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### 6. Request User Info Message
|
|
135
|
+
```typescript
|
|
136
|
+
{
|
|
137
|
+
type: "request_user_info",
|
|
138
|
+
title: "Đăng ký tư vấn", // Bắt buộc, max 100 ký tự
|
|
139
|
+
subtitle: "Vui lòng cung cấp...", // Bắt buộc, max 500 ký tự
|
|
140
|
+
imageUrl: "https://example.com/form.jpg", // Bắt buộc
|
|
141
|
+
delay: 2000,
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Interface chi tiết
|
|
146
|
+
|
|
147
|
+
### MessageItem
|
|
148
|
+
```typescript
|
|
149
|
+
interface MessageItem {
|
|
150
|
+
type: "text" | "image" | "gif" | "file" | "sticker" | "request_user_info";
|
|
151
|
+
text?: string;
|
|
152
|
+
imageUrl?: string;
|
|
153
|
+
gifUrl?: string;
|
|
154
|
+
width?: number;
|
|
155
|
+
height?: number;
|
|
156
|
+
fileToken?: string;
|
|
157
|
+
attachmentId?: string;
|
|
158
|
+
stickerAttachmentId?: string;
|
|
159
|
+
title?: string;
|
|
160
|
+
subtitle?: string;
|
|
161
|
+
delay?: number; // milliseconds
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### SendMessageSequenceRequest
|
|
166
|
+
```typescript
|
|
167
|
+
interface SendMessageSequenceRequest {
|
|
168
|
+
accessToken: string;
|
|
169
|
+
userId: string;
|
|
170
|
+
messages: MessageItem[];
|
|
171
|
+
defaultDelay?: number; // milliseconds
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### SendMessageSequenceResponse
|
|
176
|
+
```typescript
|
|
177
|
+
interface SendMessageSequenceResponse {
|
|
178
|
+
successCount: number;
|
|
179
|
+
failureCount: number;
|
|
180
|
+
results: Array<{
|
|
181
|
+
index: number;
|
|
182
|
+
type: string;
|
|
183
|
+
success: boolean;
|
|
184
|
+
response?: SendMessageResponse;
|
|
185
|
+
error?: string;
|
|
186
|
+
timestamp: number;
|
|
187
|
+
}>;
|
|
188
|
+
totalDuration: number; // milliseconds
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Ví dụ thực tế
|
|
193
|
+
|
|
194
|
+
### Chuỗi tin nhắn chào mừng khách hàng mới
|
|
195
|
+
```typescript
|
|
196
|
+
const welcomeMessages: MessageItem[] = [
|
|
197
|
+
{
|
|
198
|
+
type: "text",
|
|
199
|
+
text: "🎉 Chào mừng bạn đến với dịch vụ của chúng tôi!",
|
|
200
|
+
delay: 2000,
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
type: "sticker",
|
|
204
|
+
stickerAttachmentId: "WELCOME_STICKER_ID",
|
|
205
|
+
delay: 1500,
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
type: "image",
|
|
209
|
+
imageUrl: "https://company.com/welcome-banner.jpg",
|
|
210
|
+
text: "Khám phá các dịch vụ tuyệt vời",
|
|
211
|
+
delay: 3000,
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
type: "text",
|
|
215
|
+
text: "Chúng tôi sẽ hỗ trợ bạn 24/7. Hãy cho chúng tôi biết nếu bạn cần giúp đỡ! 💪",
|
|
216
|
+
},
|
|
217
|
+
];
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Chuỗi tin nhắn hỗ trợ kỹ thuật
|
|
221
|
+
```typescript
|
|
222
|
+
const supportMessages: MessageItem[] = [
|
|
223
|
+
{
|
|
224
|
+
type: "text",
|
|
225
|
+
text: "Chúng tôi đã nhận được yêu cầu hỗ trợ của bạn 🔧",
|
|
226
|
+
delay: 1000,
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
type: "file",
|
|
230
|
+
fileToken: "TROUBLESHOOTING_GUIDE_TOKEN",
|
|
231
|
+
delay: 2000,
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
type: "text",
|
|
235
|
+
text: "Vui lòng tham khảo hướng dẫn trên. Nếu vẫn gặp vấn đề, hãy liên hệ trực tiếp:",
|
|
236
|
+
delay: 1500,
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
type: "request_user_info",
|
|
240
|
+
title: "Thông tin liên hệ",
|
|
241
|
+
subtitle: "Để chúng tôi hỗ trợ bạn nhanh nhất",
|
|
242
|
+
imageUrl: "https://company.com/support-form.jpg",
|
|
243
|
+
},
|
|
244
|
+
];
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## Lưu ý quan trọng
|
|
248
|
+
|
|
249
|
+
1. **Delay**: Tính bằng milliseconds. Delay chỉ áp dụng giữa các tin nhắn, không có delay sau tin nhắn cuối cùng.
|
|
250
|
+
|
|
251
|
+
2. **Error Handling**: API sẽ tiếp tục gửi các tin nhắn tiếp theo ngay cả khi một tin nhắn thất bại.
|
|
252
|
+
|
|
253
|
+
3. **Rate Limiting**: Cần tuân thủ giới hạn tần suất gửi tin nhắn của Zalo để tránh bị chặn.
|
|
254
|
+
|
|
255
|
+
4. **Validation**: Mỗi loại tin nhắn có các trường bắt buộc riêng, cần đảm bảo cung cấp đầy đủ thông tin.
|
|
256
|
+
|
|
257
|
+
5. **File Upload**: Đối với file message, cần upload file trước và lấy token từ API upload của Zalo.
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
# API Gửi Chuỗi Tin Nhắn Tới Nhiều Users
|
|
262
|
+
|
|
263
|
+
API mở rộng cho phép gửi chuỗi tin nhắn tư vấn tới nhiều users cùng lúc với callback tracking real-time.
|
|
264
|
+
|
|
265
|
+
## Tính năng mới
|
|
266
|
+
|
|
267
|
+
- ✅ Gửi chuỗi tin nhắn tới nhiều users
|
|
268
|
+
- ✅ Callback tracking real-time cho từng user
|
|
269
|
+
- ✅ Thống kê chi tiết (thành công/thất bại)
|
|
270
|
+
- ✅ Delay tùy chỉnh giữa các users
|
|
271
|
+
- ✅ Loại bỏ user IDs trùng lặp tự động
|
|
272
|
+
- ✅ Error handling riêng biệt cho từng user
|
|
273
|
+
|
|
274
|
+
## Cách sử dụng
|
|
275
|
+
|
|
276
|
+
### 1. Import interface mới
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
import {
|
|
280
|
+
SendMessageSequenceToMultipleUsersRequest,
|
|
281
|
+
UserProgressInfo
|
|
282
|
+
} from "../src/services/consultation.service";
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### 2. Định nghĩa callback tracking
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
const onProgress = (progress: UserProgressInfo) => {
|
|
289
|
+
switch (progress.status) {
|
|
290
|
+
case 'started':
|
|
291
|
+
console.log(`🚀 Bắt đầu gửi cho User ${progress.userIndex + 1}/${progress.totalUsers}`);
|
|
292
|
+
break;
|
|
293
|
+
case 'completed':
|
|
294
|
+
console.log(`✅ Hoàn thành User ${progress.userIndex + 1} - Thành công: ${progress.result?.successCount}`);
|
|
295
|
+
break;
|
|
296
|
+
case 'failed':
|
|
297
|
+
console.log(`❌ Thất bại User ${progress.userIndex + 1} - Lỗi: ${progress.error}`);
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### 3. Gửi tới nhiều users
|
|
304
|
+
|
|
305
|
+
```typescript
|
|
306
|
+
const request: SendMessageSequenceToMultipleUsersRequest = {
|
|
307
|
+
accessToken: "YOUR_ACCESS_TOKEN",
|
|
308
|
+
userIds: ["USER_1", "USER_2", "USER_3"],
|
|
309
|
+
messages: [
|
|
310
|
+
{ type: "text", text: "Tin nhắn 1", delay: 1000 },
|
|
311
|
+
{ type: "text", text: "Tin nhắn 2" },
|
|
312
|
+
],
|
|
313
|
+
delayBetweenUsers: 2000, // Delay 2s giữa các user
|
|
314
|
+
onProgress, // Callback tracking
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
const result = await consultationService.sendMessageSequenceToMultipleUsers(request);
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## Interface chi tiết
|
|
321
|
+
|
|
322
|
+
### SendMessageSequenceToMultipleUsersRequest
|
|
323
|
+
```typescript
|
|
324
|
+
interface SendMessageSequenceToMultipleUsersRequest {
|
|
325
|
+
accessToken: string;
|
|
326
|
+
userIds: string[]; // Danh sách user IDs
|
|
327
|
+
messages: MessageItem[]; // Chuỗi tin nhắn
|
|
328
|
+
defaultDelay?: number; // Delay giữa tin nhắn (ms)
|
|
329
|
+
delayBetweenUsers?: number; // Delay giữa users (ms)
|
|
330
|
+
onProgress?: (progress: UserProgressInfo) => void; // Callback tracking
|
|
331
|
+
}
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### UserProgressInfo
|
|
335
|
+
```typescript
|
|
336
|
+
interface UserProgressInfo {
|
|
337
|
+
userId: string; // User ID hiện tại
|
|
338
|
+
userIndex: number; // Index của user (0-based)
|
|
339
|
+
totalUsers: number; // Tổng số users
|
|
340
|
+
status: 'started' | 'completed' | 'failed'; // Trạng thái
|
|
341
|
+
result?: SendMessageSequenceResponse; // Kết quả (nếu completed)
|
|
342
|
+
error?: string; // Lỗi (nếu failed)
|
|
343
|
+
startTime: number; // Thời gian bắt đầu
|
|
344
|
+
endTime?: number; // Thời gian kết thúc
|
|
345
|
+
}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### SendMessageSequenceToMultipleUsersResponse
|
|
349
|
+
```typescript
|
|
350
|
+
interface SendMessageSequenceToMultipleUsersResponse {
|
|
351
|
+
totalUsers: number; // Tổng số users
|
|
352
|
+
successfulUsers: number; // Số users thành công
|
|
353
|
+
failedUsers: number; // Số users thất bại
|
|
354
|
+
userResults: Array<{ // Chi tiết từng user
|
|
355
|
+
userId: string;
|
|
356
|
+
userIndex: number;
|
|
357
|
+
success: boolean;
|
|
358
|
+
messageSequenceResult?: SendMessageSequenceResponse;
|
|
359
|
+
error?: string;
|
|
360
|
+
startTime: number;
|
|
361
|
+
endTime: number;
|
|
362
|
+
duration: number;
|
|
363
|
+
}>;
|
|
364
|
+
totalDuration: number; // Tổng thời gian (ms)
|
|
365
|
+
messageStats: { // Thống kê tin nhắn
|
|
366
|
+
totalSuccessfulMessages: number;
|
|
367
|
+
totalFailedMessages: number;
|
|
368
|
+
totalMessages: number;
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
## Ví dụ thực tế
|
|
374
|
+
|
|
375
|
+
### Marketing Campaign
|
|
376
|
+
```typescript
|
|
377
|
+
const marketingMessages: MessageItem[] = [
|
|
378
|
+
{
|
|
379
|
+
type: "text",
|
|
380
|
+
text: "🎉 Flash Sale 24h - Giảm 50% tất cả sản phẩm!",
|
|
381
|
+
delay: 2000,
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
type: "image",
|
|
385
|
+
imageUrl: "https://shop.com/flash-sale-banner.jpg",
|
|
386
|
+
text: "Khuyến mãi khủng - Số lượng có hạn",
|
|
387
|
+
delay: 3000,
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
type: "text",
|
|
391
|
+
text: "⏰ Chỉ còn 12 giờ! Mua ngay: https://shop.com/sale",
|
|
392
|
+
},
|
|
393
|
+
];
|
|
394
|
+
|
|
395
|
+
const customerIds = ["CUSTOMER_1", "CUSTOMER_2", "CUSTOMER_3"];
|
|
396
|
+
|
|
397
|
+
let sentCount = 0;
|
|
398
|
+
const onProgress = (progress: UserProgressInfo) => {
|
|
399
|
+
if (progress.status === 'completed') {
|
|
400
|
+
sentCount++;
|
|
401
|
+
console.log(`📤 Đã gửi cho ${sentCount}/${progress.totalUsers} khách hàng`);
|
|
402
|
+
}
|
|
403
|
+
};
|
|
404
|
+
|
|
405
|
+
const result = await consultationService.sendMessageSequenceToMultipleUsers({
|
|
406
|
+
accessToken: "TOKEN",
|
|
407
|
+
userIds: customerIds,
|
|
408
|
+
messages: marketingMessages,
|
|
409
|
+
delayBetweenUsers: 1500, // Tránh spam
|
|
410
|
+
onProgress,
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
console.log(`🎯 Campaign hoàn thành: ${result.successfulUsers}/${result.totalUsers} khách hàng`);
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### Customer Support Notification
|
|
417
|
+
```typescript
|
|
418
|
+
const supportMessages: MessageItem[] = [
|
|
419
|
+
{
|
|
420
|
+
type: "text",
|
|
421
|
+
text: "🔧 Hệ thống sẽ bảo trì từ 2:00-4:00 sáng mai",
|
|
422
|
+
delay: 1000,
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
type: "text",
|
|
426
|
+
text: "📞 Hotline hỗ trợ 24/7: 1900-xxxx",
|
|
427
|
+
},
|
|
428
|
+
];
|
|
429
|
+
|
|
430
|
+
const allCustomers = ["USER_1", "USER_2", "USER_3", "USER_4"];
|
|
431
|
+
|
|
432
|
+
const result = await consultationService.sendMessageSequenceToMultipleUsers({
|
|
433
|
+
accessToken: "TOKEN",
|
|
434
|
+
userIds: allCustomers,
|
|
435
|
+
messages: supportMessages,
|
|
436
|
+
delayBetweenUsers: 500,
|
|
437
|
+
onProgress: (progress) => {
|
|
438
|
+
if (progress.status === 'failed') {
|
|
439
|
+
console.log(`❌ Không gửi được cho ${progress.userId}: ${progress.error}`);
|
|
440
|
+
}
|
|
441
|
+
},
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
console.log(`📢 Thông báo đã gửi tới ${result.successfulUsers} khách hàng`);
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
## So sánh API cũ vs mới
|
|
448
|
+
|
|
449
|
+
| Tính năng | API đơn user | API nhiều users |
|
|
450
|
+
|-----------|-------------|-----------------|
|
|
451
|
+
| Số lượng users | 1 user | Nhiều users |
|
|
452
|
+
| Callback tracking | ❌ | ✅ Real-time |
|
|
453
|
+
| Thống kê tổng quan | ❌ | ✅ Chi tiết |
|
|
454
|
+
| Delay giữa users | ❌ | ✅ Tùy chỉnh |
|
|
455
|
+
| Error handling | Dừng khi lỗi | Tiếp tục với user khác |
|
|
456
|
+
| Use case | Tư vấn 1-1 | Marketing, thông báo |
|
|
457
|
+
|
|
458
|
+
## Lưu ý quan trọng
|
|
459
|
+
|
|
460
|
+
1. **Rate Limiting**: Sử dụng `delayBetweenUsers` để tránh hit rate limit của Zalo
|
|
461
|
+
2. **Memory Usage**: Với số lượng users lớn, cân nhắc chia batch
|
|
462
|
+
3. **Callback Performance**: Callback không nên thực hiện operations nặng
|
|
463
|
+
4. **Error Isolation**: Lỗi của 1 user không ảnh hưởng đến users khác
|
|
464
|
+
5. **Duplicate Handling**: API tự động loại bỏ user IDs trùng lặp
|