MIT License

技术解读

以下内容由 GitRead 中文社区 编辑团队基于项目 README 与官方资料整理, 结合中文开发者的常见使用场景补充技术选型建议。具体以项目官方文档为准。

Facturas Digitales con AFIP Web Services y Node.js 深度分析

项目背景与痛点

Facturas Digitales(电子发票)是阿根廷政府为加强税法合规性而推行的一项重要措施。AFIP Web Services 是一个结合了阿根廷税务系统的一系列 API,用于电子票据和发票的生成、验证及管理。在这一背景下,emilioastarita/facturajs 项目应运而生,旨在便捷化与 AFIP Web Services 的对接,从而简化电子发票的处理流程。

对于开发者和企业而言,直接调用 AFIP Web Services 的难度较高,因为这需要深入了解复杂的 API 接口以及多种标准和协议。facturajs 便提供了一层抽象,使得集成变得更为简单,不仅降低了技术门槛,还提升了代码的可维护性和可读性。

核心技术揭秘

技术栈及架构

facturajs 采用了 Node.js 作为其主要技术栈,借助了其异步、非阻塞的 I/O 模型来提升性能和效率。关键的功能包括:

  • 通过 AFIP API 生成电子发票
  • 验证电子发票的有效性和完整性
  • 电子发票状态查询和更新

其内部架构可以大致总结为:用户请求 -> 参数校验 -> API 调用或业务逻辑执行 -> 结果返回。下面是一张简明的数据流图:

graph TD A[用户请求] --> B{"参数校验"} B -->|"通过"| C[执行业务] B -->|"失败"| D[返回错误] C --> E[AFIP API 调用] E --> F[返回结果] D --> F[返回结果]

在这个过程中,对外部 AFIP API 的调用处理尤为重要。facturajs 很好地抽象了这一过程,让最终用户只需要处理简单的对象和方法,而无需关心复杂的通信细节。

核心算法与实现原理

facturajs 使用了例如 crypto 库来处理安全相关的操作,如签名、加密解密等,确保数据在传输过程中的安全性与完整性。此外,它还利用一些设计模式,如工厂模式,来管理和配置不同的 AFIP API 服务接口,进而提供了一套统一且易扩展的 API 接口,支持了灵活多变的业务需求。

功能亮点与差异

人们一看到这种工具,往往会考虑独有优势。相较于特定领域内的其他工具包或适配器,facturajs 在以下几点上显示出独特的魅力:

  1. 全面覆盖:该工具支持多种 AFIP API,涵盖了发票的生成、认证、签章等多个环节。
  2. 易用性:相比直接与 AFIP Web Services 交互,facturajs 提供了更简单直观的 API 接口,降低了使用门槛。
  3. 灵活性:通过设计模式,如工厂模式,API 的配置非常灵活,适应于不同的业务需求及升级。

应用场景与落地建议

在生产环境使用facturajs,首先要确保你的应用已满足 Node.js 运行条件,并能正确处理 AFIP API 的响应。考虑到电子发票涉及敏感信息和重大责任,建议:

  • 安全评估:仔细评估所有安全性需求,确保敏感数据的加密和安全传输过程。
  • 容错与异常处理:部署时应留意处理异常场景,如连接中断、无效请求等情况,确保系统的健壮性。
  • 合规与法规遵循:特定国家和地区有明确的法规要求,务必确保项目符合当地法律和税务规定。

针对适合的业务场景,它是任何需要与 AFIP Web Services 交互的企业首选工具,不论是小型创业项目,还是大型企业,都可从中受益。同时,在团队中若缺少相关的技术或开发资源,facturajs 都可以轻松地弥补这些欠缺。

综合评价

facturajs 大大简化了与 AFIP Web Services 的集成过程,很好地填补了技术鸿沟,并在实际业务中提供了实用的功能。然而,也要注意到维护 API 的版本兼容性和安全性是项目持续发展的关键挑战,因此建议持续性关注并更新至最新版本。此外,项目本身虽然深受好评,但对于更广泛的国际用户来说,进一步文档化更多的功能细节及应用场景将会更有帮助。

关于

GitHub 原始描述(英文)

Facturas digitales con AFIP Web Services y nodej

描述取自 GitHub 官方 API,保持仓库作者书写的原文。

简要分析

热度分
172
价值分
77
活跃状态
活跃

语言占比

JavaScript
TypeScript

README

facturajs

facturajs

Afip Web Services desde nodejs.

~$ pnpm add facturajs
# OR
~$ npm i facturajs

WebServices de la AFIP con node

El objetivo de esta lib es facilitar la comunicación con la AFIP utilizando node.js. En mi caso particular, necesitaba generar facturas electrónicas como monotributista de manera automática.

No tiene muchas pretenciones, pero el código puede ser ilustrativo para armar otras integraciones más complejas.

Obtener certificados en la AFIP

Los servicios de AFIP están disponibles mediante SOAP y su página principal es AFIP WS.

Los servicios poseen dos entornos conocidos como homologación (para testing), y producción.

Para utilizar ambos entornos hay que obtener certificados digitales de la AFIP.

De nuestro lado lo primero es generar certificados relacionados a nuestro CUIT:

