Installation

Installer le module de facturation, créer les tables et déclarer le webhook Stripe.

Installer

npm i @lrvo/module-billing

Activer dans le .env :

LRVO_MODULE_BILLING=true

Sans cette variable, le module est chargé mais n'enregistre rien : ni tables, ni routes, ni entrée d'admin, ni tâches planifiées.

Puis régénérer les manifestes et créer les tables :

npx lrvo-modules sync   # auto-déclenché par postinstall
npx lrvo-db init        # crée les douze tables lrvo_billing_*

lrvo-db init accorde aussi les permissions billing.view et billing.manage au rôle admin, et applique les migrations en attente.

Sur un site déjà en service, une mise à jour du module se termine par npx lrvo-db migrate, qui applique les évolutions de schéma que la création de tables ne peut pas atteindre.

Version de core exigée

Le module réclame @lrvo/core 1.0.71 ou plus, et le boot refuse une combinaison plus ancienne en nommant le module.

Trois choses viennent du core et n'ont aucun substitut dans le module : la génération de app/.lrvo/public-pages.server.js, le manifeste par lequel la page de paiement s'enregistre, depuis 1.0.70 ; puis, depuis 1.0.71, la transmission des paramètres d'URL aux pages publiques, sans laquelle le retour de Stripe n'affiche aucun bandeau, et l'affichage en ligne d'un document, sans lequel les visionneuses de PDF restent vides. Les deux dernières échouent en silence, d'où le plancher relevé.

Sur un projet créé avant cette version, app/lrvo/[...path]/page.js doit gagner l'import du manifeste. La correction est automatique :

npx lrvo-doctor --fix
npx lrvo-modules sync

Sans elle, /lrvo/billing/<token> échoue au rendu sur « Could not find the module … in the React Client Manifest ».

Renseigner l'émetteur

Une facture doit nommer qui l'émet. Sans ces variables, le bloc émetteur du PDF est vide.

LRVO_MODULE_BILLING_COMPANY_NAME=Mon entreprise inc.
LRVO_MODULE_BILLING_COMPANY_ADDRESS=123 rue Principale
LRVO_MODULE_BILLING_COMPANY_CITY=Montréal
LRVO_MODULE_BILLING_COMPANY_PROVINCE=Québec
LRVO_MODULE_BILLING_COMPANY_POSTAL_CODE=H1A 1A1
LRVO_MODULE_BILLING_COMPANY_EMAIL=[email protected]
LRVO_MODULE_BILLING_COMPANY_PHONE=514 555 0100

Une entreprise inscrite aux fichiers de la TPS et de la TVQ doit faire figurer ses numéros sur toute facture de plus de 30 $ :

LRVO_MODULE_BILLING_GST_NUMBER=123456789 RT0001
LRVO_MODULE_BILLING_QST_NUMBER=1234567890 TQ0001

Ces numéros sont recopiés sur chaque facture au moment de l'émission, pas à l'affichage. Une facture déjà émise garde donc les numéros en vigueur ce jour-là.

La liste complète est dans Configuration.

Courriels

Le module envoie six courriels par core/email, qui demande la configuration courriel du projet, Resend ou SMTP. NEXT_PUBLIC_URL doit être renseignée : les liens de paiement envoyés aux clients en sont dérivés.

Sans configuration de courriel, tout le reste du module fonctionne : l'émission réussit, seul l'envoi échoue, et la tentative est journalisée puis reprise par la tâche de rappels.

Le contenu de chaque message est décrit dans Courriels.

Paiement par carte

Le paiement Stripe demande les clés du core :

STRIPE_SECRET_KEY=sk_…
STRIPE_PUBLISHABLE_KEY=pk_…
STRIPE_WEBHOOK_SECRET=whsec_…

Le webhook, à déclarer chez Stripe

Il n'y a aucun fichier à créer. L'endpoint est servi par le core, sur /lrvo/api/payments/stripe/webhook : il vérifie la signature, puis remet l'événement aux modules qui s'y sont abonnés. Le module de facturation s'abonne pendant son register(), dès que LRVO_MODULE_BILLING=true.

Le module se charge du reste : déduplication de l'événement, écriture de la transaction et envoi du reçu.

Déclarer l'endpoint dans le tableau de bord Stripe, sur https://exemple.ca/lrvo/api/payments/stripe/webhook, avec deux événements :

ÉvénementEffet
checkout.session.completedEnregistre le paiement et met le solde à jour.
charge.refundedEnregistre le remboursement, y compris s'il vient du tableau de bord Stripe.

Sans le webhook, un client peut payer sans que la facture soit créditée. Un retour de navigateur n'est pas une preuve de paiement, et le module ne l'utilise que pour afficher un bandeau.

Vérifier en local

stripe listen --forward-to localhost:3000/lrvo/api/payments/stripe/webhook

Régler une facture de test, puis rejouer l'événement :

stripe events resend <event_id>

Le solde ne doit pas bouger : l'événement est reconnu comme un doublon et ignoré.

Virement Interac

LRVO_MODULE_BILLING_INTERAC_ENABLED=true
LRVO_MODULE_BILLING_INTERAC_EMAIL=[email protected]

Une question et une réponse de sécurité sont générées à la première facture de chaque client, et affichées sur sa page de paiement. Le virement reçu est ensuite saisi à la main dans l'admin.

Si LRVO_ENCRYPTION_KEY est configurée, la réponse est chiffrée en base. Elle ne peut pas être hachée : elle doit être montrée au payeur.

Tâches planifiées

Trois tâches quotidiennes sont enregistrées automatiquement. Les désactiver sur une instance qui ne doit pas les exécuter :

LRVO_MODULE_BILLING_CRON=false

Aucun réglage n'est nécessaire pour un déploiement à plusieurs instances : chaque tâche prend un verrou en base avant de travailler, et les instances qui ne l'obtiennent pas passent leur tour.

Vérifier l'installation

  1. La section « Facturation » apparaît dans l'admin.
  2. Créer un client, puis une facture avec une ligne à 100,00 $ en TPS et TVQ. Le total affiché doit être 114,98 $.
  3. Émettre la facture. Elle reçoit un numéro de la forme FAC-2026-0001 et le client reçoit le courriel avec le PDF joint.
  4. Ouvrir le lien public dans une fenêtre de navigation privée. La ventilation des taxes et les numéros d'inscription doivent y figurer.

Sur cette page