Nordlet

← 博客

自动化跨国增值税 (VAT) 申报与 VIES 验证

开发者使用云端会计 API 将欧盟增值税 (VAT) 合规嵌入多边市场与平台中的实操指南。

Nordlet Team · · 2 分钟阅读

平台代码中的大多数增值税 (VAT) 错误都源于一个假设: 只要 VIES 验证通过,就可以对销售适用零税率。事实并非如此。如果基于这种捷径构建系统,生成的申报表在表面上看起来天衣无缝,直到审计师追问:在没有任何运输证据或一致的供应发生地 (place-of-supply) 记录的情况下,为什么能适用欧盟境内免税政策?“VAT 税号校验通过”与“该项供应被正确处理”之间存在着巨大的鸿沟,而绝大多数集成正是在这个地方悄悄出了问题。

本文将探讨如何利用云端会计 API 自动化处理跨国的 VAT 申报与 VIES 验证,并以 Nordlet 会计 API 作为实现场景。系统的核心目标是:在销售发生的瞬间捕获正确的凭证,记入不可篡改的分类账 (ledger),并生成按税收方案 (scheme) 和成员国分组且可直接用于申报的数据,而无需事后在电子表格中重新汇总各项总额。

VIES 的实际作用与局限性

VIES 是欧盟增值税信息交换系统 (EU VAT Information Exchange System)。当你提交国家代码和 VAT 税号时,它会实时查询相关的国家数据库,并返回该 VAT 信息的有效性状态。这就是它的全部功能。它确认某个税号已经注册,并且在成员国支持的情况下,已被激活用于欧盟内部贸易。

它并不能确立免征欧盟内部供应税的权利。欧盟委员会对此表述得非常明确。有效的 VIES 响应只是众多证据中的一项。你仍然需要确认客户是实际收货人、该供应符合欧盟内部交易资格、存在运输或发货证据,并且发票上载有法定要求的反向征收 (reverse-charge) 字样。

因此,首要的架构设计决策是:将 VIES 状态与 VAT 处理方式 (treatment) 存放在不同的字段中。切勿将 viesStatus: valid 直接与 zeroRated: true 绑定。一旦将这两个概念混为一谈,当证据受到质疑时,你就失去了辩护的能力。

编写集成代码前的准备工作

在调用任何端点之前,先定义好你要申报的业务范围。这部分内容看似枯燥,但如果跳过它,后期代价将十分高昂。

  • 企业设立地或拥有固定营业地 (fixed establishment) 的国家
  • 持有 VAT 登记证的国家
  • 销售的是商品、服务、数字服务,还是混合销售
  • 交易属于 B2B、B2C 还是两者兼有
  • 使用的是境内注册、OSS、IOSS、反向征收,还是多边市场视同销售供应商 (deemed-supplier) 规则
  • API 必须输出哪些成果:境内申报数据、OSS/IOSS 数据、类似立陶宛 i.SAF 的发票登记簿、纯分类账分录,或是供独立申报服务商使用的有效载荷 (payload)

这一点至关重要,因为 OSS 并不能涵盖所有交易。在企业设有营业地的国家所提供的服务,通常应当归入该国的境内申报表,而不是 OSS 申报表。从一开始就要将营业机构与主体分开建模,否则在聚合阶段会错误地路由这些供应。

同样不要在代码中硬编码每个国家的 VAT 税率。欧盟拥有标准税率、减免税率、超低税率、中间税率、零税率以及针对特定产品的特殊处理规则,且这些规则会发生变化。特定成员国针对特定产品的可靠信息来源是该国税务机关,而欧盟委员会的 TEDB 则提供了跨国的概览。请记录每次税率决策背后的来源和版本,以免未来更新税率表时,无声无息地重写了旧交易的呈现方式。

对税务决策进行建模,而不只是税率

稳健集成的核心,是位于产品与税率之间的税收分类 (tax-category) 层。将产品映射到分类,再将分类映射到各国的特定税码,最后映射到附带生效日期的税率:

