Produits de facturation
Modèle de catalogue produit et workflow de gestion admin.
Modèle de catalogue
Les produits de facturation sont stockés dans billing_products avec des
métadonnées non secrètes :
clé produit
type (
subscriptionouone_time)slug de plan
intervalle (
monthly/yearlyle cas échéant)slug de droit optionnel
Stripe price ID, géré en interne après synchronisation
métadonnées Stripe Product/Price en miroir
indicateur actif
ordre de tri
Les admins gèrent les prix produit dans Yayaw. Lorsqu'un montant produit est enregistré, Yayaw crée ou met à jour le Stripe Product correspondant, crée un nouveau Stripe Price lorsque le montant, la devise ou l'intervalle change, archive le Price précédent pour les nouveaux checkouts et stocke le Stripe price ID résultant ainsi que les métadonnées Product/Price en miroir. Les secrets Stripe restent dans les variables d'environnement.
Products & Services est la source de vérité pour les noms, prix, types,
intervalles, état de synchronisation Stripe et disponibilité checkout des
produits de facturation. Les modèles de données CMS ne doivent pas dupliquer ces
champs commerciaux.
Les coupons Stripe et codes promotionnels sont répliqués dans :
billing_stripe_couponsbilling_stripe_promotion_codes
Stripe reste la source de vérité pour les remises ; Yayaw les réplique pour les variables CMS et l'inspection MCP.
Workflow admin
Utilisez les pages admin du tableau de bord :
/dashboard/admin/billing-products, le catalogue de facturation (voir L'écran du catalogue de facturation)/dashboard/admin/billing-settings
Capacités V1 actuelles :
basculer l'état actif d'un produit
modifier le montant et la devise du produit
créer et répliquer le Stripe Product/Price via l'API Stripe
modifier l'ordre de tri
conserver des clés produit stables
Les réglages de facturation couvrent actuellement :
jours de période de grâce
réglages du dépôt GitHub pour l'accès au code
Les limites de fonctionnalités des plans vivent dans billing_plans et sont
lues par les services de facturation à l'exécution. Les quotas média et les
limites de sièges doivent être modifiés via le modèle de plan de facturation à
l'exécution, pas codés en dur dans les cartes produit.
L'écran du catalogue de facturation
/dashboard/admin/billing-products (« Produits & services », permission de
route billing-product:manage) affiche l'écran
dashboard.admin.billing-catalog. Le catalogue appartient à la plateforme :
c'est donc un écran global, une seule copie pour toute la plateforme, que
seuls les Super Admins personnalisent (voir Dashboard).
Son écran par défaut montre :
cinq chiffres, des décomptes uniquement, puisque les prix sont dans plusieurs devises et ne sont jamais additionnés : les produits, ceux en vente, les abonnements, les produits en paiement unique, et Synchronisation à vérifier (les produits dont la synchronisation Stripe a échoué, est en attente ou n'a pas de prix, la file de travail du même nom de la table) ;
Plans : la limite de sièges, la taille maximale d'un fichier et le quota de stockage de chaque plan de facturation, affichés à qui détient
billing-plan:readglobalement et modifiés par qui détientbilling-plan:manageglobalement ;les produits dans une table en pleine page de la source
system:billing-products, dans l'ordre du catalogue, 20 par page.
Les chiffres et la table listent tous les produits à qui détient
billing-product:list globalement, quelle que soit l'organisation active, et
une permission d'organisation ne les ouvre jamais.
Qui détient aussi billing-product:manage globalement (les Super Admins)
modifie un produit depuis sa ligne : un clic ouvre le formulaire avec son prix
et sa devise, s'il est en vente et son ordre d'affichage ; la clé produit est
en lecture seule. Le serveur vérifie de nouveau chaque modification
(billing-product:update, globalement) et synchronise un nouveau prix avec
Stripe avant de l'enregistrer.
La table garde les colonnes de la liste (nom, plan, type de produit,
périodicité, prix, devise, sync Stripe et en vente affichés ; clé produit,
ordre d'affichage, Price ID Stripe et produit Stripe à un clic), ses vues
enregistrées et ses favoris (billing-products), et ses files de travail
après la vue propre à l'écran : En vente, Hors vente et
Synchronisation à vérifier. Les prix s'affichent dans leur devise. Elle
propose les modes Tableau, Liste, un Kanban par statut de synchronisation
Stripe, dont on ne peut pas déplacer les cartes (un produit se modifie par son
formulaire), et des graphiques qui comptent les produits.
L'écran ne lit jamais le texte d'un échec de synchronisation Stripe (seulement s'il y en a un, pour le statut de synchronisation), l'ID de produit Stripe ni aucun secret Stripe, qui reste dans les variables d'environnement. Le Price ID Stripe s'affiche : il désigne un prix dans Stripe et n'accorde rien.
Recherche : elle ne lit que du texte : le nom, la clé produit, le plan, le type, la périodicité, le Price ID et le nom du produit Stripe, la devise et le statut de synchronisation, jamais un booléen, un ordre d'affichage ou un prix.
Pagination : au plus 100 produits par page (10, 20 ou 50 proposés).
Ordre : l'ordre du catalogue par défaut (ordre d'affichage, puis identifiant) ; les noms se trient comme on les lit (« Pro 2 » avant « Pro 10 »), dans la base.
Prix : ils ne sont jamais additionnés, moyennés ou comparés, ni dans un chiffre, ni dans un graphique, ni en pied de table.
Paramètres d'URL : les paramètres de la table sont indexés par sa source (
system:billing-products-…), etview=<id>ouvre une vue enregistrée ou une file de travail.Plans : quand le serveur refuse les limites d'un plan, l'éditeur du plan dit pourquoi.
Un assistant qui prépare un brouillon de cet écran ne lit que les colonnes de la source, jamais l'identifiant d'une ligne ni si la personne peut la modifier ; les assistants listent et modifient les produits avec les outils ci-dessous.
Contenu Produit CMS
Le seed crée un modèle de données global billing-product-content avec une
entrée par produit du catalogue de facturation. Chaque entrée est liée par le
champ verrouillé catalog_product_key et ne doit contenir que des ajouts
éditoriaux: badge, résumé, puces de fonctionnalités, libellé CTA ou état mis en
avant.
Utilisez ce modèle pour compléter les variables de catalogue dans les pages ou
sections. Utilisez {billing.product.<productKey>.*} et
{billing.price.<productKey>.*} pour les noms de produits, prix, Stripe Price
IDs et disponibilité checkout.
Workflow d'organisation
Utilisez la page de facturation d'organisation :
/dashboard/organization/billing/dashboard/organization/plans
Capacités V1 actuelles :
/billingse concentre sur le résumé du plan actif et l'activité interne/plansse concentre sur la sélection de plan et les actions de checkoutlancer un checkout d'abonnement
lancer un checkout de paiement unique (
pro_lifetime)ouvrir le portail de facturation Stripe
voir les raisons de désactivation du checkout avant de cliquer sur les actions
L'action du portail de facturation est désactivée jusqu'à ce que l'organisation possède un client Stripe enregistré. Cela évite un échec de portail confus avant que le premier checkout réussi ne crée le client dans Stripe.
Notes opérationnelles
Si un produit n'a pas de Stripe price ID synchronisé, un Stripe Price/Product en miroir actif ou comporte une erreur de synchronisation, le checkout est désactivé pour ce produit.
Les sessions Stripe Checkout d'abonnement et de paiement unique autorisent les codes promotionnels Stripe.
Le seed crée uniquement les lignes de produits manquantes et n'écrase pas les changements de catalogue gérés par opérateur.
Les clés produit sont des contrats stables. Ajoutez une nouvelle clé produit pour une nouvelle offre commerciale plutôt que de réutiliser une clé existante avec une sémantique différente.
Les Stripe Price IDs sont immuables pour le montant/la devise/l'intervalle. Les changements de montant créent un nouveau Price actif et archivent l'ancien Price pour les nouveaux checkouts.
Les données de remise sont répliquées depuis Stripe uniquement pour les usages en lecture. Créez et gouvernez les coupons/codes promotionnels dans Stripe.
Le checkout à vie en paiement unique accorde
pro_lifetimeet crée un grant durable d'accès au code indexé par session de checkout Stripe.Le checkout d'abonnement crée un grant durable d'accès au code indexé par Stripe subscription ID, puis rafraîchit ou révoque ce grant sur les événements d'abonnement.
Workflow MCP
Les outils du plan de contrôle (control plane) exposent le catalogue et le miroir des remises Stripe :
yayaw_billing_products_listyayaw_billing_product_updateyayaw_stripe_discounts_listyayaw_stripe_discounts_sync
Les écritures nécessitent control-plane:admin, l'autorisation Yayaw
billing-product:update et un reason.
Validation
Vérifications utiles après des changements du catalogue de facturation :
bun test src/lib/server/services/billing/billing-products.test.ts
bun test src/lib/server/services/billing/stripe-catalog-sync.test.ts
bun test src/lib/server/services/billing/billing-organization-view.test.ts
bun run test