Formulaire d'infos de facturation avant paiement (#abonnement)
- Nouvelle page /compte/abonnement/mes-infos avec formulaire deux colonnes (prénom, nom, SIRET, entreprise, adresse, CP, ville, pays) - Lookup SIRET via l'annuaire des entreprises pour pré-remplissage - Cases à cocher obligatoires : renonciation rétractation + CGU (modale) - Le bouton Valider est désactivé tant que les deux cases ne sont pas cochées - Pays : liste déroulante des 20 pays de la zone euro, France par défaut - Le SIRET est stocké dans users.siret (migration 0002) pour pré-remplissage - Pré-remplissage des infos Frisbii (GET customer) si déjà client - Côté Frisbii : update_customer si client existant, create_customer sinon - Les URLs accept/cancel sont désormais transmises dans le body Frisbii - Mise à jour des CGU : distinction données decp.info vs Frisbii Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -36,32 +36,38 @@ def _call(method: str, path: str, json: dict | None = None) -> dict:
|
||||
except httpx.RequestError as exc:
|
||||
raise FrisbiiError(0, str(exc)) from exc
|
||||
if resp.status_code >= 400:
|
||||
print(resp.text)
|
||||
raise FrisbiiError(resp.status_code, resp.text)
|
||||
return resp.json()
|
||||
|
||||
|
||||
def get_or_create_customer(handle: str, email: str) -> dict:
|
||||
try:
|
||||
return _call("GET", f"/v1/customer/{handle}")
|
||||
except FrisbiiError as exc:
|
||||
if exc.status_code != 404:
|
||||
raise
|
||||
return _call("POST", "/v1/customer", json={"handle": handle, "email": email})
|
||||
def get_customer(handle: str) -> dict:
|
||||
return _call("GET", f"/v1/customer/{handle}")
|
||||
|
||||
|
||||
def update_customer(handle: str, data: dict) -> dict:
|
||||
return _call("PUT", f"/v1/customer/{handle}", json=data)
|
||||
|
||||
|
||||
def create_subscription_session(
|
||||
plan_handle: str,
|
||||
customer_handle: str,
|
||||
accept_url: str,
|
||||
cancel_url: str,
|
||||
no_trial: bool = False,
|
||||
customer_handle: str | None = None,
|
||||
create_customer: dict | None = None,
|
||||
) -> str:
|
||||
body: dict = {
|
||||
"plan": plan_handle,
|
||||
"customer": customer_handle,
|
||||
"signup_method": "link",
|
||||
"generate_handle": True,
|
||||
"accept_url": accept_url,
|
||||
"cancel_url": cancel_url,
|
||||
}
|
||||
if customer_handle:
|
||||
body["customer"] = customer_handle
|
||||
elif create_customer:
|
||||
body["create_customer"] = create_customer
|
||||
if no_trial:
|
||||
body["no_trial"] = True
|
||||
data = _call("POST", "/v1/subscription", json=body)
|
||||
|
||||
@@ -3,6 +3,7 @@ import os
|
||||
from flask import Blueprint, redirect, request
|
||||
from flask_login import current_user, login_required
|
||||
|
||||
from src.auth import db as auth_db
|
||||
from src.subscriptions import client, db, plans, webhooks
|
||||
from src.utils import logger
|
||||
|
||||
@@ -28,19 +29,55 @@ def subscribe():
|
||||
cust = _customer_handle(current_user.id)
|
||||
try:
|
||||
meta = plans.plan_meta(plan_key)
|
||||
client.get_or_create_customer(cust, current_user.email)
|
||||
db.create_pending(
|
||||
current_user.id, cust, plan_key, meta["prix_ht"] if meta else None
|
||||
)
|
||||
# Anti-abus : pas de nouvel essai si l'utilisateur en a déjà consommé un.
|
||||
no_trial = db.has_used_trial(current_user.id)
|
||||
url = client.create_subscription_session(
|
||||
handle,
|
||||
cust,
|
||||
f"{base}/compte/abonnement?paiement=succes",
|
||||
f"{base}/compte/abonnement?paiement=annule",
|
||||
no_trial=no_trial,
|
||||
)
|
||||
siret = (request.form.get("siret") or "").strip()
|
||||
billing: dict = {
|
||||
"email": current_user.email,
|
||||
"first_name": request.form.get("first_name", ""),
|
||||
"last_name": request.form.get("last_name", ""),
|
||||
"address": request.form.get("address", ""),
|
||||
"city": request.form.get("city", ""),
|
||||
"postal_code": request.form.get("postal_code", ""),
|
||||
"country": request.form.get("country", "FR"),
|
||||
}
|
||||
if request.form.get("address2"):
|
||||
billing["address2"] = request.form["address2"]
|
||||
if request.form.get("company"):
|
||||
billing["company"] = request.form["company"]
|
||||
|
||||
if siret:
|
||||
auth_db.set_siret(current_user.id, siret)
|
||||
|
||||
customer_exists = True
|
||||
try:
|
||||
client.update_customer(cust, billing)
|
||||
except client.FrisbiiError as exc:
|
||||
if exc.status_code != 404:
|
||||
raise
|
||||
customer_exists = False
|
||||
|
||||
if customer_exists:
|
||||
url = client.create_subscription_session(
|
||||
handle,
|
||||
f"{base}/compte/abonnement?paiement=succes",
|
||||
f"{base}/compte/abonnement?paiement=annule",
|
||||
customer_handle=cust,
|
||||
no_trial=no_trial,
|
||||
)
|
||||
else:
|
||||
create_customer = {"handle": cust, **billing}
|
||||
if siret:
|
||||
create_customer["metadata"] = {"siret": siret}
|
||||
url = client.create_subscription_session(
|
||||
handle,
|
||||
f"{base}/compte/abonnement?paiement=succes",
|
||||
f"{base}/compte/abonnement?paiement=annule",
|
||||
create_customer=create_customer,
|
||||
no_trial=no_trial,
|
||||
)
|
||||
except client.FrisbiiError:
|
||||
logger.exception("Échec de création de session d'abonnement Frisbii")
|
||||
return redirect("/compte/abonnement?error=frisbii")
|
||||
|
||||
Reference in New Issue
Block a user