Fix redirection Frisbii après ajout de moyen de paiement au premier abonnement
accept_url/cancel_url n'existent pas dans le schéma de POST /v1/subscription (ils y sont silencieusement ignorés) : Frisbii attend ces paramètres en query string sur le lien hosted_page_links.payment_info retourné. Ajout d'un warning loggé sur signature de webhook invalide, jusque-là silencieuse. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import os
|
||||
from urllib.parse import parse_qsl, urlencode, urlsplit, urlunsplit
|
||||
|
||||
import httpx
|
||||
|
||||
@@ -61,6 +62,13 @@ def update_customer(handle: str, data: dict) -> dict:
|
||||
return _call("PUT", f"/v1/customer/{handle}", json=data)
|
||||
|
||||
|
||||
def _with_query(url: str, **params: str) -> str:
|
||||
parts = urlsplit(url)
|
||||
query = dict(parse_qsl(parts.query))
|
||||
query.update(params)
|
||||
return urlunsplit(parts._replace(query=urlencode(query)))
|
||||
|
||||
|
||||
def create_subscription_session(
|
||||
plan_handle: str,
|
||||
handle: str,
|
||||
@@ -70,12 +78,13 @@ def create_subscription_session(
|
||||
customer_handle: str | None = None,
|
||||
create_customer: dict | None = None,
|
||||
) -> str:
|
||||
# CreateSubscription (POST /v1/subscription) n'a pas de champs accept_url/
|
||||
# cancel_url : ils doivent être ajoutés en query string sur le lien
|
||||
# hosted_page_links.payment_info renvoyé, pas dans le body (cf. doc Frisbii).
|
||||
body: dict = {
|
||||
"plan": plan_handle,
|
||||
"signup_method": "link",
|
||||
"handle": handle,
|
||||
"accept_url": accept_url,
|
||||
"cancel_url": cancel_url,
|
||||
}
|
||||
if customer_handle:
|
||||
body["customer"] = customer_handle
|
||||
@@ -84,7 +93,8 @@ def create_subscription_session(
|
||||
if no_trial:
|
||||
body["no_trial"] = True
|
||||
data = _call("POST", "/v1/subscription", json=body)
|
||||
return data["hosted_page_links"]["payment_info"]
|
||||
payment_info = data["hosted_page_links"]["payment_info"]
|
||||
return _with_query(payment_info, accept_url=accept_url, cancel_url=cancel_url)
|
||||
|
||||
|
||||
def create_recurring_session(
|
||||
|
||||
@@ -148,6 +148,9 @@ def cancel():
|
||||
def webhook():
|
||||
payload = request.get_json(silent=True) or {}
|
||||
if not webhooks.verify_signature(payload, os.getenv("FRISBII_WEBHOOK_SECRET", "")):
|
||||
logger.warning(
|
||||
"Webhook Frisbii : signature invalide (event %s)", payload.get("id")
|
||||
)
|
||||
return "", 403
|
||||
|
||||
customer = payload.get("customer")
|
||||
|
||||
@@ -43,7 +43,11 @@ def test_create_subscription_session_with_customer_handle(fake_httpx):
|
||||
"https://app/ko",
|
||||
customer_handle="colibre-1",
|
||||
)
|
||||
assert url == "https://checkout.reepay.com/#/sub-1"
|
||||
assert url == (
|
||||
"https://checkout.reepay.com/"
|
||||
"?accept_url=https%3A%2F%2Fapp%2Fok&cancel_url=https%3A%2F%2Fapp%2Fko"
|
||||
"#/sub-1"
|
||||
)
|
||||
body = fake_httpx["calls"][0]["json"]
|
||||
assert body["plan"] == "plan_simple"
|
||||
assert body["handle"] == "abo-1-1"
|
||||
@@ -51,6 +55,10 @@ def test_create_subscription_session_with_customer_handle(fake_httpx):
|
||||
assert body["signup_method"] == "link"
|
||||
assert "generate_handle" not in body
|
||||
assert "prepare_subscription" not in body
|
||||
# accept_url/cancel_url ne sont pas des champs de CreateSubscription :
|
||||
# Frisbii les ignore silencieusement s'ils sont dans le body.
|
||||
assert "accept_url" not in body
|
||||
assert "cancel_url" not in body
|
||||
|
||||
|
||||
def test_create_subscription_session_no_trial(fake_httpx):
|
||||
|
||||
Reference in New Issue
Block a user