-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add support for customer portal sessions (#79)
- Loading branch information
1 parent
de2d28a
commit 09e393c
Showing
17 changed files
with
315 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
from __future__ import annotations | ||
from dataclasses import dataclass | ||
from datetime import datetime | ||
|
||
from paddle_billing.Entities.Entity import Entity | ||
from paddle_billing.Entities.CustomerPortalSessions import CustomerPortalSessionUrls | ||
|
||
|
||
@dataclass | ||
class CustomerPortalSession(Entity): | ||
id: str | ||
customer_id: str | None | ||
urls: CustomerPortalSessionUrls | ||
created_at: datetime | ||
|
||
@staticmethod | ||
def from_dict(data: dict) -> CustomerPortalSession: | ||
return CustomerPortalSession( | ||
id=data["id"], | ||
customer_id=data.get("customer_id"), | ||
urls=CustomerPortalSessionUrls.from_dict(data["urls"]), | ||
created_at=datetime.fromisoformat(data["created_at"]), | ||
) |
13 changes: 13 additions & 0 deletions
13
paddle_billing/Entities/CustomerPortalSessions/CustomerPortalSessionGeneralUrl.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
from __future__ import annotations | ||
from dataclasses import dataclass | ||
|
||
|
||
@dataclass | ||
class CustomerPortalSessionGeneralUrl: | ||
overview: str | ||
|
||
@staticmethod | ||
def from_dict(data: dict) -> CustomerPortalSessionGeneralUrl: | ||
return CustomerPortalSessionGeneralUrl( | ||
overview=data["overview"], | ||
) |
17 changes: 17 additions & 0 deletions
17
paddle_billing/Entities/CustomerPortalSessions/CustomerPortalSessionSubscriptionUrl.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
from __future__ import annotations | ||
from dataclasses import dataclass | ||
|
||
|
||
@dataclass | ||
class CustomerPortalSessionSubscriptionUrl: | ||
id: str | ||
cancel_subscription: str | ||
update_subscription_payment_method: str | ||
|
||
@staticmethod | ||
def from_dict(data: dict) -> CustomerPortalSessionSubscriptionUrl: | ||
return CustomerPortalSessionSubscriptionUrl( | ||
id=data["id"], | ||
cancel_subscription=data["cancel_subscription"], | ||
update_subscription_payment_method=data["update_subscription_payment_method"], | ||
) |
24 changes: 24 additions & 0 deletions
24
paddle_billing/Entities/CustomerPortalSessions/CustomerPortalSessionUrls.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
from __future__ import annotations | ||
from dataclasses import dataclass | ||
|
||
from paddle_billing.Entities.CustomerPortalSessions.CustomerPortalSessionGeneralUrl import ( | ||
CustomerPortalSessionGeneralUrl, | ||
) | ||
from paddle_billing.Entities.CustomerPortalSessions.CustomerPortalSessionSubscriptionUrl import ( | ||
CustomerPortalSessionSubscriptionUrl, | ||
) | ||
|
||
|
||
@dataclass | ||
class CustomerPortalSessionUrls: | ||
general: CustomerPortalSessionGeneralUrl | ||
subscriptions: list[CustomerPortalSessionSubscriptionUrl] | ||
|
||
@staticmethod | ||
def from_dict(data: dict) -> CustomerPortalSessionUrls: | ||
return CustomerPortalSessionUrls( | ||
general=CustomerPortalSessionGeneralUrl.from_dict(data["general"]), | ||
subscriptions=[ | ||
CustomerPortalSessionSubscriptionUrl.from_dict(item) for item in data.get("subscriptions", []) | ||
], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
from paddle_billing.Entities.CustomerPortalSessions.CustomerPortalSessionUrls import CustomerPortalSessionUrls | ||
from paddle_billing.Entities.CustomerPortalSessions.CustomerPortalSessionGeneralUrl import ( | ||
CustomerPortalSessionGeneralUrl, | ||
) | ||
from paddle_billing.Entities.CustomerPortalSessions.CustomerPortalSessionSubscriptionUrl import ( | ||
CustomerPortalSessionSubscriptionUrl, | ||
) |
24 changes: 24 additions & 0 deletions
24
paddle_billing/Resources/CustomerPortalSessions/CustomerPortalSessionsClient.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
from paddle_billing.ResponseParser import ResponseParser | ||
|
||
from paddle_billing.Entities.CustomerPortalSession import CustomerPortalSession | ||
|
||
from paddle_billing.Resources.CustomerPortalSessions.Operations import ( | ||
CreateCustomerPortalSession, | ||
) | ||
|
||
from typing import TYPE_CHECKING | ||
|
||
if TYPE_CHECKING: | ||
from paddle_billing.Client import Client | ||
|
||
|
||
class CustomerPortalSessionsClient: | ||
def __init__(self, client: "Client"): | ||
self.client = client | ||
self.response = None | ||
|
||
def create(self, customer_id: str, operation: CreateCustomerPortalSession) -> CustomerPortalSession: | ||
self.response = self.client.post_raw(f"/customers/{customer_id}/portal-sessions", operation) | ||
parser = ResponseParser(self.response) | ||
|
||
return CustomerPortalSession.from_dict(parser.get_data()) |
8 changes: 8 additions & 0 deletions
8
paddle_billing/Resources/CustomerPortalSessions/Operations/CreateCustomerPortalSession.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from dataclasses import dataclass | ||
|
||
from paddle_billing.Operation import Operation | ||
|
||
|
||
@dataclass | ||
class CreateCustomerPortalSession(Operation): | ||
subscription_ids: list[str] = (None,) |
3 changes: 3 additions & 0 deletions
3
paddle_billing/Resources/CustomerPortalSessions/Operations/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from paddle_billing.Resources.CustomerPortalSessions.Operations.CreateCustomerPortalSession import ( | ||
CreateCustomerPortalSession, | ||
) |
Empty file.
Empty file.
6 changes: 6 additions & 0 deletions
6
tests/Functional/Resources/CustomerPortalSessions/_fixtures/request/create_multiple.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"subscription_ids": [ | ||
"sub_01h04vsc0qhwtsbsxh3422wjs4", | ||
"sub_02h04vsc0qhwtsbsxh3422wjs4" | ||
] | ||
} |
5 changes: 5 additions & 0 deletions
5
tests/Functional/Resources/CustomerPortalSessions/_fixtures/request/create_single.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"subscription_ids": [ | ||
"sub_01h04vsc0qhwtsbsxh3422wjs4" | ||
] | ||
} |
27 changes: 27 additions & 0 deletions
27
.../Functional/Resources/CustomerPortalSessions/_fixtures/response/full_entity_multiple.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
{ | ||
"data": { | ||
"id": "cpls_01h4ge9r64c22exjsx0fy8b48b", | ||
"customer_id": "ctm_01gysfvfy7vqhpzkq8rjmrq7an", | ||
"urls": { | ||
"general": { | ||
"overview": "https://customer-portal.paddle.com/cpl_01j7zbyqs3vah3aafp4jf62qaw?action=overview&token=pga_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjdG1fMDFncm5uNHp0YTVhMW1mMDJqanplN3kyeXMiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE3Mjc2NzkyMzh9._oO12IejzdKmyKTwb7BLjmiILkx4_cSyGjXraOBUI_g" | ||
}, | ||
"subscriptions": [ | ||
{ | ||
"id": "sub_01h04vsc0qhwtsbsxh3422wjs4", | ||
"cancel_subscription": "https://customer-portal.paddle.com/cpl_01j7zbyqs3vah3aafp4jf62qaw?action=cancel_subscription&subscription_id=sub_01h04vsc0qhwtsbsxh3422wjs4&token=pga_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjdG1fMDFncm5uNHp0YTVhMW1mMDJqanplN3kyeXMiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE3Mjc2NzkyMzh9._oO12IejzdKmyKTwb7BLjmiILkx4_cSyGjXraOBUI_g", | ||
"update_subscription_payment_method": "https://customer-portal.paddle.com/cpl_01j7zbyqs3vah3aafp4jf62qaw?action=update_subscription_payment_method&subscription_id=sub_01h04vsc0qhwtsbsxh3422wjs4&token=pga_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjdG1fMDFncm5uNHp0YTVhMW1mMDJqanplN3kyeXMiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE3Mjc2NzkyMzh9._oO12IejzdKmyKTwb7BLjmiILkx4_cSyGjXraOBUI_g" | ||
}, | ||
{ | ||
"id": "sub_02h04vsc0qhwtsbsxh3422wjs4", | ||
"cancel_subscription": "https://customer-portal.paddle.com/cpl_01j7zbyqs3vah3aafp4jf62qaw?action=cancel_subscription&subscription_id=sub_02h04vsc0qhwtsbsxh3422wjs4&token=pga_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjdG1fMDFncm5uNHp0YTVhMW1mMDJqanplN3kyeXMiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE3Mjc2NzkyMzh9._oO12IejzdKmyKTwb7BLjmiILkx4_cSyGjXraOBUI_g", | ||
"update_subscription_payment_method": "https://customer-portal.paddle.com/cpl_01j7zbyqs3vah3aafp4jf62qaw?action=update_subscription_payment_method&subscription_id=sub_02h04vsc0qhwtsbsxh3422wjs4&token=pga_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjdG1fMDFncm5uNHp0YTVhMW1mMDJqanplN3kyeXMiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE3Mjc2NzkyMzh9._oO12IejzdKmyKTwb7BLjmiILkx4_cSyGjXraOBUI_g" | ||
} | ||
] | ||
}, | ||
"created_at": "2024-10-25T06:53:58Z" | ||
}, | ||
"meta": { | ||
"request_id": "fa176777-4bca-49ec-aa1e-f53885333cb7" | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
tests/Functional/Resources/CustomerPortalSessions/_fixtures/response/full_entity_single.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ | ||
"data": { | ||
"id": "cpls_01h4ge9r64c22exjsx0fy8b48b", | ||
"customer_id": "ctm_01gysfvfy7vqhpzkq8rjmrq7an", | ||
"urls": { | ||
"general": { | ||
"overview": "https://customer-portal.paddle.com/cpl_01j7zbyqs3vah3aafp4jf62qaw?action=overview&token=pga_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjdG1fMDFncm5uNHp0YTVhMW1mMDJqanplN3kyeXMiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE3Mjc2NzkyMzh9._oO12IejzdKmyKTwb7BLjmiILkx4_cSyGjXraOBUI_g" | ||
}, | ||
"subscriptions": [ | ||
{ | ||
"id": "sub_01h04vsc0qhwtsbsxh3422wjs4", | ||
"cancel_subscription": "https://customer-portal.paddle.com/cpl_01j7zbyqs3vah3aafp4jf62qaw?action=cancel_subscription&subscription_id=sub_01h04vsc0qhwtsbsxh3422wjs4&token=pga_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjdG1fMDFncm5uNHp0YTVhMW1mMDJqanplN3kyeXMiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE3Mjc2NzkyMzh9._oO12IejzdKmyKTwb7BLjmiILkx4_cSyGjXraOBUI_g", | ||
"update_subscription_payment_method": "https://customer-portal.paddle.com/cpl_01j7zbyqs3vah3aafp4jf62qaw?action=update_subscription_payment_method&subscription_id=sub_01h04vsc0qhwtsbsxh3422wjs4&token=pga_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjdG1fMDFncm5uNHp0YTVhMW1mMDJqanplN3kyeXMiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE3Mjc2NzkyMzh9._oO12IejzdKmyKTwb7BLjmiILkx4_cSyGjXraOBUI_g" | ||
} | ||
] | ||
}, | ||
"created_at": "2024-10-25T06:53:58Z" | ||
}, | ||
"meta": { | ||
"request_id": "fa176777-4bca-49ec-aa1e-f53885333cb7" | ||
} | ||
} |
127 changes: 127 additions & 0 deletions
127
tests/Functional/Resources/CustomerPortalSessions/test_CustomerPortalSessionsClient.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
from json import loads | ||
from pytest import mark | ||
from urllib.parse import unquote | ||
|
||
from paddle_billing.Entities.CustomerPortalSession import CustomerPortalSession | ||
from paddle_billing.Entities.CustomerPortalSessions import ( | ||
CustomerPortalSessionUrls, | ||
CustomerPortalSessionGeneralUrl, | ||
CustomerPortalSessionSubscriptionUrl, | ||
) | ||
|
||
from paddle_billing.Resources.CustomerPortalSessions.Operations import CreateCustomerPortalSession | ||
|
||
from tests.Utils.ReadsFixture import ReadsFixtures | ||
|
||
|
||
class TestAddressesClient: | ||
@mark.parametrize( | ||
"customer_id, operation, expected_request_body, expected_response_body, expected_path", | ||
[ | ||
( | ||
"ctm_01gysfvfy7vqhpzkq8rjmrq7an", | ||
CreateCustomerPortalSession(["sub_01h04vsc0qhwtsbsxh3422wjs4"]), | ||
ReadsFixtures.read_raw_json_fixture("request/create_single"), | ||
ReadsFixtures.read_raw_json_fixture("response/full_entity_single"), | ||
"/customers/ctm_01gysfvfy7vqhpzkq8rjmrq7an/portal-sessions", | ||
), | ||
( | ||
"ctm_01gysfvfy7vqhpzkq8rjmrq7an", | ||
CreateCustomerPortalSession(["sub_01h04vsc0qhwtsbsxh3422wjs4", "sub_02h04vsc0qhwtsbsxh3422wjs4"]), | ||
ReadsFixtures.read_raw_json_fixture("request/create_multiple"), | ||
ReadsFixtures.read_raw_json_fixture("response/full_entity_multiple"), | ||
"/customers/ctm_01gysfvfy7vqhpzkq8rjmrq7an/portal-sessions", | ||
), | ||
], | ||
ids=[ | ||
"Create portal session with single subscription ID", | ||
"Create portal session with multiple subscription IDs", | ||
], | ||
) | ||
def test_create_uses_expected_payload( | ||
self, | ||
test_client, | ||
mock_requests, | ||
customer_id, | ||
operation, | ||
expected_request_body, | ||
expected_response_body, | ||
expected_path, | ||
): | ||
expected_url = f"{test_client.base_url}{expected_path}" | ||
mock_requests.post(expected_url, status_code=201, text=expected_response_body) | ||
|
||
response = test_client.client.customer_portal_sessions.create(customer_id, operation) | ||
response_json = test_client.client.customer_portal_sessions.response.json() | ||
request_json = test_client.client.payload | ||
last_request = mock_requests.last_request | ||
|
||
assert isinstance(response, CustomerPortalSession) | ||
assert last_request is not None | ||
assert last_request.method == "POST" | ||
assert test_client.client.status_code == 201 | ||
assert ( | ||
unquote(last_request.url) == expected_url | ||
), "The URL does not match the expected URL, verify the query string is correct" | ||
assert loads(request_json) == loads( | ||
expected_request_body | ||
), "The request JSON doesn't match the expected fixture JSON" | ||
assert response_json == loads( | ||
str(expected_response_body) | ||
), "The response JSON doesn't match the expected fixture JSON" | ||
|
||
def test_create_returns_expected_response( | ||
self, | ||
test_client, | ||
mock_requests, | ||
): | ||
customer_id = "ctm_01gysfvfy7vqhpzkq8rjmrq7an" | ||
expected_path = "/customers/ctm_01gysfvfy7vqhpzkq8rjmrq7an/portal-sessions" | ||
expected_response_body = ReadsFixtures.read_raw_json_fixture("response/full_entity_multiple") | ||
|
||
expected_url = f"{test_client.base_url}{expected_path}" | ||
mock_requests.post(expected_url, status_code=201, text=expected_response_body) | ||
|
||
response = test_client.client.customer_portal_sessions.create( | ||
customer_id, | ||
CreateCustomerPortalSession(["sub_01h04vsc0qhwtsbsxh3422wjs4", "sub_02h04vsc0qhwtsbsxh3422wjs4"]), | ||
) | ||
|
||
assert isinstance(response, CustomerPortalSession) | ||
assert response.id == "cpls_01h4ge9r64c22exjsx0fy8b48b" | ||
assert response.customer_id == customer_id | ||
assert response.created_at.isoformat() == "2024-10-25T06:53:58+00:00" | ||
|
||
urls = response.urls | ||
assert isinstance(urls, CustomerPortalSessionUrls) | ||
|
||
general = urls.general | ||
assert isinstance(general, CustomerPortalSessionGeneralUrl) | ||
assert ( | ||
general.overview | ||
== "https://customer-portal.paddle.com/cpl_01j7zbyqs3vah3aafp4jf62qaw?action=overview&token=pga_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjdG1fMDFncm5uNHp0YTVhMW1mMDJqanplN3kyeXMiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE3Mjc2NzkyMzh9._oO12IejzdKmyKTwb7BLjmiILkx4_cSyGjXraOBUI_g" | ||
) | ||
|
||
subscription1 = urls.subscriptions[0] | ||
assert isinstance(subscription1, CustomerPortalSessionSubscriptionUrl) | ||
assert subscription1.id == "sub_01h04vsc0qhwtsbsxh3422wjs4" | ||
assert ( | ||
subscription1.cancel_subscription | ||
== "https://customer-portal.paddle.com/cpl_01j7zbyqs3vah3aafp4jf62qaw?action=cancel_subscription&subscription_id=sub_01h04vsc0qhwtsbsxh3422wjs4&token=pga_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjdG1fMDFncm5uNHp0YTVhMW1mMDJqanplN3kyeXMiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE3Mjc2NzkyMzh9._oO12IejzdKmyKTwb7BLjmiILkx4_cSyGjXraOBUI_g" | ||
) | ||
assert ( | ||
subscription1.update_subscription_payment_method | ||
== "https://customer-portal.paddle.com/cpl_01j7zbyqs3vah3aafp4jf62qaw?action=update_subscription_payment_method&subscription_id=sub_01h04vsc0qhwtsbsxh3422wjs4&token=pga_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjdG1fMDFncm5uNHp0YTVhMW1mMDJqanplN3kyeXMiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE3Mjc2NzkyMzh9._oO12IejzdKmyKTwb7BLjmiILkx4_cSyGjXraOBUI_g" | ||
) | ||
|
||
subscription2 = urls.subscriptions[1] | ||
assert isinstance(subscription2, CustomerPortalSessionSubscriptionUrl) | ||
assert subscription2.id == "sub_02h04vsc0qhwtsbsxh3422wjs4" | ||
assert ( | ||
subscription2.cancel_subscription | ||
== "https://customer-portal.paddle.com/cpl_01j7zbyqs3vah3aafp4jf62qaw?action=cancel_subscription&subscription_id=sub_02h04vsc0qhwtsbsxh3422wjs4&token=pga_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjdG1fMDFncm5uNHp0YTVhMW1mMDJqanplN3kyeXMiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE3Mjc2NzkyMzh9._oO12IejzdKmyKTwb7BLjmiILkx4_cSyGjXraOBUI_g" | ||
) | ||
assert ( | ||
subscription2.update_subscription_payment_method | ||
== "https://customer-portal.paddle.com/cpl_01j7zbyqs3vah3aafp4jf62qaw?action=update_subscription_payment_method&subscription_id=sub_02h04vsc0qhwtsbsxh3422wjs4&token=pga_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjdG1fMDFncm5uNHp0YTVhMW1mMDJqanplN3kyeXMiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE3Mjc2NzkyMzh9._oO12IejzdKmyKTwb7BLjmiILkx4_cSyGjXraOBUI_g" | ||
) |