Skip to Content
TCC SFEC TerminalLire la réponse

Lire la réponse

Quand vous envoyez une facture valide sur le port COM virtuel, le terminal la certifie, la persiste, et le pont relaie une trame de réponse JSON encadrée en END_JSON. Lisez les octets jusqu’à voir le marqueur END_JSON, retirez-le, puis parsez le JSON qui précède. Cette page décrit uniquement la réponse de succès ; les réponses d’erreur sont couvertes dans Erreurs & santé.

Le pont ne vous transmet que les résultats success / error et gère la liaison avec le terminal pour vous. Lire une certification est donc un échange requête/réponse propre — pas de poignée de main, pas de boucle de heartbeat, pas de démultiplexage.

Forme de la réponse de succès

La charge utile de succès est un objet JSON plat avec status = "success". Sur le fil, elle arrive exactement ainsi — notez le END_JSON final sans saut de ligne :

{"status":"success","invoice_id":"INV-2026-0001","sfec_number":"SFEC-202607-00000001-1234","qr_code":"iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAIAAAB7...<PNG Base64 tronqué>...SuQmCC","certification_date":1782864000000,"message":"Invoice certified successfully","protocol":"TCP"}END_JSON

Indentée pour la lisibilité (les champs sont émis dans cet ordre) :

{ "status": "success", "invoice_id": "INV-2026-0001", "sfec_number": "SFEC-202607-00000001-1234", "qr_code": "iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAIAAAB7...<PNG Base64 tronqué>...SuQmCC", "certification_date": 1782864000000, "message": "Invoice certified successfully", "protocol": "TCP" }

Référence champ par champ

ChampTypeObligatoireDescription
statusstringOuiDiscriminant. "success" signifie que la facture a été acceptée et persistée. Toute autre valeur (ex. "error") n’est pas un succès.
invoice_idstringOuiRenvoie le invoiceId que vous avez envoyé. Sert à corréler la réponse à votre requête. Lisez toujours l’identifiant depuis la clé invoice_id — jamais invoice_number.
sfec_numberstringOuiLe numéro de certification fiscale attribué par le terminal. C’est la valeur à stocker et imprimer sur la facture. Format décrit ci-dessous.
qr_codestringOuiUne image PNG encodée en Base64 du QR code fiscal, prête à afficher/imprimer. Ce n’est PAS le texte du QR. Décodage ci-dessous.
certification_datenumber (int64)OuiTemps epoch en millisecondes (UTC) de la certification.
messagestringOuiMessage fixe lisible. Ne branchez pas dessus ; branchez sur status.
protocolstringOuiChamp interne apposé sur chaque trame, sans signification pour votre intégration — ignorez-le.

Il n’y a aucun autre champ dans la réponse de succès. En particulier, aucun élément de signature n’est renvoyé sur le fil — la signature est intégrée au QR et conservée par le terminal.

⚠️

Gestion des valeurs nulles. Le sérialiseur du terminal n’émet pas les clés à valeur nulle — un champ nul est entièrement omis plutôt qu’envoyé comme null. Une trame où status == "success" mais où sfec_number ou qr_code est absent n’est pas utilisable pour l’impression fiscale. Règle défensive : exigez status == "success" et un sfec_number non vide et un qr_code non vide avant de considérer la facture comme certifiée.

sfec_number — le numéro de certification fiscale

sfec_number a le format :

SFEC-<yyyyMM>-<sequence>-<crc>
SegmentProductionNotes
SFECpréfixe littéralconstant
<yyyyMM>année+mois dans le fuseau Africa/Brazzavilleex. 202607 pour juillet 2026
<sequence>compteur incrémental, complété à 8 chiffresex. 00000001
<crc>4 chiffres de contrôleex. 1234

Exemple : SFEC-202607-00000001-1234.

⚠️

Traitez sfec_number comme un identifiant opaque — stockez-le et imprimez-le tel quel. Ne le parsez pas et ne le régénérez pas. Le segment <sequence> est un compteur en mémoire qui se réinitialise à 00000001 à chaque redémarrage du terminal ; il n’est donc ni globalement unique ni monotone dans le temps. Ne fondez jamais de logique métier dessus — appuyez-vous sur le sfec_number complet associé à votre propre invoiceId.

