paddle-python-sdk 1.1.1__py3-none-any.whl → 1.2.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. paddle_billing/Client.py +3 -1
  2. paddle_billing/Entities/CustomerPortalSession.py +23 -0
  3. paddle_billing/Entities/CustomerPortalSessions/CustomerPortalSessionGeneralUrl.py +13 -0
  4. paddle_billing/Entities/CustomerPortalSessions/CustomerPortalSessionSubscriptionUrl.py +17 -0
  5. paddle_billing/Entities/CustomerPortalSessions/CustomerPortalSessionUrls.py +24 -0
  6. paddle_billing/Entities/CustomerPortalSessions/__init__.py +7 -0
  7. paddle_billing/Entities/NotificationSetting.py +3 -1
  8. paddle_billing/Entities/NotificationSettings/NotificationSettingTrafficSource.py +7 -0
  9. paddle_billing/Entities/NotificationSettings/__init__.py +3 -0
  10. paddle_billing/Entities/Subscriptions/SubscriptionDiscount.py +3 -3
  11. paddle_billing/Notifications/Entities/Subscription.py +1 -1
  12. paddle_billing/Notifications/Entities/SubscriptionCreated.py +1 -1
  13. paddle_billing/Notifications/Entities/Subscriptions/SubscriptionDiscount.py +3 -3
  14. paddle_billing/Resources/CustomerPortalSessions/CustomerPortalSessionsClient.py +24 -0
  15. paddle_billing/Resources/CustomerPortalSessions/Operations/CreateCustomerPortalSession.py +9 -0
  16. paddle_billing/Resources/CustomerPortalSessions/Operations/__init__.py +3 -0
  17. paddle_billing/Resources/CustomerPortalSessions/__init__.py +0 -0
  18. paddle_billing/Resources/NotificationSettings/Operations/CreateNotificationSetting.py +2 -1
  19. paddle_billing/Resources/NotificationSettings/Operations/ListNotificationSettings.py +6 -0
  20. paddle_billing/Resources/NotificationSettings/Operations/UpdateNotificationSetting.py +2 -0
  21. paddle_billing/Resources/Notifications/NotificationsClient.py +1 -1
  22. {paddle_python_sdk-1.1.1.dist-info → paddle_python_sdk-1.2.2.dist-info}/METADATA +10 -10
  23. {paddle_python_sdk-1.1.1.dist-info → paddle_python_sdk-1.2.2.dist-info}/RECORD +32 -20
  24. {paddle_python_sdk-1.1.1.dist-info → paddle_python_sdk-1.2.2.dist-info}/WHEEL +1 -1
  25. tests/Functional/Resources/CustomerPortalSessions/__init__.py +0 -0
  26. tests/Functional/Resources/CustomerPortalSessions/test_CustomerPortalSessionsClient.py +143 -0
  27. tests/Functional/Resources/NotificationSettings/test_NotificationSettingsClient.py +127 -1
  28. tests/Functional/Resources/Notifications/test_NotificationsClient.py +2 -2
  29. tests/Functional/Resources/PaymentMethods/test_PaymentMethodsClient.py +4 -2
  30. tests/Functional/Resources/Subscriptions/test_SubscriptionsClient.py +21 -0
  31. {paddle_python_sdk-1.1.1.dist-info → paddle_python_sdk-1.2.2.dist-info}/LICENSE +0 -0
  32. {paddle_python_sdk-1.1.1.dist-info → paddle_python_sdk-1.2.2.dist-info}/top_level.txt +0 -0
paddle_billing/Client.py CHANGED
@@ -20,6 +20,7 @@ from paddle_billing.Resources.Addresses.AddressesClient import AddressesClient
20
20
  from paddle_billing.Resources.Adjustments.AdjustmentsClient import AdjustmentsClient
21
21
  from paddle_billing.Resources.Businesses.BusinessesClient import BusinessesClient
22
22
  from paddle_billing.Resources.Customers.CustomersClient import CustomersClient
23
+ from paddle_billing.Resources.CustomerPortalSessions.CustomerPortalSessionsClient import CustomerPortalSessionsClient
23
24
  from paddle_billing.Resources.Discounts.DiscountsClient import DiscountsClient
24
25
  from paddle_billing.Resources.Events.EventsClient import EventsClient
25
26
  from paddle_billing.Resources.EventTypes.EventTypesClient import EventTypesClient
@@ -85,6 +86,7 @@ class Client:
85
86
  self.adjustments = AdjustmentsClient(self)
86
87
  self.businesses = BusinessesClient(self)
87
88
  self.customers = CustomersClient(self)
89
+ self.customer_portal_sessions = CustomerPortalSessionsClient(self)
88
90
  self.discounts = DiscountsClient(self)
89
91
  self.events = EventsClient(self)
90
92
  self.event_types = EventTypesClient(self)
@@ -202,7 +204,7 @@ class Client:
202
204
  "Authorization": f"Bearer {self.__api_key}",
203
205
  "Content-Type": "application/json",
204
206
  "Paddle-Version": str(self.use_api_version),
205
- "User-Agent": "PaddleSDK/python 1.1.1",
207
+ "User-Agent": "PaddleSDK/python 1.2.2",
206
208
  }
207
209
  )
208
210
 
@@ -0,0 +1,23 @@
1
+ from __future__ import annotations
2
+ from dataclasses import dataclass
3
+ from datetime import datetime
4
+
5
+ from paddle_billing.Entities.Entity import Entity
6
+ from paddle_billing.Entities.CustomerPortalSessions import CustomerPortalSessionUrls
7
+
8
+
9
+ @dataclass
10
+ class CustomerPortalSession(Entity):
11
+ id: str
12
+ customer_id: str
13
+ urls: CustomerPortalSessionUrls
14
+ created_at: datetime
15
+
16
+ @staticmethod
17
+ def from_dict(data: dict) -> CustomerPortalSession:
18
+ return CustomerPortalSession(
19
+ id=data["id"],
20
+ customer_id=data["customer_id"],
21
+ urls=CustomerPortalSessionUrls.from_dict(data["urls"]),
22
+ created_at=datetime.fromisoformat(data["created_at"]),
23
+ )
@@ -0,0 +1,13 @@
1
+ from __future__ import annotations
2
+ from dataclasses import dataclass
3
+
4
+
5
+ @dataclass
6
+ class CustomerPortalSessionGeneralUrl:
7
+ overview: str
8
+
9
+ @staticmethod
10
+ def from_dict(data: dict) -> CustomerPortalSessionGeneralUrl:
11
+ return CustomerPortalSessionGeneralUrl(
12
+ overview=data["overview"],
13
+ )
@@ -0,0 +1,17 @@
1
+ from __future__ import annotations
2
+ from dataclasses import dataclass
3
+
4
+
5
+ @dataclass
6
+ class CustomerPortalSessionSubscriptionUrl:
7
+ id: str
8
+ cancel_subscription: str
9
+ update_subscription_payment_method: str
10
+
11
+ @staticmethod
12
+ def from_dict(data: dict) -> CustomerPortalSessionSubscriptionUrl:
13
+ return CustomerPortalSessionSubscriptionUrl(
14
+ id=data["id"],
15
+ cancel_subscription=data["cancel_subscription"],
16
+ update_subscription_payment_method=data["update_subscription_payment_method"],
17
+ )
@@ -0,0 +1,24 @@
1
+ from __future__ import annotations
2
+ from dataclasses import dataclass
3
+
4
+ from paddle_billing.Entities.CustomerPortalSessions.CustomerPortalSessionGeneralUrl import (
5
+ CustomerPortalSessionGeneralUrl,
6
+ )
7
+ from paddle_billing.Entities.CustomerPortalSessions.CustomerPortalSessionSubscriptionUrl import (
8
+ CustomerPortalSessionSubscriptionUrl,
9
+ )
10
+
11
+
12
+ @dataclass
13
+ class CustomerPortalSessionUrls:
14
+ general: CustomerPortalSessionGeneralUrl
15
+ subscriptions: list[CustomerPortalSessionSubscriptionUrl]
16
+
17
+ @staticmethod
18
+ def from_dict(data: dict) -> CustomerPortalSessionUrls:
19
+ return CustomerPortalSessionUrls(
20
+ general=CustomerPortalSessionGeneralUrl.from_dict(data["general"]),
21
+ subscriptions=[
22
+ CustomerPortalSessionSubscriptionUrl.from_dict(item) for item in data.get("subscriptions", [])
23
+ ],
24
+ )
@@ -0,0 +1,7 @@
1
+ from paddle_billing.Entities.CustomerPortalSessions.CustomerPortalSessionUrls import CustomerPortalSessionUrls
2
+ from paddle_billing.Entities.CustomerPortalSessions.CustomerPortalSessionGeneralUrl import (
3
+ CustomerPortalSessionGeneralUrl,
4
+ )
5
+ from paddle_billing.Entities.CustomerPortalSessions.CustomerPortalSessionSubscriptionUrl import (
6
+ CustomerPortalSessionSubscriptionUrl,
7
+ )
@@ -3,7 +3,7 @@ from dataclasses import dataclass
3
3
 
