diff --git a/src/subscriptions/client.py b/src/subscriptions/client.py index d8422cf..4b33394 100644 --- a/src/subscriptions/client.py +++ b/src/subscriptions/client.py @@ -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( diff --git a/src/subscriptions/routes.py b/src/subscriptions/routes.py index c884a2e..4061f7e 100644 --- a/src/subscriptions/routes.py +++ b/src/subscriptions/routes.py @@ -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") diff --git a/tests/subscriptions/test_client.py b/tests/subscriptions/test_client.py index 1b20017..0d86150 100644 --- a/tests/subscriptions/test_client.py +++ b/tests/subscriptions/test_client.py @@ -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):