// routes/purchases.js const express = require('express'); const router = express.Router(); const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY); const requireAuth = require('../middleware/auth'); const Stream, Purchase = require('../models');
// Update purchase record await Purchase.update( stripe_charge_id: session.payment_intent , where: user_id: userId, stream_id: streamId, stripe_charge_id: null ); camwhores.v
// Render the video player (e.g., HLS.js, Vimeo, or your streaming CDN) return ( <div> <h2>stream.title</h2> <video controls src=stream.video_url style= width: '100%', maxWidth: '800px' /> </div> ); // routes/purchases
// (Optional) send email receipt, log analytics, etc. // routes/purchases.js const express = require('express')
-- Streams (live or recorded) CREATE TABLE streams ( id BIGSERIAL PRIMARY KEY, model_id BIGINT REFERENCES users(id), title VARCHAR(255), is_live BOOLEAN DEFAULT FALSE, start_time TIMESTAMP, end_time TIMESTAMP, is_premium BOOLEAN DEFAULT FALSE, -- true = requires purchase/subscription price_cents INTEGER, -- optional PPV price thumbnail_url VARCHAR(255) ); | Method | URL | Description | Auth | |--------|-----|-------------|------| | GET /api/plans | List all subscription plans | Public | | POST /api/subscriptions | Create a Stripe Checkout session for a plan | Viewer (JWT) | | POST /api/webhooks/stripe | Handle subscription events ( invoice.payment_succeeded , customer.subscription.deleted ) | Stripe secret | | GET /api/streams/:id | Retrieve stream metadata; includes access flag | Viewer (JWT) | | POST /api/purchases/:streamId | Create a PPV checkout session for a specific stream | Viewer (JWT) | | GET /api/user/me | Current user profile + subscription status | Viewer/Model (JWT) |
const buyAccess = async () => const data = await axios.post(`/api/purchases/$id`); window.location.href = data.checkoutUrl; ;
if (event.type === 'checkout.session.completed') const session = event.data.object; const userId, streamId = session.metadata;