feat: Stripe Checkout integration with 7-day free trial for all subscription tiers#83
Draft
feat: Stripe Checkout integration with 7-day free trial for all subscription tiers#83
Conversation
Co-authored-by: Bitpass-dev <186615221+Bitpass-dev@users.noreply.github.com>
…eEffect dep, simplify nullish coalescing Co-authored-by: Bitpass-dev <186615221+Bitpass-dev@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Integrate Stripe Checkout for subscription management
feat: Stripe Checkout integration with 7-day free trial for all subscription tiers
Mar 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Wires up Stripe Checkout for the three subscription tiers (Single €9.99, Triple €19.99, All Access €29.99), each with a 7-day free trial. Covers the full subscription lifecycle via webhooks.
Backend
stripe.ts—create-checkout-sessionnow accepts{ priceId }and maps to plan name via hardcoded lookup; session usestrial_period_days: 7, success/cancel URLs useFRONTEND_URLwith production fallback:Webhook handlers updated/added:
checkout.session.completedsubscription_status = 'trialing', setstrial_ends_at,stripe_subscription_idcustomer.subscription.updatedsubscription.statuscustomer.subscription.deletedplan = 'free',subscription_status = 'cancelled'invoice.payment_failedsubscription_status = 'past_due'migrations/004_add_stripe_fields.sql—IF NOT EXISTSmigration forstripe_customer_id,stripe_subscription_id,trial_ends_at(safe against existing schema from001).env.example— addsSTRIPE_PUBLISHABLE_KEY, locks in the three live EUR price IDsFrontend
pages/api/create-checkout-session.ts— Next.js API proxy forwarding to backend withAuthorizationheader passthroughpages/landing.tsx— "Start Free Trial" pricing card buttons wired tohandleSubscribe(priceId); unauthenticated users redirected to/signup; per-button loading state; error display below pricing gridpages/dashboard.tsx— shows dismissible success banner (🎉 Welcome! Your 7-day free trial has started.) when?subscription=successis present; URL cleaned via shallow routingpages/checkout.tsx— updated to send{ priceId, sports }using aPLAN_PRICE_IDSmap instead of{ plan, sports }Original prompt
Stripe Checkout Integration — 7-Day Free Trial
Integrate Stripe Checkout into the AI Sports Almanac app to handle paid subscriptions for the three pricing tiers, each with a 7-day free trial.
Stripe Price IDs (live, EUR)
price_1TAAKQPfPehc9iSUDPPWTaqbprice_1TAALHPfPehc9iSUuHHj00NOprice_1TAAM8PfPehc9iSU9mJxnfDQWhat needs to be implemented
1. Backend —
AI-Sports-Almanac/backend/Install Stripe:
Add
stripetopackage.jsondependencies.New file:
AI-Sports-Almanac/backend/src/api/routes/stripe.tsCreate a new Express router with the following endpoints:
POST /api/stripe/create-checkout-session(authenticated){ priceId: string }in request bodyprice_1TAAKQPfPehc9iSUDPPWTaqb→singleprice_1TAALHPfPehc9iSUuHHj00NO→tripleprice_1TAAM8PfPehc9iSU9mJxnfDQ→all_accessmode: 'subscription'subscription_data: { trial_period_days: 7 }success_url: 'https://aisportsalmanac.io/dashboard?subscription=success'cancel_url: 'https://aisportsalmanac.io/pricing'customer_email: set to the authenticated user's emailmetadata: { userId: req.user.id, plan: planName }{ url: session.url }POST /api/stripe/webhook(public, no auth, raw body)STRIPE_WEBHOOK_SECRETenv varcheckout.session.completed→ update user's plan in DB to the plan from metadata, setsubscription_status = 'trialing', storestripe_customer_idandstripe_subscription_idcustomer.subscription.updated→ updatesubscription_statusbased onsubscription.statuscustomer.subscription.deleted→ set user plan tofree, setsubscription_status = 'cancelled'invoice.payment_failed→ setsubscription_status = 'past_due'poolfrom../../utils/dbto update the users tableloggerfrom../../utils/loggerUpdate
AI-Sports-Almanac/backend/src/index.ts:/api/stripe/webhookroute BEFORE the json body parser (this is critical for webhook signature verification)app.use('/api/stripe', stripeRouter)Update
AI-Sports-Almanac/backend/src/api/routes/admin.ts:Update
.env.exampleatAI-Sports-Almanac/backend/.env.example:Add:
New migration file:
AI-Sports-Almanac/backend/migrations/004_add_stripe_fields.sql2. Frontend —
AI-Sports-Almanac/frontend/New file:
AI-Sports-Almanac/frontend/pages/api/create-checkout-session.ts(Next.js API proxy)/api/stripe/create-checkout-sessionUpdate the pricing page / "Start Free Trial" buttons:
Look in
AI-Sports-Almanac/frontend/pages/andAI-Sports-Almanac/frontend/components/for the pricing page (likelypricing.tsxor similar, or aPricingcomponent).Add a
handleSubscribefunction that:tokenkey)/api/stripe/create-checkout-sessionwith the appropriatepriceIdurl(Stripe Checkout page)Map the buttons to the correct price IDs:
price_1TAAKQPfPehc9iSUDPPWTaqbprice_1TAALHPfPehc9iSUuHHj00NOprice_1TAAM8PfPehc9iSU9mJxnfDQNew file:
AI-Sports-Almanac/frontend/pages/dashboard/subscription-success.tsxOR handle in the dashboard page:?subscription=successquery param is present on the dashboard, show a success banner: "🎉 Welcome! Your 7-day free trial has started. Enjoy full access!"3. Root
.env.exampleupdateUpdate
AI-Sports-Almanac/.env.exampleto include the Stripe environment variables.Important notes
express.raw({ type: 'application/json' })middleware, NOTexpress.json(), for Stripe signature verification to workprocess.env.STRIPE_SECRET_KEYfor the Stripe client initialisationprocess.env.STRIPE_WEBHOOK_SECRETfor webhook verificationThis pull request was created from Copilot chat.
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.