Aller au contenu

Déployer la facturation et les paiements en ligne

Cette version fait de la facture client le document unique pour l’argent qu’un client doit, permet aux clients de payer depuis une page hébergée, et durcit la manière dont les paiements en ligne sont confirmés. Suivez les étapes dans l’ordre.

Base de données Migration Ce qu’elle ajoute
Globale 0036_payment_intents Un index, à l’échelle de la plateforme, de chaque tentative de paiement en ligne, pour qu’une notification de passerelle soit rattachée au bon locataire ; des tentatives de paiement suivies pour les factures d’abonnement des locataires eux-mêmes.
Locataire 0117_customer_invoice_lines Les lignes et totaux de facture, et le lien entre une vente à crédit et sa facture.
Locataire 0118_payments_hardening Le statut de paiement En cours d’examen et les garde-fous qui empêchent qu’un paiement soit crédité deux fois.

Lancez la migration globale, puis celle des locataires, sur la base partagée et sur chaque base de locataire dédiée :

Fenêtre de terminal
make migrate-global-up
make migrate-tenant-up

Les changements de règlements et de frais sont livrés dans leurs propres migrations et sont traités avec règlements et frais.

Variable À régler sur Pourquoi
PAY_BASE_URL API, planificateur Origine publique de l’application de paiement. Les liens de facture et les boutons de paiement sont construits dessus. Voir déployer SaleSprint Pay.
PUBLIC_API_BASE_URL API L’origine publique de cette API telle qu’une passerelle de paiement peut l’atteindre, sans /api/v1. Elle construit l’URL de webhook affichée sur chaque configuration de passerelle. Laissée vide, ce champ est vide.
PAYMENTS_SECRET_KEY API, planificateur Clé de 32 octets en base64 qui chiffre les identifiants de passerelle stockés. Se rabat sur la clé de connexion externe quand elle n’est pas définie — définissez-en une dédiée en production.
DOCUMENT_LINK_SECRET API, planificateur Clé dont dérivent les liens clients. La faire tourner invalide tous les liens déjà envoyés.

Voir déployer SaleSprint Pay.

Chaque configuration de passerelle affiche une URL de webhook en lecture seule :

{PUBLIC_API_BASE_URL}/api/v1/webhooks/payments/{gateway}

où {gateway} vaut paystack, payswitch ou hubtel.

  • Une URL par passerelle sert tous les locataires. Collez-la une fois dans le tableau de bord de ce prestataire. Les notifications sont rattachées au locataire et au paiement par la référence du paiement lui-même, aucun identifiant de locataire n’est donc nécessaire. L’ancienne forme ?tenant= fonctionne encore.
  • La même URL transporte les notifications des paiements d’abonnement des locataires.
  • Une notification n’est qu’un coup de coude. SaleSprint ne règle jamais d’après le corps de la notification ; il interroge la passerelle sur ce paiement et règle d’après la réponse de la passerelle.

Le planificateur (cmd/scheduler) est ce qui rend les paiements fiables quand une notification est en retard ou perdue. Il :

  • revérifie chaque tentative de paiement ouverte auprès de sa passerelle — encaissements marchands comme paiements d’abonnement ;
  • rejoue les notifications arrivées alors qu’un paiement était encore en attente ;
  • fait expirer les demandes que personne n’a payées, après avoir confirmé auprès de la passerelle que rien n’a été payé.

Sans lui, un paiement dont la notification n’arrive jamais reste en attente jusqu’à ce que le client revienne sur la page de paiement.

Deux paramètres à portée y contribuent, tous deux sous Payments : payments.payment_intent_expiry_minutes (combien de temps une demande de paiement reste valide) et payments.merchant_collection_hold_hours (combien de temps l’argent encaissé attend avant de devenir disponible).

Les ventes à crédit finalisées après la mise à niveau émettent leur facture automatiquement. Les ventes à crédit ouvertes d’avant continuent de fonctionner, mais n’ont pas de facture — donc ni rappels, ni lien de paiement, et elles ne figurent pas dans la liste des Factures clients — tant qu’elles ne sont pas converties.

La conversion est un appel d’API, fait une fois par locataire par un utilisateur de ce locataire autorisé à créer des factures clients :

POST /admin/customer-invoices/backfill-from-sales

(sous le préfixe habituel /api/v1 de l’API — voir la référence de l’API). Il répond en indiquant combien de factures il a émises et s’il en reste :

{ "created": 200, "remaining": true }
  • Il traite jusqu’à 200 ventes par appel. Répétez tant que remaining vaut true.
  • Il peut être relancé sans risque : une vente qui a déjà une facture est ignorée.
  • Chaque vente à crédit ouverte reçoit une facture numérotée dans la séquence normale de factures du locataire, avec une échéance tirée des conditions de paiement du client. Les paiements déjà enregistrés sur la vente sont conservés.
  • Les ventes à crédit entièrement payées sont laissées telles quelles.
  • Les clients ne reçoivent pas d’e-mail. Ce sont des dettes que le client connaît déjà.
  • Une vente qui ne peut pas être convertie est ignorée et journalisée ; les autres continuent.

À transmettre à vos locataires :

  • Créer une facture avec un statut autre que Brouillon est désormais refusé.
  • Un produit au stock suivi sur une facture émise dans les finances est refusé (stocked_product_requires_sale).
  • Une vente à crédit au-delà de la limite de crédit du client est refusée (credit_limit_exceeded), sauf si l’utilisateur détient sales.sale.credit_limit_override. Accordez-la aux superviseurs avant la mise en service, sinon les caisses seront arrêtées par des limites que personne n’appliquait auparavant.
  • Annuler une vente à crédit dont la facture porte des paiements est refusé (invoice_has_payments).
  • Un paiement ne peut pas être marqué terminé à la main, et un paiement dont le montant ou la devise ne correspond pas est mis En cours d’examen jusqu’à ce qu’un opérateur le résolve.
  • Les locataires qui paient leur propre facture d’abonnement par carte passent par la page de redirection de la passerelle ; le paiement est vérifié par rapport à une tentative créée par le serveur.