Facturation
@bext-stack/framework/billing est la couche Stripe réutilisable bext que les sites continuent de réimplémenter par site – une façade de style caissier sur la fonctionnalité Rust Fournisseurs de paiement. Il s'agit d'un wrapper fin et typé sur l'API Stripe REST (pas de SDK stripe - juste fetch et l'encodage de formulaire) plus l'élément critique en matière de sécurité que tout le monde se trompe : vérification de la signature du webhook.
Quand l'utiliser#
- Démarrez un abonnement ou un paiement ponctuel.
- Envoyez un client vers le portail de facturation Stripe.
- Fonctionnalités Gate sur un abonnement actif.
- Vérifiez les webhooks Stripe entrants en toute sécurité.
Paiement et abonnements#
import { createBilling, subscribed } from "@bext-stack/framework/billing";
const billing = createBilling({ secretKey: process.env.STRIPE_SECRET_KEY });
// action — start a subscription checkout, redirect to the returned url:
const { url } = await billing.checkoutSession({
priceId: "price_pro", mode: "subscription",
successUrl: "https://app/ok", cancelUrl: "https://app/cancel",
customer: "cus_1", // or customerEmail for a new customer
});
// gate features on an active subscription:
const subs = await billing.listSubscriptions({ customer: "cus_1" });
if (subscribed(subs)) { /* unlock */ }
await billing.cancelSubscription("sub_1", { atPeriodEnd: true });
const { url: portal } = await billing.portalSession({ customer: "cus_1", returnUrl: "https://app/account" });
| Membre | Fait |
|---|---|
createCustomer({ email, name?, metadata? }) |
créer un client Stripe |
checkoutSession({ priceId, mode?, successUrl, cancelUrl, customer? | customerEmail? }) |
une session de paiement (.url vers laquelle rediriger) |
portalSession({ customer, returnUrl }) |
une URL de session du portail de facturation |
listSubscriptions({ customer, status? }) |
les abonnements du client |
cancelSubscription(id, { atPeriodEnd? }) |
annuler maintenant (DELETE) ou en fin de période |
raw(method, path, form?) |
n’importe quel point de terminaison Stripe |
subscribed(subs, { statuses? }) |
tout abonnement donne-t-il droit (actif/en cours d'essai) |
Webhooks : vérifiez la signature#
Ne faites jamais confiance à un corps de webhook sans le vérifier. constructEvent reconstruit
${timestamp}.${payload}, HMAC-SHA256s it (hex), à temps constant se compare au v1 de l'en-tête et applique une tolérance de relecture :
import { constructEvent } from "@bext-stack/framework/billing";
export async function POST({ request }: { request: Request }) {
const body = await request.text(); // the RAW body — verify before parsing
const event = constructEvent(body, request.headers.get("stripe-signature"), process.env.STRIPE_WEBHOOK_SECRET!);
if (!event) return new Response("bad signature", { status: 400 });
if (event.type === "checkout.session.completed") { /* mark the subscription active */ }
return new Response(null, { status: 200 });
}
verifyStripeSignature(payload, header, secret, toleranceSecs?) est la forme booléenne ; signStripePayload(payload, secret, ts) crée un en-tête valide (pour tester / se moquer d'un expéditeur).
Le transport HTTP est injectable : passez secretKey pour un vrai Stripe, ou un
request simulé pour les tests : votre code de facturation est donc testable unitairement sans réseau ni clé, et la vérification du webhook est testable avec signStripePayload.
Relation avec la capacité des fournisseurs de paiement#
La fonctionnalité Rust Fournisseurs de paiement est la couture du fournisseur côté serveur. Ce module est le client isolé TypeScript qu'une application PRISM appelle directement pour les flux Stripe courants - un package réutilisable au lieu d'une colle par site.
Essayez-le#
Le démo de facturation en direct exécute le cycle de vie d'abonnement → actif → annulation sur un transport Stripe simulé (état persisté via le ORM ) et affiche une signature de webhook valide ou falsifiée acceptée/rejetée en direct. Source dans
sites/demo/src/app/examples/billing/page.tsx.
Voir aussi#
- Fournisseurs de paiement — la capacité Rust que cela complète.
- Données et migrations : où l'état de l'abonnement persiste.
- Authentification — le signataire HMAC réutilisé.
- Boîte à outils de candidature — le reste de la couche d'application TypeScript.