使用Gmail和Google Drive存储自动化PDF发票生成与发送
中级
这是一个Miscellaneous, Multimodal AI领域的自动化工作流,包含 13 个节点。主要使用 Code, Webhook, EmailSend, GoogleDrive, HttpRequest 等节点。 使用Gmail和Google Drive存储自动化PDF发票生成与发送
前置要求
- •HTTP Webhook 端点(n8n 会自动生成)
- •Google Drive API 凭证
- •可能需要目标 API 的认证凭证
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"meta": {
"instanceId": "6d51f49bab6b0dffc9b87e9dabbeb0e9b71c14bdaab2b96ec32b663d472dacc3",
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "3060dd2d-bf5b-404e-8f85-c0bc78a3075e",
"name": "便签",
"type": "n8n-nodes-base.stickyNote",
"position": [
320,
-192
],
"parameters": {
"width": 214,
"height": 272,
"content": "✅ **成功响应**"
},
"typeVersion": 1
},
{
"id": "353da029-1514-40d0-969b-bcd2816bdbcc",
"name": "Webhook触发器",
"type": "n8n-nodes-base.webhook",
"position": [
-800,
112
],
"webhookId": "56df3812-2f30-4148-9223-a6474390fe15",
"parameters": {
"path": "generate-invoice",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 2
},
{
"id": "d3c566ba-582b-4e17-b30d-580c5e617630",
"name": "处理发票数据",
"type": "n8n-nodes-base.code",
"position": [
-576,
112
],
"parameters": {
"jsCode": "// Process and validate invoice data\nconst data = $input.item.json.body;\n\n// Generate invoice number if not provided\nconst invoiceNumber = data.invoiceNumber || `INV-${new Date().getFullYear()}-${String(Date.now()).slice(-6)}`;\n\n// Process items and calculate totals\nconst items = data.items || [];\nlet subtotal = 0;\n\nconst processedItems = items.map(item => {\n const qty = parseFloat(item.quantity || item.qty || 1);\n const price = parseFloat(item.price || 0);\n const total = qty * price;\n subtotal += total;\n \n return {\n description: item.description || 'Service',\n quantity: qty,\n price: price,\n total: total.toFixed(2)\n };\n});\n\n// Calculate tax and total\nconst taxRate = parseFloat(data.taxRate || 0.1);\nconst taxAmount = subtotal * taxRate;\nconst totalAmount = subtotal + taxAmount;\n\n// Format dates\nconst currentDate = new Date().toISOString().split('T')[0];\nconst dueDate = data.dueDate || new Date(Date.now() + 30*24*60*60*1000).toISOString().split('T')[0];\n\nreturn {\n customerName: data.customerName || 'Customer',\n customerEmail: data.customerEmail,\n customerAddress: data.customerAddress || '',\n invoiceNumber: invoiceNumber,\n invoiceDate: currentDate,\n dueDate: dueDate,\n companyName: data.companyName || $env.COMPANY_NAME || 'Your Company Ltd',\n companyAddress: data.companyAddress || $env.COMPANY_ADDRESS || '123 Business Street',\n companyEmail: data.companyEmail || $env.COMPANY_EMAIL || 'billing@company.com',\n companyPhone: data.companyPhone || $env.COMPANY_PHONE || '+1-555-0123',\n items: processedItems,\n subtotal: subtotal.toFixed(2),\n taxRate: (taxRate * 100).toFixed(1),\n taxAmount: taxAmount.toFixed(2),\n totalAmount: totalAmount.toFixed(2),\n notes: data.notes || 'Thank you for your business!',\n paymentTerms: data.paymentTerms || 'Payment due within 30 days',\n timestamp: new Date().toISOString()\n};"
},
"typeVersion": 2
},
{
"id": "659c77de-7c5c-4a49-9525-07b0106460da",
"name": "生成 HTML 模板",
"type": "n8n-nodes-base.code",
"position": [
-352,
112
],
"parameters": {
"jsCode": "// Generate HTML for PDF invoice\nconst data = $input.item.json;\n\n// Create items table rows\nconst itemRows = data.items.map(item => `\n <tr>\n <td style=\"padding: 8px; border-bottom: 1px solid #eee;\">${item.description}</td>\n <td style=\"padding: 8px; border-bottom: 1px solid #eee; text-align: center;\">${item.quantity}</td>\n <td style=\"padding: 8px; border-bottom: 1px solid #eee; text-align: right;\">$${item.price.toFixed(2)}</td>\n <td style=\"padding: 8px; border-bottom: 1px solid #eee; text-align: right;\">$${item.total}</td>\n </tr>\n`).join('');\n\nconst htmlContent = `\n<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"UTF-8\">\n <style>\n body { font-family: Arial, sans-serif; margin: 0; padding: 20px; color: #333; }\n .header { display: flex; justify-content: space-between; margin-bottom: 30px; border-bottom: 2px solid #007bff; padding-bottom: 20px; }\n .company-info h1 { color: #007bff; margin: 0; font-size: 28px; }\n .company-info p { margin: 5px 0; color: #666; }\n .invoice-info { text-align: right; }\n .invoice-info h2 { color: #333; margin: 0; font-size: 24px; }\n .customer-section { margin: 30px 0; }\n .customer-section h3 { color: #333; margin-bottom: 10px; }\n .items-table { width: 100%; border-collapse: collapse; margin: 30px 0; }\n .items-table th { background: #007bff; color: white; padding: 12px 8px; }\n .totals { margin-top: 20px; }\n .totals table { margin-left: auto; width: 300px; }\n .totals td { padding: 5px 10px; }\n .totals .total-row { font-weight: bold; border-top: 2px solid #333; }\n .footer { margin-top: 40px; padding-top: 20px; border-top: 1px solid #eee; color: #666; }\n .payment-terms { background: #f8f9fa; padding: 15px; border-radius: 5px; margin-top: 20px; }\n </style>\n</head>\n<body>\n <div class=\"header\">\n <div class=\"company-info\">\n <h1>${data.companyName}</h1>\n <p>${data.companyAddress}</p>\n <p>Email: ${data.companyEmail}</p>\n <p>Phone: ${data.companyPhone}</p>\n </div>\n <div class=\"invoice-info\">\n <h2>INVOICE</h2>\n <p><strong>Invoice #:</strong> ${data.invoiceNumber}</p>\n <p><strong>Date:</strong> ${data.invoiceDate}</p>\n <p><strong>Due Date:</strong> ${data.dueDate}</p>\n </div>\n </div>\n \n <div class=\"customer-section\">\n <h3>Bill To:</h3>\n <p><strong>${data.customerName}</strong></p>\n <p>${data.customerEmail}</p>\n </div>\n \n <table class=\"items-table\">\n <thead>\n <tr>\n <th>Description</th>\n <th>Quantity</th>\n <th>Unit Price</th>\n <th>Total</th>\n </tr>\n </thead>\n <tbody>\n ${itemRows}\n </tbody>\n </table>\n \n <div class=\"totals\">\n <table>\n <tr>\n <td>Subtotal:</td>\n <td style=\"text-align: right;\">$${data.subtotal}</td>\n </tr>\n <tr>\n <td>Tax (${data.taxRate}%):</td>\n <td style=\"text-align: right;\">$${data.taxAmount}</td>\n </tr>\n <tr class=\"total-row\">\n <td><strong>Total Amount:</strong></td>\n <td style=\"text-align: right;\"><strong>$${data.totalAmount}</strong></td>\n </tr>\n </table>\n </div>\n \n <div class=\"payment-terms\">\n <h4>Payment Terms:</h4>\n <p>${data.paymentTerms}</p>\n </div>\n \n <div class=\"footer\">\n <p>${data.notes}</p>\n <p><em>Generated automatically on ${new Date().toLocaleDateString()}</em></p>\n </div>\n</body>\n</html>\n`;\n\nreturn {\n ...data,\n htmlContent: htmlContent,\n filename: `invoice-${data.invoiceNumber}.pdf`\n};"
},
"typeVersion": 2
},
{
"id": "7fe430f5-e516-4f3f-9ffd-d82e3a3db05a",
"name": "生成PDF",
"type": "n8n-nodes-base.httpRequest",
"position": [
-112,
112
],
"parameters": {
"url": "={{ $env.PDF_API_URL || 'https://api.pdfshift.io/v3/convert/pdf' }}",
"method": "POST",
"options": {
"response": {}
},
"sendBody": true,
"sendHeaders": true,
"bodyParameters": {
"parameters": [
{}
]
},
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Authorization",
"value": "Basic {{ $env.PDF_API_KEY }}"
}
]
}
},
"typeVersion": 4
},
{
"id": "9b88a23b-b415-4f2c-b818-a12a6e5c2bf6",
"name": "发送邮件给客户",
"type": "n8n-nodes-base.emailSend",
"position": [
128,
48
],
"webhookId": "f33ab465-57d0-48db-ae94-3f6d2b37c930",
"parameters": {
"html": "=Dear {{ $json.customerName }},<br><br>Thank you for your business! Please find your invoice attached.<br><br><strong>Invoice Details:</strong><br>• Invoice Number: {{ $json.invoiceNumber }}<br>• Date: {{ $json.invoiceDate }}<br>• Due Date: {{ $json.dueDate }}<br>• Amount Due: ${{ $json.totalAmount }}<br><br><strong>Payment Terms:</strong><br>{{ $json.paymentTerms }}<br><br>If you have questions, contact us at {{ $json.companyEmail }}<br><br>Best regards,<br>{{ $json.companyName }}",
"options": {},
"subject": "Invoice {{ $json.invoiceNumber }} from {{ $json.companyName }}",
"toEmail": "={{ $json.customerEmail }}",
"fromEmail": "={{ $env.COMPANY_EMAIL }}",
"emailFormat": "html"
},
"typeVersion": 2
},
{
"id": "5279d3ca-eff7-45dc-bcc6-41f85bbe2bb6",
"name": "保存到 Google Drive",
"type": "n8n-nodes-base.googleDrive",
"position": [
128,
176
],
"parameters": {
"name": "={{ $json.filename }}",
"driveId": {
"__rl": true,
"mode": "list",
"value": "My Drive"
},
"options": {},
"folderId": {
"__rl": true,
"mode": "list",
"value": "root",
"cachedResultName": "/ (Root folder)"
}
},
"typeVersion": 3
},
{
"id": "629c75bd-88a2-4ea7-a3dc-5450387d6378",
"name": "成功响应",
"type": "n8n-nodes-base.code",
"position": [
352,
112
],
"parameters": {
"jsCode": "return {\n success: true,\n message: 'Invoice generated and sent successfully',\n invoiceNumber: $json.invoiceNumber,\n customerEmail: $json.customerEmail,\n totalAmount: $json.totalAmount,\n filename: $json.filename,\n timestamp: new Date().toISOString(),\n emailSent: true,\n savedToDrive: true\n};"
},
"typeVersion": 2
},
{
"id": "921ff838-cd75-4f5b-9b29-9d96fbcac947",
"name": "响应Webhook",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
576,
112
],
"parameters": {
"options": {
"responseCode": 200
},
"respondWith": "json",
"responseBody": "={{ $json }}"
},
"typeVersion": 1
},
{
"id": "0c4bb277-7fe4-419c-bee0-69dede34a59e",
"name": "便签1",
"type": "n8n-nodes-base.stickyNote",
"position": [
96,
320
],
"parameters": {
"width": 214,
"height": 224,
"content": "☁️ **保存到云端硬盘**"
},
"typeVersion": 1
},
{
"id": "be43dfc4-8068-44db-bbcb-f81dc86d2162",
"name": "便签2",
"type": "n8n-nodes-base.stickyNote",
"position": [
32,
-208
],
"parameters": {
"width": 214,
"height": 240,
"content": "📧 **发送给客户**"
},
"typeVersion": 1
},
{
"id": "84e365dd-a54a-4ce0-a273-ae8cbfb9bf93",
"name": "便签3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-208,
-160
],
"parameters": {
"width": 214,
"height": 256,
"content": "📄 **发票生成**"
},
"typeVersion": 1
},
{
"id": "3673840a-5ac8-48ec-af6a-c30db464e73d",
"name": "便签4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-448,
-144
],
"parameters": {
"width": 214,
"height": 256,
"content": "⚙️ **准备发票**"
},
"typeVersion": 1
}
],
"pinData": {},
"connections": {
"Generate PDF": {
"main": [
[
{
"node": "Send Email to Customer",
"type": "main",
"index": 0
},
{
"node": "Save to Google Drive",
"type": "main",
"index": 0
}
]
]
},
"Webhook Trigger": {
"main": [
[
{
"node": "Process Invoice Data",
"type": "main",
"index": 0
}
]
]
},
"Success Response": {
"main": [
[
{
"node": "Respond Webhook",
"type": "main",
"index": 0
}
]
]
},
"Process Invoice Data": {
"main": [
[
{
"node": "Generate HTML Template",
"type": "main",
"index": 0
}
]
]
},
"Save to Google Drive": {
"main": [
[
{
"node": "Success Response",
"type": "main",
"index": 0
}
]
]
},
"Generate HTML Template": {
"main": [
[
{
"node": "Generate PDF",
"type": "main",
"index": 0
}
]
]
},
"Send Email to Customer": {
"main": [
[
{
"node": "Success Response",
"type": "main",
"index": 0
}
]
]
}
}
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
中级 - 杂项, 多模态 AI
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
使用Google Drive存储和Telegram提醒自动化Instagram Reel下载
使用Google Drive存储和Telegram提醒自动化Instagram Reel下载
If
Code
Webhook
+6
11 节点Aryan Shinde
文件管理
竞争对手内容差距分析器:自动化网站主题映射
使用Gemini AI、Apify和Google Sheets分析竞争对手内容差距
If
Set
Code
+10
30 节点Mychel Garzon
杂项
Slack 多语言助手(使用 Gemini 2.5 Flash)
使用Gemini 2.5 Flash自动化多语言Slack通信(日语⇄英语)
If
Code
Switch
+6
29 节点Tomohiro Goto
杂项
自动化Google Drive到FTP文件传输与JSON日志记录和报告
自动化Google Drive到FTP文件传输与JSON日志记录和报告
If
Ftp
Code
+7
15 节点Dariusz Koryto
文件管理
使用Mistral AI OCR和JigsawStack分类和提取平面图数据
使用Mistral AI OCR和JigsawStack分类和提取平面图数据
If
Code
Switch
+6
24 节点Stephan Koning
杂项
使用Groq AI和GhostGenius比较LinkedIn个人资料与职位描述
使用Groq AI和GhostGenius比较LinkedIn个人资料与职位描述的匹配度
If
Set
Code
+8
17 节点Stephan Koning
杂项
工作流信息
难度等级
中级
节点数量13
分类2
节点类型7
作者
Ibrahim Emre POLAT
@epolatSenior Software Developer specializing in automation and integrations with n8n. Experienced in .NET, PostgreSQL, and cloud-native systems. Continuously learning new tools and technologies to deliver efficient, scalable workflows.
外部链接
在 n8n.io 查看 →
分享此工作流