4
4
  from paddle_billing.Entities.Entity import Entity
5
5
  from paddle_billing.Entities.EventType import EventType
6
- from paddle_billing.Entities.NotificationSettings import NotificationSettingType
6
+ from paddle_billing.Entities.NotificationSettings import NotificationSettingType, NotificationSettingTrafficSource
7
7
 
8
8
 
9
9
  @dataclass
@@ -17,6 +17,7 @@ class NotificationSetting(Entity):
17
17
  include_sensitive_fields: bool
18
18
  subscribed_events: list[EventType]
19
19
  endpoint_secret_key: str
20
+ traffic_source: NotificationSettingTrafficSource
20
21
 
21
22
  @staticmethod
22
23
  def from_dict(data: dict) -> NotificationSetting:
@@ -30,4 +31,5 @@ class NotificationSetting(Entity):
30
31
  include_sensitive_fields=data["include_sensitive_fields"],
31
32
  subscribed_events=[EventType.from_dict(event) for event in data.get("subscribed_events", [])],
32
33
  endpoint_secret_key=data["endpoint_secret_key"],
34
+ traffic_source=NotificationSettingTrafficSource(data["traffic_source"]),
33
35
  )
@@ -0,0 +1,7 @@
1
+ from paddle_billing.PaddleStrEnum import PaddleStrEnum, PaddleStrEnumMeta
2
+
3
+
4
+ class NotificationSettingTrafficSource(PaddleStrEnum, metaclass=PaddleStrEnumMeta):
5
+ All: "NotificationSettingTrafficSource" = "all"
6
+ Platform: "NotificationSettingTrafficSource" = "platform"
7
+ Simulation: "NotificationSettingTrafficSource" = "simulation"
@@ -1 +1,4 @@
1
+ from paddle_billing.Entities.NotificationSettings.NotificationSettingTrafficSource import (
2
+ NotificationSettingTrafficSource,
3
+ )
1
4
  from paddle_billing.Entities.NotificationSettings.NotificationSettingType import NotificationSettingType
@@ -6,13 +6,13 @@ from datetime import datetime
6
6
  @dataclass
7
7
  class SubscriptionDiscount:
8
8
  id: str
9
- starts_at: datetime
10
- ends_at: datetime
9
+ starts_at: datetime | None
10
+ ends_at: datetime | None
11
11
 
12
12
  @staticmethod
13
13
  def from_dict(data: dict) -> SubscriptionDiscount:
14
14
  return SubscriptionDiscount(
15
15
  id=data["id"],
16
- starts_at=datetime.fromisoformat(data["starts_at"]),
16
+ starts_at=datetime.fromisoformat(data["starts_at"]) if data.get("starts_at") else None,
17
17
  ends_at=datetime.fromisoformat(data["ends_at"]) if data.get("ends_at") else None,
18
18
  )
@@ -69,7 +69,7 @@ class Subscription(Entity):
69
69
  paused_at=datetime.fromisoformat(data["paused_at"]) if data.get("paused_at") else None,
70
70
  started_at=datetime.fromisoformat(data["started_at"]) if data.get("started_at") else None,
71
71
  current_billing_period=(
72
- TimePeriod.from_dict(data["current_billing_period"]) if data.get("billing_details") else None
72
+ TimePeriod.from_dict(data["current_billing_period"]) if data.get("current_billing_period") else None
73
73
  ),
