Question 1Quand tu encaisses des paiements via un prestataire de paiement, par où circulent les données de carte ?
Comment fonctionne la facturation — ce que Stripe prend en charge, et l'attribution des droits par webhook
Cet article fait partie du cours Les bases de l'informatique, qui construit depuis zéro les connaissances informatiques pratiques indispensables pour programmer et faire du vibe coding.
Les données de carte s'arrêtent chez le prestataire de paiement et ne passent jamais par ton propre serveur. Des schémas montrent pourquoi c'est la notification webhook qui justifie l'ouverture des fonctionnalités payantes.
Cet article porte sur le fonctionnement de la facturation.
Il se divise en deux parties : empêcher les données de carte d'atteindre ton propre serveur, et répercuter le résultat du paiement dans ta propre application.
Le numéro de carte s'arrête sur la branche du haut et n'atteint jamais my-app.
Seule la notification qui arrive par la branche du bas justifie l'ouverture des fonctionnalités payantes.
La réception du numéro de carte comme les échanges avec l'émetteur de la carte se font du côté du prestataire de paiement, et il ne reste à my-app que l'inscription du résultat dans un enregistrement.
C'est le prestataire de paiement qui reçoit les données de carte, pas ton propre serveur
Le traitement d'un paiement nécessite le numéro de la carte, sa date d'expiration et son code de sécurité.
La norme que respectent les entreprises qui manipulent des données de carte est le PCI DSS (Payment Card Industry Data Security Standard), et un prestataire de paiement (payment service provider) est un service externe qui prend en charge les paiements par carte à ta place.
Stripe et PayPal sont les prestataires de paiement les plus connus.
L'endroit où tu places les champs de saisie détermine par où circule le numéro de carte.
| Emplacement des champs | Par où circule le numéro | Concerné par le PCI DSS |
|---|---|---|
| Reçu et stocké par my-app | my-app et le prestataire | my-app est concerné aussi |
| Reçu par my-app puis transmis | my-app et le prestataire | my-app est concerné aussi |
| Page du prestataire de paiement | Le prestataire uniquement | Périmètre minimal pour my-app |
Seule la troisième ligne laisse le numéro de carte en dehors du serveur de my-app.
Dans ce cas, my-app ne conserve que la valeur qui identifie le paiement, alors que les deux premières lignes laissent derrière elles le numéro de carte lui-même ou une trace des échanges.
Même transmis sans être stocké, le numéro passe par ton propre serveur, et dès qu'il y passe, my-app entre lui aussi dans le périmètre du PCI DSS.
Pour réduire au minimum la zone que my-app doit protéger, tu confies les champs de saisie eux-mêmes au prestataire de paiement.
- Numéro de carte, date d'expiration, code de sécurité
- Trace des échanges avec l'émetteur de la carte
- La valeur qui identifie le paiement, pay_88
- Le montant, et si le paiement a abouti
- À quel utilisateur appartient le paiement (u_1024)
Le numéro de carte ne passe pas par my-app
Si tu ne reçois jamais toi-même le numéro de carte, la responsabilité de le protéger ne retombe pas non plus sur toi.
Que tu le stockes ou que tu le transmettes aussitôt, la même responsabilité s'applique dès qu'il passe par ton propre serveur : tu confies donc les champs de saisie eux-mêmes au prestataire de paiement, et seul le fait que le paiement a abouti arrive jusqu'à my-app.
Le paiement se termine sur une page de paiement hébergée sur le domaine du prestataire
Une page de paiement hébergée (hosted checkout page ; page de paiement préparée par le prestataire de paiement et affichée sur son propre domaine) place l'écran de saisie lui-même ailleurs, pour que les données de carte ne passent jamais par ton propre serveur.
Le fait d'emmener l'utilisateur vers une page d'un autre domaine est une redirection (redirect).
À la deuxième étape, tu transmets le montant et l'adresse de retour, et le prestataire de paiement renvoie l'URL d'une page de paiement dédiée à ce paiement.
Cet échange se fait en appelant une API web, et tu y joins une clé d'API.
- La page d'inscription à l'offre payante
- /thanks, ouverte après le paiement
- La page de paiement où le numéro de carte est saisi
- my-app ne voit pas ce que contient cette page
La page de paiement est aussi proposée sous forme de cadre placé dans la page de my-app.
L'apparence change, mais les valeurs saisies aboutissent au même endroit.
C'est le prestataire de paiement qui fournit la page de paiement
La page où le numéro de carte est saisi appartient au prestataire de paiement, pas à my-app.
Une redirection emmène l'utilisateur vers cette page, et après le paiement il revient sur /thanks ; même si tu la places sous forme de cadre dans ta propre page, les valeurs saisies aboutissent au même endroit.
Ce qui justifie l'attribution des droits, c'est la notification webhook, pas la page de retour
C'est my-app, et non le prestataire de paiement, qui décide si les fonctionnalités payantes peuvent être affichées, et cet enregistrement est le droit d'accès (entitlement ; enregistrement de l'étendue des fonctionnalités accessibles à un utilisateur ayant payé).
Le simple retour de l'écran de l'utilisateur sur /thanks n'indique pas à my-app que le paiement a abouti.
Distingue deux chemins dans ce qui se passe après un paiement.
Le chemin du haut s'arrête net si l'utilisateur ferme son navigateur juste après avoir payé.
Celui du bas va de serveur à serveur : si la notification n'arrive pas, elle est renvoyée un nombre de fois et pendant une durée fixés à l'avance.
Selon celui que tu retiens comme justification, les mêmes trois personnes n'obtiennent pas les mêmes droits.
| Ce qui est arrivé à l'utilisateur | Si tu juges sur /thanks | Si tu juges sur /webhook |
|---|---|---|
| A payé et ouvert /thanks | Droits attribués | Droits attribués |
| A payé puis fermé aussitôt | Aucun droit attribué | Droits attribués |
| A ouvert /thanks sans payer | Droits attribués | Aucun droit attribué |
Si tu juges sur /thanks, celui qui a fermé son navigateur n'obtient rien, tandis que celui qui n'a pas payé obtient des droits.
La seule chose sur laquelle tu fondes l'attribution des droits est la notification du chemin du bas.
Dans un paiement, si tu appliques deux fois la même notification, la période d'accès est prolongée deux fois.
Enregistre la valeur qui identifie chaque notification, et ne modifie pas les droits à la deuxième arrivée de la même notification.
Une notification dont la signature ne correspond pas est rejetée sans modifier les droits.
La seule différence entre les deux autres est de savoir si cette notification a déjà été appliquée.
- La valeur qui identifie l'utilisateur, u_1024
- Le hachage du mot de passe
- Type d'offre (paid)
- Date de fin d'accès
- À quel utilisateur il appartient (u_1024)
- La valeur qui identifie la notification, evt_7
- La date d'application
Même si tu masques le bouton payant sur la page, ce code parvient quand même à l'appareil de l'utilisateur.
Vérifier les droits côté serveur à chaque fois, c'est la même autorisation que celle présentée dans Le fonctionnement de la connexion.
Le numéro de carte s'arrête dans le cadre du milieu et n'entre pas dans celui de droite.
Les droits sont attribués à l'arrivée de la notification de la flèche 2, pas au retour du navigateur de l'utilisateur.
C'est une notification du serveur qui signale le paiement
Ce qui signale qu'un paiement a abouti, ce n'est pas la page sur laquelle l'utilisateur revient, mais la notification qui arrive depuis le serveur du prestataire de paiement.
Tu vérifies la signature de ce qui arrive, tu laisses les droits inchangés si la notification a déjà été appliquée, tu inscris le résultat dans ta propre base de données, et c'est à partir de là que tu décides d'afficher ou non les fonctionnalités payantes.
Avec un abonnement, une notification arrive à chaque période et les droits changent
Un contrat facturé au mois ou à l'année est un abonnement (subscription ; contrat dont le paiement se répète automatiquement à intervalle fixé).
Un paiement qui se répète ne réussit pas forcément à chaque fois.
Sur la ligne de l'échec, le prestataire de paiement laisse passer quelques jours et réessaie le prélèvement.
C'est my-app qui décide de maintenir l'accès pendant ce temps ou de le couper aussitôt.
Ce qui permet de vérifier avant la mise en ligne est le mode test (test mode ; état préparé par le prestataire de paiement pour vérifier le fonctionnement sans déclencher de prélèvement réel).
Les clés d'API sont distinctes pour le test et la production : tu passes de l'une à l'autre par la valeur d'une variable d'environnement.
Définis la notification qui retire les droits avant la mise en ligne
Avec un abonnement, un paiement a lieu à chaque échéance de période, et une notification arrive à chaque fois.
Si tu ne traites que la notification qui attribue l'accès, les utilisateurs dont les paiements se sont arrêtés le conservent : décide donc, pour chaque notification reçue, l'attribution, la prolongation et le retrait, puis déroule tout le parcours en mode test avant la mise en ligne.
Vérification des connaissances
Répondez à chaque question une par une.
Question 2Sur quoi t'appuies-tu pour conclure qu'un paiement a abouti et attribuer des droits à l'utilisateur ?
Question 3Quand une notification signalant l'échec d'un paiement arrive pour un prélèvement récurrent, que fait ton application ?