Stripe
Stripe Billing adapter for subscriptions and entitlements.
Setup
lib/billing.ts
import { createEnhancedClient } from "@fuime/billing-sdk";
import { stripe } from "@fuime/billing-sdk/stripe";
export const billing = createEnhancedClient({
provider: stripe({
apiKey: process.env.STRIPE_SECRET_KEY!,
webhookSecret: process.env.STRIPE_WEBHOOK_SECRET,
}),
cache: { ttlMs: 60_000 },
plans: {
prod_pro: { features: ["api", "export"] },
prod_enterprise: { features: "*" },
},
});Environment variables
.env.local
STRIPE_SECRET_KEY=sk_live_xxx
STRIPE_WEBHOOK_SECRET=whsec_xxxHow it works
The adapter uses the Stripe API to:
- Get entitlements - Fetches the customer's active subscriptions by
metadata.userId - Parse webhooks - Verifies signatures and normalizes events
Customer metadata
The adapter looks up customers by metadata.userId. When creating a Stripe customer:
const customer = await stripe.customers.create({
email: user.email,
metadata: {
userId: user.id, // Required for the SDK
},
});Webhook events
| Stripe Event | SDK Event |
|---|---|
customer.subscription.created | subscription.created |
customer.subscription.updated | subscription.updated |
customer.subscription.deleted | subscription.deleted |
Webhook endpoint
app/api/webhooks/stripe/route.ts
import { billing } from "@/lib/billing";
export async function POST(request: Request) {
const body = await request.text();
const signature = request.headers.get("stripe-signature")!;
try {
const event = await billing.parseWebhook(body, signature);
console.log(`${event.type} for user ${event.userId}`);
return new Response("ok");
} catch (err) {
return new Response("Invalid signature", { status: 400 });
}
}Stripe Dashboard setup
- Go to Developers → Webhooks in the Stripe Dashboard
- Add an endpoint:
https://yourapp.com/api/webhooks/stripe - Select events:
customer.subscription.* - Copy the signing secret to
STRIPE_WEBHOOK_SECRET