From b53a7f363def5d36cc975561ac129daed555743a Mon Sep 17 00:00:00 2001
From: ValueOn AG
Date: Tue, 31 Mar 2026 00:47:28 +0200
Subject: [PATCH] fixes stripe
---
app.py | 25 +++++++++++++------------
env_int.env | 2 +-
modules/routes/routeSubscription.py | 21 +++++++++++++++++++--
3 files changed, 33 insertions(+), 15 deletions(-)
diff --git a/app.py b/app.py
index 63e5652a..f29436cc 100644
--- a/app.py
+++ b/app.py
@@ -489,18 +489,6 @@ def getAllowedOrigins():
CORS_ORIGIN_REGEX = r"https://.*\.(poweron\.swiss|poweron-center\.net)"
-# CORS configuration using environment variables
-app.add_middleware(
- CORSMiddleware,
- allow_origins=getAllowedOrigins(),
- allow_origin_regex=CORS_ORIGIN_REGEX,
- allow_credentials=True,
- allow_methods=["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
- allow_headers=["*"],
- expose_headers=["*"],
- max_age=86400, # Increased caching for preflight requests
-)
-
# SlowAPI rate limiter initialization
from modules.auth import limiter
from slowapi.errors import RateLimitExceeded
@@ -538,6 +526,19 @@ app.add_middleware(
ProactiveTokenRefreshMiddleware, enabled=True, check_interval_minutes=5
)
+# CORS must be registered LAST so it wraps the whole stack: every response (errors, CSRF 403,
+# rate limits) still gets Access-Control-Allow-Origin for browser cross-origin calls.
+app.add_middleware(
+ CORSMiddleware,
+ allow_origins=getAllowedOrigins(),
+ allow_origin_regex=CORS_ORIGIN_REGEX,
+ allow_credentials=True,
+ allow_methods=["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
+ allow_headers=["*"],
+ expose_headers=["*"],
+ max_age=86400,
+)
+
# Include all routers
from modules.routes.routeAdmin import router as generalRouter
diff --git a/env_int.env b/env_int.env
index 61981de1..fc9c0efd 100644
--- a/env_int.env
+++ b/env_int.env
@@ -53,7 +53,7 @@ Service_CLICKUP_OAUTH_REDIRECT_URI = http://localhost:8000/api/clickup/auth/conn
# Stripe Billing (both end with _SECRET for encryption script)
STRIPE_SECRET_KEY_SECRET = INT_ENC:Z0FBQUFBQnB5dkd5ekdBaGNGVUlOQUpncTlzLWlTV0V5OWZzQkpDczhCUGw4U1JpTHZ0d3pfYlFNWElLRlNiNlNsaDRYTGZUTkg2OUFrTW1GZXpOUjBVbmRQWjN6ekhHd2ZSQ195OHlaeWh1TmxrUm10V2R3YmdncmFLbFMzVjdqcWJMSUJPR2xuSEozclNoZG1rZVBTaWg3OFQ1Qzdxb0wyQ2RKazc2dG1aZXBUTXlvbDZqLS1KOVI5M3BGc3NQZkZRbnFpRjIwWmh2ZHlVNlpxZVo2dWNmMjQ5eW02QmtzUT09
-STRIPE_WEBHOOK_SECRET = INT_ENC:Z0FBQUFBQnB5dkd5VUszOWllM1E1YXlsdldIdENlUTd4bWhycVNBZVZzSWxlMjd4NEJwRnFVbnRaNTlGOWUyLVdxRUxySEtGRDdfbEVHM1dFTU93SHZtY1RKZkh0NG92M2cwYTQxQjQ0SFhqNXZnd21jbE52WW0wZC1oMlY3OXFFSV9sd2M1TC10N0hZa2Zha3FzX1FhcE14alo2TGFHX3QybHFxOTlQWWFZR3pabkRtOEp1Zm1zOFlrbDF0MFNkUjUyVFI5NUNZaU5TRXF4X29tcEQ2RUR1MTlXcUoxbTl0dz09
+STRIPE_WEBHOOK_SECRET = whsec_2agCQEbDPSOn2C40EJcwoPCqlvaPLF7M
STRIPE_API_VERSION = 2026-01-28.clover
# AI configuration
diff --git a/modules/routes/routeSubscription.py b/modules/routes/routeSubscription.py
index 88d0b21c..3193292c 100644
--- a/modules/routes/routeSubscription.py
+++ b/modules/routes/routeSubscription.py
@@ -291,14 +291,31 @@ def verifyCheckout(
logger.error("Failed to retrieve checkout session %s: %s", data.sessionId, e)
raise HTTPException(status_code=400, detail="Invalid session ID")
- if session.get("status") != "complete" or session.get("payment_status") != "paid":
+ payStatus = session.get("payment_status")
+ if session.get("status") != "complete":
+ return {"status": "pending", "message": "Checkout not yet completed"}
+ # Subscription checkouts with trial / $0 first period use no_payment_required, not paid.
+ if payStatus not in ("paid", "no_payment_required"):
return {"status": "pending", "message": "Checkout not yet completed"}
if session.get("mode") != "subscription":
raise HTTPException(status_code=400, detail="Not a subscription checkout session")
from modules.routes.routeBilling import _handleSubscriptionCheckoutCompleted
- _handleSubscriptionCheckoutCompleted(session, f"verify-{data.sessionId}")
+
+ try:
+ _handleSubscriptionCheckoutCompleted(session, f"verify-{data.sessionId}")
+ except Exception as e:
+ logger.exception(
+ "verifyCheckout: handler failed for session %s mandate %s: %s",
+ data.sessionId,
+ mandateId,
+ e,
+ )
+ raise HTTPException(
+ status_code=500,
+ detail="Subscription-Aktivierung nach Checkout fehlgeschlagen. Bitte erneut versuchen oder Support informieren.",
+ ) from e
return {"status": "activated", "message": "Subscription activated"}