n8n-nodes-zalo-oav3-test
Version:
Tích hợp Zalo Official Account API v3.0 vào n8n
1,697 lines • 95.2 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ZaloOA = void 0;
const n8n_workflow_1 = require("n8n-workflow");
const ZaloOADescription_1 = require("./ZaloOADescription");
const axios_1 = __importDefault(require("axios"));
const form_data_1 = __importDefault(require("form-data"));
class ZaloOA {
constructor() {
this.description = {
displayName: 'Zalo OA',
name: 'zaloOA',
icon: 'file:zalooa.svg',
group: ['transform'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Tương tác với Zalo Official Account API',
defaults: {
name: 'Zalo OA',
},
inputs: ["main"],
outputs: ["main"],
credentials: [
{
name: 'zaloOAApi',
required: true,
},
],
properties: [
{
displayName: 'Resource',
name: 'resource',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Zalo OA',
value: 'zaloOA',
},
],
default: 'zaloOA',
},
...ZaloOADescription_1.zaloOAOperations,
...ZaloOADescription_1.zaloOAFields,
],
};
}
async execute() {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y;
const items = this.getInputData();
const returnData = [];
const resource = this.getNodeParameter('resource', 0);
const operation = this.getNodeParameter('operation', 0);
const credentials = await this.getCredentials('zaloOAApi');
const accessToken = credentials.accessToken;
const baseUrl = 'https://openapi.zalo.me/v3.0/oa';
for (let i = 0; i < items.length; i++) {
try {
if (resource === 'zaloOA') {
if (operation === 'sendTextMessage') {
const userId = this.getNodeParameter('userId', i);
const text = this.getNodeParameter('text', i);
const messageType = this.getNodeParameter('messageType', i) || "cs";
const response = await axios_1.default.post(`${baseUrl}/message/${messageType}`, {
recipient: {
user_id: userId,
},
message: {
text,
},
}, {
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
else if (operation === 'sendGroupTextMessage') {
const groupId = this.getNodeParameter('groupId', i);
const text = this.getNodeParameter('text', i);
const response = await axios_1.default.post(`${baseUrl}/group/message`, {
recipient: {
group_id: groupId,
},
message: {
text,
},
}, {
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
else if (operation === 'sendImageMessage') {
const userId = this.getNodeParameter('userId', i);
const imageType = this.getNodeParameter('imageType', i);
let attachment;
if (imageType === 'imageUrl') {
const imageUrl = this.getNodeParameter('imageUrl', i);
attachment = {
type: 'template',
payload: {
template_type: 'media',
elements: [
{
media_type: 'image',
url: imageUrl,
},
],
},
};
}
else {
const imageId = this.getNodeParameter('imageId', i);
attachment = {
type: 'template',
payload: {
template_type: 'media',
elements: [
{
media_type: 'image',
attachment_id: imageId,
},
],
},
};
}
const messageType = this.getNodeParameter('messageType', i);
const response = await axios_1.default.post(`${baseUrl}/message/${messageType}`, {
recipient: {
user_id: userId,
},
message: {
attachment,
},
}, {
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
else if (operation === 'sendFileMessage') {
const userId = this.getNodeParameter('userId', i);
const fileId = this.getNodeParameter('fileId', i);
const messageType = this.getNodeParameter('messageType', i);
const response = await axios_1.default.post(`${baseUrl}/message/${messageType}`, {
recipient: {
user_id: userId,
},
message: {
attachment: {
type: 'file',
payload: {
token: fileId,
},
},
},
}, {
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
else if (operation === 'sendListMessage') {
const userId = this.getNodeParameter('userId', i);
const listTitle = this.getNodeParameter('title', i);
const elementsCollection = this.getNodeParameter('elements', i);
const elements = elementsCollection.elementsValues.map((element) => ({
title: element.title,
subtitle: element.subtitle,
image_url: element.imageUrl,
default_action: {
type: 'oa.open.url',
url: element.defaultActionUrl,
},
}));
const messageType = this.getNodeParameter('messageType', i);
const response = await axios_1.default.post(`${baseUrl}/message/${messageType}`, {
recipient: {
user_id: userId,
},
message: {
attachment: {
type: 'template',
payload: {
template_type: 'list',
elements,
buttons: [
{
title: listTitle,
type: 'oa.open.url',
payload: {
url: 'https://zalo.me'
}
}
]
},
},
},
}, {
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
else if (operation === 'getFollowerInfo') {
const userId = this.getNodeParameter('userId', i);
try {
const v3BaseUrl = 'https://openapi.zalo.me/v3.0/oa';
const dataParam = JSON.stringify({
user_id: userId,
});
const response = await axios_1.default.get(`${v3BaseUrl}/user/detail`, {
params: {
data: dataParam,
},
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
catch (error) {
console.log('Lỗi khi gọi API user/detail v3.0:', error.message);
returnData.push({
json: {
error: true,
message: `Lỗi khi gọi API lấy thông tin người dùng: ${error.message}`,
note: 'Zalo đã thay đổi API getprofile sang API user/detail trong v3.0. Vui lòng kiểm tra lại cấu hình OA và quyền truy cập.',
suggestion: 'Hãy đảm bảo rằng bạn đã cấp quyền "Quyền quản lý thông tin người dùng" cho ứng dụng và có access_token hợp lệ.',
},
pairedItem: {
item: i,
},
});
}
}
else if (operation === 'uploadImage') {
const binaryData = this.getNodeParameter('binaryData', i);
let response;
try {
if (binaryData) {
const binaryProperty = this.getNodeParameter('binaryProperty', i);
const binaryFile = items[i].binary[binaryProperty];
if (binaryFile === undefined) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `No binary data property "${binaryProperty}" exists on item.`, { itemIndex: i });
}
const buffer = await this.helpers.getBinaryDataBuffer(i, binaryProperty);
const formData = new form_data_1.default();
formData.append('file', buffer, {
filename: binaryFile.fileName || 'image.jpg',
contentType: binaryFile.mimeType,
});
console.log(`Uploading image with filename: ${binaryFile.fileName}, mime type: ${binaryFile.mimeType}`);
response = await axios_1.default.post(`${baseUrl}/upload/image`, formData, {
headers: {
access_token: accessToken,
...formData.getHeaders(),
},
});
}
else {
const imageUrl = this.getNodeParameter('imageUrl', i);
console.log(`Uploading image from URL: ${imageUrl}`);
response = await axios_1.default.post(`${baseUrl}/upload/image`, {
url: imageUrl,
}, {
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
}
console.log('Upload image response:', JSON.stringify(response.data));
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
catch (error) {
console.log('Lỗi khi upload hình ảnh:', error.message);
if (error.response) {
console.log('Response status:', error.response.status);
console.log('Response data:', JSON.stringify(error.response.data));
}
returnData.push({
json: {
error: true,
message: `Lỗi khi upload hình ảnh: ${error.message}`,
response: ((_a = error.response) === null || _a === void 0 ? void 0 : _a.data) || {},
suggestion: 'Hãy kiểm tra định dạng hình ảnh và quyền truy cập của OA.',
},
pairedItem: {
item: i,
},
});
}
}
else if (operation === 'uploadFile') {
const binaryData = this.getNodeParameter('binaryData', i);
let response;
try {
if (binaryData) {
const binaryProperty = this.getNodeParameter('binaryProperty', i);
const binaryFile = (_b = items[i].binary) === null || _b === void 0 ? void 0 : _b[binaryProperty];
if (binaryFile === undefined) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `No binary data property "${binaryProperty}" exists on item.`, { itemIndex: i });
}
const buffer = await this.helpers.getBinaryDataBuffer(i, binaryProperty);
const formData = new form_data_1.default();
formData.append('file', buffer, {
filename: binaryFile.fileName || 'file.pdf',
contentType: binaryFile.mimeType,
});
console.log(`Uploading file with filename: ${binaryFile.fileName}, mime type: ${binaryFile.mimeType}`);
response = await axios_1.default.post(`${baseUrl}/upload/file`, formData, {
headers: {
access_token: accessToken,
...formData.getHeaders(),
},
});
}
else {
const fileUrl = this.getNodeParameter('fileUrl', i);
console.log(`Uploading file from URL: ${fileUrl}`);
response = await axios_1.default.post(`${baseUrl}/upload/file`, {
url: fileUrl,
}, {
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
}
console.log('Upload file response:', JSON.stringify(response.data));
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
catch (error) {
console.log('Error uploading file:', error.message);
if (error.response) {
console.log('Response status:', error.response.status);
console.log('Response data:', JSON.stringify(error.response.data));
}
returnData.push({
json: {
error: true,
message: `Error uploading file: ${error.message}`,
response: ((_c = error.response) === null || _c === void 0 ? void 0 : _c.data) || {},
suggestion: 'Please check the file format and OA access permissions.',
},
pairedItem: {
item: i,
},
});
}
}
else if (operation === 'getTags') {
const offset = this.getNodeParameter('offset', i);
const count = this.getNodeParameter('count', i);
try {
console.log(`Lấy danh sách tag với offset: ${offset}, count: ${count}`);
const response = await axios_1.default.get(`${baseUrl}/tag/gettagsofoa`, {
headers: {
access_token: accessToken,
},
params: {
offset,
count,
},
});
console.log('Kết quả lấy danh sách tag:', JSON.stringify(response.data));
let processedData = response.data;
if (processedData.data && Array.isArray(processedData.data.tags)) {
processedData.data.tags = processedData.data.tags.map((tag) => {
const tagId = tag.tag_id || tag.id || '';
const tagName = tag.tag_name || tag.name || '';
return {
...tag,
tag_id: tagId,
tag_name: tagName,
display_info: `ID: ${tagId} - Name: ${tagName}`
};
});
processedData.usage_guide = {
message: 'Sử dụng tag_id hoặc tag_name trong các node gắn tag hoặc xóa tag',
example: 'Khi gắn tag cho người dùng, hãy sử dụng giá trị tag_id hoặc tag_name từ danh sách này'
};
}
returnData.push({
json: processedData,
pairedItem: {
item: i,
},
});
}
catch (error) {
console.log('Lỗi khi gọi API gettagsofoa v3.0:', error.message);
if (error.response) {
console.log('Response status:', error.response.status);
console.log('Response data:', JSON.stringify(error.response.data));
}
console.log('Đang thử lại với API v2.0...');
try {
const v2BaseUrl = 'https://openapi.zalo.me/v2.0/oa';
const response = await axios_1.default.get(`${v2BaseUrl}/tag/gettagsofoa`, {
headers: {
access_token: accessToken,
},
params: {
offset,
count,
},
});
console.log('Kết quả lấy danh sách tag (API v2.0):', JSON.stringify(response.data));
let processedData = response.data;
if (processedData.data && Array.isArray(processedData.data.tags)) {
processedData.data.tags = processedData.data.tags.map((tag) => {
const tagId = tag.tag_id || tag.id || '';
const tagName = tag.tag_name || tag.name || '';
return {
...tag,
tag_id: tagId,
tag_name: tagName,
display_info: `ID: ${tagId} - Name: ${tagName}`
};
});
processedData.usage_guide = {
message: 'Sử dụng tag_id hoặc tag_name trong các node gắn tag hoặc xóa tag',
example: 'Khi gắn tag cho người dùng, hãy sử dụng giá trị tag_id hoặc tag_name từ danh sách này'
};
}
returnData.push({
json: processedData,
pairedItem: {
item: i,
},
});
}
catch (innerError) {
console.log('Lỗi khi gọi API gettagsofoa v2.0:', innerError.message);
if (innerError.response) {
console.log('Response status:', innerError.response.status);
console.log('Response data:', JSON.stringify(innerError.response.data));
}
returnData.push({
json: {
error: true,
message: `Lỗi khi lấy danh sách tag: ${innerError.message}`,
response: ((_d = innerError.response) === null || _d === void 0 ? void 0 : _d.data) || {},
suggestion: 'Vui lòng kiểm tra lại quyền truy cập của OA và access_token.',
},
pairedItem: {
item: i,
},
});
}
}
}
else if (operation === 'assignTag') {
try {
const userId = this.getNodeParameter('userId', i);
const tagId = this.getNodeParameter('tagId', i);
console.log(`Gán tag cho người dùng với user_id: ${userId}, tag_id: ${tagId}`);
try {
const response = await axios_1.default.post(`${baseUrl}/tag/taguser`, {
user_id: userId,
tag_id: tagId,
}, {
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
console.log('Kết quả gán tag (sử dụng tag_id):', JSON.stringify(response.data));
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
break;
}
catch (error) {
console.log('Lỗi khi gán tag sử dụng tag_id:', error.message);
if (error.response) {
console.log('Response status:', error.response.status);
console.log('Response data:', JSON.stringify(error.response.data));
}
}
try {
const response = await axios_1.default.post(`${baseUrl}/tag/taguser`, {
user_id: userId,
tag_name: tagId,
}, {
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
console.log('Kết quả gán tag (sử dụng tag_name):', JSON.stringify(response.data));
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
catch (error) {
console.log('Lỗi khi gán tag sử dụng tag_name:', error.message);
if (error.response) {
console.log('Response status:', error.response.status);
console.log('Response data:', JSON.stringify(error.response.data));
}
returnData.push({
json: {
error: true,
message: `Lỗi khi gán tag cho người dùng: ${error.message}`,
response: ((_e = error.response) === null || _e === void 0 ? void 0 : _e.data) || {},
suggestion: 'Vui lòng kiểm tra lại user_id và tag_id/tag_name. API v3 yêu cầu sử dụng tag_name thay vì tag_id.',
},
pairedItem: {
item: i,
},
});
}
}
catch (error) {
console.log('Lỗi khi gán tag cho người dùng:', error.message);
if (error.response) {
console.log('Response status:', error.response.status);
console.log('Response data:', JSON.stringify(error.response.data));
}
returnData.push({
json: {
error: true,
message: `Lỗi khi gán tag cho người dùng: ${error.message}`,
response: ((_f = error.response) === null || _f === void 0 ? void 0 : _f.data) || {},
suggestion: 'Vui lòng kiểm tra lại user_id và tag_id/tag_name. API v3 yêu cầu sử dụng tag_name thay vì tag_id.',
},
pairedItem: {
item: i,
},
});
}
}
else if (operation === 'getOAProfile') {
try {
const response = await axios_1.default.get(`${baseUrl}/getoa`, {
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
catch (error) {
console.log('Lỗi khi gọi API getoa v3.0:', error.message);
console.log('Đang thử lại với API v2.0...');
const v2BaseUrl = 'https://openapi.zalo.me/v2.0/oa';
const response = await axios_1.default.get(`${v2BaseUrl}/getoa`, {
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
}
else if (operation === 'getFollowers') {
const offset = this.getNodeParameter('offset', i);
const count = this.getNodeParameter('count', i);
try {
const v3BaseUrl = 'https://openapi.zalo.me/v3.0/oa';
const dataParam = JSON.stringify({
offset,
count: Math.min(count, 50),
is_follower: 'true',
});
const response = await axios_1.default.get(`${v3BaseUrl}/user/getlist`, {
params: {
data: dataParam,
},
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
catch (error) {
console.log('Lỗi khi gọi API user/getlist v3.0:', error.message);
returnData.push({
json: {
error: true,
message: `Lỗi khi gọi API lấy danh sách người theo dõi: ${error.message}`,
note: 'Zalo đã thay đổi API getfollowers sang API user/getlist trong v3.0. Vui lòng kiểm tra lại cấu hình OA và quyền truy cập.',
suggestion: 'Hãy đảm bảo rằng bạn đã cấp quyền đầy đủ cho ứng dụng và có access_token hợp lệ.',
},
pairedItem: {
item: i,
},
});
}
}
else if (operation === 'uploadGif') {
const binaryData = this.getNodeParameter('binaryData', i);
let response;
try {
if (binaryData) {
const binaryProperty = this.getNodeParameter('binaryProperty', i);
const binaryFile = (_g = items[i].binary) === null || _g === void 0 ? void 0 : _g[binaryProperty];
if (binaryFile === undefined) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `No binary data property "${binaryProperty}" exists on item.`, { itemIndex: i });
}
const buffer = await this.helpers.getBinaryDataBuffer(i, binaryProperty);
const formData = new form_data_1.default();
formData.append('file', buffer, {
filename: binaryFile.fileName || 'image.gif',
contentType: binaryFile.mimeType,
});
console.log(`Uploading GIF with filename: ${binaryFile.fileName}, mime type: ${binaryFile.mimeType}`);
response = await axios_1.default.post(`${baseUrl}/upload/gif`, formData, {
headers: {
access_token: accessToken,
...formData.getHeaders(),
},
});
}
else {
const gifUrl = this.getNodeParameter('gifUrl', i);
console.log(`Downloading GIF from URL: ${gifUrl}`);
const gifResponse = await axios_1.default.get(gifUrl, { responseType: 'arraybuffer' });
const formData = new form_data_1.default();
formData.append('file', Buffer.from(gifResponse.data), {
filename: 'image.gif',
contentType: 'image/gif',
});
response = await axios_1.default.post(`${baseUrl}/upload/gif`, formData, {
headers: {
access_token: accessToken,
...formData.getHeaders(),
},
});
}
console.log('Upload GIF response:', JSON.stringify(response.data));
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
catch (error) {
console.log('Error uploading GIF:', error.message);
if (error.response) {
console.log('Response status:', error.response.status);
console.log('Response data:', JSON.stringify(error.response.data));
}
returnData.push({
json: {
error: true,
message: `Error uploading GIF: ${error.message}`,
response: ((_h = error.response) === null || _h === void 0 ? void 0 : _h.data) || {},
suggestion: 'Please check the GIF format and OA access permissions.',
},
pairedItem: {
item: i,
},
});
}
}
else if (operation === 'getRecentChat') {
const offset = this.getNodeParameter('offset', i);
const count = this.getNodeParameter('count', i);
try {
const v2BaseUrl = 'https://openapi.zalo.me/v2.0/oa';
const dataParam = JSON.stringify({
offset,
count: Math.min(count, 10),
});
const response = await axios_1.default.get(`${v2BaseUrl}/listrecentchat`, {
params: {
data: dataParam,
},
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
catch (error) {
console.log('Lỗi khi gọi API listrecentchat:', error.message);
returnData.push({
json: {
error: true,
message: `Lỗi khi gọi API lấy danh sách cuộc trò chuyện gần đây: ${error.message}`,
note: 'Vui lòng kiểm tra lại cấu hình OA và quyền truy cập.',
suggestion: 'Hãy đảm bảo rằng bạn đã cấp quyền "Quyền quản lý tin nhắn người quan tâm" cho ứng dụng và có access_token hợp lệ.',
},
pairedItem: {
item: i,
},
});
}
}
else if (operation === 'getConversation') {
const userId = this.getNodeParameter('userId', i);
const offset = this.getNodeParameter('offset', i);
const count = this.getNodeParameter('count', i);
try {
const v2BaseUrl = 'https://openapi.zalo.me/v2.0/oa';
const dataParam = JSON.stringify({
user_id: userId,
offset,
count: Math.min(count, 10),
});
const response = await axios_1.default.get(`${v2BaseUrl}/conversation`, {
params: {
data: dataParam,
},
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
catch (error) {
console.log('Lỗi khi gọi API conversation:', error.message);
returnData.push({
json: {
error: true,
message: `Lỗi khi gọi API lấy lịch sử hội thoại: ${error.message}`,
note: 'Vui lòng kiểm tra lại cấu hình OA và quyền truy cập.',
suggestion: 'Hãy đảm bảo rằng bạn đã cấp quyền "Quyền quản lý tin nhắn người quan tâm" cho ứng dụng và có access_token hợp lệ.',
},
pairedItem: {
item: i,
},
});
}
}
else if (operation === 'getMessageStatus') {
const messageId = this.getNodeParameter('messageId', i);
try {
console.log(`Kiểm tra trạng thái tin nhắn với message_id: ${messageId}`);
const response = await axios_1.default.post(`${baseUrl}/message/status`, {
message_id: messageId,
}, {
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
console.log('Kết quả kiểm tra trạng thái tin nhắn:', JSON.stringify(response.data));
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
catch (error) {
console.log('Lỗi khi gọi API message/status v3.0:', error.message);
if (error.response) {
console.log('Response status:', error.response.status);
console.log('Response data:', JSON.stringify(error.response.data));
}
returnData.push({
json: {
error: true,
message: `Lỗi khi gọi API kiểm tra trạng thái tin nhắn: ${error.message}`,
response: ((_j = error.response) === null || _j === void 0 ? void 0 : _j.data) || {},
note: 'Zalo đã thay đổi API getmessagestatus sang API message/status trong v3.0 và yêu cầu sử dụng phương thức POST thay vì GET.',
suggestion: 'Hãy đảm bảo rằng bạn đã cấp quyền "Quyền quản lý tin nhắn người quan tâm" cho ứng dụng và có access_token hợp lệ.',
},
pairedItem: {
item: i,
},
});
}
}
else if (operation === 'removeTag') {
const tagId = this.getNodeParameter('tagId', i);
const response = await axios_1.default.post(`${baseUrl}/tag/rmtag`, {
tag_id: tagId,
}, {
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
else if (operation === 'removeFollowerFromTag') {
const userId = this.getNodeParameter('userId', i);
const tagId = this.getNodeParameter('tagId', i);
const response = await axios_1.default.post(`${baseUrl}/tag/rmfollowerfromtag`, {
user_id: userId,
tag_id: tagId,
}, {
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
else if (operation === 'updateOAMenu') {
const menuItemsCollection = this.getNodeParameter('menuItems', i);
const menuItems = menuItemsCollection.menuItemsValues.map(item => {
let payload;
if (item.type === 'oa.open.url') {
payload = { url: item.payload };
}
else if (item.type === 'oa.open.phone') {
payload = { phone: item.payload };
}
else if (item.type === 'oa.query.show') {
payload = { message: item.payload };
}
else if (item.type === 'oa.open.app') {
payload = { app: item.payload };
}
else {
payload = item.payload;
}
return {
title: item.title,
type: item.type,
payload,
};
});
const response = await axios_1.default.post(`${baseUrl}/menu`, {
menu_items: menuItems,
}, {
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
else if (operation === 'updateFollowerInfo') {
try {
const userId = this.getNodeParameter('userId', i);
const infoType = this.getNodeParameter('infoType', i);
const infoValue = this.getNodeParameter('infoValue', i);
const sharedInfo = {};
switch (infoType) {
case 'name':
sharedInfo.name = infoValue;
break;
case 'phone':
sharedInfo.phone = infoValue;
break;
case 'email':
sharedInfo.email = infoValue;
break;
case 'address':
sharedInfo.address = infoValue;
break;
case 'city':
sharedInfo.city = infoValue;
break;
case 'birthday':
sharedInfo.birthday = infoValue;
break;
default:
break;
}
const dataParam = JSON.stringify({
user_id: userId,
shared_info: sharedInfo
});
console.log(`Cập nhật thông tin người dùng với user_id: ${userId}, thông tin: ${JSON.stringify(sharedInfo)}`);
const response = await axios_1.default.post(`${baseUrl}/user/update`, {
data: dataParam
}, {
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
console.log('Kết quả cập nhật thông tin người dùng:', JSON.stringify(response.data));
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
catch (error) {
console.log('Lỗi khi cập nhật thông tin người dùng:', error.message);
if (error.response) {
console.log('Response status:', error.response.status);
console.log('Response data:', JSON.stringify(error.response.data));
}
returnData.push({
json: {
error: true,
message: `Lỗi khi cập nhật thông tin người dùng: ${error.message}`,
response: ((_k = error.response) === null || _k === void 0 ? void 0 : _k.data) || {},
suggestion: 'Vui lòng kiểm tra lại user_id và quyền truy cập của OA. API v3 yêu cầu định dạng dữ liệu khác với v2.',
},
pairedItem: {
item: i,
},
});
}
}
else if (operation === 'createArticle') {
try {
const title = this.getNodeParameter('title', i);
const author = this.getNodeParameter('author', i);
const description = this.getNodeParameter('description', i);
const content = this.getNodeParameter('content', i);
const coverUrl = this.getNodeParameter('coverUrl', i);
const status = this.getNodeParameter('status', i) || 'show';
const comment = this.getNodeParameter('comment', i) || 'show';
const body = [
{
type: 'text',
content,
},
];
const cover = {
cover_type: 'photo',
photo_url: coverUrl,
status: 'show',
};
console.log(`Creating article with title: ${title}`);
const v3BaseUrl = 'https://openapi.zalo.me/v2.0';
const response = await axios_1.default.post(`${v3BaseUrl}/article/create`, {
type: 'normal',
title,
author,
cover,
description,
body,
status,
comment,
}, {
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
console.log('Create article response:', JSON.stringify(response.data));
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
catch (error) {
console.log('Error creating article:', error.message);
if (error.response) {
console.log('Response status:', error.response.status);
console.log('Response data:', JSON.stringify(error.response.data));
}
returnData.push({
json: {
error: true,
message: `Lỗi khi tạo bài viết: ${error.message}`,
response: ((_l = error.response) === null || _l === void 0 ? void 0 : _l.data) || {},
note: 'API article/create trong Zalo OA API v3.0 gặp lỗi.',
suggestion: 'Vui lòng kiểm tra các tham số bài viết và quyền truy cập của OA. Đảm bảo rằng URL hình ảnh cover hợp lệ và có thể truy cập được.',
},
pairedItem: {
item: i,
},
});
}
}
else if (operation === 'updateArticle') {
try {
const token = this.getNodeParameter('token', i);
const title = this.getNodeParameter('title', i);
const author = this.getNodeParameter('author', i);
const description = this.getNodeParameter('description', i);
const content = this.getNodeParameter('content', i);
const coverUrl = this.getNodeParameter('coverUrl', i);
const status = this.getNodeParameter('status', i) || 'show';
const comment = this.getNodeParameter('comment', i) || 'show';
const body = [
{
type: 'text',
content,
},
];
const cover = {
cover_type: 'photo',
photo_url: coverUrl,
status: 'show',
};
console.log(`Updating article with token: ${token}`);
const v3BaseUrl = 'https://openapi.zalo.me/v2.0';
const response = await axios_1.default.post(`${v3BaseUrl}/article/update`, {
id: token,
type: 'normal',
title,
author,
cover,
description,
body,
status,
comment,
}, {
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
console.log('Update article response:', JSON.stringify(response.data));
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
catch (error) {
console.log('Error updating article:', error.message);
if (error.response) {
console.log('Response status:', error.response.status);
console.log('Response data:', JSON.stringify(error.response.data));
}
returnData.push({
json: {
error: true,
message: `Lỗi khi cập nhật bài viết: ${error.message}`,
response: ((_m = error.response) === null || _m === void 0 ? void 0 : _m.data) || {},
note: 'API article/update trong Zalo OA API v3.0 gặp lỗi.',
suggestion: 'Vui lòng kiểm tra token bài viết và các tham số. Đảm bảo rằng bài viết vẫn tồn tại và URL hình ảnh cover hợp lệ.',
},
pairedItem: {
item: i,
},
});
}
}
else if (operation === 'removeArticle') {
try {
const token = this.getNodeParameter('token', i);
console.log(`Removing article with token: ${token}`);
const v3BaseUrl = 'https://openapi.zalo.me/v2.0';
const response = await axios_1.default.post(`${v3BaseUrl}/article/remove`, {
id: token,
}, {
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
console.log('Remove article response:', JSON.stringify(response.data));
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
catch (error) {
console.log('Error removing article:', error.message);
if (error.response) {
console.log('Response status:', error.response.status);
console.log('Response data:', JSON.stringify(error.response.data));
}
returnData.push({
json: {
error: true,
message: `Lỗi khi xóa bài viết: ${error.message}`,
response: ((_o = error.response) === null || _o === void 0 ? void 0 : _o.data) || {},
note: 'API article/remove trong Zalo OA API v3.0 gặp lỗi.',
suggestion: 'Vui lòng kiểm tra token bài viết. Đảm bảo rằng bài viết vẫn tồn tại và bạn có quyền xóa nó.',
},
pairedItem: {
item: i,
},
});
}
}
else if (operation === 'getArticleList') {
try {
const offset = this.getNodeParameter('offset', i);
const limit = this.getNodeParameter('limit', i);
const type = this.getNodeParameter('type', i);
console.log(`Lấy danh sách bài viết với offset: ${offset}, limit: ${limit}, type: ${type}`);
const v2BaseUrl = 'https://openapi.zalo.me/v2.0';
const response = await axios_1.default.get(`${v2BaseUrl}/article/getslice?offset=${offset}&limit=${Math.min(limit, 50)}&type=${type}`, {
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
console.log('Kết quả lấy danh sách bài viết:', JSON.stringify(response.data));
const processedData = response.data;
if (processedData.data && Array.isArray(processedData.data.medias)) {
processedData.usage_guide = {
message: 'Sử dụng trường "id" của bài viết làm token bài viết',
example: 'Khi lấy chi tiết bài viết, hãy sử dụng giá trị "id" của bài viết làm token'
};
}
returnData.push({
json: processedData,
pairedItem: {
item: i,
},
});
}
catch (error) {
console.log('Lỗi khi lấy danh sách bài viết:', error.message);
if (error.response) {
console.log('Response status:', error.response.status);
console.log('Response data:', JSON.stringify(error.response.data));
}
returnData.push({
json: {
error: true,
message: `Lỗi khi lấy danh sách bài viết: ${error.message}`,
response: ((_p = error.response) === null || _p === void 0 ? void 0 : _p.data) || {},
note: 'API article/getslice trong Zalo OA API v2.0 gặp lỗi. Theo tài liệu mới nhất, endpoint này chỉ được hỗ trợ trong v2.0.',
suggestion: 'Vui lòng kiểm tra lại tham số type (chỉ chấp nhận giá trị "normal" hoặc "video"), quyền truy cập của OA và access_token. Nếu vẫn gặp lỗi, hãy tham khảo tài liệu API mới nhất của Zalo OA tại https://developers.zalo.me/docs.',
},
pairedItem: {
item: i,
},
});
}
}
else if (operation === 'getArticleDetail') {
try {
const token = this.getNodeParameter('token', i);
console.log(`Getting article detail with token: ${token}`);
const v3BaseUrl = 'https://openapi.zalo.me/v2.0';
const response = await axios_1.default.get(`${v3BaseUrl}/article/getdetail`, {
params: {
id: token
},
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
console.log('Get article detail response:', JSON.stringify(response.data));
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
catch (error) {
console.log('Error getting article detail:', error.message);
if (error.response) {
console.log('Response status:', error.response.status);
console.log('Response data:', JSON.stringify(error.response.data));
}
returnData.push({
json: {
error: true,
message: `Lỗi khi lấy chi tiết bài viết: ${error.message}`,
response: ((_q = error.response) === null || _q === void 0 ? void 0 : _q.data) || {},
note: 'API article/getdetail trong Zalo OA API v3.0 gặp lỗi. Vui lòng kiểm tra token bài viết.',
suggestion: 'Hãy đảm bảo rằng token bài viết chính xác và bài viết vẫn tồn tại. Nếu vẫn gặp lỗi, hãy tham khảo tài liệu API mới nhất của Zalo OA.',
},
pairedItem: {
item: i,
},
});
}
}
else if (operation === 'createProduct') {
try {
const name = this.getNodeParameter('name', i);
const price = this.getNodeParameter('price', i);
const description = this.getNodeParameter('description', i);
const code = this.getNodeParameter('code', i);
const categoryId = this.getNodeParameter('categoryId', i);
const status = this.getNodeParameter('status', i) || 'show';
const photosCollection = this.getNodeParameter('photos', i);
const photos = photosCollection.photosValues.map((photo) => ({
photo_url: photo.photoUrl,
}));
console.log(`Creating product with name: ${name}, price: ${price}`);
const response = await axios_1.default.post(`${baseUrl}/store/product/create`, {
name,
price,
description,
code,
category_id: categoryId,
photos,
status,
}, {
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
console.log('Create product response:', JSON.stringify(response.data));
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
catch (error) {
console.log('Error creating product:', error.message);
if (error.response) {
console.log('Response status:', error.response.status);
console.log('Response data:', JSON.stringify(error.response.data));
}
returnData.push({
json: {
error: true,
message: `Error creating product: ${error.message}`,
response: ((_r = error.response) === null || _r === void 0 ? void 0 : _r.data) || {},
suggestion: 'Please check the product parameters and OA access permissions.',
},
pairedItem: {
item: i,
},
});
}
}
else if (operation === 'updateProduct') {
try {
const productId = this.getNodeParameter('productId', i);
const name = this.getNodeParameter('name', i);
const price = this.getNodeParameter('price', i);
const description = this.getNodeParameter('description', i);
const code = this.getNodeParameter('code', i);
const categoryId = this.getNodeParameter('categoryId', i);
const status = this.getNodeParameter('status', i) || 'show';
const photosCollection = this.getNodeParameter('photos', i);
const photos = photosCollection.photosValues.map((photo) => ({
photo_url: photo.photoUrl,
}));
console.log(`Updating product with ID: ${productId}, name: ${name}`);
const response = await axios_1.default.post(`${baseUrl}/store/product/update`, {
id: productId,
name,
price,
description,
code,
category_id: categoryId,
photos,
status,
}, {
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
console.log('Update product response:', JSON.stringify(response.data));
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
catch (error) {
console.log('Error updating product:', error.message);
if (error.response) {
console.log('Response status:', error.response.status);
console.log('Response data:', JSON.stringify(error.response.data));
}
returnData.push({
json: {
error: true,
message: `Error updating product: ${error.message}`,
response: ((_s = error.response) === null || _s === void 0 ? void 0 : _s.data) || {},
suggestion: 'Please check the product ID and parameters.',
},
pairedItem: {
item: i,
},
});
}
}
else if (operation === 'getProductInfo') {
try {
const productId = this.getNodeParameter('productId', i);
console.log(`Getting product info with ID: ${productId}`);
const dataParam = JSON.stringify({
id: productId,
});
const response = await axios_1.default.get(`${baseUrl}/store/product/getproduct`, {
params: {
data: dataParam,
},
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
console.log('Get product info response:', JSON.stringify(response.data));
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
catch (error) {
console.log('Error getting product info:', error.message);
if (error.response) {
console.log('Response status:', error.response.status);
console.log('Response data:', JSON.stringify(error.response.data));
}
returnData.push({
json: {
error: true,
message: `Error getting product info: ${error.message}`,
response: ((_t = error.response) === null || _t === void 0 ? void 0 : _t.data) || {},
suggestion: 'Please check the product ID.',
},
pairedItem: {
item: i,
},
});
}
}
else if (operation === 'getProductList') {
try {
const offset = this.getNodeParameter('offset', i);
const limit = this.getNodeParameter('limit', i);
const categoryId = this.getNodeParameter('categoryId', i) || '';
console.log(`Getting product list with offset: ${offset}, limit: ${limit}`);
const dataParam = {
offset,
limit: Math.min(limit, 50),
};
if (categoryId) {
dataParam.category_id = categoryId;
}
const response = await axios_1.default.get(`${baseUrl}/store/product/getproductofoa`, {
params: {
data: JSON.stringify(dataParam),
},
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
console.log('Get product list response:', JSON.stringify(response.data));
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
catch (error) {
console.log('Error getting product list:', error.message);
if (error.response) {
console.log('Response status:', error.response.status);
console.log('Response data:', JSON.stringify(error.response.data));
}
returnData.push({
json: {
error: true,
message: `Error getting product list: ${error.message}`,
response: ((_u = error.response) === null || _u === void 0 ? void 0 : _u.data) || {},
suggestion: 'Please check the parameters and OA access permissions.',
},
pairedItem: {
item: i,
},
});
}
}
else if (operation === 'createCategory') {
try {
const name = this.getNodeParameter('name', i);
const description = this.getNodeParameter('description', i);
const status = this.getNodeParameter('status', i) || 'show';
const parentId = this.getNodeParameter('parentId', i) || '';
const requestData = {
name,
description,
status,
};
if (parentId) {
requestData.parent_id = parentId;
}
console.log(`Creating category with name: ${name}`);
const response = await axios_1.default.post(`${baseUrl}/store/category/create`, requestData, {
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
console.log('Create category response:', JSON.stringify(response.data));
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
catch (error) {
console.log('Error creating category:', error.message);
if (error.response) {
console.log('Response status:', error.response.status);
console.log('Response data:', JSON.stringify(error.response.data));
}
returnData.push({
json: {
error: true,
message: `Error creating category: ${error.message}`,
response: ((_v = error.response) === null || _v === void 0 ? void 0 : _v.data) || {},
suggestion: 'Please check the category parameters and OA access permissions.',
},
pairedItem: {
item: i,
},
});
}
}
else if (operation === 'updateCategory') {
try {
const categoryId = this.getNodeParameter('categoryId', i);
const name = this.getNodeParameter('name', i);
const description = this.getNodeParameter('description', i);
const status = this.getNodeParameter('status', i) || 'show';
const parentId = this.getNodeParameter('parentId', i) || '';
const requestData = {
id: categoryId,
name,
description,
status,
};
if (parentId) {
requestData.parent_id = parentId;
}
console.log(`Updating category with ID: ${categoryId}, name: ${name}`);
const response = await axios_1.default.post(`${baseUrl}/store/category/update`, requestData, {
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
console.log('Update category response:', JSON.stringify(response.data));
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
catch (error) {
console.log('Error updating category:', error.message);
if (error.response) {
console.log('Response status:', error.response.status);
console.log('Response data:', JSON.stringify(error.response.data));
}
returnData.push({
json: {
error: true,
message: `Error updating category: ${error.message}`,
response: ((_w = error.response) === null || _w === void 0 ? void 0 : _w.data) || {},
suggestion: 'Please check the category ID and parameters.',
},
pairedItem: {
item: i,
},
});
}
}
else if (operation === 'getCategoryList') {
try {
const offset = this.getNodeParameter('offset', i);
const limit = this.getNodeParameter('limit', i);
console.log(`Getting category list with offset: ${offset}, limit: ${limit}`);
const dataParam = JSON.stringify({
offset,
limit: Math.min(limit, 50),
});
const response = await axios_1.default.get(`${baseUrl}/store/category/getcategoryofoa`, {
params: {
data: dataParam,
},
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
console.log('Get category list response:', JSON.stringify(response.data));
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
catch (error) {
console.log('Error getting category list:', error.message);
if (error.response) {
console.log('Response status:', error.response.status);
console.log('Response data:', JSON.stringify(error.response.data));
}
returnData.push({
json: {
error: true,
message: `Error getting category list: ${error.message}`,
response: ((_x = error.response) === null || _x === void 0 ? void 0 : _x.data) || {},
suggestion: 'Please check the parameters and OA access permissions.',
},
pairedItem: {
item: i,
},
});
}
}
else if (operation === 'createOrder') {
try {
const userId = this.getNodeParameter('userId', i);
const shippingName = this.getNodeParameter('shippingName', i);
const shippingPhone = this.getNodeParameter('shippingPhone', i);
const shippingAddress = this.getNodeParameter('shippingAddress', i);
const shippingCity = this.getNodeParameter('shippingCity', i);
const shippingFee = this.getNodeParameter('shippingFee', i);
const discount = this.getNodeParameter('discount', i);
const total = this.getNodeParameter('total', i);
const orderItemsCollection = this.getNodeParameter('orderItems', i);
const items = orderItemsCollection.itemsValues.map((item) => ({
product_id: item.productId,
quantity: item.quantity,
price: item.price,
}));
const requestData = {
user_id: userId,
shipping: {
name: shippingName,
phone: shippingPhone,
address: shippingAddress,
city: shippingCity,
},
items,
shipping_fee: shippingFee,
discount,
total,
};
console.log(`Creating order for user: ${userId}`);
const response = await axios_1.default.post(`${baseUrl}/store/order/create`, requestData, {
headers: {
access_token: accessToken,
'Content-Type': 'application/json',
},
});
console.log('Create order response:', JSON.stringify(response.data));
returnData.push({
json: response.data,
pairedItem: {
item: i,
},
});
}
catch (error) {
console.log('Error creating order:', error.message);
if (error.response) {
console.log('Response status:', error.response.status);
console.log('Response data:', JSON.stringify(error.response.data));
}
returnData.push({
json: {
error: true,
message: `Error creating order: ${error.message}`,
response: ((_y = error.response) === null || _y === void 0 ? void 0 : _y.data) || {},
suggestion: 'Please check the order parameters and OA access permissions.',
},
pairedItem: {
item: i,
},
});
}
}
}
}
catch (error) {
if (this.continueOnFail()) {
returnData.push({
json: {
error: error.message,
},
pairedItem: {
item: i,
},
});
continue;
}
throw new n8n_workflow_1.NodeOperationError(this.getNode(), error, {
itemIndex: i,
});
}
}
return [returnData];
}
}
exports.ZaloOA = ZaloOA;
//# sourceMappingURL=ZaloOA.node.js.map