product/service
    → tax category
    → country-specific tax code
    → effective-dated rate and treatment

导致申报数据漂移的不安全做法是 product SKU → 21% VAT。同一产品在不同国家适用不同的税率,且税率可能在税期中间发生变化。Nordlet 自身的欧盟 VAT 合规指南正是推荐这种基于分类的映射,而不是将产品直接绑定到百分比。

你的税收分类体系应当保持稳定且内部化:标准税率商品、减免税率商品、电子提供服务、普通服务、免税供应、零税率供应、欧盟内部 B2B 反向征收、欧盟内部远程销售、IOSS 进口、视同供应商交易。下游的一切处理都以此分类体系为准。

将 VIES 验证作为异步凭证工作流

官方 VIES 服务暴露了一个 SOAP/WSDL 接口,接收两位国家代码和 VAT 税号。其文档记录的缺陷对于错误处理至关重要:输入无效、全局及成员国并发限制、服务不可用、成员国不可用以及超时。请将这些视为截然不同的结果,而不是单一的“失败”大杂烩。

一个能够承受高并发和审计考验的工作流应当包含以下步骤:

  1. 标准化 VAT 税号:将前缀大写,剥离允许的空格或标点符号,同时单独保留用户原本输入的值。
  2. 在发起网络调用之前,在本地校验国家代码和税号的格式。
  3. 将标准化后的税号提交给 VIES。
  4. 存储标准化 ID、请求和响应时间戳、有效/无效/未处理状态、原始响应、任何服务错误、客户与发票 ID,以及应用层的决策。
  5. 在明确且有文档记录的期限内缓存成功的查询结果。
  6. 以指数退避策略重试瞬时技术故障。
  7. 将未解析或矛盾的案例路由至人工审核。
  8. 在缓存结果过期时,或在证据至关重要的交易发生前重新进行验证。

Nordlet 会在添加客户时检查欧盟 VAT 税号,并在开具发票前(如果之前的检查结果已过期)重新检查。无论检查发生在平台内部还是你自己的代码中,这都是你应当复制的行为。

关键原则:切勿让结账流程与 VIES 保持同步。服务中断并不等同于税号无效。如果在销售期间 VIES 超时,请将交易挂起以待审核,或为其分配一个临时状态。因第三方委员会服务的在线状态而阻塞结账流程只会产生大量的客服工单,而将优质客户错误分类为无效客户则后果更严重。

将验证状态与税务处理分离

获得 VIES 结果后,决策引擎还有更多工作要做。请将这些数据作为不同的字段进行存储:

{
  "viesStatus": "valid",
  "vatTreatment": "intra_eu_b2b_reverse_charge",
  "evidenceStatus": "reviewed",
  "placeOfSupply": "DE"
}

在应用反向征收或免税政策之前,引擎应当测试:客户是否确实为收货人、客户国家和 VAT 前缀是否一致、供应是否符合欧盟内部交易资格、是否适用特殊的供应发生地规则、是否存在运输证据、卖家是否作为视同供应商行事,以及发票是否包含必需的法定用语。未能通过上述任何其他测试的有效 VIES 状态并不等于绿灯放行。

在开票时创建不可篡改的 VAT 决策

在创建发票时,将完整的决策过程与其一同持久化,而不仅仅是最终税率:

invoice
  ├─ line tax category
  ├─ place of supply
  ├─ VAT scheme
  ├─ country-specific rate
  ├─ rate-table version
  ├─ VIES evidence reference
  ├─ location-evidence references
  ├─ legal-basis reference
  └─ marketplace-role flags

欧盟发票规则要求包含供应商和客户详细信息、发票号、描述、应税金额、VAT 税率、VAT 金额,以及任何反向征收或免税信息。红字发票(贷项通知单,credit notes)和修改件需要对原始发票建立明确的引用。

