Accueil
Driver v1.1 — cloud

Introduction

Le Driver MCF (Machine de Certification Fiscale) est un service local qui s'exécute sur le poste de travail et assure la communication entre votre logiciel de facturation et le terminal MCF Eltrade CC300. Il fonctionne en deux modes : mode local (API REST sur http://127.0.0.1:38917) et mode cloud (client WebSocket sortant vers le serveur SFE, pour les contextes SaaS multi-tenant où les opérateurs travaillent sur mobile ou tablette).

Sécurisé

JWT RS256 + HMAC-SHA256 pour l'intégrité des données

Léger

Binaire Rust autonome, aucune dépendance à installer

Multi-OS

Windows, macOS (Intel + Apple Silicon) et Linux

Architecture

Le système se compose de trois briques qui communiquent entre elles :

SFE (Logiciel)
Driver MCF
Terminal MCF (USB)

Mode local : le SFE appelle le driver en HTTP. Mode cloud : le driver se connecte au cloud SFE via WebSocket et reçoit les factures à certifier.

Installation du Driver

Téléchargez le binaire correspondant à votre système d'exploitation depuis la page de téléchargements.

WindowsInstallation Windows

  1. Téléchargez e-mecef-driver-x86_64-pc-windows-gnu.exe
  2. Placez le fichier dans un répertoire de votre choix (ex : C:\eltrade\)
  3. Créez un fichier .env dans le même répertoire (voir Configuration)
  4. Lancez l'exécutable en tant qu'administrateur ou configurez-le comme service Windows
  5. Vérifiez le démarrage : ouvrez http://127.0.0.1:38917/health dans le navigateur

Capture d'écran à venir

Installeur Windows — fenêtre d'installation du Driver MCF

macOSInstallation macOS

  1. Téléchargez le binaire correspondant à votre architecture (Apple Silicon ou Intel)
  2. Rendez-le exécutable :
chmod +x e-mecef-driver-aarch64-apple-darwin
  1. Créez le fichier de configuration (voir Configuration)
  2. Au premier lancement, macOS peut demander une autorisation de sécurité (Préférences Système → Sécurité)
  3. Vérifiez le démarrage : curl http://127.0.0.1:38917/health

Capture d'écran à venir

macOS — autorisation de sécurité et lancement du Driver

LinuxInstallation Linux

# Téléchargement et installation
chmod +x e-mecef-driver-x86_64-unknown-linux-gnu
sudo mv e-mecef-driver-x86_64-unknown-linux-gnu /usr/local/bin/e-mecef-driver

# Création du répertoire de configuration
mkdir -p ~/.config/mcf-driver
cp .env.example ~/.config/mcf-driver/.env

# Lancement
e-mecef-driver

Pour un démarrage automatique, créez un service systemd (voir la documentation avancée).

Configuration

La configuration du driver se fait via un fichier .env. Créez ce fichier à côté du binaire (ou dans le répertoire de configuration de la plateforme).

# Exemple de fichier .env
DEVICE_PORT=
DEVICE_VID=03EB
DEVICE_PID=6119
DEVICE_BAUD=115200

DRIVER_PORT=38917
DRIVER_HOST=127.0.0.1

LICENSE_SERVER_URL=https://votre-serveur-licence.com
LICENSE_FILE=./license.json
VariableDéfautDescription
DEVICE_PORT(auto)Port série du MCF. Vide = détection automatique par VID:PID.
DEVICE_VID03EBVendor ID USB du MCF Eltrade.
DEVICE_PID6119Product ID USB du MCF Eltrade.
DEVICE_BAUD115200Vitesse de communication (bauds).
DRIVER_PORT38917Port HTTP du serveur local du driver.
DRIVER_HOST127.0.0.1Adresse d'écoute (ne pas modifier en prod).
DRIVER_CORS_ORIGINS(vide = Any)Origines CORS autorisées, séparées par virgules.
LICENSE_SERVER_URLhttps://e-mecef.codarno.comURL du serveur de licence E-MeCeF.
LICENSE_FILE./license.jsonChemin vers le fichier de licence local.
MCF_MOCKfalsetrue = simulateur MCF interne (pas de matériel requis) + vérification de licence désactivée. Réservé au développement — les factures générées ne sont pas fiscalement valides.
DRIVER_MODElocalMode de fonctionnement : local (API HTTP 127.0.0.1 uniquement) ou cloud (client WebSocket sortant vers le serveur SFE).
DRIVER_WSS_URL(vide)URL WSS du serveur SFE. Ex : wss://app.sfe.com/mcf/ws. Requis si DRIVER_MODE=cloud.
DRIVER_API_KEY(vide)Clé d'API de l'organisation (= clé de licence) pour s'authentifier auprès du serveur SFE. Requis si DRIVER_MODE=cloud.