74
74
  scheduled_change=(
75
75
  SubscriptionScheduledChange.from_dict(data["scheduled_change"])
@@ -71,7 +71,7 @@ class SubscriptionCreated(Entity):
71
71
  paused_at=datetime.fromisoformat(data["paused_at"]) if data.get("paused_at") else None,
72
72
  started_at=datetime.fromisoformat(data["started_at"]) if data.get("started_at") else None,
73
73
  current_billing_period=(
74
- TimePeriod.from_dict(data["current_billing_period"]) if data.get("billing_details") else None
74
+ TimePeriod.from_dict(data["current_billing_period"]) if data.get("current_billing_period") else None
75
75
  ),
76
76
  scheduled_change=(
77
77
  SubscriptionScheduledChange.from_dict(data["scheduled_change"])
@@ -6,13 +6,13 @@ from datetime import datetime
6
6
  @dataclass
7
7
  class SubscriptionDiscount:
8
8
  id: str
9
- starts_at: datetime
10
- ends_at: datetime
9
+ starts_at: datetime | None
10
+ ends_at: datetime | None
11
11
 
12
12
  @staticmethod
13
13
  def from_dict(data: dict) -> SubscriptionDiscount:
14
14
  return SubscriptionDiscount(
15
15
  id=data["id"],
16
- starts_at=datetime.fromisoformat(data["starts_at"]),
16
+ starts_at=datetime.fromisoformat(data["starts_at"]) if data.get("starts_at") else None,
17
17
  ends_at=datetime.fromisoformat(data["ends_at"]) if data.get("ends_at") else None,
18
18
  )
@@ -0,0 +1,24 @@
1
+ from paddle_billing.ResponseParser import ResponseParser
2
+
3
+ from paddle_billing.Entities.CustomerPortalSession import CustomerPortalSession
4
+
5
+ from paddle_billing.Resources.CustomerPortalSessions.Operations import (
6
+ CreateCustomerPortalSession,
7
+ )
8
+
9
+ from typing import TYPE_CHECKING
10
+
11
+ if TYPE_CHECKING:
12
+ from paddle_billing.Client import Client
13
+
14
+
15
+ class CustomerPortalSessionsClient:
16
+ def __init__(self, client: "Client"):
17
+ self.client = client
18
+ self.response = None
19
+
20
+ def create(self, customer_id: str, operation: CreateCustomerPortalSession) -> CustomerPortalSession:
21
+ self.response = self.client.post_raw(f"/customers/{customer_id}/portal-sessions", operation)
22
+ parser = ResponseParser(self.response)
23
+
24
+ return CustomerPortalSession.from_dict(parser.get_data())
@@ -0,0 +1,9 @@
1
+ from dataclasses import dataclass
2
+
3
+ from paddle_billing.Operation import Operation
4
+ from paddle_billing.Undefined import Undefined
5
+
6
+
7
+ @dataclass
8
+ class CreateCustomerPortalSession(Operation):
9
+ subscription_ids: list[str] | Undefined = Undefined()
@@ -0,0 +1,3 @@
1
+ from paddle_billing.Resources.CustomerPortalSessions.Operations.CreateCustomerPortalSession import (
2
+ CreateCustomerPortalSession,
3
+ )
@@ -3,7 +3,7 @@ from dataclasses import dataclass
3
3
  from paddle_billing.Operation import Operation
4
4
  from paddle_billing.Undefined import Undefined
5
5
  from paddle_billing.Entities.Events import EventTypeName
6
- from paddle_billing.Entities.NotificationSettings import NotificationSettingType
6
+ from paddle_billing.Entities.NotificationSettings import NotificationSettingType, NotificationSettingTrafficSource
7
7
 
8
8
 
9
9
  @dataclass
@@ -14,3 +14,4 @@ class CreateNotificationSetting(Operation):
14
14
  type: NotificationSettingType
15
15
  include_sensitive_fields: bool
16
16
  api_version: int | Undefined = Undefined()
17
+ traffic_source: NotificationSettingTrafficSource | Undefined = Undefined()
@@ -2,15 +2,19 @@ from paddle_billing.HasParameters import HasParameters
2
2
 
3
3
  from paddle_billing.Resources.Shared.Operations import Pager
4
4
 
5
+ from paddle_billing.Entities.NotificationSettings import NotificationSettingTrafficSource
6
+
5
7
 
6
8
  class ListNotificationSettings(HasParameters):
7
9
  def __init__(
8
10
  self,
9
11
  pager: Pager | None = None,
10
12
  active: bool | None = None,
13
+ traffic_source: NotificationSettingTrafficSource | None = None,
11
14
  ):
12
15
  self.pager = pager
13
16
  self.active = active
17
+ self.traffic_source = traffic_source
14
18
 
15
19
  def get_parameters(self) -> dict:
16
20
  parameters = {}
@@ -18,5 +22,7 @@ class ListNotificationSettings(HasParameters):
18
22
  parameters.update(self.pager.get_parameters())
19
23
  if self.active is not None:
20
24
  parameters["active"] = "true" if self.active else "false"
25
+ if self.traffic_source is not None:
26
+ parameters["traffic_source"] = self.traffic_source.value
21
27
 
22
28
  return parameters
@@ -3,6 +3,7 @@ from dataclasses import dataclass
3
3
  from paddle_billing.Operation import Operation
4
4
  from paddle_billing.Undefined import Undefined
5
5
  from paddle_billing.Entities.Events import EventTypeName
6
+ from paddle_billing.Entities.NotificationSettings import NotificationSettingTrafficSource
6
7
 
7
8
 
8
9
  @dataclass
@@ -13,3 +14,4 @@ class UpdateNotificationSetting(Operation):
13
14
  api_version: int | Undefined = Undefined()
14
15
  include_sensitive_fields: bool | Undefined = Undefined()
15
16
  subscribed_events: list[EventTypeName] | Undefined = Undefined()
17
+ traffic_source: NotificationSettingTrafficSource | Undefined = Undefined()
@@ -34,7 +34,7 @@ class NotificationsClient:
34
34
  return Notification.from_dict(parser.get_data())
35
35
 
36
36
  def replay(self, notification_id: str) -> str:
37
- self.response = self.client.post_raw(f"/notifications/{notification_id}")
37
+ self.response = self.client.post_raw(f"/notifications/{notification_id}/replay")
38
38
  parser = ResponseParser(self.response)
39
39
  data = parser.get_data()
40
40
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: paddle-python-sdk
3
- Version: 1.1.1
3
+ Version: 1.2.2
4
4
  Summary: Paddle's Python SDK for Paddle Billing
5
5
  Home-page: https://developer.paddle.com/api-reference/overview
6
6
  Author: Paddle and contributors
@@ -16,16 +16,16 @@ Classifier: Programming Language :: Python :: 3.13
16
16
  Requires-Python: >=3.11
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: LICENSE
19
- Requires-Dist: requests >=2.31
20
- Requires-Dist: urllib3 >=1.26.18
19
+ Requires-Dist: requests>=2.31
20
+ Requires-Dist: urllib3>=1.26.18
21
21
  Provides-Extra: dev
22
- Requires-Dist: pytest <8.4.0,>=7.4.4 ; extra == 'dev'
23
- Requires-Dist: pytest-cov ~=4.1.0 ; extra == 'dev'
24
- Requires-Dist: requests-mock ~=1.11.0 ; extra == 'dev'
25
- Requires-Dist: setuptools >=69.0.3 ; extra == 'dev'
26
- Requires-Dist: pre-commit >=3.8.0 ; extra == 'dev'
27
- Requires-Dist: black >=24.8.0 ; extra == 'dev'
28
- Requires-Dist: flake8 >=7.1.1 ; extra == 'dev'
22
+ Requires-Dist: pytest<8.4.0,>=7.4.4; extra == "dev"
23
+ Requires-Dist: pytest-cov~=4.1.0; extra == "dev"
24
+ Requires-Dist: requests-mock~=1.11.0; extra == "dev"
25
+ Requires-Dist: setuptools>=69.0.3; extra == "dev"
26
+ Requires-Dist: pre-commit>=3.8.0; extra == "dev"
27
+ Requires-Dist: black>=24.8.0; extra == "dev"
28
+ Requires-Dist: flake8>=7.1.1; extra == "dev"
29
29
 
30
30
  [![Build Status](https://img.shields.io/github/actions/workflow/status/PaddleHQ/paddle-python-sdk/publish_to_pypi.yml)](https://github.com/PaddleHQ/paddle-python-sdk/actions/?query=branch%3Amain)
31
31
  [![PyPI](https://img.shields.io/pypi/v/paddle-python-sdk.svg)](https://pypi.python.org/pypi/paddle-python-sdk)
@@ -4,7 +4,7 @@ examples/event_polling.py,sha256=580dg_8CFrSCA89Mr1ny4V1gtB3-hk-LfePTbI7DT5w,217
4
4
  examples/get_products.py,sha256=4V7ZG1SH6Oxojufbtzm_TMySw4cOBMQ99mgQK_hlwFQ,1875
5
5
  examples/logger.py,sha256=AxmQmMrsM0ZqMIUnh6iARiczL4S4F9OqQcOu-67owNg,1042
6
6
  examples/webhook_verification.py,sha256=qkNscNdNZUAgxEIk83tCiljN2VmfePZ_k8zTliKz2QY,1205
7
- paddle_billing/Client.py,sha256=72lbeMx8wy_l49RzEbnWRiWes_wq48AYggJPVi4DNDw,8594
7
+ paddle_billing/Client.py,sha256=cxkmBfaCq8-I3SgeszfWEWBjO65MQogWrno0fP4dn_A,8787
8
8
  paddle_billing/EnumStringify.py,sha256=iDvKULZat3jx9A-_PhvoN6CbFGf2pyxrQeYZxqX9n8M,48
9
9
  paddle_billing/Environment.py,sha256=sY4nrJUwlTugsZKncieAnvfCojqCcKWi4X7rFzjFeSQ,417
10
10
  paddle_billing/FiltersNone.py,sha256=HxjE6RJb7sy6txphpZSrCTQZt1Ua0XpIz8NDLHC43zo,268
@@ -24,6 +24,7 @@ paddle_billing/Entities/Business.py,sha256=wlnAd_lC0Fuw7_BHKZGHt8q-aeLYO6MjO92EY
24
24
  paddle_billing/Entities/CreditBalance.py,sha256=aGCsfSf-qZl6kVTfHd41_1raiNuI29picji-bj7-lvg,673
25
25
  paddle_billing/Entities/Customer.py,sha256=3Ae2wmopq5CWL5FKiWGjXkEVcDVWLZHKCF4N3cjtFO4,1165
26
26
  paddle_billing/Entities/CustomerAuthToken.py,sha256=Zsm0NJDHRt9TYLTRXueW_m01piRA2QLRJ6SkfB_fLWo,493
27
+ paddle_billing/Entities/CustomerPortalSession.py,sha256=t39dE7yMb6d7VYzkLPZi_YwD3DZZ1zLnEM-ycd2lb2E,709
27
28
  paddle_billing/Entities/DateTime.py,sha256=vJJRO6nASbJzESSk0LO6RxfroHnkvOBDfJKLswovbHE,1512
28
29
  paddle_billing/Entities/Discount.py,sha256=btcN1MSiKSDd-p5HMQikijDRIl2HGf-USd8pZ3CmGjE,1993
29
30
  paddle_billing/Entities/Entity.py,sha256=8zY_ehy4uqylrgY4Qo9yzsSPnpPa5PluzqytE9wcXrA,271
@@ -32,7 +33,7 @@ paddle_billing/Entities/EventType.py,sha256=tBKeM6hWSbbcLLSWR4yuuRBV3Y2kPNmOU_29
32
33
  paddle_billing/Entities/IPAddresses.py,sha256=ElpiJi-YSDXz7vc7OT908XL3qQH4BxrpjGZo3SJOIO8,339
33
34
  paddle_billing/Entities/Notification.py,sha256=pfFpwziRegGfr4cb5QMFZqtPafpP7AASHAmv6Ab6of4,1745
34
35
  paddle_billing/Entities/NotificationLog.py,sha256=ezWhRCVPFu1S-p-bvbWL1zxN_52dOe0loZCVGn83XFc,693
35
- paddle_billing/Entities/NotificationSetting.py,sha256=a4D9Sugwe6X2XDqicJ1aOyW7se2H5iiy5m3T0Mvu_D8,1145
36
+ paddle_billing/Entities/NotificationSetting.py,sha256=Gyav9M8EQ6zawLlshmpLdmjxyKaZ4KCZf2XJ8oXhQyE,1317
36
37
  paddle_billing/Entities/PaymentMethod.py,sha256=aZf4lCinK7rPeWRuIUBEa_mLQ72zASAzkqfESVlKzEY,1168
37
38
  paddle_billing/Entities/Price.py,sha256=mE2n4ajmjCAXZN9BJoJtIewIreLvwGTNOJUm-VzsnOA,2256
38
39
  paddle_billing/Entities/PricePreview.py,sha256=8EJ9Li4cQrWtYoDm0088pZJbnplCs35w9mrW2zRMf7A,1328
@@ -73,13 +74,18 @@ paddle_billing/Entities/Collections/TransactionCollection.py,sha256=gF1Kf9m5Gxc9
73
74
  paddle_billing/Entities/Collections/TransactionPreviewCollection.py,sha256=Rr8wgUgKItTqpRpJd12lJTH6Omgl0TSwdtvhpu23fKM,610
74
75
  paddle_billing/Entities/Collections/TransactionsDataCollection.py,sha256=cbOXZiwzK0zExvuep3W0abTTBuUuXA4gNuf2EyBR_p4,589
75
76
  paddle_billing/Entities/Collections/__init__.py,sha256=pxBG0tG74_DLxZ_hoA21X06u76fa2zMoRoLQEEPeRko,1980
77
+ paddle_billing/Entities/CustomerPortalSessions/CustomerPortalSessionGeneralUrl.py,sha256=aiGkjhzPtZHDMJvSxbubf5cvCxTIUkPPSZhzLm9AMuQ,321
78
+ paddle_billing/Entities/CustomerPortalSessions/CustomerPortalSessionSubscriptionUrl.py,sha256=FQLBqkLwbf47YmkHF1H_rsp-yU3FGLgEt_E5qInPK24,543
79
+ paddle_billing/Entities/CustomerPortalSessions/CustomerPortalSessionUrls.py,sha256=mDQgMnmJqjiS7PUboZYomV9OapZs6OHDgUtlyHUFuz4,862
80
+ paddle_billing/Entities/CustomerPortalSessions/__init__.py,sha256=DdA-g5zgW3A3ciOuMDebsQMhWkbbEv_fbAmLH4NOrio,385
76
81
  paddle_billing/Entities/Discounts/DiscountStatus.py,sha256=ss0Btu04U7NEXYgWxlnkUOWINjSXILu67LWEgLb1DaA,304
77
82
  paddle_billing/Entities/Discounts/DiscountType.py,sha256=7JQCM_dN2PGHSiA-jzBHTIRVMVTRFKdHAMKxDxpQgf0,270
78
83
  paddle_billing/Entities/Discounts/__init__.py,sha256=2zGGjrklZaaWj0iAwFRvTs_87yl8TOYy6R2RcH2kT_4,148
79
84
  paddle_billing/Entities/Events/EventTypeName.py,sha256=K4JCac5Ib7xDEMedCJ2ZzRtsTFcOHsa-qLFRUAqurJ8,3022
80
85
  paddle_billing/Entities/Events/__init__.py,sha256=DBvU5TZXroY6IACIhh26VV8TWoagJAkne8e9Pz9YdPs,71
86
+ paddle_billing/Entities/NotificationSettings/NotificationSettingTrafficSource.py,sha256=5jga7qMivQXyU55XOPMGvwsLO1wEPA0Mur40knDgEks,340
81
87
  paddle_billing/Entities/NotificationSettings/NotificationSettingType.py,sha256=zm3kpN5T5QkKp3-3JUpZphUrXCD992OkClAIahqxbns,241
82
- paddle_billing/Entities/NotificationSettings/__init__.py,sha256=RtvGSG7pvbHWv7LwyoeHV7VKxzHWGILnWVDUPF1y44U,105
88
+ paddle_billing/Entities/NotificationSettings/__init__.py,sha256=OTmdXcuJiirwGjTvUkz5ZnT3wLPCszzUcbskRpMdYhU,237
83
89
  paddle_billing/Entities/Notifications/NotificationEvent.py,sha256=uehDqPUWmuIZfhGsk8oQcqAO9w5TSPlpM1iuvEjT6H0,1488
84
90
  paddle_billing/Entities/Notifications/NotificationOrigin.py,sha256=pFqjHhIlqMZZn81F-rILrRGZnJy6bv1Hr6C9hiR3eXg,232
85
91
  paddle_billing/Entities/Notifications/NotificationPayout.py,sha256=EMLVwHDnCFhjWUxtUJBUhnnRVi6Gx_kRusHfeY3V1q4,719
@@ -164,7 +170,7 @@ paddle_billing/Entities/Subscriptions/SubscriptionAdjustmentItem.py,sha256=a0QNB
164
170
  paddle_billing/Entities/Subscriptions/SubscriptionAdjustmentPreview.py,sha256=vd1fXc9X0IecddOkMxNivHgU0C2-2cGV37iVqotrcds,725
165
171
  paddle_billing/Entities/Subscriptions/SubscriptionCharge.py,sha256=toASyrKTGeZ7X0ppmjinFGO5MeaeZWINEK8vyerzDDo,428
166
172
  paddle_billing/Entities/Subscriptions/SubscriptionCredit.py,sha256=ahrlS0k4yqJd5zeZUrD_nuchnRleIE0xE_WUoKaZ4Zg,428
167
- paddle_billing/Entities/Subscriptions/SubscriptionDiscount.py,sha256=Nog-KneHL0z_YWouN83n37W2jSMFPeatnl7dsmOi5fI,505
173
+ paddle_billing/Entities/Subscriptions/SubscriptionDiscount.py,sha256=Wb7leFA5DoWgUdPmGqFyXzSeX-NSAzeuRJ4nwG5qaQc,554
168
174
  paddle_billing/Entities/Subscriptions/SubscriptionEffectiveFrom.py,sha256=YNu4jUYx9TZfb-s3uQeBMGRwwlJaW46j1aW1v94QlvI,289
169
175
  paddle_billing/Entities/Subscriptions/SubscriptionItem.py,sha256=y9wC5Z9oPdetfrHZtXGV0qewDUSuDQ7QodB9DI6SwFA,1549
170
176
  paddle_billing/Entities/Subscriptions/SubscriptionItemStatus.py,sha256=vzrvLhi_g_SQXvQgSSQcMPziKE9eTQpPX6Wj7Xo-RkE,302
@@ -226,8 +232,8 @@ paddle_billing/Notifications/Entities/Payout.py,sha256=Zezrof-earP-RFiFopjRIIPys
226
232
  paddle_billing/Notifications/Entities/Price.py,sha256=CNrkC_2JabAzMFqNtTevgfCGT8lIZgxpwNDK9vkIuH8,2257
227
233
  paddle_billing/Notifications/Entities/Product.py,sha256=9JnGoO3uhcb73pv3FcPr3FMLpmZMiAmdamhrBNlgmM8,1678
228
234
  paddle_billing/Notifications/Entities/Report.py,sha256=3y31hAwPjtKLeXrkvdr6Xzqi2_C924y6nCk100KfpOw,1069
229
- paddle_billing/Notifications/Entities/Subscription.py,sha256=oCTN8t-39xIezzDTJDuAfXfNza5jFkPjRfhldhtPO0E,3428
230
- paddle_billing/Notifications/Entities/SubscriptionCreated.py,sha256=3tig0K-_WwQHqJZlv1Uqr80MtEoCa2NJxKuYhMi60R8,3542
235
+ paddle_billing/Notifications/Entities/Subscription.py,sha256=DWqzvSRLgB-GPvAaNfFXZpiXTVTFsuo_RTSXCULpQEk,3435
236
+ paddle_billing/Notifications/Entities/SubscriptionCreated.py,sha256=3bjut0UsAQuRWUQUSJJM77WU6bh8pZdU4j0_kzqeaF8,3549
231
237
  paddle_billing/Notifications/Entities/Transaction.py,sha256=R_35BgHAv6AWFy-ppGmAraTj84dMI3pEK7M66BdlhKU,2956
232
238
  paddle_billing/Notifications/Entities/UndefinedEntity.py,sha256=pvqWMXLkGXzHysRqYppYAN8MXqoE81Hth1zkkwDzY9U,287
233
239
  paddle_billing/Notifications/Entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -301,7 +307,7 @@ paddle_billing/Notifications/Entities/Shared/__init__.py,sha256=UvruDr0XkWMEt05B
301
307
  paddle_billing/Notifications/Entities/Subscriptions/SubscriptionAdjustmentItem.py,sha256=aED3Eq_OIWuR9RynjvVxa6LhuF6yYDfdpmRB9kiXbTg,730
302
308
  paddle_billing/Notifications/Entities/Subscriptions/SubscriptionCharge.py,sha256=RZ9TkL9UckSUJ8stglrI_Ri71sy_-AZmbsTx2790sXQ,442
303
309
  paddle_billing/Notifications/Entities/Subscriptions/SubscriptionCredit.py,sha256=v1R271DEZz8emuvxlpTPpNNR68Ye9OgFjoGSczQSs-0,442
304
- paddle_billing/Notifications/Entities/Subscriptions/SubscriptionDiscount.py,sha256=Nog-KneHL0z_YWouN83n37W2jSMFPeatnl7dsmOi5fI,505
310
+ paddle_billing/Notifications/Entities/Subscriptions/SubscriptionDiscount.py,sha256=Wb7leFA5DoWgUdPmGqFyXzSeX-NSAzeuRJ4nwG5qaQc,554
305
311
  paddle_billing/Notifications/Entities/Subscriptions/SubscriptionEffectiveFrom.py,sha256=YNu4jUYx9TZfb-s3uQeBMGRwwlJaW46j1aW1v94QlvI,289
306
312
  paddle_billing/Notifications/Entities/Subscriptions/SubscriptionItem.py,sha256=B-lUpjsNNASRTdQIEZc6Q0aqgxI5yq6luJ2ceF-boVQ,1707
307
313
  paddle_billing/Notifications/Entities/Subscriptions/SubscriptionItemStatus.py,sha256=vzrvLhi_g_SQXvQgSSQcMPziKE9eTQpPX6Wj7Xo-RkE,302
@@ -382,6 +388,10 @@ paddle_billing/Resources/Businesses/Operations/CreateBusiness.py,sha256=zDQ-V7El
382
388
  paddle_billing/Resources/Businesses/Operations/ListBusinesses.py,sha256=41XRKW61uAN9hepj2Nps0g2H5AtL7O2JqQUcyGhzt6M,1595
383
389
  paddle_billing/Resources/Businesses/Operations/UpdateBusiness.py,sha256=fzijE9x9ru58jOW5Rq-ZvV_LtFc7m6rksyJQiSNwyLA,562
384
390
  paddle_billing/Resources/Businesses/Operations/__init__.py,sha256=mctosPK-Kdb4n_AmdIqVFKeldZxcjw8e4k4iWWoRml0,267
391
+ paddle_billing/Resources/CustomerPortalSessions/CustomerPortalSessionsClient.py,sha256=GXW4jlb9d5nKxPS9D-azjC082g09e-DZQP6mg6lsu0s,804
392
+ paddle_billing/Resources/CustomerPortalSessions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
393
+ paddle_billing/Resources/CustomerPortalSessions/Operations/CreateCustomerPortalSession.py,sha256=EvIwrW-2fmC4xgh3XCJJmjya52aAj0YvkFOJk-yzNto,246
394
+ paddle_billing/Resources/CustomerPortalSessions/Operations/__init__.py,sha256=2DBura-28E1UBZHCZ4kFkorjY-s8zADPrCLCVjo8KaU,136
385
395
  paddle_billing/Resources/Customers/CustomersClient.py,sha256=sYouOQZipuAG4ScusIepg7xM9B76BL2nF-21_WwLBDM,2691
386
396
  paddle_billing/Resources/Customers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
387
397
  paddle_billing/Resources/Customers/Operations/CreateCustomer.py,sha256=IxY4Df6S8f51VPM-CIrTQnPFjhoTh1l3BeBA7XseUNw,394
@@ -409,11 +419,11 @@ paddle_billing/Resources/NotificationLogs/Operations/ListNotificationLogs.py,sha
409
419
  paddle_billing/Resources/NotificationLogs/Operations/__init__.py,sha256=l1v_KIPhYuzh_A6iQqMV7qAwsXVA7ZUmJ9rj5I0dXwY,107
410
420
  paddle_billing/Resources/NotificationSettings/NotificationSettingsClient.py,sha256=H2WellbE39sWqe0fw4eGfLlWwyQAhhe2zKGGY0SORvY,2207
411
421
  paddle_billing/Resources/NotificationSettings/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
412
- paddle_billing/Resources/NotificationSettings/Operations/CreateNotificationSetting.py,sha256=HgdTNmxQJ6XkgNgjcG4Eeo66wgpuHBwqOkjbCy2rfHg,525
413
- paddle_billing/Resources/NotificationSettings/Operations/ListNotificationSettings.py,sha256=zrFaeqguZyP3wwuunOMUbe03FRQMtTriVXMmBafVBAY,611
414
- paddle_billing/Resources/NotificationSettings/Operations/UpdateNotificationSetting.py,sha256=mm4xFqUPlcab_aU1MxAlLCObkv79Tbesb4v5K3T5F8k,557
422
+ paddle_billing/Resources/NotificationSettings/Operations/CreateNotificationSetting.py,sha256=eSCFN3WDAA0c57PJcCASNQb74ImU4BV0f3vT8ZyW0Uk,638
423
+ paddle_billing/Resources/NotificationSettings/Operations/ListNotificationSettings.py,sha256=sz2TT0dKYPG8UJbueuvjfXJkzIgqDQmA6JnjgHHPHVs,932
424
+ paddle_billing/Resources/NotificationSettings/Operations/UpdateNotificationSetting.py,sha256=6CV3u0LphqLuE4f8rQix2zikzv2W1YbZpNSYTfg-LCg,726
415
425
  paddle_billing/Resources/NotificationSettings/Operations/__init__.py,sha256=qdVp3OkbMefkvJ-fOuYxNtN02Oj6kskQ1QD8MCBcxXc,361
416
- paddle_billing/Resources/Notifications/NotificationsClient.py,sha256=k11E2qp1OIRzB9XpurN1gCMH85H5EKUHQD1d5uPycJ4,1475
426
+ paddle_billing/Resources/Notifications/NotificationsClient.py,sha256=tlB54KClOGAgXCQsmwzivllzrlspCbFv1LHOMnWOplo,1482
417
427
  paddle_billing/Resources/Notifications/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
418
428
  paddle_billing/Resources/Notifications/Operations/ListNotifications.py,sha256=SCqonil6IAkS0g_NROyDQ5VO2RL-ghcr14Uwk2SJSZA,2355
419
429
  paddle_billing/Resources/Notifications/Operations/__init__.py,sha256=4IoWBPYjRPK37GAMhfrxVH5IpAygcaqm3EpwYdvm1IM,98
@@ -539,6 +549,8 @@ tests/Functional/Resources/Adjustments/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JC
539
549
  tests/Functional/Resources/Adjustments/test_AdjustmentsClient.py,sha256=WJdb0EZ0xSf9O10R-gyfb78ltcUgJUxtRD_gyI3g1u0,14229
540
550
  tests/Functional/Resources/Businesses/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
541
551
  tests/Functional/Resources/Businesses/test_BusinessesClient.py,sha256=uUAydFqmXq3snmu--gGVI5nNrpg6oySQM_Ulg9q-G1Q,12727
552
+ tests/Functional/Resources/CustomerPortalSessions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
553
+ tests/Functional/Resources/CustomerPortalSessions/test_CustomerPortalSessionsClient.py,sha256=n33TXcOD0c6twPECsebfJA_AxLDJV_XV8WixWzvcSvw,7430
542
554
  tests/Functional/Resources/Customers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
543
555
  tests/Functional/Resources/Customers/test_CustomersClient.py,sha256=tWDmre025VMQuUGcK6UE12Ulh7Ju_BeprKon2bM-OLk,14755
544
556
  tests/Functional/Resources/Discounts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -552,11 +564,11 @@ tests/Functional/Resources/IPAddresses/test_IPAddressesClient.py,sha256=XpEdHyjd
552
564
  tests/Functional/Resources/NotificationLogs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
553
565
  tests/Functional/Resources/NotificationLogs/test_NotificationLogsClient.py,sha256=O70t8-DDawumaHvwiazENl2bcLabivS24MJDcpLPljc,2666
554
566
  tests/Functional/Resources/NotificationSettings/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
555
- tests/Functional/Resources/NotificationSettings/test_NotificationSettingsClient.py,sha256=EbRqcQ0e1M8lfrsLKfWhzyhs4gYoZfVQzFPyDOo_qxk,16538
567
+ tests/Functional/Resources/NotificationSettings/test_NotificationSettingsClient.py,sha256=3anSxEUd4pi7r4PHA_DfLbEApsFd3n4paN6KJHuaRxU,22409
556
568
  tests/Functional/Resources/Notifications/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
557
- tests/Functional/Resources/Notifications/test_NotificationsClient.py,sha256=JgGw5NV6kHi4lsh5wWM0LAilpnWZX-3xT994GaRxoqg,12734
569
+ tests/Functional/Resources/Notifications/test_NotificationsClient.py,sha256=7mc8gluq4ZgZdZGkemsvy4etHDru1m7GFasuQn4-elo,12740
558
570
  tests/Functional/Resources/PaymentMethods/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
559
- tests/Functional/Resources/PaymentMethods/test_PaymentMethodsClient.py,sha256=U9dYiAVXcY6K-NL4lYamz7tPpGeo6OZcCnxcR6EH8LE,12046
571
+ tests/Functional/Resources/PaymentMethods/test_PaymentMethodsClient.py,sha256=wIDGk0TPg6QoFySpLulsGE4ui9ucF5dpal8QQeygCtY,12183
560
572
  tests/Functional/Resources/Prices/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
561
573
  tests/Functional/Resources/Prices/test_PricesClient.py,sha256=48EtY6zhChPIel57xGQdMsfQEy3mhgMqQ5_nkwnMS6s,13024
562
574
  tests/Functional/Resources/PricingPreviews/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -566,7 +578,7 @@ tests/Functional/Resources/Products/test_ProductsClient.py,sha256=FlYIjv09RM4rJt
566
578
  tests/Functional/Resources/Reports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
567
579
  tests/Functional/Resources/Reports/test_ReportsClient.py,sha256=jIOHBQ3YSw0rXrOKxlhIUGtqptUZMBWsMJHBwlhjOxg,13438
568
580
  tests/Functional/Resources/Subscriptions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
569
- tests/Functional/Resources/Subscriptions/test_SubscriptionsClient.py,sha256=8vzLjVg5RER_nT08dLKEhghNGKw7Am2iOc_9wzzfiwk,60829
581
+ tests/Functional/Resources/Subscriptions/test_SubscriptionsClient.py,sha256=9TW7z378xzu-JBTuPkOGY_CThzwQC7P97XYl-PK48bg,61719
570
582
  tests/Functional/Resources/Transactions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
571
583
  tests/Functional/Resources/Transactions/test_TransactionsClient.py,sha256=K3t47sr-HdqPosSXsERsjIGKhbxuWvP2pAdvBD_vLt4,59187
572
584
  tests/Unit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -581,8 +593,8 @@ tests/Utils/ReadsFixture.py,sha256=M3Ot3xHXp_C7vwttna9deLPHBAO8ml2Jb4thhHOJJ38,1
581
593
  tests/Utils/TestClient.py,sha256=-wc7hJMuR6WC-ukw0c7I59b5-8hj_-nzq__-2M81elg,1453
582
594
  tests/Utils/TestLogger.py,sha256=pFO9x711buRmg-8DAqpzIJP_hr21JPty1_ZQRcwoGKk,554
583
595
  tests/Utils/__init__.py,sha256=JtqJNPKqbNZ9exlpXlF3yj_9cfylPGlvopjQYi7yYTA,37
584
- paddle_python_sdk-1.1.1.dist-info/LICENSE,sha256=e5Sn9mzCdpjnqCLxXpGHNKdYB6JlRSTLhN_CD4WSO6w,10770
585
- paddle_python_sdk-1.1.1.dist-info/METADATA,sha256=-N-g5TIIPex2-fkIZ5K3YOhMaLJ78XOrPgojn8L7vIM,7392
586
- paddle_python_sdk-1.1.1.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
587
- paddle_python_sdk-1.1.1.dist-info/top_level.txt,sha256=9a07VPng7o5wK8VAXkl6NC30xrNbW9zff_02jHyHi4c,30
588
- paddle_python_sdk-1.1.1.dist-info/RECORD,,
596
+ paddle_python_sdk-1.2.2.dist-info/LICENSE,sha256=e5Sn9mzCdpjnqCLxXpGHNKdYB6JlRSTLhN_CD4WSO6w,10770
597
+ paddle_python_sdk-1.2.2.dist-info/METADATA,sha256=0SKd4ERW64ijPyBiKdgxrguG1zP-lvlVD_hpCPjYqgo,7376
598
+ paddle_python_sdk-1.2.2.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
599
+ paddle_python_sdk-1.2.2.dist-info/top_level.txt,sha256=9a07VPng7o5wK8VAXkl6NC30xrNbW9zff_02jHyHi4c,30
600
+ paddle_python_sdk-1.2.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.5.0)
2
+ Generator: setuptools (75.6.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -0,0 +1,143 @@
1
+ from json import loads
2
+ from pytest import mark
3
+ from urllib.parse import unquote
4
+
5
+ from paddle_billing.Entities.CustomerPortalSession import CustomerPortalSession
6
+ from paddle_billing.Entities.CustomerPortalSessions import (
7
+ CustomerPortalSessionUrls,
8
+ CustomerPortalSessionGeneralUrl,
9
+ CustomerPortalSessionSubscriptionUrl,
10
+ )
11
+
12
+ from paddle_billing.Resources.CustomerPortalSessions.Operations import CreateCustomerPortalSession
13
+
14
+ from tests.Utils.ReadsFixture import ReadsFixtures
15
+
16
+
17
+ class TestAddressesClient:
18
+ @mark.parametrize(
19
+ "customer_id, operation, expected_request_body, expected_response_body, expected_path",
20
+ [
21
+ (
22
+ "ctm_01gysfvfy7vqhpzkq8rjmrq7an",
23
+ CreateCustomerPortalSession(["sub_01h04vsc0qhwtsbsxh3422wjs4"]),
24
+ ReadsFixtures.read_raw_json_fixture("request/create_single"),
25
+ ReadsFixtures.read_raw_json_fixture("response/full_entity_single"),
26
+ "/customers/ctm_01gysfvfy7vqhpzkq8rjmrq7an/portal-sessions",
27
+ ),
28
+ (
29
+ "ctm_01gysfvfy7vqhpzkq8rjmrq7an",
30
+ CreateCustomerPortalSession(["sub_01h04vsc0qhwtsbsxh3422wjs4", "sub_02h04vsc0qhwtsbsxh3422wjs4"]),
31
+ ReadsFixtures.read_raw_json_fixture("request/create_multiple"),
32
+ ReadsFixtures.read_raw_json_fixture("response/full_entity_multiple"),
33
+ "/customers/ctm_01gysfvfy7vqhpzkq8rjmrq7an/portal-sessions",
34
+ ),
35
+ (
36
+ "ctm_01gysfvfy7vqhpzkq8rjmrq7an",
37
+ CreateCustomerPortalSession([]),
38
+ ReadsFixtures.read_raw_json_fixture("request/create_empty"),
39
+ ReadsFixtures.read_raw_json_fixture("response/full_entity_empty"),
40
+ "/customers/ctm_01gysfvfy7vqhpzkq8rjmrq7an/portal-sessions",
41
+ ),
42
+ (
43
+ "ctm_01gysfvfy7vqhpzkq8rjmrq7an",
44
+ CreateCustomerPortalSession(),
45
+ "{}",
46
+ ReadsFixtures.read_raw_json_fixture("response/full_entity_empty"),
47
+ "/customers/ctm_01gysfvfy7vqhpzkq8rjmrq7an/portal-sessions",
48
+ ),
49
+ ],
50
+ ids=[
51
+ "Create portal session with single subscription ID",
52
+ "Create portal session with multiple subscription IDs",
53
+ "Create portal session with empty subscription IDs",
54
+ "Create portal session with omitted subscription IDs",
55
+ ],
56
+ )
57
+ def test_create_uses_expected_payload(
58
+ self,
59
+ test_client,
60
+ mock_requests,
61
+ customer_id,
62
+ operation,
63
+ expected_request_body,
64
+ expected_response_body,
65
+ expected_path,
66
+ ):
67
+ expected_url = f"{test_client.base_url}{expected_path}"
68
+ mock_requests.post(expected_url, status_code=201, text=expected_response_body)
69
+
70
+ response = test_client.client.customer_portal_sessions.create(customer_id, operation)
71
+ response_json = test_client.client.customer_portal_sessions.response.json()
72
+ request_json = test_client.client.payload
73
+ last_request = mock_requests.last_request
74
+
75
+ assert isinstance(response, CustomerPortalSession)
76
+ assert last_request is not None
77
+ assert last_request.method == "POST"
78
+ assert test_client.client.status_code == 201
79
+ assert (
80
+ unquote(last_request.url) == expected_url
81
+ ), "The URL does not match the expected URL, verify the query string is correct"
82
+ assert loads(request_json) == loads(
83
+ expected_request_body
84
+ ), "The request JSON doesn't match the expected fixture JSON"
85
+ assert response_json == loads(
86
+ str(expected_response_body)
87
+ ), "The response JSON doesn't match the expected fixture JSON"
88
+
89
+ def test_create_returns_expected_response(
90
+ self,
91
+ test_client,
92
+ mock_requests,
93
+ ):
94
+ customer_id = "ctm_01gysfvfy7vqhpzkq8rjmrq7an"
95
+ expected_path = "/customers/ctm_01gysfvfy7vqhpzkq8rjmrq7an/portal-sessions"
96
+ expected_response_body = ReadsFixtures.read_raw_json_fixture("response/full_entity_multiple")
97
+
98
+ expected_url = f"{test_client.base_url}{expected_path}"
99
+ mock_requests.post(expected_url, status_code=201, text=expected_response_body)
100
+
101
+ response = test_client.client.customer_portal_sessions.create(
102
+ customer_id,
103
+ CreateCustomerPortalSession(["sub_01h04vsc0qhwtsbsxh3422wjs4", "sub_02h04vsc0qhwtsbsxh3422wjs4"]),
104
+ )
105
+
106
+ assert isinstance(response, CustomerPortalSession)
107
+ assert response.id == "cpls_01h4ge9r64c22exjsx0fy8b48b"
108
+ assert response.customer_id == customer_id
109
+ assert response.created_at.isoformat() == "2024-10-25T06:53:58+00:00"
110
+
111
+ urls = response.urls
112
+ assert isinstance(urls, CustomerPortalSessionUrls)
113
+
114
+ general = urls.general
115
+ assert isinstance(general, CustomerPortalSessionGeneralUrl)
116
+ assert (
117
+ general.overview
118
+ == "https://customer-portal.paddle.com/cpl_01j7zbyqs3vah3aafp4jf62qaw?action=overview&token=pga_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjdG1fMDFncm5uNHp0YTVhMW1mMDJqanplN3kyeXMiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE3Mjc2NzkyMzh9._oO12IejzdKmyKTwb7BLjmiILkx4_cSyGjXraOBUI_g"
119
+ )
120
+
121
+ subscription1 = urls.subscriptions[0]
122
+ assert isinstance(subscription1, CustomerPortalSessionSubscriptionUrl)
123
+ assert subscription1.id == "sub_01h04vsc0qhwtsbsxh3422wjs4"
124
+ assert (
125
+ subscription1.cancel_subscription
126
+ == "https://customer-portal.paddle.com/cpl_01j7zbyqs3vah3aafp4jf62qaw?action=cancel_subscription&subscription_id=sub_01h04vsc0qhwtsbsxh3422wjs4&token=pga_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjdG1fMDFncm5uNHp0YTVhMW1mMDJqanplN3kyeXMiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE3Mjc2NzkyMzh9._oO12IejzdKmyKTwb7BLjmiILkx4_cSyGjXraOBUI_g"
127
+ )
128
+ assert (
129
+ subscription1.update_subscription_payment_method
130
+ == "https://customer-portal.paddle.com/cpl_01j7zbyqs3vah3aafp4jf62qaw?action=update_subscription_payment_method&subscription_id=sub_01h04vsc0qhwtsbsxh3422wjs4&token=pga_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjdG1fMDFncm5uNHp0YTVhMW1mMDJqanplN3kyeXMiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE3Mjc2NzkyMzh9._oO12IejzdKmyKTwb7BLjmiILkx4_cSyGjXraOBUI_g"
131
+ )
132
+
133
+ subscription2 = urls.subscriptions[1]
134
+ assert isinstance(subscription2, CustomerPortalSessionSubscriptionUrl)
135
+ assert subscription2.id == "sub_02h04vsc0qhwtsbsxh3422wjs4"
136
+ assert (
137
+ subscription2.cancel_subscription
138
+ == "https://customer-portal.paddle.com/cpl_01j7zbyqs3vah3aafp4jf62qaw?action=cancel_subscription&subscription_id=sub_02h04vsc0qhwtsbsxh3422wjs4&token=pga_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjdG1fMDFncm5uNHp0YTVhMW1mMDJqanplN3kyeXMiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE3Mjc2NzkyMzh9._oO12IejzdKmyKTwb7BLjmiILkx4_cSyGjXraOBUI_g"
139
+ )
140
+ assert (
141
+ subscription2.update_subscription_payment_method
142
+ == "https://customer-portal.paddle.com/cpl_01j7zbyqs3vah3aafp4jf62qaw?action=update_subscription_payment_method&subscription_id=sub_02h04vsc0qhwtsbsxh3422wjs4&token=pga_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjdG1fMDFncm5uNHp0YTVhMW1mMDJqanplN3kyeXMiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE3Mjc2NzkyMzh9._oO12IejzdKmyKTwb7BLjmiILkx4_cSyGjXraOBUI_g"
143
+ )
@@ -5,7 +5,7 @@ from urllib.parse import unquote
5
5
  from paddle_billing.Entities.Collections import NotificationSettingCollection
6
6
  from paddle_billing.Entities.Events import EventTypeName
7
7
  from paddle_billing.Entities.NotificationSetting import NotificationSetting
8
- from paddle_billing.Entities.NotificationSettings import NotificationSettingType
8
+ from paddle_billing.Entities.NotificationSettings import NotificationSettingType, NotificationSettingTrafficSource
9
9
 
10
10
  from paddle_billing.Resources.Shared.Operations import Pager
11
11
 
@@ -71,10 +71,61 @@ class TestNotificationSettingsClient:
71
71
  ReadsFixtures.read_raw_json_fixture("response/full_entity"),
72
72
  "/notification-settings",
73
73
  ),
74
+ (
75
+ CreateNotificationSetting(
76
+ description="Slack notifications",
77
+ type=NotificationSettingType.Url,
78
+ destination="https://hooks.slack.com/example",
79
+ include_sensitive_fields=False,
80
+ subscribed_events=[
81
+ EventTypeName.TransactionCreated,
82
+ ],
83
+ traffic_source=NotificationSettingTrafficSource.All,
84
+ ),
85
+ ReadsFixtures.read_raw_json_fixture("request/create_traffic_all"),
86
+ 200,
87
+ ReadsFixtures.read_raw_json_fixture("response/minimal_entity"),
88
+ "/notification-settings",
89
+ ),
90
+ (
91
+ CreateNotificationSetting(
92
+ description="Slack notifications",
93
+ type=NotificationSettingType.Url,
94
+ destination="https://hooks.slack.com/example",
95
+ include_sensitive_fields=False,
96
+ subscribed_events=[
97
+ EventTypeName.TransactionCreated,
98
+ ],
99
+ traffic_source=NotificationSettingTrafficSource.Platform,
100
+ ),
101
+ ReadsFixtures.read_raw_json_fixture("request/create_traffic_platform"),
102
+ 200,
103
+ ReadsFixtures.read_raw_json_fixture("response/minimal_entity"),
104
+ "/notification-settings",
105
+ ),
106
+ (
107
+ CreateNotificationSetting(
108
+ description="Slack notifications",
109
+ type=NotificationSettingType.Url,
110
+ destination="https://hooks.slack.com/example",
111
+ include_sensitive_fields=False,
112
+ subscribed_events=[
113
+ EventTypeName.TransactionCreated,
114
+ ],
115
+ traffic_source=NotificationSettingTrafficSource.Simulation,
116
+ ),
117
+ ReadsFixtures.read_raw_json_fixture("request/create_traffic_simulation"),
118
+ 200,
119
+ ReadsFixtures.read_raw_json_fixture("response/minimal_entity"),
120
+ "/notification-settings",
121
+ ),
74
122
  ],
75
123
  ids=[
76
124
  "Create notification-setting with basic data",
77
125
  "Create notification-setting with full data",
126
+ "Create notification-setting for all traffic",
127
+ "Create notification-setting for platform traffic",
128
+ "Create notification-setting for simulation traffic",
78
129
  ],
79
130
  )
80
131
  def test_create_notification_setting_uses_expected_payload(
@@ -158,11 +209,44 @@ class TestNotificationSettingsClient:
158
209
  ReadsFixtures.read_raw_json_fixture("response/full_entity"),
159
210
  "/notification-settings/ntfset_01gkpjp8bkm3tm53kdgkx6sms7",
160
211
  ),
212
+ (
213
+ "ntfset_01gkpjp8bkm3tm53kdgkx6sms7",
214
+ UpdateNotificationSetting(
215
+ traffic_source=NotificationSettingTrafficSource.All,
216
+ ),
217
+ ReadsFixtures.read_raw_json_fixture("request/update_traffic_all"),
218
+ 200,
219
+ ReadsFixtures.read_raw_json_fixture("response/full_entity"),
220
+ "/notification-settings/ntfset_01gkpjp8bkm3tm53kdgkx6sms7",
221
+ ),
222
+ (
223
+ "ntfset_01gkpjp8bkm3tm53kdgkx6sms7",
224
+ UpdateNotificationSetting(
225
+ traffic_source=NotificationSettingTrafficSource.Platform,
226
+ ),
227
+ ReadsFixtures.read_raw_json_fixture("request/update_traffic_platform"),
228
+ 200,
229
+ ReadsFixtures.read_raw_json_fixture("response/full_entity"),
230
+ "/notification-settings/ntfset_01gkpjp8bkm3tm53kdgkx6sms7",
231
+ ),
232
+ (
233
+ "ntfset_01gkpjp8bkm3tm53kdgkx6sms7",
234
+ UpdateNotificationSetting(
235
+ traffic_source=NotificationSettingTrafficSource.Simulation,
236
+ ),
237
+ ReadsFixtures.read_raw_json_fixture("request/update_traffic_simulation"),
238
+ 200,
239
+ ReadsFixtures.read_raw_json_fixture("response/full_entity"),
240
+ "/notification-settings/ntfset_01gkpjp8bkm3tm53kdgkx6sms7",
241
+ ),
161
242
  ],
162
243
  ids=[
163
244
  "Update notification setting with basic data",
164
245
  "Update notification setting with partial data",
165
246
  "Update notification setting with full data",
247
+ "Create notification-setting for all traffic",
248
+ "Create notification-setting for platform traffic",
249
+ "Create notification-setting for simulation traffic",
166
250
  ],
167
251
  )
168
252
  def test_update_notification_setting_uses_expected_payload(
@@ -272,6 +356,24 @@ class TestNotificationSettingsClient:
272
356
  ),
273
357
  "/notification-settings?after=ntfset_01gkpjp8bkm3tm53kdgkx6sms7&order_by=id[desc]&per_page=100",
274
358
  ),
