Aller au contenu

Abonnements et paiements

Ce document décrit les offres d'abonnement, les moyens de paiement acceptés et le traitement des webhooks Stripe.


Offres d'abonnement

Les offres sont stockées en base (entité Plan) et administrables depuis le back-office (/admin/plans). Chaque plan porte :

Champ Description
name, description Intitulé et présentation de l'offre
monthlyPrice, yearlyPrice Tarifs mensuel et annuel
features Liste des fonctionnalités incluses
cardsIncluded Nombre de cartes comprises dans l'offre
additionalCardPrice Tarif d'une carte supplémentaire
badge, popular Mise en avant dans la grille tarifaire
isActive Visibilité de l'offre
sortOrder Ordre d'affichage

Un abonnement souscrit est représenté par l'entité Subscription :

Statut Signification
PENDING Souscrit, en attente de règlement
ACTIVE Actif
CANCELLED Résilié
EXPIRED Échu

Périodicité de facturation : MONTHLY ou YEARLY.

Tout compte ROLE_USER dépourvu d'abonnement se voit attribuer automatiquement un abonnement gratuit lors de son premier accès au tableau de bord (SubscriptionService::createFreeSubscriptionForUser()).


Moyens de paiement

L'entité Payment reconnaît les moyens suivants :

Constante Valeur Usage
CREDIT_CARD CREDIT_CARD Carte bancaire via Stripe
ORANGE_MONEY ORANGE_MONEY Paiement mobile — non implémenté : six contrôleurs rejettent ce moyen de paiement dès sa sélection (voir Configuration § Paiements)
DELIVERY_CASH DELIVERY_CASH Paiement à la livraison
PRO_SUBSCRIPTION PRO_SUBSCRIPTION Règlement d'un abonnement professionnel
COMPANY_FREE COMPANY_FREE Attribution gratuite à une entreprise
MANUAL MANUAL Saisie manuelle par un administrateur

Statuts d'un paiement :

Constante Valeur
PENDING_STATUS PENDING
ACCEPTED_STATUS ACCEPTED
COMPLETED_STATUS COMPLETED
REJECTED_STATUS REJECTED

Intégration Stripe

Configuration

Variable Rôle
STRIPE_PUBLIC_KEY Clé publique, utilisée côté navigateur
STRIPE_SECRET_KEY Clé secrète, utilisée côté serveur
STRIPE_WEBHOOK_SECRET Secret de signature des webhooks

Ces valeurs sont des secrets : elles ne doivent jamais être committées.

Deux modes d'encaissement

  • Checkout Session — l'utilisateur est redirigé vers une page de paiement hébergée par Stripe. Utilisé pour les commandes web et les abonnements.
  • PaymentIntent — l'encaissement est confirmé depuis le client. Utilisé par l'API mobile (/api/physical-cards/{id}/create-payment-intent puis .../confirm-payment).

Webhooks

Endpoint : POST /stripe/webhook (StripeWebhookController)

La signature de chaque requête est vérifiée avec STRIPE_WEBHOOK_SECRET avant tout traitement. Une charge utile illisible ou une signature invalide donne lieu à une réponse 400.

Événements traités

checkout.session.completed

  1. La commande est identifiée par la métadonnée order_id de la session.
  2. Si payment_status vaut paid :
  3. la commande passe au statut « En Attente » ;
  4. le paiement associé passe à COMPLETED, avec enregistrement de son payment_intent ;
  5. les cartes physiques en PENDING_PAYMENT passent à CONFIRMED.

Si aucune carte physique n'est encore rattachée à la commande, le webhook ne la crée pas : cette création est laissée à la page de succès, faute d'accès à la session utilisateur depuis un webhook.

payment_intent.succeeded

Le paiement est retrouvé par son stripePaymentIntentId et n'est mis à jour que s'il est encore PENDING. Il passe alors à COMPLETED, la commande à CONFIRMED, et les cartes physiques en PENDING_PAYMENT à CONFIRMED.

payment_intent.payment_failed

Le paiement passe à REJECTED, ainsi que la commande associée.

Tout autre type d'événement est ignoré, avec une réponse 200 afin d'éviter les renvois répétés de Stripe.

Configuration côté Stripe

Déclarez l'URL https://<votre-domaine>/stripe/webhook dans le tableau de bord Stripe, en souscrivant aux trois événements ci-dessus, puis reportez le secret de signature dans STRIPE_WEBHOOK_SECRET.

Tester en local

stripe listen --forward-to localhost:8000/stripe/webhook
stripe trigger checkout.session.completed

La commande stripe listen affiche un secret de signature temporaire, à placer dans STRIPE_WEBHOOK_SECRET le temps de la session de test.


Cycle de vie d'une commande de carte physique

Panier
  └─> Commande créée            Order: DRAFT / En attente de paiement
        └─> Paiement initié     Payment: PENDING      PhysicalCard: PENDING_PAYMENT
              └─> Webhook OK    Payment: COMPLETED    PhysicalCard: CONFIRMED
                    └─> Fabrication                   PhysicalCard: PROCESSING
                          └─> Expédition              PhysicalCard: SHIPPED
                                └─> Réception         PhysicalCard: DELIVERED

Les changements de statut opérés depuis le back-office sont consignés dans le journal d'audit (AuditLog::ACTION_ORDER_STATUS_UPDATED).


Factures

Les factures sont générées en PDF par DomPdfService et téléchargeables depuis le back-office :

  • /admin/invoice/payment/{id} — facture d'un paiement
  • /admin/pro-payments/{id}/invoice — facture d'un paiement professionnel