Détection automatique du port série

Si DEVICE_PORT est vide, le driver recherche automatiquement le MCF par son identifiant USB (VID:PID). La route GET /ports retourne la liste des ports disponibles pour faciliter le diagnostic.

Interface GUI — écran de configuration du port série
Interface GUI — écran de configuration du port série

Activation de la licence

Pour émettre des factures certifiées, le driver doit être activé avec une clé de licence valide. L'activation lie la licence à la machine (via son NIM — Numéro d'Identification de la Machine).

Procédure d'activation

1

Obtenez une clé de licence

Achetez une licence depuis votre espace client E-MeCeF et récupérez la clé au format XXXXX-XXXXX-XXXXX-XXXXX.

2

Démarrez le driver

Assurez-vous que le driver est en cours d'exécution et accessible sur http://127.0.0.1:38917.

3

Activez via l'interface GUI

Ouvrez la GUI, allez dans Paramètres → Licence, entrez votre clé et cliquez sur Activer.

4

Vérification

L'activation est confirmée par un message de succès. La licence est sauvegardée localement dans license.json.

Interface GUI — fenêtre d'activation de la licence
Interface GUI — fenêtre d'activation de la licence

Activation via l'API

Vous pouvez également activer la licence directement via l'API REST :

POST http://127.0.0.1:38917/license/activate
Content-Type: application/json

{
  "key": "ABCDE-FGHIJ-KLMNO-PQRST",
  "nim": "NIM-de-la-machine"
}

Interface graphique (GUI)

La GUI est une application de bureau native qui pilote le driver local. Elle comporte trois onglets : Tableau de bord, Paramètres et Service.

Tableau de bord

L'onglet principal affiche l'état en temps réel du système sous forme de trois cartes :

  • Driver — état En cours / Arrêté et numéro de version.
  • Appareil MCF — Connecté, Non connecté, ou Mode mock (simulé) si MCF_MOCK=true.
  • Licence — validité, plan, NIM, quota de factures (émises / max / restantes) et date d'expiration.

Les boutons Démarrer, Arrêter et Actualiser permettent de contrôler le processus driver. Lorsque la licence est absente ou invalide, un formulaire d'activation apparaît directement dans le tableau de bord (champs clé de licence et NIM).

GUI — tableau de bord avec statut driver, MCF et licence
GUI — tableau de bord avec statut driver, MCF et licence

Paramètres

L'onglet Paramètres permet de configurer tous les aspects du driver :

  • Chemin vers le binaire driver (avec sélecteur de fichier).
  • Port série MCF (ex. COM3 ou /dev/ttyUSB0), VID, PID et vitesse de communication (baudrate).
  • Adresse et port HTTP du serveur local (hôte + port).
  • URL du serveur de licence et chemin vers le fichier license.json.
  • Mode mock MCF — case à cocher pour activer le simulateur sans matériel.
  • Mode cloud (WebSocket) — sélecteur Local / Cloud, URL WSS et clé API (voir section dédiée ci-dessous).

Après enregistrement, si le driver est en cours d'exécution, il redémarre automatiquement pour appliquer la nouvelle configuration.

GUI — écran des paramètres et configuration
GUI — écran des paramètres et configuration

Gestion du service système

L'onglet Service permet d'installer le driver comme service système (démarrage automatique au boot), sans avoir à le lancer manuellement. Le gestionnaire utilisé dépend de la plateforme :

  • macOS — LaunchAgent launchd (plist utilisateur).
  • Linux — service utilisateur systemd.
  • Windows — entrée HKCU\Run dans le registre.

Les actions disponibles sont : Installer, Désinstaller, Démarrer et Arrêter le service, selon son état courant.

GUI — onglet Service avec gestion launchd/systemd
GUI — onglet Service avec gestion launchd/systemd

Mode cloud (WebSocket)

Par défaut, le driver expose une API REST sur http://127.0.0.1:38917 (mode local). En activant le mode cloud, il initie lui-même une connexion WebSocket permanente vers le serveur SFE. Cette connexion est sortante — aucun port à ouvrir, fonctionne derrière n'importe quel NAT ou firewall.

