发票处理系统用于提交
高级
这是一个Invoice Processing, AI Summarization领域的自动化工作流,包含 24 个节点。主要使用 If, Code, Xero, Gmail, Slack 等节点。 通过 Gmail、OCR.space、Slack 和 Xero 实现发票处理的自动化
前置要求
- •Google 账号和 Gmail API 凭证
- •Slack Bot Token 或 Webhook URL
- •可能需要目标 API 的认证凭证
- •Google Sheets API 凭证
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"id": "QHTTTSIjepK3ipPO",
"meta": {
"instanceId": "a9990cea8ba499cd2caa870c8ec5e719a88b31e6ed62907b6084053e5dc1857a",
"templateCredsSetupCompleted": true
},
"name": "发票处理系统用于提交",
"tags": [
{
"id": "CMJL1dF3mMlRu0Jb",
"name": "Invoice Processing",
"createdAt": "2025-10-11T20:13:04.997Z",
"updatedAt": "2025-10-11T20:13:04.997Z"
}
],
"nodes": [
{
"id": "189e9199-b377-4acc-a0e7-d5769e69a762",
"name": "Gmail 触发器",
"type": "n8n-nodes-base.gmailTrigger",
"position": [
-96,
16
],
"parameters": {
"simple": false,
"filters": {
"q": "has:attachment filename:pdf"
},
"options": {
"downloadAttachments": true
},
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
}
},
"credentials": {
"gmailOAuth2": {
"id": "d2kfFLUV2qlW2o43",
"name": "Gmail account"
}
},
"typeVersion": 1.3
},
{
"id": "7c5278ea-c32f-4f55-9ba4-4448c06c21f0",
"name": "JavaScript 代码",
"type": "n8n-nodes-base.code",
"position": [
80,
16
],
"parameters": {
"jsCode": "// Get email data\nconst email = $input.item.json;\nconst binary = $input.item.binary;\n\n// Check if we have binary attachments\nif (!binary || Object.keys(binary).length === 0) {\n return { \n json: { \n error: 'No invoice attachment found',\n emailId: email.id,\n emailSubject: email.subject\n } \n };\n}\n\n// Find first PDF or image attachment\nlet invoiceFile = null;\nlet invoiceKey = null;\n\nfor (const key in binary) {\n const file = binary[key];\n if (file.mimeType?.includes('pdf') || \n file.mimeType?.includes('image') ||\n file.mimeType?.includes('png') ||\n file.mimeType?.includes('jpg')) {\n invoiceFile = file;\n invoiceKey = key;\n break;\n }\n}\n\nif (!invoiceFile) {\n return { \n json: { \n error: 'No PDF or image attachment found',\n emailId: email.id,\n emailSubject: email.subject\n } \n };\n}\n\n// The binary data in n8n is already base64 encoded\n// Just use it directly without re-encoding\nlet base64Data = invoiceFile.data;\n\n// If it's a Buffer, convert to base64 string\nif (Buffer.isBuffer(base64Data)) {\n base64Data = base64Data.toString('base64');\n}\n\n// Build the data URL for OCR.space\nconst dataUrl = `data:${invoiceFile.mimeType};base64,${base64Data}`;\n\nreturn {\n json: {\n emailId: email.id,\n emailSubject: email.subject,\n emailFrom: email.from,\n emailDate: email.date,\n attachmentData: base64Data,\n attachmentName: invoiceFile.fileName,\n mimeType: invoiceFile.mimeType,\n dataUrl: dataUrl\n }\n};"
},
"typeVersion": 2
},
{
"id": "4ddb1479-1b7f-4f8d-ad41-1a92654c98c8",
"name": "在表格中追加或更新行",
"type": "n8n-nodes-base.googleSheets",
"position": [
1296,
-48
],
"parameters": {
"columns": {
"value": {
"Amount": "={{ $json.amount }}",
"Status": "Pending",
"Vendor": "={{ $json.vendor }}",
"Currency": "={{ $json.currency }}",
"Due Date": "={{ $json.dueDate }}",
"Email ID": "={{ $node[\"Code in JavaScript\"].json.emailId }}",
"Timestamp": "={{ $now.format('yyyy-MM-dd HH:mm:ss') }}",
"Description": "={{ $json.description }}",
"Invoice Date": "={{ $json.invoiceDate }}",
"Invoice Number": "={{ $json.invoiceNumber }}"
},
"schema": [
{
"id": "Invoice Number",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Invoice Number",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Vendor",
"type": "string",
"display": true,
"required": false,
"displayName": "Vendor",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Amount",
"type": "string",
"display": true,
"required": false,
"displayName": "Amount",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Currency",
"type": "string",
"display": true,
"required": false,
"displayName": "Currency",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Invoice Date",
"type": "string",
"display": true,
"required": false,
"displayName": "Invoice Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Due Date",
"type": "string",
"display": true,
"required": false,
"displayName": "Due Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Description",
"type": "string",
"display": true,
"required": false,
"displayName": "Description",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email ID",
"type": "string",
"display": true,
"required": false,
"displayName": "Email ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Status",
"type": "string",
"display": true,
"required": false,
"displayName": "Status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Timestamp",
"type": "string",
"display": true,
"required": false,
"displayName": "Timestamp",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Processed By",
"type": "string",
"display": true,
"required": false,
"displayName": "Processed By",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"Invoice Number"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1TWE856dG0g0bSRr3M4SKPcpnJ32veWlq3m_DWJoSaTQ/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "=\"YOUR_SPREADSHEET_ID\""
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "hVo2bSobLUbf5b3a",
"name": "Google Sheets account"
}
},
"typeVersion": 4.7
},
{
"id": "abea5730-c60f-47f4-83b3-50cb42c6c9e0",
"name": "Slack 审批请求",
"type": "n8n-nodes-base.slack",
"position": [
1904,
-48
],
"webhookId": "4f4fa1f8-f072-4ceb-b802-68904622847d",
"parameters": {
"select": "channel",
"message": "=🧾 *New Invoice Requires Approval*\n\n*Vendor:* {{ $json.vendor }}\n*Amount:* ${{ $json.amount }} {{ $json.currency }}\n*Invoice #:* {{ $json.invoiceNumber }}\n*Due Date:* {{ $json.dueDate }}\n*Description:* {{ $json.description }}",
"options": {},
"channelId": {
"__rl": true,
"mode": "list",
"value": "C09LDKZJGBB",
"cachedResultName": "invoice-approvals"
},
"operation": "sendAndWait",
"authentication": "oAuth2",
"approvalOptions": {
"values": {
"approvalType": "double"
}
}
},
"credentials": {
"slackOAuth2Api": {
"id": "plTTzKNjrWG2CYjh",
"name": "Slack account"
}
},
"typeVersion": 2.3
},
{
"id": "955f6439-8d79-4f9f-b35c-7bf3e39f6aad",
"name": "Slack 拒绝消息",
"type": "n8n-nodes-base.slack",
"position": [
1296,
144
],
"webhookId": "e4b6a100-ab6c-4908-8909-a37c5c210aad",
"parameters": {
"text": "=Channel: #invoice-approvals\n\nText:\n❌ *Invoice Auto-Rejected*\n\nAn invoice was rejected by AI analysis:\n\n- From: {{ $node[\"Code in JavaScript\"].json.emailFrom }}\n- Subject: {{ $node[\"Code in JavaScript\"].json.emailSubject }}\n- Reason: Did not pass qualification checks\n- Confidence: {{ $json.confidence }}%\n- Red Flags: {{ $json.redFlags.join(', ') }}\n\nThe email has been labeled \"Rejected\" in Gmail.",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "C09LDKZJGBB",
"cachedResultName": "invoice-approvals"
},
"otherOptions": {},
"authentication": "oAuth2"
},
"credentials": {
"slackOAuth2Api": {
"id": "plTTzKNjrWG2CYjh",
"name": "Slack account"
}
},
"typeVersion": 2.3
},
{
"id": "424382f8-ff99-457e-9714-569c83e29157",
"name": "检查资格",
"type": "n8n-nodes-base.if",
"position": [
1040,
0
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "1237bc0c-6f1a-4a3b-98ff-45369c8ebc06",
"operator": {
"type": "boolean",
"operation": "equals"
},
"leftValue": "={{ $json.qualified }}",
"rightValue": true
}
]
}
},
"typeVersion": 2.2
},
{
"id": "be9d4c45-2bb3-4ca4-944e-65045fa75a60",
"name": "解析发票数据",
"type": "n8n-nodes-base.code",
"position": [
720,
0
],
"parameters": {
"jsCode": "// Get OCR result\nconst ocrResult = $json;\n\n// Extract the text\nlet extractedText = '';\n\nif (ocrResult.ParsedResults && ocrResult.ParsedResults[0]) {\n extractedText = ocrResult.ParsedResults[0].ParsedText;\n} else {\n return {\n json: {\n error: 'OCR failed to extract text',\n qualified: false,\n redFlags: ['Could not read invoice text']\n }\n };\n}\n\n// Helper function to parse dates correctly without timezone issues\nfunction parseDate(dateString) {\n // Try to parse dates like \"October 1, 2025\"\n const date = new Date(dateString + ' 12:00:00 UTC'); // Add noon UTC to avoid timezone shifts\n \n if (!isNaN(date)) {\n const year = date.getUTCFullYear();\n const month = String(date.getUTCMonth() + 1).padStart(2, '0');\n const day = String(date.getUTCDate()).padStart(2, '0');\n return `${year}-${month}-${day}`;\n }\n \n return '';\n}\n\n// Parse invoice fields using regex\nconst invoiceData = {\n qualified: true,\n vendor: '',\n invoiceNumber: '',\n amount: 0,\n currency: 'USD',\n invoiceDate: '',\n dueDate: '',\n description: '',\n confidence: 100,\n redFlags: []\n};\n\n// Extract Vendor (line after \"From:\")\nconst vendorMatch = extractedText.match(/From:\\s*([^\\n]+)/i);\nif (vendorMatch) {\n invoiceData.vendor = vendorMatch[1].trim();\n}\n\n// Extract Invoice Number\nconst invoiceNumMatch = extractedText.match(/Invoice Number:\\s*([^\\n]+)/i);\nif (invoiceNumMatch) {\n invoiceData.invoiceNumber = invoiceNumMatch[1].trim();\n}\n\n// Extract Amount (from \"Total:\" line) - CRITICAL!\nconst totalMatch = extractedText.match(/Total:\\s*\\$\\s*([0-9,]+\\.?[0-9]*)/i);\nif (totalMatch) {\n invoiceData.amount = parseFloat(totalMatch[1].replace(/,/g, ''));\n}\n\n// If Total not found, try Amount line\nif (invoiceData.amount === 0) {\n const amountMatch = extractedText.match(/Amount:\\s*\\$\\s*([0-9,]+\\.?[0-9]*)/i);\n if (amountMatch) {\n invoiceData.amount = parseFloat(amountMatch[1].replace(/,/g, ''));\n }\n}\n\n// Extract Currency\nconst currencyMatch = extractedText.match(/(USD|EUR|GBP|CAD)/i);\nif (currencyMatch) {\n invoiceData.currency = currencyMatch[1].toUpperCase();\n}\n\n// Extract Invoice Date - FIXED!\nconst dateMatch = extractedText.match(/Date:\\s*([^\\n]+)/i);\nif (dateMatch) {\n const dateStr = dateMatch[1].trim();\n invoiceData.invoiceDate = parseDate(dateStr);\n}\n\n// Extract Due Date - FIXED!\nconst dueMatch = extractedText.match(/Due Date:\\s*([^\\n]+)/i);\nif (dueMatch) {\n const dateStr = dueMatch[1].trim();\n invoiceData.dueDate = parseDate(dateStr);\n}\n\n// Extract Description\nconst descMatch = extractedText.match(/Description:\\s*([^\\n]+)/i);\nif (descMatch) {\n invoiceData.description = descMatch[1].trim();\n}\n\n// Validation checks\nif (!invoiceData.vendor) {\n invoiceData.qualified = false;\n invoiceData.redFlags.push('Missing vendor name');\n}\n\nif (!invoiceData.invoiceNumber) {\n invoiceData.qualified = false;\n invoiceData.redFlags.push('Missing invoice number');\n}\n\nif (invoiceData.amount === 0) {\n invoiceData.qualified = false;\n invoiceData.redFlags.push('Missing or invalid amount');\n}\n\nif (invoiceData.amount > 10000) {\n invoiceData.qualified = false;\n invoiceData.redFlags.push('Amount exceeds $10,000');\n}\n\nreturn {\n json: invoiceData\n};"
},
"typeVersion": 2
},
{
"id": "36afc95e-af94-4c98-a458-744e9bfd1139",
"name": "格式化用于 Slack",
"type": "n8n-nodes-base.code",
"position": [
1504,
-48
],
"parameters": {
"jsCode": "const sheetData = $node[\"Append or update row in sheet\"].json;\n\nreturn {\n json: {\n vendor: sheetData.Vendor,\n amount: sheetData.Amount,\n currency: sheetData.Currency,\n invoiceNumber: sheetData[\"Invoice Number\"],\n invoiceDate: sheetData[\"Invoice Date\"], // ← ADD THIS LINE!\n dueDate: sheetData[\"Due Date\"],\n description: sheetData.Description\n }\n};"
},
"typeVersion": 2
},
{
"id": "b524a093-e827-4049-b0c9-809dc839465e",
"name": "拒绝消息",
"type": "n8n-nodes-base.slack",
"position": [
2896,
16
],
"webhookId": "019dcb52-375d-4fff-9e0d-d4d5b4ac0282",
"parameters": {
"text": "❌ Invoice rejected",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "C09LDKZJGBB",
"cachedResultName": "invoice-approvals"
},
"otherOptions": {},
"authentication": "oAuth2"
},
"credentials": {
"slackOAuth2Api": {
"id": "plTTzKNjrWG2CYjh",
"name": "Slack account"
}
},
"typeVersion": 2.3
},
{
"id": "afcf2f08-41ec-4ce5-bb32-98733317379f",
"name": "成功消息",
"type": "n8n-nodes-base.slack",
"position": [
3248,
-176
],
"webhookId": "ae7fc4b9-99a3-41ad-ba4e-4e4a15a52303",
"parameters": {
"text": "✅ Invoice posted to Xero",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "C09LDKZJGBB",
"cachedResultName": "invoice-approvals"
},
"otherOptions": {},
"authentication": "oAuth2"
},
"credentials": {
"slackOAuth2Api": {
"id": "plTTzKNjrWG2CYjh",
"name": "Slack account"
}
},
"typeVersion": 2.3
},
{
"id": "2a70f5c0-db5f-44eb-8eb8-24c978892049",
"name": "更新拒绝状态",
"type": "n8n-nodes-base.googleSheets",
"position": [
2704,
16
],
"parameters": {
"columns": {
"value": {
"Status": "Rejected",
"Invoice Number": "={{ $('Clean Invoice Payload').item.json.invoiceNumber }}"
},
"schema": [
{
"id": "Invoice Number",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Invoice Number",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Vendor",
"type": "string",
"display": true,
"required": false,
"displayName": "Vendor",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Amount",
"type": "string",
"display": true,
"required": false,
"displayName": "Amount",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Currency",
"type": "string",
"display": true,
"required": false,
"displayName": "Currency",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Invoice Date",
"type": "string",
"display": true,
"required": false,
"displayName": "Invoice Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Due Date",
"type": "string",
"display": true,
"required": false,
"displayName": "Due Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Description",
"type": "string",
"display": true,
"required": false,
"displayName": "Description",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email ID",
"type": "string",
"display": true,
"required": false,
"displayName": "Email ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Status",
"type": "string",
"display": true,
"required": false,
"displayName": "Status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Timestamp",
"type": "string",
"display": true,
"required": false,
"displayName": "Timestamp",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Processed By",
"type": "string",
"display": true,
"required": false,
"displayName": "Processed By",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "row_number",
"type": "number",
"display": true,
"removed": true,
"readOnly": true,
"required": false,
"displayName": "row_number",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"Invoice Number"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1TWE856dG0g0bSRr3M4SKPcpnJ32veWlq3m_DWJoSaTQ/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "=\"YOUR_SPREADSHEET_ID\""
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "hVo2bSobLUbf5b3a",
"name": "Google Sheets account"
}
},
"typeVersion": 4.7
},
{
"id": "f775d6e5-a97b-4aea-be73-f6a3030cbfc3",
"name": "更新批准状态",
"type": "n8n-nodes-base.googleSheets",
"position": [
3024,
-176
],
"parameters": {
"columns": {
"value": {
"Status": "Approved",
"Invoice Number": "={{ $('Clean Invoice Payload').item.json.invoiceNumber }}"
},
"schema": [
{
"id": "Invoice Number",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Invoice Number",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Vendor",
"type": "string",
"display": true,
"required": false,
"displayName": "Vendor",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Amount",
"type": "string",
"display": true,
"required": false,
"displayName": "Amount",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Currency",
"type": "string",
"display": true,
"required": false,
"displayName": "Currency",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Invoice Date",
"type": "string",
"display": true,
"required": false,
"displayName": "Invoice Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Due Date",
"type": "string",
"display": true,
"required": false,
"displayName": "Due Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Description",
"type": "string",
"display": true,
"required": false,
"displayName": "Description",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email ID",
"type": "string",
"display": true,
"required": false,
"displayName": "Email ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Status",
"type": "string",
"display": true,
"required": false,
"displayName": "Status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Timestamp",
"type": "string",
"display": true,
"required": false,
"displayName": "Timestamp",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Processed By",
"type": "string",
"display": true,
"required": false,
"displayName": "Processed By",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "row_number",
"type": "number",
"display": true,
"removed": true,
"readOnly": true,
"required": false,
"displayName": "row_number",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"Invoice Number"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "id",
"value": "=Sheet1"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "=\"YOUR_SPREADSHEET_ID\""
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "hVo2bSobLUbf5b3a",
"name": "Google Sheets account"
}
},
"typeVersion": 4.7
},
{
"id": "b062f234-61a1-4913-8135-be9d9be322a8",
"name": "添加已处理标签",
"type": "n8n-nodes-base.gmail",
"position": [
2832,
-176
],
"webhookId": "a5cbed4c-0c43-4bf0-8114-e8fbbf987e9e",
"parameters": {
"labelIds": [
"Label_3710233975993850496"
],
"messageId": "={{$node[\"Code in JavaScript\"].json.emailId}}",
"operation": "addLabels"
},
"credentials": {
"gmailOAuth2": {
"id": "d2kfFLUV2qlW2o43",
"name": "Gmail account"
}
},
"typeVersion": 2.1
},
{
"id": "854afcd4-6559-4753-b75d-2a65766c492d",
"name": "添加已拒绝标签",
"type": "n8n-nodes-base.gmail",
"position": [
2432,
16
],
"webhookId": "2e5f020d-ed42-438c-8744-4fdd602145c7",
"parameters": {
"labelIds": [
"Label_8899302689673155790"
],
"messageId": "={{$node[\"Code in JavaScript\"].json.emailId}}",
"operation": "addLabels"
},
"credentials": {
"gmailOAuth2": {
"id": "d2kfFLUV2qlW2o43",
"name": "Gmail account"
}
},
"typeVersion": 2.1
},
{
"id": "025efb16-32dd-4a7e-8349-baef18b32040",
"name": "获取多个联系人",
"type": "n8n-nodes-base.xero",
"position": [
2416,
-176
],
"parameters": {
"limit": 1,
"options": {},
"resource": "contact",
"operation": "getAll",
"organizationId": "=9a46b4a9-feac-446e-a04d-4e7421565898"
},
"credentials": {
"xeroOAuth2Api": {
"id": "XfSNoqDEDyivPRYX",
"name": "Xero account"
}
},
"typeVersion": 1
},
{
"id": "b43a1017-8ecb-4c39-b92f-8865349ccec2",
"name": "清理发票有效载荷",
"type": "n8n-nodes-base.code",
"position": [
1696,
-48
],
"parameters": {
"jsCode": "const invoiceData = { ...$node[\"Format for Slack\"].json };\n\n// Strip off any vendor or itemCode field that might be passed\ndelete invoiceData.vendor;\ndelete invoiceData.itemCode;\ndelete invoiceData[\"Item Code Name or ID\"]; // Just in case\n\nreturn [{ json: invoiceData }];\n"
},
"typeVersion": 2
},
{
"id": "a77a3860-e69a-428f-b74e-d926859c83e3",
"name": "创建发票",
"type": "n8n-nodes-base.httpRequest",
"position": [
2624,
-176
],
"parameters": {
"url": "https://api.xero.com/api.xro/2.0/Invoices",
"method": "POST",
"options": {},
"jsonBody": "={\n \"Type\": \"ACCPAY\",\n \"Contact\": {\n \"ContactID\": \"{{$node[\"Get many contacts\"].json.ContactID}}\"\n },\n \"Date\": \"{{$node[\"Format for Slack\"].json.invoiceDate}}\",\n \"DueDate\": \"{{$node[\"Format for Slack\"].json.dueDate}}\",\n \"InvoiceNumber\": \"{{$node[\"Format for Slack\"].json.invoiceNumber}}\",\n \"Reference\": \"{{$node[\"Format for Slack\"].json.invoiceNumber}}\",\n \"Status\": \"DRAFT\",\n \"LineAmountTypes\": \"Exclusive\",\n \"LineItems\": [\n {\n \"Description\": \"{{$node[\"Format for Slack\"].json.description}}\",\n \"Quantity\": 1,\n \"UnitAmount\": {{$node[\"Format for Slack\"].json.amount}},\n \"AccountCode\": \"463\",\n \"TaxType\": \"INPUT2\"\n }\n ]\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Accept",
"value": "application/json"
},
{
"name": "xero-tenant-id",
"value": "=\"{{$credentials.xero.apiKey}}\""
}
]
},
"nodeCredentialType": "xeroOAuth2Api"
},
"credentials": {
"xeroOAuth2Api": {
"id": "XfSNoqDEDyivPRYX",
"name": "Xero account"
}
},
"typeVersion": 4.2
},
{
"id": "270ea877-b081-4704-8137-3cbcf62606fb",
"name": "有有效附件吗?",
"type": "n8n-nodes-base.if",
"position": [
288,
16
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "5b78e677-d068-411a-8c43-e41a9725f370",
"operator": {
"type": "number",
"operation": "notExists",
"singleValue": true
},
"leftValue": "={{$json.error}}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "4128986d-09d7-44b5-a9f5-5f8a532c1712",
"name": "是否已批准?",
"type": "n8n-nodes-base.if",
"position": [
2128,
-48
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "b58f3729-809c-4b21-9210-6c581dbeed50",
"operator": {
"type": "boolean",
"operation": "equals"
},
"leftValue": "={{ $json.data.approved }}",
"rightValue": true
}
]
}
},
"typeVersion": 2.2
},
{
"id": "8400ed04-51ba-4cc6-92cc-abb03a09e258",
"name": "提取文本",
"type": "n8n-nodes-base.httpRequest",
"position": [
544,
0
],
"parameters": {
"url": "https://api.ocr.space/parse/image",
"method": "POST",
"options": {},
"jsonBody": "={\n \"name\": \"apikey\",\n \"value\": \"{{$credentials.ocrspaceApi.apiKey}}\"\n}",
"sendBody": true,
"specifyBody": "json"
},
"typeVersion": 4.2
},
{
"id": "d132fdec-f017-49f6-a4bc-8a938df37d98",
"name": "便签",
"type": "n8n-nodes-base.stickyNote",
"position": [
-912,
-464
],
"parameters": {
"width": 608,
"height": 1696,
"content": "### 使用 Gmail、OCR.space、Slack 和 Xero 自动化发票处理"
},
"typeVersion": 1
},
{
"id": "b16d6e58-0125-4735-b939-040945fcc89b",
"name": "便签1",
"type": "n8n-nodes-base.stickyNote",
"position": [
1008,
-336
],
"parameters": {
"width": 1248,
"height": 640,
"content": "## 2. 在 Slack 中批准或拒绝发票"
},
"typeVersion": 1
},
{
"id": "af22b982-18c5-4adc-9e88-d7ecf53f357c",
"name": "便签2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-144,
-336
],
"parameters": {
"width": 1120,
"height": 640,
"content": "## 1. 从 Gmail 提取和解析发票"
},
"typeVersion": 1
},
{
"id": "422c5b66-d77a-4224-b689-e4b57152373e",
"name": "便签3",
"type": "n8n-nodes-base.stickyNote",
"position": [
2288,
-336
],
"parameters": {
"width": 1168,
"height": 640,
"content": "## 3. 将结果同步到 Xero 并通知"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "a1d9da45-06e7-460c-9c56-bc430ee568b6",
"connections": {
"Extract Text": {
"main": [
[
{
"node": "Parse Invoice Data",
"type": "main",
"index": 0
}
]
]
},
"Gmail Trigger": {
"main": [
[
{
"node": "Code in JavaScript",
"type": "main",
"index": 0
}
]
]
},
"Was Approved?": {
"main": [
[
{
"node": "Get many contacts",
"type": "main",
"index": 0
}
],
[
{
"node": "Add Rejected label",
"type": "main",
"index": 0
}
]
]
},
"Create invoice": {
"main": [
[
{
"node": "Add Processed label",
"type": "main",
"index": 0
}
]
]
},
"Format for Slack": {
"main": [
[
{
"node": "Clean Invoice Payload",
"type": "main",
"index": 0
}
]
]
},
"Get many contacts": {
"main": [
[
{
"node": "Create invoice",
"type": "main",
"index": 0
}
]
]
},
"Add Rejected label": {
"main": [
[
{
"node": "Update Rejected Status",
"type": "main",
"index": 0
}
]
]
},
"Code in JavaScript": {
"main": [
[
{
"node": "Has Valid Attachment?",
"type": "main",
"index": 0
}
]
]
},
"Parse Invoice Data": {
"main": [
[
{
"node": "Check Qualification",
"type": "main",
"index": 0
}
]
]
},
"Add Processed label": {
"main": [
[
{
"node": "Update Approved Status",
"type": "main",
"index": 0
}
]
]
},
"Check Qualification": {
"main": [
[
{
"node": "Append or update row in sheet",
"type": "main",
"index": 0
}
],
[
{
"node": "Slack Rejection message",
"type": "main",
"index": 0
}
]
]
},
"Clean Invoice Payload": {
"main": [
[
{
"node": "Slack Approval Request",
"type": "main",
"index": 0
}
]
]
},
"Has Valid Attachment?": {
"main": [
[
{
"node": "Extract Text",
"type": "main",
"index": 0
}
]
]
},
"Slack Approval Request": {
"main": [
[
{
"node": "Was Approved?",
"type": "main",
"index": 0
}
]
]
},
"Update Approved Status": {
"main": [
[
{
"node": "Success message",
"type": "main",
"index": 0
}
]
]
},
"Update Rejected Status": {
"main": [
[
{
"node": "Rejection message",
"type": "main",
"index": 0
}
]
]
},
"Append or update row in sheet": {
"main": [
[
{
"node": "Format for Slack",
"type": "main",
"index": 0
}
]
]
}
}
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
高级 - 发票处理, AI 摘要总结
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
基于HubSpot上下文的AI邮件回复与Slack审批
基于HubSpot上下文的AI邮件回复与Slack审批
If
Code
Gmail
+8
19 节点Miha
客户关系管理
AI 客户支持分流与摘要系统
使用GPT-4o、Slack和CRM集成自动处理客户支持
If
Set
Code
+10
32 节点NodeAlchemy
工单管理
主动智能客户支持中心
使用GPT-4、Gmail和Trello的自动邮件支持分诊
If
Code
Gmail
+6
14 节点Marth
工单管理
支持收件箱到常见问题解答回填(Gmail/Outlook)
使用GPT-4o、Gmail、Notion和Slack将支持邮件转换为常见问题解答
If
Code
Gmail
+7
21 节点Rahul Joshi
工单管理
AI简历处理与GitHub分析(VLM运行)
AI简历处理与GitHub分析(VLM运行)
If
Code
Gmail
+7
18 节点Shahrear
人工智能
AI驱动的发票提取与自动化系统
使用Gemini AI、Google Sheets和Gmail通知提取和处理发票
If
Set
Code
+8
32 节点Yashraj singh sisodiya
发票处理
工作流信息
难度等级
高级
节点数量24
分类2
节点类型9
作者
Abi Odedeyi
@abiodedeyiAutomation Builder with extensive experience helping businesses streamline processes and generate revenue.
外部链接
在 n8n.io 查看 →
分享此工作流