Le paiement des licences
Comment le site vend ses deux licences : le paiement, les pages de Stripe et de PayPal, le paiement test, le webhook, le reçu et sa clé de licence, et comment changer les offres ou vendre par une boutique externe.
Pour le pack Full Stack
D'une licence à un reçu
- Sur la page des tarifs, l'acheteur appuie sur Get single project ou Get Studio. Le Purchase summary montre la licence, ce qu'elle couvre et le total, et Continue to checkout ouvre
/checkout?license=singleou?license=studio. - Le paiement demande un e-mail, un nom complet et un moyen de paiement, Card ou PayPal, ainsi que l'accord sur les conditions de la licence. Continue to payment les envoie à l'API, qui écrit la commande (une référence comme
NS-7KQ2-M9XD) à son propre prix : le navigateur n'en envoie jamais un. - L'acheteur paie sur la page de Stripe ou de PayPal, ou sur le paiement test du site quand ce moyen n'a pas de clés. Les données de carte ne sont jamais saisies sur votre site.
- La page où revient l'acheteur,
/checkout/success, demande à l'API de vérifier le paiement auprès du fournisseur, puis de nouveau toutes les trois secondes, jusqu'à cinq fois, tant qu'il est en cours de traitement. Une fois que l'API l'a vérifié, la commande est payée, le reçu affiche la clé de licence (commeNSK-4F7Q-2M9X-HB3T-8KRD) avec Copy the license key, et le reçu est envoyé par e-mail à l'acheteur.
Le site ne décide jamais qu'une commande est payée. Une commande n'est payée que par le webhook signé de Stripe, par la session Stripe que l'API relit au retour de l'acheteur, ou par la capture PayPal que l'API fait à ce retour. Un seul d'entre eux émet la clé et l'e-mail, quel que soit le nombre qui arrivent. Un acheteur qui quitte la page de paiement arrive sur /checkout/cancelled, qui indique qu'aucun argent n'a été prélevé et propose Try again.
Moyens de paiement
| Méthode | Défini dans le .env de l'API | Comment elle fonctionne |
|---|---|---|
| Carte, sur Stripe | STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET | Stripe Checkout en mode paiement. Le prix voyage avec chaque session : rien n'a besoin d'être créé d'abord dans Stripe. Stripe ramène l'acheteur sur /checkout/success ou /checkout/cancelled. |
| PayPal | PAYPAL_CLIENT_ID, PAYPAL_CLIENT_SECRET (une application REST PayPal), PAYPAL_ENV (sandbox par défaut, ou live) | La page de PayPal. L'API capture le paiement approuvé quand l'acheteur revient sur /checkout/success. |
| Paiement test | rien : il prend tout moyen sans clés | La page du site /checkout/test, avec Pay et Cancel payment. Il ne débite personne. |
- Chaque moyen passe par son fournisseur dès que les clés de celui-ci sont définies, et par le paiement test jusque-là : une installation neuve peut donc finaliser un achat tout de suite.
- Tant qu'aucun moyen ne déplace de l'argent réel (pas de clés, une clé Stripe
sk_test_ou le sandbox PayPal), le paiement indique qu'il est en mode test. Avec une clé de test Stripe, il nomme la carte de test :4242 4242 4242 4242, n'importe quelle date future et n'importe quel CVC. - Utilisez d'abord des clés de test : elles ne déplacent aucun argent. Au démarrage, l'API consigne, pour chaque fournisseur, s'il accepte des paiements de test ou réels.
- Les clés de Stripe sont les mêmes que celles qu'utilise la facturation des abonnements du tableau de bord.
Le webhook Stripe
Les commandes de licences et les abonnements des espaces de travail partagent un seul webhook Stripe. Avant la mise en ligne, enregistrez-le dans Stripe sur l'adresse publique de votre API et mettez son secret de signature dans STRIPE_WEBHOOK_SECRET :
https://<your-api>/api/billing/webhooks/stripePour les licences, l'API agit sur checkout.session.completed (la commande est payée) et checkout.session.expired (la commande a échoué). Elle distingue une session de licence d'une session d'abonnement par la métadonnée kind: license de la session. PayPal n'a besoin d'aucun webhook : la capture se fait au retour de l'acheteur.
Avec STRIPE_SECRET_KEY défini et STRIPE_WEBHOOK_SECRET vide, le journal de l'API le signale au démarrage et chaque envoi est refusé par un 400 qui nomme la variable. Une commande par carte n'est alors payée que lorsque l'acheteur revient sur la page du reçu.
Sur votre ordinateur, Stripe ne peut pas atteindre l'API, et un paiement test aboutit quand même : la page de retour interroge l'API, qui relit la session chez Stripe. Définissez WEBSITE_URL avec l'adresse du site, car chaque lien de retour que l'API donne à Stripe et à PayPal en est construit, dans la langue de l'acheteur.
Statuts de commande
| Statut | Signification | Ce que dit la page du reçu |
|---|---|---|
pending | Écrite, pas encore payée. | « Checking your payment. », puis « Your payment is still processing. » avec Check again. |
paid | Vérifiée auprès du fournisseur ; la clé de licence est émise. | « Thank you. Studio is yours. » (avec la licence achetée), les détails de la commande et la clé. |
failed | La session de Stripe a expiré, PayPal a refusé la capture, ou la page du fournisseur n'a pas pu s'ouvrir. | « The payment did not go through. » avec Try again. |
cancelled | L'acheteur a quitté la page de paiement. | « This order was cancelled. » |
Le reçu n'affiche la clé de licence que pour une commande payée, et marque une commande de test par « Test payment: no money moved. » Si le webhook de Stripe signale plus tard un paiement pour une commande annulée ou échouée (un acheteur qui est revenu en arrière et a payé dans un autre onglet), cette commande devient payée.
Limites et sécurité
- Une commande ne se lit que par son identifiant, 32 caractères aléatoires que seuls portent les liens de retour de l'acheteur et l'e-mail du reçu. Il n'existe aucune liste de commandes qu'un visiteur pourrait parcourir.
- Chaque envoi porte son propre jeton : appuyer deux fois sur Continue to payment ouvre la même commande et la même page de paiement, jamais un second débit.
- Chaque adresse peut démarrer dix paiements par heure ; le suivant indique « Too many attempts from this address. Try again in an hour. » Derrière un reverse proxy, définissez
TRUST_PROXY=1dans le.envde l'API, sinon tous les acheteurs partagent le quota du proxy. - Aucune taxe n'est ajoutée. Configurez la fiscalité de votre pays avant d'encaisser de vrais paiements ; les frais propres à Stripe et à PayPal s'y ajoutent séparément.
L'e-mail du reçu
L'e-mail d'une commande payée donne la référence de la commande, la licence, le montant, la clé de licence et un lien vers le reçu. Il est envoyé via SMTP_HOST et les autres paramètres SMTP_* ; sans eux, il est écrit dans le journal de l'API. Le texte de l'e-mail est en anglais dans les deux langues, dans back-end/src/modules/licenses/services/license-checkout.service.ts ; le lien du reçu s'ouvre dans la langue dans laquelle l'acheteur a payé.
Changer les licences et leurs prix
Le prix est conservé à deux endroits, qui doivent concorder :
| Fichier | Ce qu'il détermine |
|---|---|
back-end/src/modules/licenses/constants/license-offers.ts | Ce que l'API facture, en centimes (19900 et 39900, dollars américains), et le nom sur la page du fournisseur et sur le reçu. |
website/src/config/licenses.ts | Ce que le site affiche, le nombre de produits finaux que couvre chaque licence, la carte recommandée, et les lignes que liste chaque carte (leurs textes sont sous PricingPage.licenses dans website/messages/pricing/en.json et ar.json). |
Un prix modifié dans le site seul ne change que ce que la page affiche : l'acheteur paie toujours le montant de l'API. Les deux identifiants de licence, single et studio, sont écrits dans les deux fichiers, la requête de paiement de l'API et les messages du site : une troisième licence est donc une modification dans chacun.
Vendre par une boutique externe
Définissez NEXT_PUBLIC_PURCHASE_URL_SINGLE et NEXT_PUBLIC_PURCHASE_URL_STUDIO avec le paiement de la boutique pour chaque licence et reconstruisez le site (avec Docker Compose, PURCHASE_URL_SINGLE et PURCHASE_URL_STUDIO dans le .env à côté de docker-compose.yml). Continue to checkout ouvre alors cette adresse à la place de /checkout. Une licence laissée vide garde le paiement du site.
Sans l'API
Quand le site fonctionne sur ses données d'exemple intégrées, le paiement est vérifié et traité dans le navigateur : une commande ouvre le paiement test du site, Pay émet une clé de licence sur le reçu, et les commandes ne sont gardées que dans ce navigateur. Rien n'est débité ni envoyé.
En mode démo
Inclus avec votre achat. Connectez-vous pour le lire, ou ouvrez-le dans votre téléchargement.
Comment se comporte le paiement sur une démo publique.
Les routes derrière
| Route | Rôle |
|---|---|
GET /api/licenses/checkout/options | Les moyens proposés, le fournisseur qui prend chacun (stripe, paypal ou simulator) et testMode. |
POST /api/licenses/checkout | license (single ou studio), email, name, method (card ou paypal), locale (en ou ar) et clientToken. Répond l'identifiant de la commande et la page où payer ; 429 au-delà de la limite, 503 payment_unavailable quand la page du fournisseur n'a pas pu s'ouvrir. |
GET /api/licenses/orders/:id | La commande, avec sa clé de licence une fois payée. |
POST /api/licenses/orders/:id/confirm | Demande au fournisseur si le paiement a abouti. |
POST /api/licenses/orders/:id/cancel | L'acheteur a quitté la page de paiement. |
POST /api/licenses/orders/:id/simulate | Le pay ou cancel du paiement test, pour une commande prise par le paiement test. |
Toutes sont publiques : l'identifiant d'une commande prouve que le lecteur en est l'acheteur. Un identifiant qui n'a pas 32 caractères hexadécimaux, ou qui ne correspond à aucune commande, répond 404 order_not_found.