DRIVER_MODE=local

Mode LOCAL (défaut)

API REST sur 127.0.0.1:38917 — le SFE appelle le driver directement depuis le même réseau local.

DRIVER_MODE=cloud

Mode CLOUD (nouveau)

Le driver se connecte au serveur SFE via WebSocket. Les factures sont poussées depuis le cloud et traitées localement.

Pourquoi le mode cloud ?

En mode cloud, les opérateurs peuvent être sur mobile, tablette ou un browser distant — ils ne peuvent jamais atteindre 127.0.0.1 d'un autre réseau. Le mode cloud résout ce problème : le driver établit lui-même la connexion vers le serveur SFE, qui peut ensuite pousser des factures à certifier depuis n'importe quel appareil connecté à Internet.

Flux de certification

1

Mobile / Browser

L'opérateur valide une facture dans l'interface SFE.

2

Cloud SFE

Le serveur stocke le payload MCF pré-calculé et pousse un message BILL vers le driver via WebSocket.

3

Driver MCF (local)

Le driver reçoit le message, appelle le terminal MCF via le port série et obtient le QR code + numéro DGI.

4

Cloud SFE

Le driver répond BILL_RESULT (status: success) avec le QR code. Le serveur met à jour la facture et notifie le client.

5

Mobile / Browser

L'opérateur voit la facture certifiée (QR code affiché), 1 à 3 secondes après validation.

Configuration

Activez le mode cloud dans le fichier .env :

DRIVER_MODE=cloud
DRIVER_WSS_URL=wss://app.sfe.com/mcf/ws
DRIVER_API_KEY=sk_org_xxxxxxxxxxxx   # clé API fournie par l'admin SFE

Ou via la GUI → Paramètres → Mode cloud (WebSocket) : sélecteur Local / Cloud, champs URL WSS et Clé API.

Authentification

La clé API (DRIVER_API_KEY) est transmise lors de la poignée de main WebSocket (handshake HTTP/1.1 Upgrade), dans l'en-tête standard Authorization :

GET /mcf/ws HTTP/1.1
Host: app.sfe.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: <clé générée automatiquement>
Sec-WebSocket-Version: 13
Authorization: Bearer sk_org_xxxxxxxxxxxx

Le serveur SFE doit vérifier cet en-tête avant d'accepter l'upgrade (répondre 401 Unauthorized si absent ou invalide). Une fois la connexion établie, aucun header supplémentaire n'est nécessaire — les messages JSON circulent librement sur le canal ouvert.

Reconnexion automatique

En cas de déconnexion, le driver se reconnecte automatiquement avec un exponential backoff (1 s → 2 s → 4 s → … → 60 s). Les factures reçues pendant la déconnexion restent en statut PENDING_MCF côté cloud et sont traitées dès que le driver se reconnecte.

Protocole de messages

Le WebSocket expose exactement les mêmes opérations que l'API HTTP. Tous les messages suivent le format uniforme { type, status, data|error }.

Message entrant (Cloud → Driver)Équivalent HTTPRéponse (type)
BILLPOST /billBILL_RESULT
CHECKGET /checkCHECK_RESULT
INFOGET /infoINFO_RESULT
PORTSGET /portsPORTS_RESULT
LICENSE_STATUSGET /license/statusLICENSE_STATUS_RESULT
LICENSE_ACTIVATEPOST /license/activateLICENSE_ACTIVATE_RESULT
LICENSE_RENEWPOST /license/renewLICENSE_RENEW_RESULT

Serveur → Driver (facture)

{ "type": "BILL", "invoiceId": "uuid", "payload": { ...BillInput... } }
{ "type": "PONG" }

Driver → Serveur (succès)

{
  "type": "BILL_RESULT",
  "invoiceId": "uuid",
  "status": "success",
  "data": {
    "qr_code": "BFSECEF01;...",
    "security_code": "MOCKSIG000001",
    "nim": "XX01000001-1",
    "ifu": "0000000000001",
    "invoice_number": "SFEMOCK001/1",
    "datetime": "20260512210432",
    "bill_counter": "1",
    "total_counter": "1",
    "bill_type": "FV",
    "mcf_reference": "XX01000001-1-1"
  }
}

Driver → Serveur (erreur)

{ "type": "BILL_RESULT", "invoiceId": "uuid", "status": "error", "error": "Licence invalide" }

