feat: Stripe integration complete - products created, DB migration, payment_failed handler, credit buttons wired
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m5s
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m5s
- Create Stripe products/prices (Starter/Pro/Business monthly+yearly) - Fix CRITICAL bug: add subscription_ends_at + cancel_at_period_end columns to users table - Alembic migration: f6a7b8c9d0e1_add_subscription_ends_at_cancel_at_period_end - Fix: implement handle_payment_failed() to set subscription_status=PAST_DUE - Fix: harmonize .env.production Stripe variable names to match pricing_config.py - Fix: add missing FRONTEND_URL and STRIPE_PUBLISHABLE_KEY to .env.production - Add all Stripe Price IDs (test mode) to .env.production - Wire credit purchase buttons to /api/v1/auth/create-credits-checkout - Dashboard sync post-checkout was already implemented (no change needed) Stripe test keys: configured in .env.production Webhook: must be configured on server via stripe CLI or Stripe Dashboard Webhook URL: https://wordly.art/api/v1/auth/webhook/stripe
This commit is contained in:
77
scripts/stripe_setup.py
Normal file
77
scripts/stripe_setup.py
Normal file
@@ -0,0 +1,77 @@
|
||||
"""
|
||||
Script de setup Stripe : crée les produits et prix dans Stripe Dashboard.
|
||||
Lance avec : python scripts/stripe_setup.py
|
||||
"""
|
||||
import stripe
|
||||
import sys
|
||||
|
||||
SK = "sk_test_51SkSHkCKXUJE51jnbEtXZ0nKiTHTa8ohDwLH8fZiDVEx6Ze0g5dg4fGJJgX1VgNHvF93GE3HTramT3oQrCaqOxid00OXTcZlsW"
|
||||
stripe.api_key = SK
|
||||
|
||||
PLANS = [
|
||||
{"id": "starter", "name": "Wordly Starter", "monthly_eur": 900, "yearly_eur": 8640},
|
||||
{"id": "pro", "name": "Wordly Pro", "monthly_eur": 1900, "yearly_eur": 18240},
|
||||
{"id": "business","name": "Wordly Business","monthly_eur": 4900, "yearly_eur": 47040},
|
||||
]
|
||||
|
||||
results = {}
|
||||
for plan in PLANS:
|
||||
print(f"\n>> Creation produit {plan['name']}...")
|
||||
# Search existing product first
|
||||
existing = stripe.Product.search(query=f"name:'{plan['name']}'", limit=1)
|
||||
if existing.data:
|
||||
product = existing.data[0]
|
||||
print(f" Produit existant: {product.id}")
|
||||
else:
|
||||
product = stripe.Product.create(
|
||||
name=plan["name"],
|
||||
metadata={"plan_id": plan["id"]}
|
||||
)
|
||||
print(f" Produit créé: {product.id}")
|
||||
|
||||
# Monthly price
|
||||
monthly_prices = stripe.Price.list(product=product.id, active=True, limit=10)
|
||||
monthly_price = None
|
||||
yearly_price = None
|
||||
for p in monthly_prices.data:
|
||||
if p.recurring and p.recurring.interval == "month" and p.unit_amount == plan["monthly_eur"]:
|
||||
monthly_price = p
|
||||
if p.recurring and p.recurring.interval == "year" and p.unit_amount == plan["yearly_eur"]:
|
||||
yearly_price = p
|
||||
|
||||
if not monthly_price:
|
||||
monthly_price = stripe.Price.create(
|
||||
product=product.id,
|
||||
unit_amount=plan["monthly_eur"],
|
||||
currency="eur",
|
||||
recurring={"interval": "month"},
|
||||
metadata={"plan_id": plan["id"], "billing": "monthly"}
|
||||
)
|
||||
print(f" Prix mensuel créé: {monthly_price.id}")
|
||||
else:
|
||||
print(f" Prix mensuel existant: {monthly_price.id}")
|
||||
|
||||
if not yearly_price:
|
||||
yearly_price = stripe.Price.create(
|
||||
product=product.id,
|
||||
unit_amount=plan["yearly_eur"],
|
||||
currency="eur",
|
||||
recurring={"interval": "year"},
|
||||
metadata={"plan_id": plan["id"], "billing": "yearly"}
|
||||
)
|
||||
print(f" Prix annuel créé: {yearly_price.id}")
|
||||
else:
|
||||
print(f" Prix annuel existant: {yearly_price.id}")
|
||||
|
||||
results[plan["id"]] = {
|
||||
"monthly": monthly_price.id,
|
||||
"yearly": yearly_price.id,
|
||||
}
|
||||
|
||||
print("\n" + "="*60)
|
||||
print("Variables à ajouter dans .env.production et .env :")
|
||||
print("="*60)
|
||||
for plan_id, ids in results.items():
|
||||
print(f"STRIPE_PRICE_{plan_id.upper()}_MONTHLY={ids['monthly']}")
|
||||
print(f"STRIPE_PRICE_{plan_id.upper()}_YEARLY={ids['yearly']}")
|
||||
print("="*60)
|
||||
Reference in New Issue
Block a user