Nordlet 的分类账是不可篡改的,因此纠错需要通过诸如红字发票或冲销分录等新分录来进行,而不是直接编辑已关闭的记录。即使你的存储技术上允许覆盖,也应当围绕该模型构建你的消费端。编辑已关闭的发票会破坏原始申报与更正之间的关联,而这正是审计师所追踪的血缘关系。

记账、Webhooks 与幂等性

一笔销售会记入复式记账分录,同时保留商业交易以及按国家和方案拆分的 VAT 负债。一笔境内销售可能会记入:

Dr 应收账款 / 支付清算
    Cr 收入
    Cr 应付增值税 - 德国 - 境内

一笔欧盟内部 B2B 反向征收销售会记入不含销项税的收入,并附带反向征收凭证的引用。具体的会计科目表由你决定;重要的是,报告维度必须附加到每一笔分录上:成员国、方案、税收分类、税率、税期、源发票以及更正血缘。

通过 Webhooks 而不是轮询来驱动状态变更。Nordlet 会发出诸如 sale_invoice.paid 的事件,对投递进行签名,并采用退避策略进行重试。为每一次写入赋予一个具有确定性的幂等键 (idempotency key):

sale:{platform_order_id}:invoice:{invoice_version}

你的消费端也必须具备幂等性。Webhook 可能会重复到达、延迟到达,或者在原始请求已经成功后才触发。校验签名、记录事件 ID、将格式错误的事件隔离、通过持久化队列处理,并按计划将 Webhook 状态与 API 进行对账。如果你以前没有处理过带签名的 Webhooks 与幂等键,这里往往隐藏着最隐蔽的重复分录 Bug。

为 OSS 进行分组并生成可直接申报的导出数据

对于符合条件的 OSS 交易,按以下维度对分类账数据进行分组:方案、消费成员国、供应类型、税率分类、税率、应税金额、VAT 金额、发货或营业地成员国、币种以及更正税期。

欧盟境内方案 (Union scheme) 申报表按消费成员国对供应进行分类,并区分了来自识别成员国的服务、来自其他固定营业地的服务,以及从不同成员国发货的商品。它分别报告标准税率和减免税率的应税金额与 VAT 金额。免税和零税率供应则完全不计入 OSS 申报表。

几个容易踩坑的实务细节:

  • 欧盟及非欧盟 OSS 税期为季度制;IOSS 为月度制。申报表和税款缴纳截止日期为次月底。
  • 即使没有发生相关供应,每个税期也必须进行零申报。请生成税期检查清单并自动创建零值申报表。
  • OSS 申报表以欧元为单位,需要转换时采用税期最后一天的欧洲央行 (ECB) 参考汇率。请存储源币种、汇率、汇率日期、转换后金额及转换方法。

导出数据应当来自已锁定的分类账,绝不能来自旁路的电子表格。电子表格的汇总总计会丢失更正记录、发货国家、税率和凭证。导出内容应包含申报期、方案、消费成员国、发货国、供应分类、税率、应税金额与 VAT 金额、币种与应用的汇率、本期和前期更正金额、源发票 ID、红字发票引用以及对账总额。

明确 API 在此处交付的内容。Nordlet 根据发票和分类账(包含前期更正)计算 OSS 和 IOSS 申报表,分发立陶宛 (FR0600)、德国 (UStVA) 和波兰 (JPK_V7M) 的境内申报包,并为立陶宛生成符合 VMI 要求的 i.SAF 登记册。这就是可用于申报的数据。单次 API 调用并不会通过各个国家的网关代为提交各国的 VAT 申报表,也没有任何申报表会代表你提交给税务机关。应当将会计处理、申报表生成、导出、网关提交和付款确认作为系统中的独立状态,切勿假设单次调用就能搞定一切。 EU VAT 引擎指南 记录了引擎解决的案例及其警告触发的位置。

锁定期

在审查和批准之后,将发票与分类账分录进行对账,将分类账 VAT 余额与申报数据集进行对账,导出申报表,记录申报和付款凭证,然后锁定该税期。 Nordlet 会阻止向已锁定的月份写入分录,包括通过 API 写入。锁定后的更正需计入后面的税期,并显式链接到原始单据及受影响的申报期。