359
+ (
360
+ ListNotificationSettings(
361
+ traffic_source=NotificationSettingTrafficSource.All,
362
+ ),
363
+ "/notification-settings?traffic_source=all",
364
+ ),
365
+ (
366
+ ListNotificationSettings(
367
+ traffic_source=NotificationSettingTrafficSource.Platform,
368
+ ),
369
+ "/notification-settings?traffic_source=platform",
370
+ ),
371
+ (
372
+ ListNotificationSettings(
373
+ traffic_source=NotificationSettingTrafficSource.Simulation,
374
+ ),
375
+ "/notification-settings?traffic_source=simulation",
376
+ ),
275
377
  ],
276
378
  ids=[
277
379
  "List all notification-settings",
@@ -279,6 +381,9 @@ class TestNotificationSettingsClient:
279
381
  "List inactive notification-settings",
280
382
  "List notification-settings with pagination",
281
383
  "List notification-settings with pagination after",
384
+ "List notification-settings for all traffic",
385
+ "List notification-settings for platform traffic",
386
+ "List notification-settings for simulation traffic",
282
387
  ],
283
388
  )
284
389
  def test_list_notification_settings_hits_expected_url(
@@ -331,6 +436,24 @@ class TestNotificationSettingsClient:
331
436
 
332
437
  assert len(allNotificationSettings) == 2
333
438
 
439
+ def test_list_notification_entities_have_traffic_source(
440
+ self,
441
+ test_client,
442
+ mock_requests,
443
+ ):
444
+ mock_requests.get(
445
+ f"{test_client.base_url}/notification-settings",
446
+ status_code=200,
447
+ text=ReadsFixtures.read_raw_json_fixture("response/list_default"),
448
+ )
449
+
450
+ response = test_client.client.notification_settings.list()
451
+
452
+ assert isinstance(response, NotificationSettingCollection)
453
+ assert response.items[0].traffic_source == NotificationSettingTrafficSource.All
454
+ assert response.items[1].traffic_source == NotificationSettingTrafficSource.Platform
455
+ assert response.items[2].traffic_source == NotificationSettingTrafficSource.Simulation
456
+
334
457
  @mark.parametrize(
335
458
  "notification_setting_id, expected_response_status, expected_response_body, expected_url",
336
459
  [
@@ -370,6 +493,9 @@ class TestNotificationSettingsClient:
370
493
  str(expected_response_body)
371
494
  ), "The response JSON generated by ResponseParser() doesn't match the expected fixture JSON"
372
495
 
496
+ assert response.type == NotificationSettingType.Url
497
+ assert response.traffic_source == NotificationSettingTrafficSource.Platform
498
+
373
499
  @mark.parametrize(
374
500
  "notification_setting_id, expected_response_status, expected_path",
375
501
  [
@@ -259,12 +259,12 @@ class TestNotificationsClient:
259
259
  200,
260
260
  ReadsFixtures.read_raw_json_fixture("response/replay"),
261
261
  "ntf_01h46h1s2zabpkdks7yt4vkgkc",
262
- "/notifications/nft_01h8441jn5pcwrfhwh78jqt8hk",
262
+ "/notifications/nft_01h8441jn5pcwrfhwh78jqt8hk/replay",
263
263
  )
264
264
  ],
265
265
  ids=["Replay a notification by its id"],
266
266
  )
267
- def test_replacy_notification_returns_expected_response(
267
+ def test_replay_notification_returns_expected_response(
268
268
  self,
269
269
  test_client,
270
270
  mock_requests,
@@ -204,6 +204,7 @@ class TestPaymentMethodsClient:
204
204
  str(expected_response_body)
205
205
  ), "The response JSON generated by ResponseParser() doesn't match the expected fixture JSON"
206
206
 
207
+ assert response.id == "paymtd_01hs8zx6x377xfsfrt2bqsevbw"
207
208
  assert response.customer_id == "ctm_01hv6y1jedq4p1n0yqn5ba3ky4"
208
209
  assert response.address_id == "add_01hv8h6jj90jjz0d71m6hj4r9z"
209
210
  assert response.paypal is None
@@ -215,7 +216,7 @@ class TestPaymentMethodsClient:
215
216
  card = response.card
216
217
  assert isinstance(card, Card)
217
218
  assert card.type == "visa"
218
- assert card.last4 == 2
219
+ assert card.last4 == "0002"
219
220
  assert card.expiry_month == 1
220
221
  assert card.expiry_year == 2025
221
222
  assert card.cardholder_name == "Sam Miller"
@@ -249,6 +250,7 @@ class TestPaymentMethodsClient:
249
250
  str(expected_response_body)
250
251
  ), "The response JSON generated by ResponseParser() doesn't match the expected fixture JSON"
251
252
 
253
+ assert response.id == "paymtd_01hs8zx6x377xfsfrt2bqsevbw"
252
254
  assert response.customer_id == "ctm_01hv6y1jedq4p1n0yqn5ba3ky4"
253
255
  assert response.address_id == "add_01hv8h6jj90jjz0d71m6hj4r9z"
254
256
  assert response.card is None
@@ -269,7 +271,7 @@ class TestPaymentMethodsClient:
269
271
  ):
