Stripe checkout: products created, signup flow with plan selection, API endpoints

This commit is contained in:
2026-04-13 20:29:08 +02:00
parent ce79bdb43a
commit da059c081e
4 changed files with 235 additions and 60 deletions
+2 -1
View File
@@ -4,7 +4,8 @@ module.exports = {
script: '/var/www/autojobs/backend/start_server.py',
interpreter: 'python3',
env: {
DB_PATH: '/var/www/autojobs/autojobs.db'
DB_PATH: '/var/www/autojobs/autojobs.db',
STRIPE_SECRET_KEY: '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'
},
autorestart: true,
watch: false,
+107 -2
View File
@@ -1,8 +1,10 @@
"""
AutoJobs API — FastAPI Backend
Multi-user job search with per-user API keys + subscription plans
import os
import stripe
"""
from fastapi import FastAPI, HTTPException, Depends, APIRouter
from fastapi import FastAPI, HTTPException, Depends, APIRouter, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from pydantic import BaseModel
@@ -926,4 +928,107 @@ def admin_reset_usage(user_id: str = None):
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
uvicorn.run(app, host="0.0.0.0", port=8000)
# --- Stripe Price IDs ---
STRIPE_PRICE_IDS = {
"free": None,
"starter": "price_1TLp9OEqqBlW1z4N8zXPHPjM",
"pro": "price_1TLp9PEqqBlW1z4NmP5sVrA1",
"ultra": "price_1TLp9QEqqBlW1z4NpjjV13Kb",
"unlimited": "price_1TLp9REqqBlW1z4NR2c92fmM",
"agency_starter": "price_1TLp9SEqqBlW1z4Ny9MabLz3",
"agency_growth": "price_1TLp9TEqqBlW1z4N2t2noudV",
"agency_scale": "price_1TLp9UEqqBlW1z4NgWPSg7nr",
"agency_pro": "price_1TLp9VEqqBlW1z4NgtQWlUnv",
"agency_enterprise": None,
}
# --- Stripe Checkout Endpoint ---
@app.post("/autojobs/api/create-checkout")
async def create_checkout(request: Request):
try:
body = await request.json()
plan_id = body.get("plan_id")
user_id = body.get("user_id")
user_type = body.get("user_type", "private")
if not plan_id or not user_id:
return JSONResponse({"error": "Missing plan_id or user_id"}, status_code=400)
price_id = STRIPE_PRICE_IDS.get(plan_id)
if price_id is None and plan_id != "agency_enterprise":
return JSONResponse({"error": "Invalid plan"}, status_code=400)
user = db.get("SELECT * FROM users WHERE id = ?", (user_id,))
if not user:
return JSONResponse({"error": "User not found"}, status_code=404)
if plan_id == "free":
# Free plan - just update and return
db.run("UPDATE users SET plan = ?, user_type = ? WHERE id = ?", (plan_id, user_type, user_id))
return JSONResponse({"success": True, "plan": plan_id})
if plan_id == "agency_enterprise":
return JSONResponse({"error": "Contact us for enterprise pricing"}, status_code=400)
# Get or create Stripe customer
stripe.api_key = os.environ.get("STRIPE_SECRET_KEY")
customer = stripe.Customer.create(
email=user["email"],
name=user["name"],
metadata={"autojobs_user_id": str(user_id)}
)
checkout_session = stripe.checkout.Session.create(
customer=customer.id,
payment_method_types=["card"],
line_items=[{"price": price_id, "quantity": 1}],
mode="subscription",
success_url="https://hostpioneers.com/autojobs/dashboard?session_id={CHECKOUT_SESSION_ID}",
cancel_url="https://hostpioneers.com/autojobs/pricing?canceled=true",
metadata={"user_id": str(user_id), "plan_id": plan_id, "user_type": user_type},
subscription_data={"metadata": {"user_id": str(user_id), "plan_id": plan_id}}
)
return JSONResponse({"checkout_url": checkout_session.url})
except Exception as e:
import traceback
return JSONResponse({"error": str(e), "trace": traceback.format_exc()}, status_code=500)
# --- Stripe Webhook ---
@app.post("/autojobs/api/stripe-webhook")
async def stripe_webhook(request: Request):
stripe.api_key = os.environ.get("STRIPE_SECRET_KEY")
payload = await request.body()
sig = request.headers.get("stripe-signature", "")
webhook_secret = os.environ.get("STRIPE_WEBHOOK_SECRET", "")
try:
if webhook_secret:
event = stripe.Webhook.construct_event(payload, sig, webhook_secret)
else:
event = json.loads(payload)
event_type = event.get("type", "")
if event_type == "checkout.session.completed":
session = event["data"]["object"]
user_id = session["metadata"]["user_id"]
plan_id = session["metadata"]["plan_id"]
stripe_sub_id = session.get("subscription")
db.run("UPDATE users SET plan = ?, stripe_subscription_id = ?, stripe_customer_id = ? WHERE id = ?",
(plan_id, stripe_sub_id, session.get("customer"), user_id))
elif event_type == "customer.subscription.deleted":
sub = event["data"]["object"]
customer_id = sub.get("customer")
db.run("UPDATE users SET plan = 'free' WHERE stripe_customer_id = ?", (customer_id,))
return JSONResponse({"received": True})
except Exception as e:
import traceback
return JSONResponse({"error": str(e), "trace": traceback.format_exc()}, status_code=400)