{ "type": "PING" }   // heartbeat toutes les 30 s

Le driver envoie un PING JSON toutes les 30 s. Le serveur doit répondre PONG. Si la connexion est perdue, le driver se reconnecte automatiquement (exponential backoff).

Référence API

Le driver expose une API REST sur http://127.0.0.1:38917. Les routes protégées nécessitent une licence valide.

MéthodeRouteAuth.Description
GET/healthNonStatut du driver, version, infos licence et device.
GET/checkNonTeste la connexion avec le MCF (port série).
GET/portsNonListe les ports série disponibles sur le système.
POST/license/activateNonActive une licence avec clé + NIM de la machine.
POST/license/renewNonRenouvelle le token JWT de la licence active.
GET/license/statusNonRetourne le statut de la licence courante.
GET/infoOui¹Informations du device MCF et contribuable.
POST/billOui¹Crée et certifie une facture sur le MCF.

¹ En mode MCF_MOCK=true, la vérification de licence est désactivée pour toutes les routes protégées.

Exemple : créer une facture

Requête minimale avec un article et un paiement en espèces :

POST http://127.0.0.1:38917/bill
Content-Type: application/json

{
  "isf": "SFE-2026-000042",
  "invoice_number": "FAC-2026-000042",
  "client_type": "PM",
  "client_ifu": "1234567890123",
  "client_name": "Entreprise ACME SARL",
  "price_mode": "TTC",
  "vt": "FV",
  "products": [
    {
      "label": "Prestation de service informatique",
      "tax": "B",
      "price": 150000,
      "quantity": 1,
      "itype": "LOCSER"
    }
  ],
  "payments": [
    {
      "mode": "V",
      "amount": 150000
    }
  ]
}

Réponse en cas de succès :

HTTP/1.1 200 OK

{
  "qr_code": "BFSECEF01;XX01000001-1;MOCKSIG000001;0000000000001;20260511143000",
  "security_code": "MOCKSIG000001",
  "nim": "XX01000001-1",
  "ifu": "0000000000001",
  "invoice_number": "SFE-2026-000042",
  "datetime": "20260511143000",
  "bill_counter": "1",
  "total_counter": "1",
  "bill_type": "FV",
  "mcf_reference": "XX01000001-1-1"
}

Exemple : créer une facture d'avoir

Pour émettre un avoir sur une facture déjà certifiée, utilisez la valeur mcf_reference retournée par le POST /bill original comme champ rn. Le format attendu est {NIM}-{TC} (ex : AB01000001-1-50). Ne pas utiliser invoice_number — le MCF stocke sa propre référence interne et rejettera tout autre valeur.

POST http://127.0.0.1:38917/bill
Content-Type: application/json

{
  "isf": "SFE-2026-000043",
  "invoice_number": "AV-2026-000001",
  "rt": "FA",
  "receipt_nature": "RAN",
  "rn": "XX01000001-1-1",
  "price_mode": "TTC",
  "products": [
    {
      "label": "Prestation de service informatique",
      "tax": "B",
      "price": 150000,
      "quantity": 1,
      "itype": "LOCSER"
    }
  ],
  "payments": [
    {
      "mode": "E",
      "amount": 150000
    }
  ]
}

Modèles

BillInput — Corps de la requête POST /bill