270
272
  customer_id = "ctm_01hv6y1jedq4p1n0yqn5ba3ky4"
271
273
  payment_method_id = "paymtd_01hs8zx6x377xfsfrt2bqsevbw"
272
- expected_response_status = 200
274
+ expected_response_status = 204
273
275
  expected_path = "/customers/ctm_01hv6y1jedq4p1n0yqn5ba3ky4/payment-methods/paymtd_01hs8zx6x377xfsfrt2bqsevbw"
274
276
 
275
277
  expected_url = f"{test_client.base_url}{expected_path}"
@@ -371,6 +371,27 @@ class TestSubscriptionsClient:
371
371
  str(expected_response_body)
372
372
  ), "The response JSON generated by ResponseParser() doesn't match the expected fixture JSON"
373
373
 
374
+ def test_list_subscriptions_supports_null_discount_starts_at(
375
+ self,
376
+ test_client,
377
+ mock_requests,
378
+ ):
379
+ mock_requests.get(
380
+ f"{test_client.base_url}/subscriptions",
381
+ status_code=200,
382
+ text=ReadsFixtures.read_raw_json_fixture("response/list_default"),
383
+ )
384
+
385
+ response = test_client.client.subscriptions.list(ListSubscriptions())
386
+
387
+ assert isinstance(response, SubscriptionCollection)
388
+ assert response.items[0].discount is None
389
+ assert response.items[1].discount is None
390
+ assert response.items[2].discount.starts_at is None
391
+ assert response.items[2].discount.ends_at is None
392
+ assert response.items[3].discount.starts_at.isoformat() == "2024-04-12T10:18:47.635628+00:00"
393
+ assert response.items[3].discount.ends_at.isoformat() == "2024-05-12T10:18:47.635628+00:00"
394
+
374
395
  @mark.parametrize(
375
396
  "subscription_id, includes, expected_response_status, expected_response_body, expected_url",
376
397
  [