fix: Stripe billing portal auto-config programmatique, separation changer-forfait vs gerer-facturation
Some checks failed
Deploy to Production / Build and Deploy (push) Has been cancelled
Some checks failed
Deploy to Production / Build and Deploy (push) Has been cancelled
This commit is contained in:
@@ -434,6 +434,65 @@ async def cancel_subscription(user_id: str) -> Dict[str, Any]:
|
||||
return {"error": str(e)}
|
||||
|
||||
|
||||
# ─── cached portal config id (created once per process) ───────────────────────
|
||||
_PORTAL_CONFIG_ID: Optional[str] = None
|
||||
|
||||
|
||||
def _get_or_create_portal_config() -> Optional[str]:
|
||||
"""
|
||||
Return a Stripe Customer Portal configuration ID.
|
||||
Creates one programmatically if none exists yet, so no Stripe Dashboard
|
||||
manual setup is required.
|
||||
"""
|
||||
global _PORTAL_CONFIG_ID
|
||||
if _PORTAL_CONFIG_ID:
|
||||
return _PORTAL_CONFIG_ID
|
||||
|
||||
try:
|
||||
# Re-use the first existing configuration if there is one
|
||||
existing = stripe.billing_portal.Configuration.list(active=True, limit=1)
|
||||
if existing.data:
|
||||
_PORTAL_CONFIG_ID = existing.data[0].id
|
||||
return _PORTAL_CONFIG_ID
|
||||
|
||||
# Create a minimal configuration programmatically
|
||||
config = stripe.billing_portal.Configuration.create(
|
||||
business_profile={
|
||||
"headline": "Wordly.art — Gérer mon abonnement",
|
||||
},
|
||||
features={
|
||||
"invoice_history": {"enabled": True},
|
||||
"payment_method_update": {"enabled": True},
|
||||
"subscription_cancel": {
|
||||
"enabled": True,
|
||||
"mode": "at_period_end", # keeps access until end of paid period
|
||||
"proration_behavior": "none",
|
||||
"cancellation_reason": {
|
||||
"enabled": True,
|
||||
"options": [
|
||||
"too_expensive",
|
||||
"missing_features",
|
||||
"switched_service",
|
||||
"unused",
|
||||
"other",
|
||||
],
|
||||
},
|
||||
},
|
||||
"customer_update": {
|
||||
"enabled": True,
|
||||
"allowed_updates": ["email", "name", "address"],
|
||||
},
|
||||
},
|
||||
)
|
||||
_PORTAL_CONFIG_ID = config.id
|
||||
logger.info("Stripe portal configuration created: %s", _PORTAL_CONFIG_ID)
|
||||
return _PORTAL_CONFIG_ID
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Failed to get/create Stripe portal config: %s", e)
|
||||
return None
|
||||
|
||||
|
||||
async def get_billing_portal_url(user_id: str) -> Optional[str]:
|
||||
"""Get Stripe billing portal URL for customer"""
|
||||
if not is_stripe_configured():
|
||||
@@ -444,11 +503,20 @@ async def get_billing_portal_url(user_id: str) -> Optional[str]:
|
||||
return None
|
||||
|
||||
try:
|
||||
session = stripe.billing_portal.Session.create(
|
||||
customer=user.stripe_customer_id,
|
||||
return_url=f"{os.getenv('FRONTEND_URL', 'http://localhost:3000')}/dashboard/profile?tab=subscription"
|
||||
)
|
||||
config_id = _get_or_create_portal_config()
|
||||
kwargs: Dict[str, Any] = {
|
||||
"customer": user.stripe_customer_id,
|
||||
"return_url": (
|
||||
f"{os.getenv('FRONTEND_URL', 'http://localhost:3000')}"
|
||||
"/dashboard/profile?tab=subscription"
|
||||
),
|
||||
}
|
||||
if config_id:
|
||||
kwargs["configuration"] = config_id
|
||||
|
||||
session = stripe.billing_portal.Session.create(**kwargs)
|
||||
return session.url
|
||||
except Exception as e:
|
||||
logger.error("get_billing_portal_url error: %s", e)
|
||||
return None
|
||||
|
||||
|
||||
Reference in New Issue
Block a user