n8n 第三方服务集成 - 连接常用 SaaS 平台
在现代企业环境中,我们通常需要使用多个 SaaS 平台来完成不同的业务需求。n8n 提供了丰富的第三方服务集成能力,让我们能够轻松连接和自动化这些平台之间的数据流转。
Google Workspace 集成
Google Sheets 操作
Google Sheets 是最常用的在线表格工具,n8n 提供了完整的 Google Sheets 节点支持。
基本配置
json
{
"authentication": "oAuth2Api",
"resource": "sheet",
"operation": "read",
"documentId": "your-sheet-id",
"sheetName": "Sheet1",
"range": "A1:Z1000"
}
读取数据
javascript
// 从 Google Sheets 读取数据并处理
const sheetData = items[0].json;
// 数据清洗和转换
const processedData = sheetData.map(row => ({
id: row.ID,
name: row.Name?.trim(),
email: row.Email?.toLowerCase(),
status: row.Status || 'pending',
createdAt: new Date(row['Created At']).toISOString()
}));
// 过滤有效数据
const validData = processedData.filter(item =>
item.email && item.email.includes('@')
);
return validData.map(item => ({ json: item }));
写入数据
javascript
// 批量写入数据到 Google Sheets
const dataToWrite = items.map(item => [
item.json.id,
item.json.name,
item.json.email,
item.json.status,
new Date().toISOString()
]);
// 添加表头
const headers = ['ID', 'Name', 'Email', 'Status', 'Updated At'];
const finalData = [headers, ...dataToWrite];
return [{
json: {
range: 'A1:E' + (finalData.length),
values: finalData
}
}];
Gmail 自动化
javascript
// Gmail 邮件自动分类和处理
function categorizeEmail(email) {
const subject = email.subject.toLowerCase();
const from = email.from.toLowerCase();
// 订单相关邮件
if (subject.includes('order') || subject.includes('订单')) {
return {
category: 'orders',
priority: 'high',
action: 'forward_to_sales'
};
}
// 客服相关邮件
if (subject.includes('support') || subject.includes('help')) {
return {
category: 'support',
priority: 'medium',
action: 'create_ticket'
};
}
// 发票相关邮件
if (subject.includes('invoice') || subject.includes('发票')) {
return {
category: 'finance',
priority: 'high',
action: 'forward_to_finance'
};
}
return {
category: 'general',
priority: 'low',
action: 'archive'
};
}
const emailData = items[0].json;
const classification = categorizeEmail(emailData);
return [{
json: {
...emailData,
classification,
processedAt: new Date().toISOString()
}
}];
Microsoft 365 集成
Excel Online 操作
javascript
// Microsoft Excel Online 数据处理
async function processExcelData(workbookId, worksheetName) {
// 读取 Excel 数据
const excelData = await getExcelData(workbookId, worksheetName);
// 数据分析和处理
const analysis = {
totalRows: excelData.length,
summary: {},
trends: []
};
// 按类别统计
const categoryStats = excelData.reduce((acc, row) => {
const category = row.Category || 'Unknown';
if (!acc[category]) {
acc[category] = { count: 0, total: 0 };
}
acc[category].count++;
acc[category].total += parseFloat(row.Amount || 0);
return acc;
}, {});
analysis.summary = categoryStats;
// 生成趋势数据
const monthlyData = excelData.reduce((acc, row) => {
const month = new Date(row.Date).toISOString().substring(0, 7);
if (!acc[month]) acc[month] = 0;
acc[month] += parseFloat(row.Amount || 0);
return acc;
}, {});
analysis.trends = Object.entries(monthlyData).map(([month, amount]) => ({
month,
amount
}));
return analysis;
}
const workbookId = items[0].json.workbookId;
const analysis = await processExcelData(workbookId, 'Data');
return [{ json: analysis }];
Outlook 邮件处理
javascript
// Outlook 邮件自动回复和转发
function generateAutoReply(originalEmail) {
const templates = {
support: {
subject: 'Re: {{ originalSubject }} - 已收到您的咨询',
body: `
感谢您的咨询!
我们已收到您的邮件,工单号:{{ ticketId }}
我们的客服团队将在24小时内回复您。
如有紧急问题,请致电:400-123-4567
此邮件为自动回复,请勿直接回复。
`
},
sales: {
subject: 'Re: {{ originalSubject }} - 销售咨询确认',
body: `
感谢您对我们产品的关注!
我们已安排专业的销售顾问为您服务。
预计将在2个工作日内与您联系。
如需加急处理,请联系:sales@company.com
`
}
};
const emailType = detectEmailType(originalEmail);
const template = templates[emailType] || templates.support;
const ticketId = generateTicketId();
return {
to: originalEmail.from,
subject: template.subject.replace('{{ originalSubject }}', originalEmail.subject),
body: template.body.replace('{{ ticketId }}', ticketId),
ticketId
};
}
function detectEmailType(email) {
const subject = email.subject.toLowerCase();
const body = email.body.toLowerCase();
if (subject.includes('price') || subject.includes('buy') || body.includes('purchase')) {
return 'sales';
}
return 'support';
}
function generateTicketId() {
return 'TK' + Date.now().toString().slice(-8);
}
const originalEmail = items[0].json;
const autoReply = generateAutoReply(originalEmail);
return [{ json: autoReply }];
Salesforce 集成
客户数据同步
javascript
// Salesforce 客户数据同步
class SalesforceSync {
constructor(config) {
this.config = config;
this.accessToken = null;
}
async authenticate() {
const response = await fetch(`${this.config.loginUrl}/services/oauth2/token`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
grant_type: 'password',
client_id: this.config.clientId,
client_secret: this.config.clientSecret,
username: this.config.username,
password: this.config.password + this.config.securityToken
})
});
const result = await response.json();
this.accessToken = result.access_token;
this.instanceUrl = result.instance_url;
}
async createLead(leadData) {
if (!this.accessToken) await this.authenticate();
const response = await fetch(`${this.instanceUrl}/services/data/v52.0/sobjects/Lead/`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(leadData)
});
return await response.json();
}
async updateAccount(accountId, accountData) {
if (!this.accessToken) await this.authenticate();
const response = await fetch(`${this.instanceUrl}/services/data/v52.0/sobjects/Account/${accountId}`, {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${this.accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(accountData)
});
return response.ok;
}
async queryRecords(soql) {
if (!this.accessToken) await this.authenticate();
const response = await fetch(
`${this.instanceUrl}/services/data/v52.0/query/?q=${encodeURIComponent(soql)}`,
{
headers: {
'Authorization': `Bearer ${this.accessToken}`
}
}
);
const result = await response.json();
return result.records;
}
}
// 使用 Salesforce 同步
const salesforce = new SalesforceSync({
loginUrl: 'https://login.salesforce.com',
clientId: process.env.SF_CLIENT_ID,
clientSecret: process.env.SF_CLIENT_SECRET,
username: process.env.SF_USERNAME,
password: process.env.SF_PASSWORD,
securityToken: process.env.SF_SECURITY_TOKEN
});
const customerData = items[0].json;
// 创建潜在客户
const leadResult = await salesforce.createLead({
FirstName: customerData.firstName,
LastName: customerData.lastName,
Email: customerData.email,
Company: customerData.company,
Phone: customerData.phone,
LeadSource: 'Website'
});
return [{ json: { leadId: leadResult.id, success: leadResult.success } }];
Slack 深度集成
工作流状态通知
javascript
// Slack 工作流状态通知系统
class SlackWorkflowNotifier {
constructor(webhookUrl, botToken) {
this.webhookUrl = webhookUrl;
this.botToken = botToken;
}
async sendWorkflowStatus(workflowData) {
const { name, status, duration, results } = workflowData;
const statusEmoji = {
success: '✅',
warning: '⚠️',
error: '❌',
running: '🔄'
};
const statusColor = {
success: 'good',
warning: 'warning',
error: 'danger',
running: '#36a64f'
};
const attachment = {
color: statusColor[status],
title: `${statusEmoji[status]} 工作流: ${name}`,
fields: [
{
title: '状态',
value: status.toUpperCase(),
short: true
},
{
title: '执行时间',
value: duration,
short: true
}
],
footer: 'n8n 自动化平台',
ts: Math.floor(Date.now() / 1000)
};
if (results) {
attachment.fields.push({
title: '处理结果',
value: `成功: ${results.success || 0}, 失败: ${results.failed || 0}`,
short: false
});
}
const payload = {
text: `工作流 ${name} 执行${status === 'success' ? '成功' : '异常'}`,
attachments: [attachment]
};
await fetch(this.webhookUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
}
async createChannel(channelName, purpose) {
const response = await fetch('https://slack.com/api/conversations.create', {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.botToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: channelName,
purpose: purpose
})
});
return await response.json();
}
async inviteToChannel(channelId, userIds) {
const response = await fetch('https://slack.com/api/conversations.invite', {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.botToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
channel: channelId,
users: userIds.join(',')
})
});
return await response.json();
}
}
// 使用 Slack 通知
const slackNotifier = new SlackWorkflowNotifier(
process.env.SLACK_WEBHOOK_URL,
process.env.SLACK_BOT_TOKEN
);
const workflowStatus = {
name: '客户数据同步',
status: 'success',
duration: '2分30秒',
results: {
success: 150,
failed: 2
}
};
await slackNotifier.sendWorkflowStatus(workflowStatus);
return [{ json: { notificationSent: true } }];
支付平台集成
Stripe 支付处理
javascript
// Stripe 支付事件处理
function processStripeWebhook(event) {
const { type, data } = event;
switch (type) {
case 'payment_intent.succeeded':
return handlePaymentSuccess(data.object);
case 'payment_intent.payment_failed':
return handlePaymentFailure(data.object);
case 'customer.subscription.created':
return handleSubscriptionCreated(data.object);
case 'customer.subscription.deleted':
return handleSubscriptionCanceled(data.object);
default:
return { action: 'log', message: `Unhandled event type: ${type}` };
}
}
function handlePaymentSuccess(paymentIntent) {
return {
action: 'fulfill_order',
orderId: paymentIntent.metadata.order_id,
amount: paymentIntent.amount / 100,
currency: paymentIntent.currency,
customerId: paymentIntent.customer,
paymentMethod: paymentIntent.payment_method,
notification: {
type: 'payment_success',
message: `Payment of ${paymentIntent.amount / 100} ${paymentIntent.currency} received`
}
};
}
function handlePaymentFailure(paymentIntent) {
return {
action: 'handle_payment_failure',
orderId: paymentIntent.metadata.order_id,
failureReason: paymentIntent.last_payment_error?.message,
customerId: paymentIntent.customer,
notification: {
type: 'payment_failed',
message: `Payment failed: ${paymentIntent.last_payment_error?.message}`
}
};
}
function handleSubscriptionCreated(subscription) {
return {
action: 'activate_subscription',
subscriptionId: subscription.id,
customerId: subscription.customer,
planId: subscription.items.data[0].price.id,
status: subscription.status,
notification: {
type: 'subscription_created',
message: `New subscription created for customer ${subscription.customer}`
}
};
}
const stripeEvent = items[0].json;
const result = processStripeWebhook(stripeEvent);
return [{ json: result }];
社交媒体集成
Twitter 自动化
javascript
// Twitter 内容发布和监控
class TwitterAutomation {
constructor(apiKeys) {
this.apiKeys = apiKeys;
}
async postTweet(content, options = {}) {
const tweetData = {
text: content,
...options
};
const response = await fetch('https://api.twitter.com/2/tweets', {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.apiKeys.bearerToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(tweetData)
});
return await response.json();
}
async searchTweets(query, options = {}) {
const params = new URLSearchParams({
query: query,
max_results: options.maxResults || 10,
'tweet.fields': 'created_at,author_id,public_metrics'
});
const response = await fetch(`https://api.twitter.com/2/tweets/search/recent?${params}`, {
headers: {
'Authorization': `Bearer ${this.apiKeys.bearerToken}`
}
});
return await response.json();
}
async analyzeMentions(mentions) {
const analysis = {
total: mentions.length,
sentiment: { positive: 0, negative: 0, neutral: 0 },
topKeywords: {},
engagement: { likes: 0, retweets: 0, replies: 0 }
};
mentions.forEach(tweet => {
// 简单的情感分析
const sentiment = this.analyzeSentiment(tweet.text);
analysis.sentiment[sentiment]++;
// 关键词提取
const keywords = this.extractKeywords(tweet.text);
keywords.forEach(keyword => {
analysis.topKeywords[keyword] = (analysis.topKeywords[keyword] || 0) + 1;
});
// 互动数据
if (tweet.public_metrics) {
analysis.engagement.likes += tweet.public_metrics.like_count;
analysis.engagement.retweets += tweet.public_metrics.retweet_count;
analysis.engagement.replies += tweet.public_metrics.reply_count;
}
});
return analysis;
}
analyzeSentiment(text) {
const positiveWords = ['good', 'great', 'awesome', 'love', 'excellent'];
const negativeWords = ['bad', 'terrible', 'hate', 'awful', 'worst'];
const lowerText = text.toLowerCase();
const positiveCount = positiveWords.filter(word => lowerText.includes(word)).length;
const negativeCount = negativeWords.filter(word => lowerText.includes(word)).length;
if (positiveCount > negativeCount) return 'positive';
if (negativeCount > positiveCount) return 'negative';
return 'neutral';
}
extractKeywords(text) {
const words = text.toLowerCase()
.replace(/[^\w\s]/g, '')
.split(/\s+/)
.filter(word => word.length > 3);
const stopWords = ['this', 'that', 'with', 'have', 'will', 'from', 'they', 'been'];
return words.filter(word => !stopWords.includes(word));
}
}
// 使用 Twitter 自动化
const twitter = new TwitterAutomation({
bearerToken: process.env.TWITTER_BEARER_TOKEN
});
// 搜索品牌提及
const mentions = await twitter.searchTweets('@yourcompany OR "your company"', {
maxResults: 50
});
// 分析提及内容
const analysis = await twitter.analyzeMentions(mentions.data || []);
return [{ json: { mentions: mentions.data, analysis } }];
小结
第三方服务集成是 n8n 的核心优势之一:
- OAuth 认证:安全地连接各种 SaaS 平台
- 数据同步:实现不同平台间的数据流转
- 事件驱动:基于 Webhook 的实时集成
- 批量操作:高效处理大量数据
- 错误处理:完善的异常处理和重试机制
下一篇文章,我们将学习自定义节点开发,这是扩展 n8n 功能的高级技术。
记住,集成第三方服务时要特别注意 API 限制、认证安全和数据隐私。合理的缓存和批量处理策略能够显著提升集成的效率和稳定性。