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-intentpuis.../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¶
- La commande est identifiée par la métadonnée
order_idde la session. - Si
payment_statusvautpaid: - la commande passe au statut « En Attente » ;
- le paiement associé passe à
COMPLETED, avec enregistrement de sonpayment_intent; - les cartes physiques en
PENDING_PAYMENTpassent à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¶
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