ChampTypeRequisDescription
isfstringOuiIdentifiant Système de Facturation (ISF) — référence interne unique de la facture dans le SFE.
invoice_numberstringOuiNuméro de facture interne (affiché sur le ticket).
productsProductInput[]OuiListe des articles de la facture (minimum 1).
paymentsPaymentInput[]OuiListe des paiements (minimum 1).
operator_idstringNonIdentifiant de l'opérateur/caissier (OPID). Défaut : "1".
operator_namestringNonNom de l'opérateur/caissier (OPNOM). Défaut : "Caisse".
client_type"CC"|"PM"|"PP"|"PC"NonType de client. CC = Client comptant (défaut), PM = Personne morale, PP = Personne physique, PC = Personne physique commerçant.
client_ifustringNonIFU du client (obligatoire si client_type = PM ou PP).
client_namestringNonNom ou raison sociale du client.
client_addressstringNonAdresse du client.
client_phonestringNonNuméro de téléphone du client.
client_emailstringNonAdresse e-mail du client.
client_rccmstringNonNuméro RCCM (Registre du Commerce) du client.
price_mode"TTC"|"HT"NonMode de saisie des prix. TTC = toutes taxes comprises (défaut), HT = hors taxes.
vt"FV"|"FT"|"EV"|"ET"NonType de facture vente. FV = Facture de vente (défaut), FT = Facture d'acompte, EV = Facture de vente à l'exportation, ET = Facture d'acompte à l'exportation.
rt"FA"|"EA"NonType de facture d'avoir. FA = Facture d'avoir, EA = Facture d'avoir à l'exportation. Nécessite rn et receipt_nature.
rnstringNonRéférence MCF de la facture d'origine (obligatoire si rt est défini). Doit être la valeur mcf_reference retournée par le POST /bill de la facture originale. Format : {NIM}-{TC} (ex : "AB01000001-1-50"). Ne pas utiliser invoice_number — le MCF ne le reconnaîtra pas.
receipt_nature"COR"|"RAN"|"RAM"|"RRR"NonNature de la facture d'avoir (obligatoire si rt défini). COR = Correction, RAN = Annulation, RAM = Avoir suite reprise de biens/services, RRR = Remise, ristourne, rabais.
psvbstringNonGroupe PSVB (Prélèvement Sécurité Ventes Boissons) applicable : A | B | C | D. Vide ou absent = aucun précompte PSVB. Non applicable aux factures d'avoir.
supplementary_infoAdditionalInfoEntry[]NonInformations supplémentaires libres (commentaires, régime fiscal, compte bancaire…) envoyées via la commande 36h.

BillResponse — Réponse de POST /bill

ChampTypeRequisDescription
qr_codestringOuiCode QR à imprimer sur la facture certifiée. Format : BFSECEF01;{NIM};{SIG};{IFU};{DT}.
security_codestringOuiCode SECeF/DGI (SIG) — élément de sécurité à imprimer sur la facture.
nimstringOuiNuméro d'Identification de la Machine (NIM) au format NIM-ACNT.
ifustringOuiIdentifiant Fiscal Unique du contribuable.
invoice_numberstringOuiNuméro de facture SFE confirmé par le MCF.
datetimestringOuiDate et heure de certification au format AAAAMMJJHHmmss.
bill_counterstringOuiFC — compteur par type de facture.
total_counterstringOuiTC — compteur total de factures (utilisé dans mcf_reference).
bill_typestringOuiType de facture certifiée (FV, FA, EV…).
mcf_referencestringOuiRéférence MCF de cette facture, à conserver et passer comme champ rn pour tout avoir ultérieur. Format : {NIM}-{TC} (ex : "AB01000001-1-50").

ProductInput — Article de facture

ChampTypeRequisDescription
labelstringOuiDésignation de l'article (1–64 caractères).
tax"A".."P"OuiGroupe de taxe MCF (16 groupes A à P selon la configuration du terminal).
pricenumberOuiPrix unitaire (TTC ou HT selon price_mode), doit être positif.
quantitynumberNonQuantité (défaut : 1).
itype"LOCBIE"|"LOCSER"|"IMPBIE"|"IMPSER"NonType d'article. LOCBIE = Bien local, LOCSER = Service local, IMPBIE = Bien importé, IMPSER = Service importé.
internal_codestringNonCode interne / référence article (max 24 caractères).
specific_tax_ratestringNonTaux de taxe spécifique (ex. "0.05" pour 5 %). À fournir avec specific_tax_total.
specific_tax_totalnumberNonMontant total de la taxe spécifique calculé pour cette ligne.
specific_tax_descstringNonLibellé de la taxe spécifique.
original_pricenumberNonPrix d'origine avant remise ou modification.
price_change_explanationstringNonMotif du changement de prix.

PaymentInput — Paiement

ChampTypeRequisDescription
mode"V"|"C"|"M"|"D"|"E"|"A"OuiMode : V = Virement, C = Carte bancaire, M = Mobile Money, D = Chèque, E = Espèces, A = Autre.
amountnumberOuiMontant du paiement, doit être positif.

AdditionalInfoEntry — Champ d'information supplémentaire (36h)

ChampTypeRequisDescription
lidstringOuiIdentifiant du champ. A..H = Lignes de commentaire A–H, REGIMP = Régime d'imposition, COMBAN = Comptes bancaires, SERIMP = Centre d'impôts.
contentstringNonContenu du champ (texte libre, optionnel selon le LID).

FAQ & Dépannage

Besoin d'aide supplémentaire ?

Contactez notre support ou consultez votre espace client.