fexed stripe webhook
This commit is contained in:
parent
b53a7f363d
commit
350c699473
2 changed files with 41 additions and 12 deletions
|
|
@ -994,6 +994,25 @@ class BillingObjects:
|
|||
)
|
||||
return created
|
||||
|
||||
def ensureActivationBudget(self, mandateId: str, planKey: str) -> Optional[Dict[str, Any]]:
|
||||
"""Idempotent: credit the activation budget only if no SUBSCRIPTION credit exists yet."""
|
||||
poolAccount = self.getMandateAccount(mandateId)
|
||||
if not poolAccount:
|
||||
return self.creditSubscriptionBudget(mandateId, planKey, periodLabel="Erstaktivierung")
|
||||
|
||||
existing = self.db.getRecordset(
|
||||
BillingTransaction,
|
||||
recordFilter={
|
||||
"accountId": poolAccount["id"],
|
||||
"transactionType": TransactionTypeEnum.CREDIT.value,
|
||||
"referenceType": ReferenceTypeEnum.SUBSCRIPTION.value,
|
||||
},
|
||||
)
|
||||
if existing:
|
||||
return None
|
||||
|
||||
return self.creditSubscriptionBudget(mandateId, planKey, periodLabel="Erstaktivierung")
|
||||
|
||||
# =========================================================================
|
||||
# Workflow Cost Query
|
||||
# =========================================================================
|
||||
|
|
|
|||
|
|
@ -273,10 +273,8 @@ def verifyCheckout(
|
|||
):
|
||||
"""Verify a Stripe Checkout Session and activate the subscription if paid.
|
||||
|
||||
This is the synchronous counterpart to the checkout.session.completed webhook.
|
||||
It's called by the frontend immediately after returning from Stripe to handle
|
||||
environments where webhooks may be delayed or unavailable (e.g. localhost dev).
|
||||
The logic is idempotent — if the webhook already processed the session, this is a no-op.
|
||||
Idempotent: if the webhook already processed the session, returns success.
|
||||
Called by the frontend immediately after returning from Stripe.
|
||||
"""
|
||||
mandateId = _resolveMandateId(context)
|
||||
if not mandateId:
|
||||
|
|
@ -294,7 +292,6 @@ def verifyCheckout(
|
|||
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"}
|
||||
|
||||
|
|
@ -306,19 +303,32 @@ def verifyCheckout(
|
|||
try:
|
||||
_handleSubscriptionCheckoutCompleted(session, f"verify-{data.sessionId}")
|
||||
except Exception as e:
|
||||
logger.exception(
|
||||
"verifyCheckout: handler failed for session %s mandate %s: %s",
|
||||
logger.warning(
|
||||
"verifyCheckout: handler raised 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
|
||||
|
||||
from modules.serviceCenter.services.serviceSubscription.mainServiceSubscription import (
|
||||
getService as getSubscriptionService,
|
||||
)
|
||||
from modules.datamodels.datamodelSubscription import OPERATIVE_STATUSES
|
||||
|
||||
subService = getSubscriptionService(context.user, mandateId)
|
||||
operative = subService.getOperativeSubscription(mandateId)
|
||||
if operative and operative.get("status") in [s.value for s in OPERATIVE_STATUSES]:
|
||||
planKey = operative.get("planKey", "")
|
||||
if planKey:
|
||||
try:
|
||||
from modules.interfaces.interfaceDbBilling import _getRootInterface as _getBillingRoot
|
||||
_getBillingRoot().ensureActivationBudget(mandateId, planKey)
|
||||
except Exception as ex:
|
||||
logger.warning("verifyCheckout: ensureActivationBudget failed: %s", ex)
|
||||
return {"status": "activated", "message": "Subscription activated"}
|
||||
|
||||
return {"status": "pending", "message": "Subscription activation pending — webhook may still be processing."}
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# SysAdmin: global subscription overview
|
||||
|
|
|
|||
Loading…
Reference in a new issue