OFD电子发票号码提取器
功能概述
本技能专门用于解析 OFD(Open Fixed-layout Document)格式的电子发票,自动提取发票号码及关键信息并生成 Excel 文件:
- 多类型支持:增值税电子普通发票、增值税电子专用发票、全电发票(数电票)
- 批量处理:支持单次最多 200 个 OFD 文件批量提取
- 全字段提取:发票号码、发票代码、开票日期、金额、税额、价税合计、购销方名称及税号
- 自动查重:自动识别重复发票号码并单独标记
- Excel 导出:生成包含「发票明细」「统计信息」「失败列表」「重复列表」多 Sheet 的 Excel 报表
- 标准解析:基于 OFD 国标(GB/T 33190)结构,通过 CustomTag 语义标签 + ObjectRef + TextObject 链路精准提取
触发指令
- "提取OFD电子发票"
- "OFD电子发票提取"
- "提取OFD"
- "OFD发票解析"
- "读取OFD发票"
- "OFD发票号码提取"
依赖环境
- Python 3.10+
- pandas
- openpyxl
- tkinter(Python 内置 GUI 库,随 Python 安装)
工作流程
阶段一:上传文件(弹窗界面)
当用户触发技能后,PC 端弹出 tkinter 操作弹窗:
- 点击「添加文件」选择单个或多个 .ofd 文件
- 或点击「添加文件夹」批量导入某文件夹下所有 OFD 文件(最多 200 个)
- 可点击「清空列表」重新选择
- 确认后点击「确定」开始提取
阶段二:自动解析提取
程序按 OFD 标准结构解析每个文件:
- 解压 OFD(ZIP 格式)
- 读取
Document.xml获取文档结构 - 定位
CustomTags.xml->CustomTag.xml语义标签文件 - 解析
InvoiceNo、IssueDate、BuyerName、SellerName、TaxExclusiveTotalAmount等字段 - 通过
ObjectRef->PageRef->Content.xml->TextObject->TextCode链路提取实际文本 - 支持多 ObjectRef 拼接(如金额拆分为货币符号 + 数字两个对象)
- 自动过滤货币符号(¥/¥)、逗号、空格等无关字符
阶段三:导出结果
提取完成后自动生成 Excel 文件保存到桌面:
- 发票明细 Sheet:序号、发票号码、发票代码、开票日期、金额、税额、价税合计、购销方名称及税号、文件名称、提取时间
- 统计信息 Sheet:总文件数、成功提取数、失败数、重复数
- 失败列表 Sheet:失败文件路径及失败原因(如有)
- 重复列表 Sheet:重复发票号码(如有)
文件名格式:OFD发票号码提取结果_YYYYMMDD_HHMMSS.xlsx
技术细节
OFD 解析原理
OFD 文件本质是 ZIP 压缩包,内部采用 XML 描述文档结构和内容。发票语义数据存储在 Doc_X/Tags/CustomTag.xml 中,其中每个字段标签(如 InvoiceNo)不直接包含文本值,而是通过 ObjectRef 引用页面内容中的 TextObject ID。程序需要:
- 从
Document.xml获取CustomTags路径和页面映射 - 解析
CustomTag.xml获取字段标签及其ObjectRef引用 - 通过
PageRef定位到对应页面的Content.xml - 在
Content.xml中根据TextObject ID找到TextCode获取实际文本
回退机制
如果标准 CustomTag 解析未找到发票号码,程序会回退到通用 XML 标签搜索模式,遍历所有 XML 文件,查找 InvoiceNumber、发票号码、InvoiceNo 等标签,并支持正则匹配 20 位数字。
使用示例
用户:提取OFD电子发票
WorkBuddy:[弹出文件选择窗口]
用户:[选择 3 个 .ofd 文件,点击确定]
WorkBuddy:✅ 提取完成!成功 3 个,失败 0 个
发票号码:26372000003529013986
发票号码:26372000003529013987
发票号码:26372000003529013988
Excel 文件已保存到桌面
注意事项
- 仅支持 .ofd 格式文件,不支持 PDF 发票
- 单文件大小限制 20MB
- 程序在本地运行,不上传任何发票数据到服务器
- 需要安装 Python 运行环境及 pandas、openpyxl 依赖
支付宝付费改造契约(PAYSKILL)
本技能为付费技能(PAYSKILL)。调用遵循支付宝 AI 生意画像契约,由平台调度层执行 probe → pay → complete → ack 流程:
- probe(探测):平台调用前先探测是否已持有本技能的支付宝有效订阅 / 付费凭证。已付费则直接放行。
- 402 Payment-Needed:未付费时,脚本向标准输出返回 HTTP 状态
402与Payment-Needed标记,提示用户通过支付宝完成付费(pay),平台据此唤起付费页。 - complete(扣费确认):用户在支付宝完成扣费后,平台下发
Payment-Proof(付费凭证)。 - ack(验签放行):平台携带
Payment-Proof重试本次调用;scripts/payment_gate.py验签该凭证,确认有效后放行主流程。
订阅持久化与幂等:
- 付费状态缓存在本地
.pay_cache/state.json,避免每次调用重复付费(订阅持久化)。 - 同一
Payment-Proof在 24h 幂等窗口内仅生效一次,避免重复扣费。
现金流改造后的调用套路:
用户调用 → 平台 probe →
未付费:下发 402 Payment-Needed → 支付宝 pay → complete → 下发 Payment-Proof
已付费/携带 Proof:脚本 ack 验签 → 放行主流程
本契约由 SkillHUB 平台调度层解析,脚本本地仅处理
402/验签/持久化三环节;付费本体交给支付宝。
支付宝 AI 按量付费(Machine Pay / A2M)改造说明
本 Skill 已按支付宝官方 A2M 协议改造为 Pay Skill,付费闸口位于 scripts/payment_gate.py,统一调用云端计费服务 https://pay.pembroli.cn/api/resource。
付费流程
- 未付费调用时,服务端返回 HTTP 402 +
Payment-Needed头,携带金额、商户、订单号及 RSA2 签名。 - 买家侧
payment_gate.py收到 402 后引导用户完成支付,平台回传Payment-Proof。 - 客户端携带
Payment-Proof重试资源端点。
验付调用
服务端收到 Payment-Proof 后,调用支付宝验付接口(alipay.aipay.agent.payment.verify)核验凭证有效性(trade_no、out_trade_no、active 状态),验证失败返回 400,验证通过才进入资源发放。
履约确认
资源发放成功后,服务端异步调用履约确认接口(alipay.aipay.agent.fulfillment.confirm,trade_no)回执,标记本笔订单已履约;并按 out_trade_no 做幂等,重复请求直接返回已缓存结果,杜绝重复收费。
幂等与缓存
买家侧按 slug 本地缓存 Payment-Proof(24h TTL),有效期内免重复支付;服务端按订单号幂等,保证同一笔订单只履约一次。
Scan to join WeChat group