@mostajs/paiement-tpe
v0.5.0
Published
Terminaux de paiement électronique : un PORT commun (demander / annuler / état / sonder) et des DIALECTES qui déclarent leurs capacités (autonome, protocole CAISSE-CONCERT, nexo/ISO 20022, lecteur PSP, SoftPOS, SATIM). Paiement EN PRÉSENCE, appareil local
Maintainers
Readme
@mostajs/paiement-tpe
Le port commun des Terminaux de Paiement Électronique, et des dialectes qui déclarent ce que chaque famille de terminal sait faire.
Auteur : Dr Hamid MADANI [email protected] · Licence : AGPL-3.0-or-later · Zéro dépendance npm
Le problème
On écrit une caisse aujourd'hui. On ne sait pas quel terminal sera branché dessus — ni s'il sera relié à la caisse, ni s'il acceptera un montant poussé, ni s'il saura être interrogé après coup. Et le jour de l'installation, il sera trop tard pour réécrire.
Ce module permet d'écrire l'application maintenant et de brancher le terminal ensuite.
L'idée : les capacités se DÉCLARENT
Chaque famille de terminal est décrite par un dialecte — une donnée, pas une sous-classe — qui annonce ce qu'il sait faire :
import { creerTerminal, dialecteParNom } from '@mostajs/paiement-tpe';
const terminal = creerTerminal({ dialecte: dialecteParNom(process.env.TPE_DIALECTE) });
if (terminal.capacites.poussemontant) {
await terminal.demander({ reference: c.id, montant: 1380, devise: 'EUR', uniteMineure: 2 });
} else {
// Le terminal ne reçoit pas de montant : quelqu'un le tape, et CONSTATE le résultat.
await terminal.confirmerManuel({ reference: c.id, verdict: 'accepte', acteur: session.id, … });
}L'application lit les capacités au lieu de les supposer. null veut dire à établir — jamais
« oui par optimisme ».
Savoir si l'appareil répond
await terminal.sonder(); // 'joignable' | 'muet' | 'inconnu''inconnu' quand le dialecte ne sait pas sonder — jamais false, qui ferait croire l'appareil
en panne alors qu'on n'en sait rien.
Le verdict qui compte : indetermine
Sept issues sont possibles ; celle-ci est la plus importante :
indetermine— la réponse est perdue. On ignore si le client a été débité.
C'est le cas le plus coûteux de tout l'encaissement. Le ranger sous « refusé » ferait rembourser un
client déjà remboursé, ou perdre une vente encaissée. Toute application qui consomme ce module doit
avoir un geste pour ce verdict-là — pas un else.
Les six familles
| dialecte | ce que c'est | état |
|---|---|---|
| autonome | terminal non relié : montant tapé à la main, constat repris par un humain | écrit |
| caisse-3.2 | protocole CAISSE/CONCERT 3.x — standard français | à écrire |
| nexo | nexo / ISO 20022 — standard ouvert européen | à écrire |
| psp-lecteur | lecteur d'un prestataire (Stripe Terminal, SumUp…) | à écrire |
| softpos | Tap to Pay : le téléphone lit la carte | à écrire |
| satim | switch interbancaire algérien (CIB / Edahabia) | à écrire |
« À écrire » est une information, pas un manque : un pilote écrit sans l'appareil serait un protocole deviné. Un dialecte non écrit échoue bruyamment — il ne rend jamais un succès vide.
Ce que ce module ne fait pas
- Il ne tarife pas, ne facture pas, ne comptabilise pas.
- Il ne stocke aucun numéro de carte — jamais, sous aucune forme.
- Il ne rend pas une caisse conforme. Encaisser fait entrer dans la loi anti-fraude à la TVA (caisse certifiée). Ce module fournit le port ; la conformité est une affaire d'exploitant et de comptable.
- Il ne fait pas de paiement en ligne →
@mostajs/paiement(asynchrone, webhook, redirection). Ici, tout est en présence et synchrone.
Persistance
Le module déclare son entité par le contrat (@mostajs/module-contract) :
import { register } from '@mostajs/paiement-tpe/register';Reglement (reglements) est APPEND-ONLY : rien n'y est mis à jour ni effacé. C'est la brique
que la certification exigera, et elle ne coûte rien à poser maintenant.
Documentation
llms.txt (fiche dense) · docs/01 état de l'art · docs/02 audit · docs/03 plan de dev ·
docs/04 plan de test · CHANGELOG.md
