convex-billing

Tambahkan penagihan/pembayaran Stripe ke aplikasi Convex melalui @convex-dev/stripe (checkout + webhook + gating).

npx skills add https://github.com/get-convex/agent-skills --skill convex-billing

Add billing / payments

Wire Stripe to Convex using @convex-dev/stripe: a checkout action, an httpAction webhook registered by the component (signature-verified automatically), subscription state stored in the component's tables, and server-side gating via a query.

Workflow

  1. Install the component: npm install @convex-dev/stripe.
  2. Create convex/convex.config.ts:
    import { defineApp } from 'convex/server';
    import stripe from '@convex-dev/stripe/convex.config.js';
    const app = defineApp();
    app.use(stripe);
    export default app;
    
  3. Store Stripe keys in Convex env (use the env micro power): STRIPE_SECRET_KEY (sk_test_… / sk_live_…) and STRIPE_WEBHOOK_SECRET (whsec_…).
  4. Create convex/http.ts to register the webhook route (the component handles signature verification automatically):
    import { httpRouter } from 'convex/server';
    import { components } from './_generated/api';
    import { registerRoutes } from '@convex-dev/stripe';
    const http = httpRouter();
    registerRoutes(http, components.stripe, { webhookPath: '/stripe/webhook' });
    export default http;
    
  5. Create convex/billing.ts with a checkout action and a subscription-gate query:
    import { action, query } from './_generated/server';
    import { components } from './_generated/api';
    import { StripeSubscriptions } from '@convex-dev/stripe';
    import { v } from 'convex/values';
    const stripeClient = new StripeSubscriptions(components.stripe, {});
    export const createSubscriptionCheckout = action({
      args: { priceId: v.string() },
      returns: v.object({ sessionId: v.string(), url: v.union(v.string(), v.null()) }),
      handler: async (ctx, args) => {
        const identity = await ctx.auth.getUserIdentity();
        if (!identity) throw new Error('Not authenticated');
        const customer = await stripeClient.getOrCreateCustomer(ctx, { userId: identity.subject, email: identity.email, name: identity.name });
        return await stripeClient.createCheckoutSession(ctx, { priceId: args.priceId, customerId: customer.customerId, mode: 'subscription', successUrl: `${process.env.SITE_URL ?? 'http://localhost:3000'}/?success=true`, cancelUrl: `${process.env.SITE_URL ?? 'http://localhost:3000'}/?canceled=true`, subscriptionMetadata: { userId: identity.subject } });
      },
    });
    export const isSubscribed = query({
      args: {},
      returns: v.boolean(),
      handler: async (ctx) => {
        const identity = await ctx.auth.getUserIdentity();
        if (!identity) return false;
        const subscriptions = await ctx.runQuery(components.stripe.public.listSubscriptionsByUserId, { userId: identity.subject });
        return subscriptions.some((sub) => sub.status === 'active' || sub.status === 'trialing');
      },
    });
    
  6. Run npx convex dev --once — it will install the component and push the functions. Verify output shows ✔ Installed component stripe.
  7. In Stripe Dashboard → Webhooks: add endpoint https://<deployment>.convex.site/stripe/webhook, subscribe to checkout.session.completed, customer.subscription.*, invoice.*, payment_intent.*. Copy the signing secret as STRIPE_WEBHOOK_SECRET.

Rules

  • Use @convex-dev/stripe (npm: @convex-dev/stripe@^0.1.4) — it handles webhook signature verification internally via registerRoutes; do NOT write a manual constructEvent webhook.
  • Stripe keys live in Convex env (use the env micro power): STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET.
  • Gate on server-stored subscription state via isSubscribed query (reads component tables), not client claims.
  • convex/convex.config.ts must import from '@convex-dev/stripe/convex.config.js' (not .ts) — the .js extension is required by the Convex bundler.

Lebih banyak skill dari get-convex

convex-performance-audit
get-convex
Mengaudit performa Convex untuk pembacaan, langganan, kontensi penulisan, dan batas fungsi. Gunakan untuk fitur lambat, temuan wawasan, konflik OCC, atau amplifikasi pembacaan.
developmentdatabasedata-analysis
convex
get-convex
Mengarahkan permintaan Convex umum ke skill proyek yang tepat. Gunakan saat pengguna bertanya skill Convex mana yang harus digunakan atau memberikan tugas aplikasi Convex yang tidak dispesifikasikan secara jelas.
developmentdatabase
convex-setup-auth
get-convex
Menyiapkan auth Convex, pemetaan identitas, dan kontrol akses. Gunakan untuk login, penyedia auth, tabel pengguna, fungsi yang dilindungi, atau peran dalam aplikasi Convex.
developmentdatabaseapi
convex-quickstart
get-convex
Membuat atau menambahkan Convex ke aplikasi. Gunakan untuk proyek Convex baru, npm create convex@latest, pengaturan frontend, variabel lingkungan, atau menjalankan npx convex dev pertama kali.
developmentdatabase
convex-migration-helper
get-convex
Merencanakan migrasi skema dan data Convex dengan widen-migrate-narrow dan @convex-dev/migrations. Gunakan untuk perubahan skema yang bersifat breaking, backfill, pembentukan ulang tabel, atau peluncuran tanpa downtime.
developmentdatabase
convex-create-component
get-convex
Membangun komponen Convex yang dapat digunakan kembali dengan tabel terisolasi dan API yang menghadap aplikasi. Gunakan untuk komponen baru, modul backend yang dapat digunakan kembali, integrasi, atau pekerjaan batas komponen.
developmentdatabase
convex-migrate
get-convex
Migrasikan skema + isi ulang data pada aplikasi Convex yang diterapkan menggunakan @convex-dev/migrations.
developmentdatabase
convex-optimize
get-convex
Audit dan optimalkan aplikasi Convex yang ada: keamanan, skala, peningkatan, observabilitas.