Installation et configuration de la file d'impression
Les API
L'applicationdepot-vente.fvdw.fr présente une API pour consommer les données de la file d'impression.
Les requêtes s'effectuent en GET et sont disponibles aux adresses suivantes
- https://depot-vente.fvdw.fr/SPL-PING-
code organisation - https://depot-vente.fvdw.fr/SPL-NEXT-
code organisation - https://depot-vente.fvdw.fr/SPL-GET-
numéro de document - https://depot-vente.fvdw.fr/SPL-DEL-
numéro de document
PING
Permet de tester la connexion au serveur et valider le code organisation.Cet appel retourne un flux JSON.
> curl https:/depot-vente.fvdw.fr/SPL-PING-6B024676
{'error':false,'message':'OK Démo'}
Valeurs de retour
| Clé | Type | Valeur |
|---|---|---|
| error | boolean | true|false |
| message | string | OK ou la cause de l'erreur |
NEXT
Interroge le serveur : si il existe : donne le prochain document à imprimer.Si il existe au moins un document est dans la file
> curl https:/depot-vente.fvdw.fr/SPL-NEXT-6B024676
{'pdf_b64':'JVBERi … U9GCg==','spool_slug':'285481266561','crc':2025417623,'error':false}
Si la file d'attente est vide
> curl https:/depot-vente.fvdw.fr/SPL-NEXT-6B024676
{'pdf_b64':'','spool_slug':'','crc':false,'error':false,'message':"Aucun document PDF dans la file d'attente"}
Valeurs de retour
| Clé | Type | Valeur |
|---|---|---|
| pdf_b64 | string | s'il existe : une chaine encodée en base 64 ou vide s'il n'existe pas |
| spool_slug | string | s'il existe : une série de chiffres, identifiant unique du document ou vide s'il n'existe pas |
| crc | string | s'il existe : une série de chiffres, résultat du CRC32 du pdf (non encodé) ou False s'il n'existe pas |
| error | boolean | true|false |
| message | string | Cette clé existe uniquement si une erreur se produit la cause de l'erreur |
GET
Demande un document de la file d'attente.On spécifie l'identifiant du document dans l'url
SPL-GET-xxx où xxx est le numéro
retourné lors de l'appel de SPL-NEXT, sous la clé "spool_slug". Sur base de l'exemple ci-dessus : l'url devient SPL-GET-285481266561
Le document est dans la file d'attente.
> curl https:/depot-vente.fvdw.fr/SPL-GET-285481266561
{'pdf_b64':"JVBERi0 … RU9GCg==','spool_slug':'285481266561','crc':2025417623,'error":false}
Le document n'est pas dans la file d'attente.
> curl https:/depot-vente.fvdw.fr/SPL-GET-285481266000
{'error':true,'message':'Aucun document PDF avec le code #285481266560'}
Valeurs de retour
| Clé | Type | Valeur |
|---|---|---|
| pdf_b64 | string | s'il existe : une chaine encodée en base 64 |
| spool_slug | string | s'il existe : une série de chiffres, identifiant unique du document ou vide s'il n'existe pas |
| crc | string | s'il existe : une série de chiffres, résultat du CRC32 du pdf (non encodé) ou False s'il n'existe pas |
| error | boolean | true|false |
| message | string | Cette clé existe uniquement si une erreur se produit la cause de l'erreur |
DEL
Demande l'effacement d'un document de la file d'attente.On spécifie l'identifiant du document dans l'url
SPL-GET-xxx où xxx est le numéro
retourné lors de l'appel de SPL-NEXT, sous la clé 'spool_slug'. Sur base de l'exemple ci-dessus : l'url devient
SPL-DEL-285481266561
Le document est dans la file d'attente.
> curl https:/depot-vente.fvdw.fr/SPL-DEL-285481266561
{'error':false,'message':"Document #285481266561 effac\u00e9 de la file d'attente"}
Le document n'est pas dans la file d'attente.
> curl https:/depot-vente.fvdw.fr/SPL-DEL-285481266000
{'error':false,'message':"Aucun document PDF \u00e0 effacer de la file d'attente"}
Valeurs de retour
| Clé | Type | Valeur |
|---|---|---|
| error | boolean | true|false |
| message | string | message de confirmation ou la cause de l'erreur |
Le client
Le client (installé sur le Poste 3) doit utiliser les API (service impression) pour obtenir les documents PDF à imprimer issus de la file d'attente (sur le serveur depot-vente.fvdw.fr).
Le fonctionnement préconisé est une boucle sur la méthode
SPL-NEXT-… qui attend les documents de la file d'impression.
Si des documents sont disponibles, on transforme les données encodée en base 64 pour obtenir un fichier PDF que l'on passe à
un programme chargé d'imprimer ce document.Quand le document est traité, il faut demander au serveur d'effacer ce document de la file d'attente
Exemple de client d'impression sous windows
Un script (qui tient sur un seul fichier) écrit en python interroge le serveur via les API, et utilise le programme Sumatra PDF pour imprimer le fichier PDF sur l'imprimante par défaut.Le choix de Sumatra PDF se justifie par le fait que ce programme est gratuit, léger et peut même être installé en version portable (dézippez l'archive là où vous le désirez).
Script python
# (c) depot-vente.fvdw.fr - mars 2026
#
# Script pour consommer la file d'attente des documents PDF pour impression
#
import base64
import time
import tempfile
import os
import subprocess
import json
import binascii
from urllib.request import urlopen
from urllib.error import URLError, HTTPError
# -------------------------------------------------------------------------------------
def getRemote(url):
try:
with urlopen(url, timeout=10) as response:
resp_data = json.loads(response.read())
except HTTPError as e:
return {'success' : False, 'message': f"Erreur HTTP : {e.code} - {e.reason}" }
except URLError as e:
return {'success' : False, 'message': f"Erreur URL : {e.reason}" }
except TimeoutError:
return {'success' : False, 'message': f"Erreur Timeout 10s" }
except Exception as e:
return {'success' : False, 'message': f"Une erreur inattendue est survenue : {e}"}
finally:
# print(f"Requête réussie. Code HTTP : {response.getcode()}")
# print(content[:100]) # Affiche les 100 premiers caractères
resp_data["success"] = True
return resp_data
# -------------------------------------------------------------------------------------
def print_pdf(pdf_data, sumatra_path):
# Enregistre le PDF dans un fichier temporaire
with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as f:
f.write(pdf_data)
pdf_path = f.name
# Imprime le PDF via SumatraPDF
try:
subprocess.run([sumatra_path, "-print-to-default", pdf_path], check=True)
except Exception as e:
print( f"Impression via Sumatra : Une erreur inattendue est survenue : {e}")
return False
finally:
# Supprime le fichier local temporaire après impression
os.unlink(pdf_path)
return True
# -------------------------------------------------------------------------------------
def ping(url):
ret = getRemote(url)
ret["action"] = "ping"
if not ret["success"]:
ret["error"] = True
else :
if ret["error"]:
ret["success"] = False
return ret
# -------------------------------------------------------------------------------------
def del_document(url):
"""
Demande de supression du document côté serveur (file d'attente)
"""
ret = getRemote(url)
ret["action"] = "del"
if not ret["success"]:
print("Erreur " + ret["message"])
return ret
# -------------------------------------------------------------------------------------
def next_document(url):
"""
Interroge la file d'attente : si au moins un document en attente retourne
le binaire du 1er document de la file
"""
content = getRemote(url)
content["action"] = "next"
if not content['success']:
# Erreur
content["pdf_data"] = False
return content
if not content['pdf_b64']:
# Pas de fichier en attente
content["pdf_data"] = False
return content
# ctrl CRC
pdf_data = base64.b64decode(content['pdf_b64'])
crc = binascii.crc32(pdf_data)
if crc != content["crc"] :
content["success"] = False
content["message"] = "Le flux reçu est corrompu !"
content["pdf_b64"] = "/"
content["pdf_data"] = False
return content
content["pdf_b64"] = "/"
content["pdf_data"] = pdf_data # data binaires
## print("Ctrl : local crc = %d - remote crc = %d " % (crc, content["crc"]) )
return content
# -------------------------------------------------------------------------------------
def main():
"""
Boucle sur les douments de la file d'attente
"""
ret = ping(g_ping_url)
if not ret["success"]:
print("Echec de connexion au serveur : " + ret["message"])
return
print("Appuyez sur 'Ctrl'+'Z' pour arrêter")
while True:
ret = next_document(g_next_url)
if ret["success"]:
if ret["pdf_data"]:
# document à traiter
print("Impression du document #%s..." % (ret["spool_slug"]))
if not print_pdf(ret["pdf_data"], g_sumatra_path):
print("Echec impression")
else:
print("Document imprimé")
# supression cote serveur
r = del_document(g_del_url + ret["spool_slug"])
if not r["success"]:
print("Echec mise à jour du serveur")
else:
print("Serveur mis à jour")
else:
print("Pas de document en attente ... pause (30 sec)")
# ATTENTION : ne pas utiliser une valeur inférieure à 30 (secondes) sans quoi les
# performances globales seront diminuées
time.sleep(30)
else:
print("Erreur : %s" % (ret["message"]))
# -------------------------------------------------------------------------------------
# -------------------------------------------------------------------------------------
if __name__ == "__main__":
## ICI : les variables a ajuster selon votre configuration
## Vous trouverez les url depuis le menu "administration" -> "paramètres de l'application".
## Si vous avez activé "Utiliser la file d'impression des documents PDF" = Oui, les url seront affichées
## en dessous des paramètres
g_ping_url = "https:/depot-vente.fvdw.fr/SPL-PING-6B024676"
g_next_url = "https:/depot-vente.fvdw.fr/SPL-NEXT-6B024676"
g_del_url = "https:/depot-vente.fvdw.fr/SPL-DEL-"
g_sumatra_path = r"C:\Program Files\SumatraPDF\SumatraPDF.exe"
## FIN des variables
main()