diff --git a/src/subscriptions/client.py b/src/subscriptions/client.py index 59be217..cab5248 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 @@ -137,5 +138,20 @@ def get_subscription(subscription_handle: str) -> dict: return _call("GET", f"/v1/subscription/{subscription_handle}") +def get_payment_info_url(sub_handle: str, accept_url: str, cancel_url: str) -> str: + sub = get_subscription(sub_handle) + url = sub["hosted_page_links"]["payment_info"] + parts = urlsplit(url) + query = dict(parse_qsl(parts.query)) + query["accept_url"] = accept_url + query["cancel_url"] = cancel_url + new_query = urlencode(query) + # If URL has a fragment (hash-based routing), append params to fragment + if parts.fragment: + return f"{urlunsplit((parts.scheme, parts.netloc, parts.path, '', ''))}#{parts.fragment}?{new_query}" + else: + return urlunsplit(parts._replace(query=new_query)) + + def get_plan(plan_handle: str) -> dict: return _call("GET", f"/v1/plan/{plan_handle}") diff --git a/tests/subscriptions/test_client.py b/tests/subscriptions/test_client.py index 347795a..e86d8c9 100644 --- a/tests/subscriptions/test_client.py +++ b/tests/subscriptions/test_client.py @@ -89,3 +89,45 @@ def test_http_error_raises_frisbii_error(fake_httpx): with pytest.raises(client.FrisbiiError) as exc: client.get_plan("plan_simple") assert exc.value.status_code == 500 + + +def test_get_payment_info_url_appends_query_params(fake_httpx): + fake_httpx["queue"].append( + fake_httpx["Response"]( + 200, + { + "handle": "abo-1-1", + "hosted_page_links": { + "payment_info": "https://checkout.reepay.com/#/subscription/pay/en_GB/x/abo-1-1" + }, + }, + ) + ) + url = client.get_payment_info_url( + "abo-1-1", + "https://app/compte/abonnement?carte=succes", + "https://app/compte/abonnement?carte=annule", + ) + assert url.startswith( + "https://checkout.reepay.com/#/subscription/pay/en_GB/x/abo-1-1" + ) + assert "accept_url=https%3A%2F%2Fapp%2Fcompte%2Fabonnement%3Fcarte%3Dsucces" in url + assert "cancel_url=https%3A%2F%2Fapp%2Fcompte%2Fabonnement%3Fcarte%3Dannule" in url + + +def test_get_payment_info_url_merges_existing_query_string(fake_httpx): + fake_httpx["queue"].append( + fake_httpx["Response"]( + 200, + { + "handle": "abo-1-2", + "hosted_page_links": { + "payment_info": "https://checkout.reepay.com/pay/abo-1-2?locale=fr" + }, + }, + ) + ) + url = client.get_payment_info_url("abo-1-2", "https://app/ok", "https://app/ko") + assert "locale=fr" in url + assert "accept_url=https%3A%2F%2Fapp%2Fok" in url + assert "cancel_url=https%3A%2F%2Fapp%2Fko" in url