常见失败模式与规避方法

失败模式 原因 规避方法
将有效的 VIES 结果视为适用零税率的充分条件 VIES 无法确立免税权利 将客户、供应、运输和发票凭证与验证结果一同存储
将无效结果视为未进行 VAT 登记的证明 该税号可能未被激活用于欧盟内部贸易,或者数据库存在滞后 区分无效、未处理和技术故障;将争议路由至人工审核
使结账流程与 VIES 保持同步 并发限制、超时、服务中断 异步验证、短期缓存、退避重试、使用临时状态
永久缓存验证结果 登记和激活状态会发生变化 存储时间戳和过期时间;在结果过期时于开票前重新检查
将产品直接映射到 VAT 百分比 税率和免税政策取决于国家和日期 产品 -> 分类 -> 国家税码 -> 附带生效日期的税率
从电子表格中重新拼凑 OSS 数据 总计会遗漏更正、发货国和凭证 从带有分录维度的不可篡改分类账中派生数据
将境内营业地服务计入 OSS 某些服务属于境内申报范畴 对营业机构单独建模,在聚合前按方案路由
遗漏零申报 OSS 要求每个税期都必须进行申报 生成检查清单并自动创建零值申报表
编辑已关闭的发票进行更正 破坏了申报与更正之间的关联 在后续税期中使用红字发票或冲销分录

我们会优先做什么

如果要从明天开始构建此集成,我们会在触碰任何申报端点之前,先构建税收分类层和 VAT 决策记录。保持分类体系稳定,将产品映射到分类,并确保决策记录能够捕获原始的国家信号以及选择某个供应发生地的原因。其他的一切——VIES、记账、OSS 分组、导出——都建立在这一数据模型正确的基础之上。

然后,我们将 VIES 作为异步凭证步骤接入,分离出四种状态,并在沙盒公司中运行它,针对棘手的边缘情况(超时、未处理结果、前缀不匹配)使用测试夹具(fixtures),然后再将其部署到接近生产的环境中。如果数据模型从第一笔分录开始就携带了凭证和报告维度,上述失败模式几乎完全是可以避免的。

FAQ

VIES 响应有效是否意味着我可以对欧盟内部 B2B 销售适用零税率?

不能。VIES 确认 VAT 税号已注册,并且在支持的地区已激活用于欧盟内部贸易。免征欧盟内部供应税的权利取决于额外的证据:客户是否为实际收货人、运输或发货证明、正确的供应发生地以及必需的发票用语。应当将 VIES 结果作为输入之一,而不是最终决策。

VIES 验证是否应该阻塞结账流程?

不应该。VIES 可能会超时或达到并发限制,服务中断并不等同于税号无效。应当进行异步验证、在有文档记录的期限内缓存成功的结果、对瞬时故障进行重试,并将模棱两可的案例挂起以待审核并赋予临时状态,而不是让销售失败。

云端会计 API 能自动提交 VAT 申报表吗?

它可以生成按方案和成员国分组且可用于申报的数据,这些数据根据包含更正的不可篡改分类账计算得出。它是否同时通过各个国家的申报网关进行提交,取决于具体的产品和国家。 Nordlet 计算 OSS 和 IOSS 申报表,分发立陶宛、德国和波兰的境内申报包,并为立陶宛生成符合 VMI 要求的 i.SAF 登记册,但它不会代表你向税务机关提交任何内容。应当将会计处理、申报表生成、导出、网关提交和付款视为独立的状态,切勿假设单次调用就能到处申报。

锁定税期后如何处理更正?

将其记入后续税期中,并显式链接到原始单据及受影响的申报期。 Nordlet 会阻止向已锁定的月份写入新分录(包括通过 API 写入),因此更正需要通过红字发票或冲销分录来进行,而不是直接编辑。这保持了原始申报与调整之间的血缘关系。

延伸阅读