# Crear clave privada
~ $ openssl genrsa -out private/private_key.key 2048 
# Crear certificado
~ $ openssl req -new -key private/private_key.key -subj "/C=AR/O=TU_EMPRESA/CN=TU_SISTEMA/serialNumber=CUIT TU_CUIT" -out private/afip.csr

(*) Dónde dice CUIT TU_CUIT es importante el espacio y conservar la palabra “CUIT”.

Adherirse a homologación (testing)

En este pdf (WSASS como adherirse) pueden ver el proceso de adhesión al servicio de homologación. Básicamente das de alta el servicio y le cargas el CSR generado en el paso anterior, la página web te va a entregar otro cert que lo tenes que copiar y lo guardas en un archivo de texto: private/cert.pem. El último paso, en esa misma página, sería autorizar tu cert al servicio que quieras usar. En mi caso quería el de facturas digitales llamado: wsfe.

Ejemplo de uso

Crear una factura electrónica

En este ejemplo pueden ver como crear una factura electrónica con el último número de comprobante válido.

Para poder ver más en detalle que está sucediendo se puede configurar el LOG_LEVEL y namespace de DEBUG:

~$ LOG_LEVEL=3 DEBUG=facturajs node dist/examples/create-bill-monotributo.js
# Salida:
# Last bill number:  43
# Next bill number to create:  44
# Created bill {
#     "FeCabResp": {
#         "Cuit": "XXXXXXXXXX",
#         "PtoVta": 2,
#         "CbteTipo": 11,
#         "FchProceso": "20180423081028",
#         "CantReg": 1,
#         "Resultado": "A",
#         "Reproceso": "N"
#     },
#     "FeDetResp": {
#         "FECAEDetResponse": [
#             {
#                 "Concepto": 1,
#                 "DocTipo": 99,
#                 "DocNro": "0",
#                 "CbteDesde": "44",
#                 "CbteHasta": "44",
#                 "CbteFch": "20180423",
#                 "Resultado": "A",
#                 "CAE": "68174646182386",
#                 "CAEFchVto": "20180503"
#             }
#         ]
#     }
# }
Ejecutar cualquier método del WebService

De manera general cualquier método del WebService se puede llamar con execRemote(servicio, método, parámetros), por ejemplo:

const afip = new AfipServices(config);
afip.execRemote('wsfev1', 'FECAESolicitar', {
    Auth: {Cuit: 27000000000},
    params: {
        CbteTipo: 11,
        PtoVta: 2
    }    
}).then(res => console.log(res))
Config

El constructor AfipServices acepta un objeto que cumpla con la interfaz de IConfigService. La descripción de sus propiedades:

  • homo Un booleano que determina el uso del entorno de homologación.
  • cacheTokensPath Path a un file dónde se cachearan los tokens obtenidos para no solicitarlos cada vez.
  • tokensExpireInHours La cantidad de horas en la que expirará el archivo de tokens cacheados.
  • privateKeyContents El contenido de la private key (no hace falta path en este caso)
  • privateKeyPath Path a la private key (al igual que antes podemos omitir el contenido)
  • certContents El contenido del certificado (no hace falta path en este caso)
  • certPath Path al certificado (al igual que antes podemos omitir el contenido)
  • useLegacyTls Habilita o deshabilita la configuración de compatibilidad TLS para servidores AFIP viejos. Por defecto está activada. En Node 24 puede destrabar errores como dh key too small. Si querés desactivarla, usá false.
  • tlsRequestOptions Opciones avanzadas para el https.Agent usado por las llamadas SOAP/WSDL. Sirve para sobreescribir manualmente opciones TLS si hace falta.
Nota acerca de métodos de cifrado openssl

En algunos sistemas operativos con una versión de la configuración de openssl mas nueva se reportó un error porque openssl rechaza los métodos de cifrado de AFIP. Algunos usuarios reportaron que en un sistema Debian la solución fue editar /etc/ssl/openssl.cnf. Y comentar la siguiente línea:

# CipherString = DEFAULT@SECLEVEL=2

Ahora la librería ya aplica por defecto una configuración de compatibilidad TLS, sin tocar la configuración global del sistema:

const afip = new AfipServices({
    homo: true,
    cacheTokensPath: './tmp/tokens.json',
    tokensExpireInHours: 12,
    privateKeyPath: './private/private_key.key',
    certPath: './private/cert.pem',
});

Si necesitás desactivarla explícitamente:

const afip = new AfipServices({
    homo: true,
    cacheTokensPath: './tmp/tokens.json',
    tokensExpireInHours: 12,
    privateKeyPath: './private/private_key.key',
    certPath: './private/cert.pem',
    useLegacyTls: false,
});

Si necesitás más control, podés pasar opciones manuales:

const afip = new AfipServices({
    homo: true,
    cacheTokensPath: './tmp/tokens.json',
    tokensExpireInHours: 12,
    privateKeyPath: './private/private_key.key',
    certPath: './private/cert.pem',
    tlsRequestOptions: {
        ciphers: 'DEFAULT@SECLEVEL=1',
    },
});
Proyectos relacionados
  • SOAP de la AFIP a REST enciende un server expressjs y sirve de wrapper alrededor del SOAP para poder consumir los servicios con una interfaz REST. A partir de ese repo se armó esta lib.
Colaboradores
  • mbenedettini

评论

暂无评论