AI PLAY玩法更新持续收录
← 回到更新流

2026-09-14 · 原文发布日

n8n模板:发票PDF上传后自动提取字段入库并通知

免费模板,webhook接收上传的发票PDF,提取并清洗文本后让gpt-4o-mini把供应商、发票号、日期、金额、币种、税额等解析成JSON,校验必填字段,合格的写入PostgreSQL发票表并在Slack发通知,不合格的记入失败表并告警,最后给调用方返回成败状态。不同格式发票可调整提取提示词与字段类型。

原文要点

来源是WeblineIndia发布在n8n官方模板库的免费工作流:POST webhook端点/invoice-upload以二进制字段file接收发票PDF,提取文本并清理空白与换行,用OpenAI的gpt-4o-mini把供应商、发票号、日期、金额、币种、税额、类别解析成JSON,校验供应商名与总金额等必填字段,合格写入PostgreSQL的public.invoices并向Slack频道发通知,不合格写入public.failed_invoices并告警,最后向调用方返回成功或失败的JSON响应。页面未提供可直接下载的工作流JSON,也未给出表结构、提示词全文与费用数据。

这次做成什么

在自有n8n实例里搭通这条发票处理流水线,用一张虚构发票PDF跑通从上传到入库、Slack通知、失败落库的完整分支。由于原模板页不提供可导入文件,下列节点配置、提示词、建表语句均为本站按页面描述独立编写的重建方案,节点名与字段映射需在导入原模板后逐项核对。

准备什么

  • 一个可登录的n8n实例(云版或自托管均可),有创建webhook的权限
  • OpenAI API密钥,且账号可调用gpt-4o-mini模型
  • 一个PostgreSQL数据库及有建表、写表权限的账号
  • Slack工作区及可发消息的OAuth应用或Incoming Webhook
  • 一份虚构测试发票PDF(示例生成方法见步骤一),不得使用真实客户发票

具体怎么做

  1. 建两张表

    在PostgreSQL中执行下方材料里的建表SQL,创建public.invoices与public.failed_invoices,字段与后续映射一一对应,避免入库时列名不匹配报错。

  2. 造测试发票并配置入口

    用任意文本工具按下方example.input的内容生成一张测试PDF(另存为PDF即可)。在n8n新建工作流,加Webhook节点:Method选POST,Path填invoice-upload,Binary Data开启并约定二进制字段名为file;按原文要求调用方必须以file字段名上传。

  3. 提取并清洗文本

    接Extract from File节点,Operation选PDF、提取为文本;再接一个Code节点做清洗:把连续空白、多余换行压成单个空格,减少模型误读。示例代码:return items.map(i=>({json:{text:i.json.data.replace(/\s+/g,' ').trim()}}));

  4. 调用OpenAI解析

    接OpenAI节点(Model选gpt-4o-mini,凭据填自己的API密钥),System消息使用下方材料中的完整提示词,User消息传入清洗后的text,开启JSON输出格式,要求只返回对象不加解释。

  5. 校验并分支

    接IF节点,条件设为vendor非空且total_amount大于0。True分支接Postgres节点插入public.invoices,字段映射vendor_name→vendor、invoice_no→invoice_number、invoice_date、total_amount、currency、tax_amount、category;再接Slack节点向目标频道发成功通知,最后Respond to Webhook返回{"status":"success"}。False分支把原文与错误原因写入public.failed_invoices,向同一Slack频道发告警,返回{"status":"failed"}。

可直接复制的材料

发票字段提取提示词(粘贴到OpenAI节点System消息)

本站独立编写,替代原文未公开的提取提示词;字段名必须与建表SQL和映射一致,可按自家发票格式增删。

你是发票信息提取助手。从用户给的发票文本中提取以下字段并只返回一个JSON对象,不要输出任何其他文字:{"vendor":供应商名称字符串,"invoice_number":发票号码字符串,"invoice_date":开票日期,格式YYYY-MM-DD,"total_amount":含税总金额数字,不带货币符号,"currency":三字母币种代码如CNY或USD,"tax_amount":税额数字,没有则填0,"category":从[办公用品,差旅,软件服务,咨询服务,其他]中选一个}。若某字段在文本中找不到,字符串字段填null,数字字段填null。日期一律转成YYYY-MM-DD。

建表SQL(在PostgreSQL执行一次)

本站独立编写的示例结构,列类型可按需调整;若导入原模板,以模板实际映射的列名为准。

CREATE TABLE IF NOT EXISTS public.invoices (
  id SERIAL PRIMARY KEY,
  vendor_name TEXT,
  invoice_no TEXT,
  invoice_date DATE,
  total_amount NUMERIC(12,2),
  currency VARCHAR(3),
  tax_amount NUMERIC(12,2),
  category TEXT,
  created_at TIMESTAMP DEFAULT now()
);
CREATE TABLE IF NOT EXISTS public.failed_invoices (
  id SERIAL PRIMARY KEY,
  raw_text TEXT,
  error_reason TEXT,
  created_at TIMESTAMP DEFAULT now()
);

调用方测试命令(webhook联调用)

二进制字段名必须是file(原页面明确要求);自托管实例把域名换成本地地址如http://localhost:5678。

curl -X POST https://你的n8n域名/webhook/invoice-upload -F "file=@./测试发票.pdf;type=application/pdf"

输入与输出示例

本站虚构演示输入与期望输出,非原作者运行结果,未在本站实测。

输入

虚构发票文本:深圳市星桥办公用品有限公司,发票号码INV-2026-0914,开票日期2026年9月10日,价税合计人民币1,280.00元,税额147.79元,内容为打印纸与墨盒。

对应输出

OpenAI节点应返回{"vendor":"深圳市星桥办公用品有限公司","invoice_number":"INV-2026-0914","invoice_date":"2026-09-10","total_amount":1280.00,"currency":"CNY","tax_amount":147.79,"category":"办公用品"};随后invoices表新增一行,Slack收到含供应商与金额的成功通知,webhook返回{"status":"success"}。

做完检查这些

  • curl上传测试PDF后,webhook响应体为{"status":"success"}且HTTP状态为200
  • 查询public.invoices能看到vendor_name、invoice_no、total_amount等字段全部写入且类型正确
  • Slack目标频道同时出现一条成功通知,内容含供应商名和金额
  • 把total_amount故意置空的坏PDF走False分支:failed_invoices出现记录、Slack出现告警、响应为{"status":"failed"}

容易卡住的地方

  • 二进制字段名必须叫file,写成其他名字会导致提取节点读不到文件
  • 模型名gpt-4o-mini需你的OpenAI账号实际可用,否则OpenAI节点报模型不存在错误
  • 金额若按文本类型入库,后续求和会出错,表字段建议NUMERIC类型
  • 发票日期格式多样(如09/10/2026歧义),提示词里要强制YYYY-MM-DD并在坏数据上实测
  • 本页不含可导入的工作流JSON,全部连线需按页面描述自行重建

原文与作者资料 ↗

本站借助AI整理来源事实,独立编写中文操作指南与示例。示例不代表实际运行结果;来源效果尚未由本站独立复现。付费模板与模型、服务费用分别计算。

原文标题
Process and validate invoices with OpenAI, PostgreSQL, and Slack
原作者
WeblineIndia
原始发布日期
2026-09-14T08:42:21.600Z
来源
https://n8n.io/workflows/19558