Conformidad TSE — Documentación para inspectores fiscales¶
Este documento está dirigido a inspectores fiscales, autoridades tributarias y asesores fiscales y describe la implementación técnica de la conexión TSE en el sistema de caja DiKAS conforme a los requisitos legales vigentes.
1. Fundamentos legales¶
DiKAS cumple los requisitos de las siguientes normativas:
| Normativa | Contenido |
|---|---|
| § 146a AO | Llevanza correcta de la caja, obligación de utilizar una TSE |
| KassenSichV | Reglamento de seguridad de cajas — requisitos técnicos de la TSE |
| AEAO sobre § 146a AO | Decreto de aplicación con especificaciones detalladas sobre ProcessTypes, ProcessData y código QR |
| DSFinV-K | Interfaz digital de la administración tributaria para sistemas de caja |
| GDPdU / GoBD | Principios para la llevanza y conservación correctas de libros (inspección digital de empresas) |
2. Tipos de proceso firmados (ProcessTypes)¶
DiKAS firma todos los procesos relevantes para la caja conforme a la AEAO sobre el § 146a AO, no solo los recibos de caja. Se utilizan tres ProcessTypes conforme a DSFinV-K:
2.1 Kassenbeleg-V1¶
| Propiedad | Valor |
|---|---|
| ProcessType | Kassenbeleg-V1 |
| Procesos desencadenantes | Cada pago finalizado (venta directa, pago de mesa, anulación) |
| Entities | Receipt (DocumentType: Receipt2) |
Formato de ProcessData:
Ejemplos:
Beleg^119.00_19.00:19.00 # Ein Steuersatz (19%)
Beleg^50.00_19.00:5.00_7.00:2.00 # Zwei Steuersätze (19% + 7%)
Beleg^0.00_0.00:0.00 # Nullbeleg
Todos los importes se formatean con dos decimales y un punto como separador decimal (Invariant Culture), conforme a la especificación DSFinV-K.
2.2 Bestellung-V1¶
| Propiedad | Valor |
|---|---|
| ProcessType | Bestellung-V1 |
| Procesos desencadenantes | Cada realización de pedido en el servicio de mesa |
| Entities | OpenBon (DocumentType: OpenBon) |
Formato de ProcessData:
Ejemplo:
En los pedidos agrupados (lote), la firma TSE se almacena en el primer recibo del lote. Los ProcessData contienen todas las posiciones del pedido completo.
2.3 SonstigerVorgang¶
| Propiedad | Valor |
|---|---|
| ProcessType | SonstigerVorgang |
| Procesos desencadenantes | Apertura de turno, cierre de turno, cierre de caja, gastos |
| Entities | Exchange, DayClose, Spending |
Formato de ProcessData:
Tipos de proceso concretos:
| Tipo de proceso | Descripción | Ejemplo de ProcessData |
|---|---|---|
AVSichOpen |
Apertura de turno | AVSichOpen^Schichteroeffnung^200.00 |
AVSichClose |
Cierre de turno | AVSichClose^Schichtschliessung^350.00 |
AVKassenschnitt |
Cierre de caja (informe Z) | AVKassenschnitt^Tagesabschluss^1500.00 |
AVBelegabbruch |
Proceso de anulación | AVBelegabbruch^Storno |
AVSons662 |
Gasto/retirada de efectivo | AVSonstige^Ausgabe^50.00 |
3. Campos de datos de la TSE en los documentos¶
Cada documento firmado almacena los siguientes 9 campos TSE (implementados mediante la interfaz ITseDataHolder):
| Campo | Tipo | Descripción |
|---|---|---|
TseTransactionNumber |
String | Número de transacción único de la TSE |
TseSignature |
String | Firma digital (codificada en Base64) |
TseStartTime |
DateTime | Inicio de la firma (UTC) |
TseEndTime |
DateTime | Fin de la firma (UTC) |
TseSignatureCounter |
UInt64 | Contador de firmas monótonamente creciente |
TseProcessData |
String | Datos de proceso firmados (véase el apartado 2) |
TseProcessType |
String | Identificador de ProcessType |
TseSerialNumber |
String | Número de serie de la TSE utilizada |
TseError |
String | Mensaje de error en caso de fallo de firma (null si tiene éxito) |
Estos campos se almacenan en las siguientes entidades:
- Receipt — Recibos de caja (venta, anulación, devolución)
- OpenBon — Posiciones de pedido (recibo principal en pedidos agrupados)
- Exchange — Aperturas y cierres de turno
- DayClose — Cierres de caja (informes Z)
- Spending — Gastos y retiradas de efectivo
4. Formato del código QR (DSFinV-K anexo I)¶
Cada recibo de caja contiene un código QR con los datos de la TSE en el formato estandarizado conforme a DSFinV-K anexo I:
V0;{KassenSeriennummer};{ProcessType};{ProcessData};{TransaktionsNr};{SignaturZähler};{StartZeit};{EndZeit};{SigAlgorithmus};{LogZeitformat};{Signatur};{PublicKey}
Concreto:
V0;KASSE-001;Kassenbeleg-V1;Beleg^29.30_19.00:4.68;12345;67890;2026-03-13T18:30:00.000Z;2026-03-13T18:30:01.000Z;ecdsa-plain-SHA256;unixTime;a8f3c2d1e5b7...;PK123...
| Posición | Campo | Origen |
|---|---|---|
| 1 | Versión | Siempre V0 |
| 2 | Número de serie de la caja | CashPointSerialNumber de BackendConfig |
| 3 | ProcessType | TseProcessType del comprobante |
| 4 | ProcessData | TseProcessData del comprobante |
| 5 | Número de transacción | TseTransactionNumber del comprobante |
| 6 | Contador de firmas | TseSignatureCounter del comprobante |
| 7 | Hora de inicio | TseStartTime (ISO 8601, UTC) |
| 8 | Hora de fin | TseEndTime (ISO 8601, UTC) |
| 9 | Algoritmo de firma | SigAlg de TseConfig (estándar: ecdsa-plain-SHA256) |
| 10 | Formato de hora del registro | LogTimeFormat de TseConfig (estándar: unixTime) |
| 11 | Firma | TseSignature del comprobante |
| 12 | Clave pública | PublicKey de TseConfig |
5. Identificación de la caja (ClientId)¶
La identificación de la caja sigue una cadena de respaldo de tres niveles:
| Prioridad | Origen | Descripción |
|---|---|---|
| 1 | CashPointSerialNumber |
Número de serie de la caja configurado explícitamente (licencia) |
| 2 | BonIdServer |
Identificador del servidor de recibos de BackendConfig |
| 3 | "1" |
Valor estándar de respaldo |
Esta ClientId se transmite en cada firma TSE como identificador de la caja y aparece en el código QR como número de serie de la caja.
6. Configuración de la TSE¶
La configuración de la TSE se almacena en el documento configTSE (TseConfig):
| Campo | Descripción |
|---|---|
PublicKey |
Clave pública de la TSE |
Serial |
Número de serie de la TSE |
SigAlg |
Algoritmo de firma (estándar: ecdsa-plain-SHA256) |
LogTimeFormat |
Formato de hora de los registros de la TSE (estándar: unixTime) |
LocalPath |
Ruta local a la TSE de hardware |
SetupDate |
Fecha de puesta en servicio de la TSE |
DecomissionDate |
Fecha de retirada de servicio de la TSE |
TSESerialId |
ID de serie interno |
Conexiones de TSE admitidas¶
| Tipo | Implementación | Descripción |
|---|---|---|
| Hardware (Swissbit) | SwissbitTseService |
Acceso USB directo a la TSE de Swissbit |
| Proxy (red) | TseProxyService |
TSE a través de proxy HTTP (p. ej. Fiskaltrust) |
| Router | TseServiceRouter |
Reenvío automático: se prefiere el proxy, con respaldo en el hardware |
7. Tolerancia a fallos y registro¶
Registro de fallos de la TSE (TseOutageLog)¶
Conforme a la AEAO sobre el § 146a AO, DiKAS documenta automáticamente cada fallo de la TSE:
| Campo | Descripción |
|---|---|
StartTime |
Inicio del fallo (UTC) |
EndTime |
Fin del fallo (UTC, null si todavía persiste) |
Reason |
Causa (p. ej. «TSE not available», «TSE timeout») |
AffectedTransactions |
Número de transacciones afectadas |
Proceso en caso de fallo de la TSE:
- La firma TSE falla → se establece el campo
TseErroren el documento - Se crea una nueva entrada
TseOutageLog(con StartTime y Reason) - El proceso de caja no se bloquea: la transacción se almacena sin firma
- En la siguiente firma exitosa se cierran todas las entradas de fallo abiertas (se establece EndTime)
Timeout: Cada firma TSE tiene un timeout de 5 segundos. En caso de superarse, se establece TseError = "TSE timeout".
Verificación en la inspección¶
En cada documento con TseError != null existe un fallo de firma documentado. La correspondiente entrada TseOutageLog acredita el periodo y la causa del fallo.
8. Exportación de datos para la inspección de empresas¶
8.1 Exportación DSFinV-K¶
DiKAS exporta todos los datos de caja en formato DSFinV-K (interfaz digital de la administración tributaria para sistemas de caja):
- Todos los archivos CSV prescritos conforme a la especificación DSFinV-K
- Exportación referida a un periodo posible
- Contiene: registros individuales, datos maestros, datos de la TSE, cierres de caja
8.2 Exportación TSE-TAR¶
Exportación directa de los datos de registro de la TSE como archivo TAR:
- Exportación completa: Todas las transacciones almacenadas en la TSE
- Exportación filtrada: Por periodo (startDate/endDate)
- Endpoint de la API:
GET /api/v1/tse/export/tar
8.3 Exportación GDPdU¶
Para la inspección digital de empresas conforme a GDPdU/GoBD:
- Archivo de exportación estructurado con todos los datos relevantes a efectos fiscales
- Legible por máquina para software de inspección (IDEA, AIS, etc.)
8.4 Exportación DATEV¶
Para la contabilidad corriente del asesor fiscal:
- 7 modos de exportación (cierre de caja, ProBon, ProÖffnungstag, WGR, WGR2, NachRechnung, gastos)
- Formato EXTF v13 con claves BU correctas (USt 3/2/40, VSt 9/8/40)
- Opcionalmente cifrada (ZIP AES-256) y enviable por correo electrónico
9. Proceso de firma en detalle¶
9.1 Desarrollo de una firma¶
Kassenvorgang → TseSigningHelper → ITseService → TSE (Hardware/Proxy)
│ │
│ 1. BackendConfig laden │
│ 2. Prüfen: TSE verfügbar? │
│ 3. ProcessData aufbauen │
│ 4. ClientId auflösen │
│ 5. SignReceiptAsync aufrufen ───────→│
│ 6. Ergebnis auf Entity speichern ←──│
│ 7. OutageLog aktualisieren │
└──────────────────────────────────────┘
9.2 ¿Qué manejadores firman?¶
| Handler | Proceso | ProcessType |
|---|---|---|
ProcessDirectSaleCommand |
Venta directa | Kassenbeleg-V1 |
ProcessTablePaymentCommand |
Pago de mesa | Kassenbeleg-V1 |
VoidReceiptCommand |
Anulación | Kassenbeleg-V1 |
CreateOpenBonCommand |
Pedido individual | Bestellung-V1 |
CreateOpenBonsBatchCommand |
Pedido agrupado | Bestellung-V1 |
OpenExchangeCommand |
Apertura de turno | SonstigerVorgang |
CloseExchangeCommand |
Cierre de turno | SonstigerVorgang |
PerformDayCloseCommand |
Cierre de caja | SonstigerVorgang |
CreateSpendingCommand |
Gasto/retirada de efectivo | SonstigerVorgang |
9.3 Tratamiento de errores¶
La firma TSE está implementada como no bloqueante:
- Los errores de la TSE se documentan en el campo
TseError, y el proceso se almacena igualmente - Un
try/catchen torno a todo el proceso de firma evita que los problemas de la TSE perturben el funcionamiento de la caja - El método
HandleOutageLogAsyncactualiza el registro de fallos después de cada firma (éxito o error)
10. Integridad de los registros¶
Firma sin lagunas¶
DiKAS garantiza la firma sin lagunas de todos los procesos relevantes para la caja mediante:
- Lógica de firma centralizada: Todas las firmas se realizan a través de
TseSigningHelper; no existe ninguna forma de finalizar un proceso relevante para la caja sin invocar la TSE - Contador de firmas monótono: El
TseSignatureCounterlo gestiona la TSE y crece de forma monótona. Las lagunas en el contador indican fallos que están documentados en elTseOutageLog - Números de transacción: Cada transacción de la TSE recibe un
TseTransactionNumberúnico - Marcas de tiempo: Se almacenan el momento de inicio y de fin de cada firma
Protección contra manipulación¶
- Algoritmo de firma: ECDSA con SHA-256 (ecdsa-plain-SHA256)
- El hardware de la TSE está certificado por el BSI (Common Criteria)
- La clave pública de la TSE está almacenada en la TseConfig y puede utilizarse para la verificación de la firma
- Las modificaciones posteriores en documentos firmados son detectables mediante la firma criptográfica
11. Indicaciones de inspección para inspectores fiscales¶
¿Dónde encuentra los datos de la TSE?¶
| Fuente de datos | Acceso |
|---|---|
| Campos TSE en los comprobantes | En cada documento Receipt/OpenBon/Exchange/DayClose/Spending |
| Códigos QR | En los recibos de caja impresos |
| Registro de fallos de la TSE | Documentos TseOutageLog en la base de datos |
| Configuración de la TSE | Documento configTSE |
| Exportación DSFinV-K | Admin → Configuración → Exportación → DSFinV-K |
| Exportación TSE-TAR | Admin → Configuración → TSE → Exportación |
| Exportación GDPdU | Admin → Configuración → Exportación → GDPdU |
¿Cómo comprueba las firmas?¶
- Escanear el código QR: Cada recibo contiene un código QR en formato V0 (DSFinV-K anexo I)
- Exportar TSE-TAR: El archivo TAR contiene todos los datos de registro de la TSE y puede validarse con herramientas de inspección
- Comprobar el contador de firmas: El contador monótonamente creciente no debe presentar lagunas inexplicadas
- Registro de fallos: Las lagunas en el contador de firmas deben explicarse mediante entradas TseOutageLog
- Clave pública: Se encuentra en la TseConfig y puede utilizarse para la comprobación matemática de firmas individuales
Lista de verificación para la inspección de caja¶
- El número de serie de la TSE coincide con el comunicado a Hacienda
- El contador de firmas no tiene lagunas (lagunas explicables mediante registros de fallos)
- Los ProcessTypes se corresponden con las especificaciones de la AEAO (Kassenbeleg-V1, Bestellung-V1, SonstigerVorgang)
- Los formatos de ProcessData son conformes a DSFinV-K
- El formato del código QR se corresponde con DSFinV-K anexo I (formato V0)
- Las marcas de tiempo son plausibles (inicio < fin, en orden cronológico ascendente)
- Los tiempos de fallo de la TSE están documentados y son verificables
- Todos los tipos de proceso relevantes para la caja se firman (no solo los recibos de caja)
- La exportación DSFinV-K es completa y legible por máquina
- El certificado de la TSE estaba vigente durante el periodo de inspección
12. Datos técnicos clave¶
| Propiedad | Valor |
|---|---|
| Algoritmo de firma | ECDSA con SHA-256 (ecdsa-plain-SHA256) |
| Formato del código QR | DSFinV-K anexo I, versión V0 |
| Formato de hora | ISO 8601, UTC (yyyy-MM-ddTHH |
| Formato de importes | Invariant Culture, 2 decimales (p. ej. 119.00) |
| Timeout de la TSE | 5 segundos por firma |
| TSE admitidas | Swissbit (USB), proxy de red |
| Comportamiento ante fallos | No bloqueante, registro automático |
| Base de datos | CouchDB o SQLite/SQL Server (configurable) |
| Base de la API | .NET 10, Clean Architecture, CQRS con MediatR |
| Cobertura de pruebas | 17 pruebas TSE dedicadas (firma, ProcessData, código QR, respaldo) |
Anexo: Asignación tipo de proceso → documento → base de datos¶
| Proceso de caja | ProcessType | Entity | DocumentType | Colección de base de datos |
|---|---|---|---|---|
| Venta directa (efectivo/tarjeta) | Kassenbeleg-V1 | Receipt | Receipt2 | receipt2 |
| Pago de mesa | Kassenbeleg-V1 | Receipt | Receipt2 | receipt2 |
| Anulación | Kassenbeleg-V1 | Receipt | Receipt2 | receipt2 |
| Pedido (mesa) | Bestellung-V1 | OpenBon | OpenBon | openbon |
| Pedido agrupado | Bestellung-V1 | OpenBon | OpenBon | openbon |
| Apertura de turno | SonstigerVorgang | Exchange | Exchange2 | exchange2 |
| Cierre de turno | SonstigerVorgang | Exchange | Exchange2 | exchange2 |
| Cierre de caja (informe Z) | SonstigerVorgang | DayClose | DayClose2 | dayclose2 |
| Gasto/retirada de efectivo | SonstigerVorgang | Spending | CashPointSpending | cashpointspending |