qr_code — un PNG Base64, pas du texte QR

Le qr_code est une image PNG du QR code fiscal, encodée en Base64 sans saut de ligne.

La chaîne reçue est donc base64(png_bytes) sans saut de ligne, alphabet Base64 standard, remplissage (padding) présent, et sans préfixe data: — juste le Base64 brut du PNG. Pour l’utiliser, décodez-le en octets et passez-les à n’importe quel moteur de rendu/imprimante comme un PNG. Ne tentez pas de le lire comme du texte QR — c’est une image, pas le contenu encodé.

Décodage du QR (exemples)

Python (pyserial) :

import base64 import json import serial # pip install pyserial DELIM = b"END_JSON" ser = serial.Serial( port="COM10", baudrate=115200, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, timeout=35, # secondes ; doit dépasser le temps de certification du terminal ) raw = ser.read_until(DELIM) # bloque jusqu'à END_JSON ou timeout if not raw.endswith(DELIM): raise TimeoutError("serial read timed out before END_JSON") resp = json.loads(raw[:-len(DELIM)].decode("utf-8")) invoice_id = resp["invoice_id"] # renvoie votre invoiceId sfec_number = resp["sfec_number"] # ex. "SFEC-202607-00000001-1234" certification_date = resp["certification_date"] # epoch ms, ex. 1782864000000 png_bytes = base64.b64decode(resp["qr_code"]) # sans préfixe "data:", sans saut de ligne with open(f"{sfec_number}.png", "wb") as f: f.write(png_bytes)

C# (System.IO.Ports + System.Text.Json) :

string json = port.ReadTo("END_JSON"); // renvoie le texte avant le marqueur using JsonDocument doc = JsonDocument.Parse(json); JsonElement root = doc.RootElement; string invoiceId = root.GetProperty("invoice_id").GetString(); string sfecNumber = root.GetProperty("sfec_number").GetString(); long certificationDate = root.GetProperty("certification_date").GetInt64(); // epoch ms byte[] pngBytes = Convert.FromBase64String(root.GetProperty("qr_code").GetString()); File.WriteAllBytes(sfecNumber + ".png", pngBytes);

Java (jSerialComm + org.json) :

JSONObject resp = new JSONObject(readFrame(port)); // le helper retire END_JSON String invoiceId = resp.getString("invoice_id"); String sfecNumber = resp.getString("sfec_number"); long certificationDate = resp.getLong("certification_date"); // epoch ms byte[] pngBytes = Base64.getDecoder().decode(resp.getString("qr_code")); Files.write(Paths.get(sfecNumber + ".png"), pngBytes);

certification_date — epoch en millisecondes

certification_date est un temps Unix epoch en millisecondes (UTC). Divisez par 1000 pour des secondes. Pour l’affichage, les horodatages fiscaux du terminal utilisent le fuseau Africa/Brazzaville (UTC+1) ; présentez-le dans ce fuseau pour rester cohérent avec le terminal.

from datetime import datetime, timezone, timedelta ms = resp["certification_date"] # ex. 1782864000000 dt = datetime.fromtimestamp(ms / 1000, tz=timezone(timedelta(hours=1))) # Africa/Brazzaville = UTC+1 print(dt.isoformat())

Corréler une réponse à sa requête

invoice_id dans la réponse est la même chaîne que le invoiceId envoyé. Utilisez-le pour associer une réponse à sa requête :

requête : {"invoiceId":"INV-2026-0001", ...}END_JSON réponse : {"status":"success","invoice_id":"INV-2026-0001", ...}END_JSON // même valeur

Comme le pont ne transmet que les trames success / error, la prochaine trame END_JSON lue après l’envoi d’une facture est son résultat de certification. invoiceId est unique — renvoyer le même invoiceId produit une erreur DUPLICATE_INVOICE, pas un second succès.

Ce que le QR / la signature attestent. La facture est signée de façon sécurisée par le terminal. Vous recevez le QR comme PNG prêt à imprimer et vous stockez/imprimez sfec_number (et certification_date) ; les éléments de signature ne sont pas renvoyés dans la réponse — ils sont intégrés dans le QR et conservés par le terminal.


Étape suivante → Erreurs & santé de connexion