@warriorteam/redai-zalo-sdk 1.26.1 → 1.26.2
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/dist/services/consultation.service.d.ts +50 -17
- package/dist/services/consultation.service.d.ts.map +1 -1
- package/dist/services/consultation.service.js +120 -26
- package/dist/services/consultation.service.js.map +1 -1
- package/package.json +1 -1
- package/examples/article-status-update.ts +0 -178
- package/examples/broadcast-example.ts +0 -201
- package/examples/consultation-service-example.ts +0 -390
- package/examples/get-all-articles-example.ts +0 -171
- package/examples/group-message-list.ts +0 -288
- package/examples/oa-auth-with-pkce.ts +0 -179
- package/examples/promotion-examples.ts +0 -514
- package/examples/send-message-sequence.ts +0 -200
- package/examples/user-list-post-example.ts +0 -186
- package/examples/video-upload-combined.example.ts +0 -228
- package/examples/webhook-message-classification.ts +0 -285
- package/examples/zns-template-edit.example.ts +0 -317
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Broadcast Message Example
|
|
3
|
-
*
|
|
4
|
-
* Ví dụ về cách sử dụng BroadcastService để gửi tin truyền thông broadcast
|
|
5
|
-
* đến nhiều người dùng dựa trên tiêu chí targeting
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { ZaloSDK } from "../src/index";
|
|
9
|
-
|
|
10
|
-
async function broadcastExample() {
|
|
11
|
-
// Khởi tạo SDK
|
|
12
|
-
const zalo = new ZaloSDK({
|
|
13
|
-
appId: "your-app-id",
|
|
14
|
-
appSecret: "your-app-secret",
|
|
15
|
-
debug: true
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
// Access token của OA (cần có quyền broadcast)
|
|
19
|
-
const accessToken = "your-oa-access-token";
|
|
20
|
-
|
|
21
|
-
// ID của article attachment đã được tạo trước
|
|
22
|
-
const articleAttachmentId = "bd5ea46bb32e5a0033f";
|
|
23
|
-
|
|
24
|
-
try {
|
|
25
|
-
console.log("=== Broadcast Message Examples ===\n");
|
|
26
|
-
|
|
27
|
-
// Example 1: Broadcast đến tất cả người dùng ở Hồ Chí Minh
|
|
28
|
-
console.log("1. Broadcast to Ho Chi Minh City users:");
|
|
29
|
-
const hcmTarget = zalo.broadcast.createBroadcastTarget({
|
|
30
|
-
cities: ["Hồ Chí Minh"]
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
const hcmResult = await zalo.broadcast.sendBroadcastMessage(
|
|
34
|
-
accessToken,
|
|
35
|
-
{ target: hcmTarget },
|
|
36
|
-
articleAttachmentId
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
console.log("HCM broadcast result:", {
|
|
40
|
-
messageId: hcmResult.data.message_id,
|
|
41
|
-
error: hcmResult.error,
|
|
42
|
-
message: hcmResult.message
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
// Example 2: Broadcast đến nam giới 25-34 tuổi
|
|
46
|
-
console.log("\n2. Broadcast to male users aged 25-34:");
|
|
47
|
-
const maleTarget = zalo.broadcast.createBroadcastTarget({
|
|
48
|
-
gender: "MALE",
|
|
49
|
-
ages: ["25-34"]
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
const maleResult = await zalo.broadcast.sendBroadcastMessage(
|
|
53
|
-
accessToken,
|
|
54
|
-
{ target: maleTarget },
|
|
55
|
-
articleAttachmentId
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
console.log("Male 25-34 broadcast result:", {
|
|
59
|
-
messageId: maleResult.data.message_id,
|
|
60
|
-
error: maleResult.error,
|
|
61
|
-
message: maleResult.message
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
// Example 3: Broadcast đến người dùng iOS ở miền Nam
|
|
65
|
-
console.log("\n3. Broadcast to iOS users in South Vietnam:");
|
|
66
|
-
const iosTarget = zalo.broadcast.createBroadcastTarget({
|
|
67
|
-
platform: ["IOS"],
|
|
68
|
-
locations: ["SOUTH"]
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
const iosResult = await zalo.broadcast.sendBroadcastMessage(
|
|
72
|
-
accessToken,
|
|
73
|
-
{ target: iosTarget },
|
|
74
|
-
articleAttachmentId
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
console.log("iOS South broadcast result:", {
|
|
78
|
-
messageId: iosResult.data.message_id,
|
|
79
|
-
error: iosResult.error,
|
|
80
|
-
message: iosResult.message
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
// Example 4: Broadcast phức tạp - Nữ giới 18-24 tuổi, dùng Android, ở Hà Nội và Đà Nẵng
|
|
84
|
-
console.log("\n4. Complex targeting broadcast:");
|
|
85
|
-
const complexTarget = zalo.broadcast.createBroadcastTarget({
|
|
86
|
-
gender: "FEMALE",
|
|
87
|
-
ages: ["18-24"],
|
|
88
|
-
platform: ["ANDROID"],
|
|
89
|
-
cities: ["Hà Nội", "Đà Nẵng"]
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
const complexResult = await zalo.broadcast.sendBroadcastMessage(
|
|
93
|
-
accessToken,
|
|
94
|
-
{ target: complexTarget },
|
|
95
|
-
articleAttachmentId
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
console.log("Complex targeting broadcast result:", {
|
|
99
|
-
messageId: complexResult.data.message_id,
|
|
100
|
-
error: complexResult.error,
|
|
101
|
-
message: complexResult.message
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
// Example 5: Gửi nhiều broadcast messages cùng lúc
|
|
105
|
-
console.log("\n5. Multiple broadcast messages (Sequential):");
|
|
106
|
-
const multipleAttachmentIds = [
|
|
107
|
-
"bd5ea46bb32e5a0033f",
|
|
108
|
-
"cd6fb57cc43f6b1144g",
|
|
109
|
-
"de7gc68dd54g7c2255h"
|
|
110
|
-
];
|
|
111
|
-
|
|
112
|
-
const multipleTarget = zalo.broadcast.createBroadcastTarget({
|
|
113
|
-
cities: ["Hà Nội"],
|
|
114
|
-
gender: "ALL"
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
const multipleResult = await zalo.broadcast.sendMultipleBroadcastMessages(
|
|
118
|
-
accessToken,
|
|
119
|
-
{ target: multipleTarget },
|
|
120
|
-
multipleAttachmentIds,
|
|
121
|
-
{
|
|
122
|
-
mode: 'sequential',
|
|
123
|
-
delay: 2000, // 2 seconds delay between messages
|
|
124
|
-
onProgress: (progress) => {
|
|
125
|
-
console.log(`Progress: ${progress.completed}/${progress.total} - Current: ${progress.currentAttachmentId}`);
|
|
126
|
-
console.log(`Success: ${progress.successful}, Failed: ${progress.failed}`);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
);
|
|
130
|
-
|
|
131
|
-
console.log("Multiple broadcast result:", {
|
|
132
|
-
totalMessages: multipleResult.totalMessages,
|
|
133
|
-
successful: multipleResult.successfulMessages,
|
|
134
|
-
failed: multipleResult.failedMessages,
|
|
135
|
-
duration: `${multipleResult.totalDuration}ms`,
|
|
136
|
-
mode: multipleResult.mode
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
// Example 6: Gửi nhiều broadcast messages song song
|
|
140
|
-
console.log("\n6. Multiple broadcast messages (Parallel):");
|
|
141
|
-
const parallelResult = await zalo.broadcast.sendMultipleBroadcastMessages(
|
|
142
|
-
accessToken,
|
|
143
|
-
{ target: multipleTarget },
|
|
144
|
-
multipleAttachmentIds,
|
|
145
|
-
{
|
|
146
|
-
mode: 'parallel',
|
|
147
|
-
onProgress: (progress) => {
|
|
148
|
-
console.log(`Parallel progress: ${progress.completed}/${progress.total}`);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
);
|
|
152
|
-
|
|
153
|
-
console.log("Parallel broadcast result:", {
|
|
154
|
-
totalMessages: parallelResult.totalMessages,
|
|
155
|
-
successful: parallelResult.successfulMessages,
|
|
156
|
-
failed: parallelResult.failedMessages,
|
|
157
|
-
duration: `${parallelResult.totalDuration}ms`,
|
|
158
|
-
mode: parallelResult.mode
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
// Example 7: Hiển thị các mã targeting có sẵn
|
|
162
|
-
console.log("\n7. Available targeting codes:");
|
|
163
|
-
console.log("City codes:", Object.keys(zalo.broadcast.getCityCodes()).slice(0, 10), "...");
|
|
164
|
-
console.log("Age group codes:", zalo.broadcast.getAgeGroupCodes());
|
|
165
|
-
console.log("Gender codes:", zalo.broadcast.getGenderCodes());
|
|
166
|
-
console.log("Location codes:", zalo.broadcast.getLocationCodes());
|
|
167
|
-
console.log("Platform codes:", zalo.broadcast.getPlatformCodes());
|
|
168
|
-
|
|
169
|
-
} catch (error) {
|
|
170
|
-
console.error("Broadcast error:", error);
|
|
171
|
-
|
|
172
|
-
if (error.code) {
|
|
173
|
-
switch (error.code) {
|
|
174
|
-
case 3001:
|
|
175
|
-
console.error("Không có quyền gửi broadcast. Liên hệ Zalo để được cấp quyền.");
|
|
176
|
-
break;
|
|
177
|
-
case 3002:
|
|
178
|
-
console.error("Article attachment không tồn tại hoặc đã hết hạn.");
|
|
179
|
-
break;
|
|
180
|
-
case 3003:
|
|
181
|
-
console.error("Targeting criteria không hợp lệ.");
|
|
182
|
-
break;
|
|
183
|
-
case 3004:
|
|
184
|
-
console.error("Vượt quá giới hạn broadcast cho phép.");
|
|
185
|
-
break;
|
|
186
|
-
case 3005:
|
|
187
|
-
console.error("Nội dung vi phạm chính sách Zalo.");
|
|
188
|
-
break;
|
|
189
|
-
default:
|
|
190
|
-
console.error("Lỗi không xác định:", error.message);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// Chạy example nếu file được execute trực tiếp
|
|
197
|
-
if (require.main === module) {
|
|
198
|
-
broadcastExample().catch(console.error);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
export { broadcastExample };
|
|
@@ -1,390 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Ví dụ sử dụng ConsultationService - Dịch vụ tin nhắn tư vấn
|
|
3
|
-
*
|
|
4
|
-
* Ví dụ này minh họa cách sử dụng ConsultationService để:
|
|
5
|
-
* - Gửi tin nhắn tư vấn văn bản
|
|
6
|
-
* - Gửi hình ảnh hỗ trợ
|
|
7
|
-
* - Gửi file hướng dẫn
|
|
8
|
-
* - Xử lý lỗi và retry
|
|
9
|
-
* - Tích hợp với webhook
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { ZaloSDK, ZaloSDKError, SendMessageResponse } from "../src/index";
|
|
13
|
-
|
|
14
|
-
// Cấu hình SDK
|
|
15
|
-
const zalo = new ZaloSDK({
|
|
16
|
-
appId: "your-app-id",
|
|
17
|
-
appSecret: "your-app-secret",
|
|
18
|
-
debug: true
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
// Access token của OA (lấy từ quá trình authentication)
|
|
22
|
-
const ACCESS_TOKEN = "your-oa-access-token";
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Ví dụ 1: Gửi tin nhắn tư vấn cơ bản
|
|
26
|
-
*/
|
|
27
|
-
async function basicConsultationExample() {
|
|
28
|
-
console.log("=== Ví dụ 1: Tin nhắn tư vấn cơ bản ===");
|
|
29
|
-
|
|
30
|
-
try {
|
|
31
|
-
// Gửi tin nhắn văn bản tư vấn
|
|
32
|
-
const response = await zalo.consultation.sendTextMessage(
|
|
33
|
-
ACCESS_TOKEN,
|
|
34
|
-
{ user_id: "user-id-here" },
|
|
35
|
-
{
|
|
36
|
-
type: "text",
|
|
37
|
-
text: "Xin chào! Cảm ơn bạn đã liên hệ với chúng tôi. Tôi có thể hỗ trợ gì cho bạn hôm nay?"
|
|
38
|
-
}
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
console.log("✅ Gửi tin nhắn thành công!");
|
|
42
|
-
console.log("Message ID:", response.message_id);
|
|
43
|
-
console.log("User ID:", response.user_id);
|
|
44
|
-
|
|
45
|
-
if (response.quota) {
|
|
46
|
-
console.log("Quota còn lại:", response.quota.remain);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
} catch (error) {
|
|
50
|
-
if (error instanceof ZaloSDKError) {
|
|
51
|
-
console.error("❌ Lỗi Zalo API:", error.message);
|
|
52
|
-
console.error("Mã lỗi:", error.code);
|
|
53
|
-
} else {
|
|
54
|
-
console.error("❌ Lỗi không xác định:", error);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Ví dụ 2: Gửi hình ảnh hỗ trợ
|
|
61
|
-
*/
|
|
62
|
-
async function imageConsultationExample() {
|
|
63
|
-
console.log("\n=== Ví dụ 2: Gửi hình ảnh hỗ trợ ===");
|
|
64
|
-
|
|
65
|
-
try {
|
|
66
|
-
const response = await zalo.consultation.sendImageMessage(
|
|
67
|
-
ACCESS_TOKEN,
|
|
68
|
-
{ user_id: "user-id-here" },
|
|
69
|
-
{
|
|
70
|
-
type: "image",
|
|
71
|
-
attachment: {
|
|
72
|
-
type: "image",
|
|
73
|
-
payload: {
|
|
74
|
-
url: "https://example.com/support-guide.jpg"
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
console.log("✅ Gửi hình ảnh hỗ trợ thành công!");
|
|
81
|
-
console.log("Message ID:", response.message_id);
|
|
82
|
-
|
|
83
|
-
} catch (error) {
|
|
84
|
-
console.error("❌ Lỗi gửi hình ảnh:", error);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Ví dụ 3: Gửi file hướng dẫn
|
|
90
|
-
*/
|
|
91
|
-
async function fileConsultationExample() {
|
|
92
|
-
console.log("\n=== Ví dụ 3: Gửi file hướng dẫn ===");
|
|
93
|
-
|
|
94
|
-
try {
|
|
95
|
-
const response = await zalo.consultation.sendFileMessage(
|
|
96
|
-
ACCESS_TOKEN,
|
|
97
|
-
{ user_id: "user-id-here" },
|
|
98
|
-
{
|
|
99
|
-
type: "file",
|
|
100
|
-
url: "https://example.com/user-manual.pdf",
|
|
101
|
-
filename: "Hướng dẫn sử dụng.pdf",
|
|
102
|
-
attachment: {
|
|
103
|
-
type: "file",
|
|
104
|
-
payload: {
|
|
105
|
-
url: "https://example.com/user-manual.pdf"
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
);
|
|
110
|
-
|
|
111
|
-
console.log("✅ Gửi file hướng dẫn thành công!");
|
|
112
|
-
console.log("Message ID:", response.message_id);
|
|
113
|
-
|
|
114
|
-
} catch (error) {
|
|
115
|
-
console.error("❌ Lỗi gửi file:", error);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Ví dụ 4: Hệ thống hỗ trợ khách hàng thông minh
|
|
121
|
-
*/
|
|
122
|
-
class SmartCustomerSupport {
|
|
123
|
-
private zalo: ZaloSDK;
|
|
124
|
-
private accessToken: string;
|
|
125
|
-
|
|
126
|
-
constructor(zalo: ZaloSDK, accessToken: string) {
|
|
127
|
-
this.zalo = zalo;
|
|
128
|
-
this.accessToken = accessToken;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Xử lý câu hỏi của khách hàng
|
|
133
|
-
*/
|
|
134
|
-
async handleCustomerQuestion(userId: string, question: string) {
|
|
135
|
-
console.log(`\n📞 Xử lý câu hỏi từ user ${userId}: "${question}"`);
|
|
136
|
-
|
|
137
|
-
try {
|
|
138
|
-
// Phân tích câu hỏi và tạo phản hồi
|
|
139
|
-
const response = this.analyzeQuestion(question);
|
|
140
|
-
|
|
141
|
-
// Gửi tin nhắn phản hồi
|
|
142
|
-
await this.zalo.consultation.sendTextMessage(
|
|
143
|
-
this.accessToken,
|
|
144
|
-
{ user_id: userId },
|
|
145
|
-
{
|
|
146
|
-
type: "text",
|
|
147
|
-
text: response.text
|
|
148
|
-
}
|
|
149
|
-
);
|
|
150
|
-
|
|
151
|
-
// Gửi thêm tài liệu hỗ trợ nếu cần
|
|
152
|
-
if (response.needsDocument) {
|
|
153
|
-
await this.sendSupportDocument(userId, response.documentType);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
console.log("✅ Đã phản hồi khách hàng thành công!");
|
|
157
|
-
|
|
158
|
-
} catch (error) {
|
|
159
|
-
console.error("❌ Lỗi xử lý câu hỏi khách hàng:", error);
|
|
160
|
-
|
|
161
|
-
// Gửi tin nhắn lỗi cho khách hàng
|
|
162
|
-
await this.sendErrorMessage(userId);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Phân tích câu hỏi và tạo phản hồi
|
|
168
|
-
*/
|
|
169
|
-
private analyzeQuestion(question: string) {
|
|
170
|
-
const lowerQuestion = question.toLowerCase();
|
|
171
|
-
|
|
172
|
-
if (lowerQuestion.includes("đăng nhập") || lowerQuestion.includes("login")) {
|
|
173
|
-
return {
|
|
174
|
-
text: "Để đăng nhập vào hệ thống, bạn vui lòng:\n1. Truy cập trang đăng nhập\n2. Nhập email và mật khẩu\n3. Nhấn 'Đăng nhập'\n\nNếu quên mật khẩu, bạn có thể sử dụng chức năng 'Quên mật khẩu'.",
|
|
175
|
-
needsDocument: true,
|
|
176
|
-
documentType: "login_guide"
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
if (lowerQuestion.includes("thanh toán") || lowerQuestion.includes("payment")) {
|
|
181
|
-
return {
|
|
182
|
-
text: "Chúng tôi hỗ trợ các phương thức thanh toán sau:\n• Thẻ tín dụng/ghi nợ\n• Ví điện tử (MoMo, ZaloPay)\n• Chuyển khoản ngân hàng\n• Thanh toán khi nhận hàng (COD)\n\nBạn cần hỗ trợ về phương thức nào?",
|
|
183
|
-
needsDocument: true,
|
|
184
|
-
documentType: "payment_guide"
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
if (lowerQuestion.includes("giao hàng") || lowerQuestion.includes("shipping")) {
|
|
189
|
-
return {
|
|
190
|
-
text: "Thông tin về giao hàng:\n• Nội thành: 1-2 ngày\n• Ngoại thành: 2-3 ngày\n• Tỉnh khác: 3-5 ngày\n\nPhí ship được tính theo khoảng cách và trọng lượng đơn hàng.",
|
|
191
|
-
needsDocument: false,
|
|
192
|
-
documentType: null
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// Phản hồi mặc định
|
|
197
|
-
return {
|
|
198
|
-
text: "Cảm ơn bạn đã liên hệ! Tôi đã ghi nhận câu hỏi của bạn. Đội ngũ hỗ trợ sẽ phản hồi trong vòng 24 giờ.\n\nCác vấn đề phổ biến:\n• Đăng nhập\n• Thanh toán\n• Giao hàng\n• Đổi trả\n\nBạn có thể hỏi cụ thể về các vấn đề này để được hỗ trợ nhanh hơn.",
|
|
199
|
-
needsDocument: false,
|
|
200
|
-
documentType: null
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Gửi tài liệu hỗ trợ
|
|
206
|
-
*/
|
|
207
|
-
private async sendSupportDocument(userId: string, documentType: string) {
|
|
208
|
-
const documents = {
|
|
209
|
-
login_guide: {
|
|
210
|
-
url: "https://example.com/guides/login-guide.pdf",
|
|
211
|
-
filename: "Hướng dẫn đăng nhập.pdf"
|
|
212
|
-
},
|
|
213
|
-
payment_guide: {
|
|
214
|
-
url: "https://example.com/guides/payment-guide.pdf",
|
|
215
|
-
filename: "Hướng dẫn thanh toán.pdf"
|
|
216
|
-
}
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
const doc = documents[documentType as keyof typeof documents];
|
|
220
|
-
if (!doc) return;
|
|
221
|
-
|
|
222
|
-
await this.zalo.consultation.sendFileMessage(
|
|
223
|
-
this.accessToken,
|
|
224
|
-
{ user_id: userId },
|
|
225
|
-
{
|
|
226
|
-
type: "file",
|
|
227
|
-
url: doc.url,
|
|
228
|
-
filename: doc.filename,
|
|
229
|
-
attachment: {
|
|
230
|
-
type: "file",
|
|
231
|
-
payload: {
|
|
232
|
-
url: doc.url
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* Gửi tin nhắn lỗi
|
|
241
|
-
*/
|
|
242
|
-
private async sendErrorMessage(userId: string) {
|
|
243
|
-
try {
|
|
244
|
-
await this.zalo.consultation.sendTextMessage(
|
|
245
|
-
this.accessToken,
|
|
246
|
-
{ user_id: userId },
|
|
247
|
-
{
|
|
248
|
-
type: "text",
|
|
249
|
-
text: "Xin lỗi, hiện tại hệ thống đang gặp sự cố. Vui lòng thử lại sau hoặc liên hệ hotline: 1900-xxxx để được hỗ trợ trực tiếp."
|
|
250
|
-
}
|
|
251
|
-
);
|
|
252
|
-
} catch (error) {
|
|
253
|
-
console.error("❌ Không thể gửi tin nhắn lỗi:", error);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* Ví dụ 5: Retry mechanism
|
|
260
|
-
*/
|
|
261
|
-
async function sendWithRetry(
|
|
262
|
-
userId: string,
|
|
263
|
-
message: string,
|
|
264
|
-
maxRetries: number = 3
|
|
265
|
-
): Promise<SendMessageResponse | null> {
|
|
266
|
-
console.log(`\n🔄 Gửi tin nhắn với retry (tối đa ${maxRetries} lần)`);
|
|
267
|
-
|
|
268
|
-
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
269
|
-
try {
|
|
270
|
-
console.log(`Lần thử ${attempt}/${maxRetries}`);
|
|
271
|
-
|
|
272
|
-
const response = await zalo.consultation.sendTextMessage(
|
|
273
|
-
ACCESS_TOKEN,
|
|
274
|
-
{ user_id: userId },
|
|
275
|
-
{ type: "text", text: message }
|
|
276
|
-
);
|
|
277
|
-
|
|
278
|
-
console.log("✅ Gửi thành công!");
|
|
279
|
-
return response;
|
|
280
|
-
|
|
281
|
-
} catch (error) {
|
|
282
|
-
console.log(`❌ Lần thử ${attempt} thất bại:`, error instanceof ZaloSDKError ? error.message : error);
|
|
283
|
-
|
|
284
|
-
if (attempt === maxRetries) {
|
|
285
|
-
console.log("❌ Đã thử hết số lần cho phép");
|
|
286
|
-
return null;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
// Đợi trước khi thử lại (exponential backoff)
|
|
290
|
-
const delay = Math.pow(2, attempt) * 1000;
|
|
291
|
-
console.log(`⏳ Đợi ${delay}ms trước khi thử lại...`);
|
|
292
|
-
await new Promise(resolve => setTimeout(resolve, delay));
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
return null;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* Ví dụ 6: Tích hợp với webhook
|
|
301
|
-
*/
|
|
302
|
-
function setupWebhookIntegration() {
|
|
303
|
-
console.log("\n🔗 Thiết lập tích hợp webhook");
|
|
304
|
-
|
|
305
|
-
const customerSupport = new SmartCustomerSupport(zalo, ACCESS_TOKEN);
|
|
306
|
-
|
|
307
|
-
// Giả lập xử lý webhook event
|
|
308
|
-
const handleWebhookEvent = async (event: any) => {
|
|
309
|
-
console.log("📨 Nhận webhook event:", event.event_name);
|
|
310
|
-
|
|
311
|
-
switch (event.event_name) {
|
|
312
|
-
case "user_send_text":
|
|
313
|
-
const userId = event.sender.id;
|
|
314
|
-
const userMessage = event.message.text;
|
|
315
|
-
|
|
316
|
-
// Kiểm tra xem có phải câu hỏi cần hỗ trợ không
|
|
317
|
-
if (userMessage.includes("help") ||
|
|
318
|
-
userMessage.includes("hỗ trợ") ||
|
|
319
|
-
userMessage.includes("support")) {
|
|
320
|
-
|
|
321
|
-
await customerSupport.handleCustomerQuestion(userId, userMessage);
|
|
322
|
-
}
|
|
323
|
-
break;
|
|
324
|
-
|
|
325
|
-
case "user_send_sticker":
|
|
326
|
-
// Phản hồi sticker bằng tin nhắn thân thiện
|
|
327
|
-
await zalo.consultation.sendTextMessage(
|
|
328
|
-
ACCESS_TOKEN,
|
|
329
|
-
{ user_id: event.sender.id },
|
|
330
|
-
{
|
|
331
|
-
type: "text",
|
|
332
|
-
text: "Cảm ơn bạn! 😊 Tôi có thể hỗ trợ gì cho bạn không?"
|
|
333
|
-
}
|
|
334
|
-
);
|
|
335
|
-
break;
|
|
336
|
-
|
|
337
|
-
default:
|
|
338
|
-
console.log("Event không cần xử lý:", event.event_name);
|
|
339
|
-
}
|
|
340
|
-
};
|
|
341
|
-
|
|
342
|
-
return handleWebhookEvent;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
/**
|
|
346
|
-
* Chạy tất cả ví dụ
|
|
347
|
-
*/
|
|
348
|
-
async function runAllExamples() {
|
|
349
|
-
console.log("🚀 Bắt đầu chạy các ví dụ ConsultationService\n");
|
|
350
|
-
|
|
351
|
-
// Ví dụ cơ bản
|
|
352
|
-
await basicConsultationExample();
|
|
353
|
-
await imageConsultationExample();
|
|
354
|
-
await fileConsultationExample();
|
|
355
|
-
|
|
356
|
-
// Ví dụ hệ thống hỗ trợ thông minh
|
|
357
|
-
const customerSupport = new SmartCustomerSupport(zalo, ACCESS_TOKEN);
|
|
358
|
-
await customerSupport.handleCustomerQuestion("user123", "Tôi không đăng nhập được");
|
|
359
|
-
await customerSupport.handleCustomerQuestion("user456", "Làm sao để thanh toán?");
|
|
360
|
-
|
|
361
|
-
// Ví dụ retry
|
|
362
|
-
await sendWithRetry("user789", "Tin nhắn test retry");
|
|
363
|
-
|
|
364
|
-
// Thiết lập webhook
|
|
365
|
-
const webhookHandler = setupWebhookIntegration();
|
|
366
|
-
|
|
367
|
-
// Giả lập một số webhook events
|
|
368
|
-
await webhookHandler({
|
|
369
|
-
event_name: "user_send_text",
|
|
370
|
-
sender: { id: "user123" },
|
|
371
|
-
message: { text: "Tôi cần hỗ trợ về đăng nhập" }
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
console.log("\n✅ Hoàn thành tất cả ví dụ!");
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
// Chạy ví dụ nếu file được execute trực tiếp
|
|
378
|
-
if (require.main === module) {
|
|
379
|
-
runAllExamples().catch(console.error);
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
export {
|
|
383
|
-
basicConsultationExample,
|
|
384
|
-
imageConsultationExample,
|
|
385
|
-
fileConsultationExample,
|
|
386
|
-
SmartCustomerSupport,
|
|
387
|
-
sendWithRetry,
|
|
388
|
-
setupWebhookIntegration,
|
|
389
|
-
runAllExamples
|
|
390
|
-
};
|