FAQ — TCC SFEC Terminal
Questions fréquentes et dépannage de l’intégration TCC SFEC Terminal (terminal Android via port COM série virtuel). Pour la connexion complète, voir Connexion série ; pour la charge utile, Envoyer une facture ; pour les codes d’erreur, Erreurs & santé ; pour comparer les modes, la FAQ générale.
Une règle sous-tend la plupart des pannes série : chaque trame est l’objet JSON suivi du marqueur ASCII littéral END_JSON — jamais un saut de ligne. Pour envoyer, écrivez <json>END_JSON. Pour recevoir, accumulez les octets jusqu’à voir END_JSON, retirez-le, puis parsez.
Langages & protocole
Quels langages puis-je utiliser pour écrire le client série ?
Tout langage avec accès aux ports COM virtuels. Ce guide donne des exemples idiomatiques en Python (pyserial), C# (System.IO.Ports + System.Text.Json) et Java (com.fazecast.jSerialComm + org.json). Le client est une simple boucle requête/réponse — ouvrir COM10, écrire <json>END_JSON, lire jusqu’à END_JSON — aucun SDK spécial requis.
Dois-je gérer des heartbeats ou une poignée de main ?
Non. Le pont gère la liaison avec le terminal pour vous. Un client série n’a besoin d’aucune boucle de heartbeat, d’aucune poignée de main, d’aucun démultiplexage — c’est un échange requête/réponse propre.
Que signifie le champ protocol dans les réponses ?
C’est un champ interne présent dans chaque réponse ; il n’a aucune signification pour votre intégration — ignorez-le.
Puis-je vérifier la santé du lien sans certifier de facture ?
Oui. Écrivez {"type":"ping","source":"erp","timestamp":"..."}END_JSON ; le pont répond {"type":"pong","source":"middleware","timestamp":"..."}END_JSON. Le pont n’envoie jamais de ping non sollicité, donc ce ping→pong initié par votre logiciel est une sonde de liveness sûre.
Charge utile & enums
Quelles chaînes d’enum exactes dois-je envoyer ?
invoiceType = salesInvoice | creditNote ; recipientType = individual | business | government | foreign ; paymentMethod = cash | bank_transfer | mobile_money | cheque | card ; items[].type = product | service ; items[].discountType = fixed | percentage. Elles sont sensibles à la casse et au style — une mauvaise chaîne renvoie INVALID_PAYLOAD.
Quelles devises sont acceptées ?
Exactement XAF, USD, EUR. Toute autre → VALIDATION_ERROR sur currency.
Quelle est la règle de l’invoiceId ?
Requis, au plus 23 caractères, et clé de déduplication. Le réutiliser renvoie DUPLICATE_INVOICE. Aucune autre contrainte de format n’est imposée — vous choisissez le schéma.
qr_code est-il le texte du QR ou une image ?
C’est une image PNG encodée en Base64 (sans saut de ligne), pas le texte brut du QR. Décodez le champ qr_code de la réponse de succès en octets pour afficher ou imprimer le PNG directement.
Dépannage
Le pont se ferme au démarrage en réclamant des privilèges administrateur
Il n’a pas été lancé avec élévation ; le pont nécessite des droits administrateur. Clic droit sur l’exécutable → Exécuter en tant qu’administrateur, puis relancer.
COM10 non créé / port occupé
Si le pont ne parvient pas à mettre COM10 à disposition : soit COM10 est encore détenu par un autre processus (fermez l’ERP résiduel, un terminal série, ou un ancien pont mal arrêté), soit le pont n’est pas lancé en Administrateur. Si c’est votre client qui ne peut pas ouvrir COM10 (port not found / access denied) : démarrez le pont en Administrateur d’abord, ou COM10 est déjà ouvert par une autre application (deux clients ne peuvent pas le partager).
J’envoie une facture mais la lecture n’aboutit jamais / expire
Sur série, ce n’est presque jamais l’encadrement vers le terminal — le pont s’en charge — mais que le pont ne s’est jamais attaché au terminal, ou que votre lecture a abandonné trop tôt :
- Le terminal est-il allumé, connecté et l’application en cours d’exécution ? Ordre de démarrage : le terminal d’abord, puis le pont.
- Le terminal est-il bien relié au poste hôte ? Si le pont ne parvient pas à joindre le terminal, vérifiez le branchement et la mise en service du terminal, puis relancez le pont. En cas de doute, contactez le support.
- Confirmez la connexion dans la console du pont. Un pont sain affiche une confirmation de connexion au terminal. Si vous ne la voyez jamais, la faute est aux causes 1–2, pas à votre code série.
- Votre read timeout est-il assez long ? Le terminal a un budget de 30 s par facture. Mettez votre délai de lecture à ≥ 35 s.
INVALID_PAYLOAD
Trois causes concrètes sur série : (a) JSON malformé ; (b) chaîne d’enum inconnue (utilisez uniquement les chaînes exactes documentées) ; (c) \n utilisé au lieu de END_JSON — la cause série la plus fréquente. Sérialisez compact (une seule ligne, sans saut de ligne intégré) et ajoutez END_JSON.
VALIDATION_ERROR
Le JSON a été parsé mais a échoué à la validation métier. La réponse porte un tableau errors[], une entrée par échec avec un field et un message. Deux causes : champs destinataire manquants selon recipientType, ou incohérence des montants (anti-fraude, tolérance ±0.01). Corrigez chaque field signalé — voir Erreurs & santé.
DUPLICATE_INVOICE
Retourné quand une facture au même invoiceId est déjà certifiée (la clé de déduplication est invoiceId). Traitez-le comme de l’idempotence, pas un échec dur : affichez la certification déjà stockée plutôt que d’allouer un nouveau numéro, et utilisez un invoiceId neuf pour une facture réellement nouvelle. Ne mutez jamais la charge utile en réutilisant le même id.
PROCESSING_TIMEOUT / terminal lent
Le terminal a un budget de 30 s par facture ; le dépasser donne PROCESSING_TIMEOUT. Si vous n’obtenez rien du tout, la faute est souvent côté client : read timeout trop bas (mettez-le à ≥ 35 s) ou terminal réellement occupé/lent. Si la certification a légitimement expiré, retentez avec le même invoiceId (idempotent).
MESSAGE_TOO_LARGE
La trame de requête a dépassé 1 Mo. Réduisez la charge utile ; cause fréquente : un logoImg Base64 volumineux.
Réponses tronquées ou collées ensemble
Vous lisez un segment de taille fixe au lieu d’accumuler jusqu’à END_JSON. Une seule lecture série peut renvoyer une trame partielle, ou deux trames collées, car la réponse de succès embarque un PNG QR Base64 de plusieurs Ko. Bufferisez les octets, découpez sur END_JSON, retirez-le, puis parsez.
Glossaire
- SFEC : le système de facturation électronique certifiée de la DGID ; aussi le préfixe du numéro fiscal.
- TCC : l’application / le terminal de certification Android que vous intégrez (l’Android SFEC App).
- DGID : l’administration fiscale (couramment Direction Générale des Impôts et des Domaines).
- NIU : numéro d’identification du contribuable, validé comme exactement 16 ou 17 caractères.
sfec_number: numéro de certification fiscale renvoyé au succès, formatSFEC-<yyyyMM>-<séquence 8 chiffres>-<CRC 4 chiffres>; opaque, la séquence se réinitialise au redémarrage du terminal.END_JSON: le marqueur ASCII littéral qui termine chaque trame série dans les deux sens.