Skip to content

Commit e7e34a6

Browse files
committed
Add helper / alias endpoints
1 parent 38812de commit e7e34a6

11 files changed

Lines changed: 124 additions & 77 deletions

README.md

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ paddle.refund_product_payment(order_id=1234, amount=0.01, reason='reason')
138138

139139
# Subscription API
140140
paddle.list_plans()
141+
paddle.get_plan(plan=123)
141142
paddle.create_plan(
142143
plan_name='plan_name',
143144
plan_trial_days=14,
@@ -150,6 +151,19 @@ paddle.create_plan(
150151
paddle.list_subscription_users()
151152
paddle.cancel_subscription(subscription_id=1234)
152153
paddle.update_subscription(subscription_id=1234, pause=True)
154+
paddle.update_subscription(
155+
subscription_id=1234,
156+
quantity=10.00,
157+
currency='USD',
158+
recurring_price=10.00,
159+
bill_immediately=False,
160+
plan_id=123,
161+
prorate=True,
162+
keep_modifiers=True,
163+
passthrough='passthrough',
164+
)
165+
paddle.pause_subscription(subscription_id=1234)
166+
paddle.resume_subscription(subscription_id=1234)
153167
paddle.preview_update_subscription(
154168
subscription_id=123,
155169
bill_immediately=True,
@@ -177,14 +191,12 @@ The below endpoints have been implimented but are not working correctly accordin
177191

178192
* [Generate License](https://developer.paddle.com/api-reference/product-api/licenses/createlicense) - `Paddle error 108 - Unable to find requested product`
179193
* [Create pay link](https://developer.paddle.com/api-reference/product-api/pay-links/createpaylink) - `Paddle error 108 - Unable to find requested product`
180-
* [Reschedule subscription payment](https://developer.paddle.com/api-reference/subscription-api/payments/updatepayment) - `Paddle error 122 - Provided date is not valid`
194+
* [Reschedule subscription payment](https://developer.paddle.com/api-reference/subscription-api/payments/updatepayment) - `Paddle error 122 - Provided date is not valid` - After manually testing via Paddles API reference I believe this is an issue with Paddle's API.
181195

182196

183197
## ToDo
184198
* Fix generate license, create pay link and reschedule payment endpoints
185-
* Work out if we want to include 'alias' methods like pause_subscription
186199
* Get test coverage to 100%
187-
* Docs (auto docs?)
188200
* Use `pytest-mock` `Spy` to check params, json, urls etc for test requests
189201
* Needed to any tests which skip due to missing data
190202
* How to deal with the manual cleanup?

docs/api_reference.rst

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ API Reference
33

44
Below is a :ref:`full list<Full reference>` of the Paddle Client methods. :ref:`Supported Paddle endpoints` lists the Paddle API endpoints in the same order as they are in the `Paddle API Reference <https://developer.paddle.com/api-reference>`_
55

6+
There are also several *helper* methods implimented on top of the Paddle endpoints to make usage of the API easier.
7+
8+
For example the ``pause_subscription`` and ``resume_subscription`` methods have been added on top of ``update_subscription`` as to pause or resume a subscription the ``update_subscription`` endpoint is used but only the ``pause`` parameter can be set (and will fail if any others are).
9+
610

711
Supported Paddle endpoints
812
--------------------------
@@ -27,11 +31,11 @@ As listed in the `Paddle API Reference <https://developer.paddle.com/api-referen
2731

2832
**Subscription API**
2933

30-
- :meth:`List Plans<paddle.PaddleClient.list_plans>`
34+
- :meth:`List Plans<paddle.PaddleClient.list_plans>` - (Including :meth:`Get Plan<paddle.PaddleClient.get_plan>`)
3135
- :meth:`Create Plan<paddle.PaddleClient.create_plan>`
3236
- :meth:`List Subscription Users<paddle.PaddleClient.list_subscription_users>`
3337
- :meth:`Cancel Subscription<paddle.PaddleClient.cancel_subscription>`
34-
- :meth:`Update Subscription<paddle.PaddleClient.update_subscription>`
38+
- :meth:`Update Subscription<paddle.PaddleClient.update_subscription>` - (Including :meth:`Pause Subscription<paddle.PaddleClient.pause_subscription>` and :meth:`Resume Subscription<paddle.PaddleClient.resume_subscription>`)
3539
- :meth:`Preview Subscription Update<paddle.PaddleClient.preview_subscription_update>`
3640
- :meth:`Add Modifier<paddle.PaddleClient.add_modifier>`
3741
- :meth:`Delete Modifier<paddle.PaddleClient.delete_modifier>`

paddle/_pay_links.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,14 @@ def create_pay_link(
4444
`Create Pay Link Paddle docs <https://developer.paddle.com/api-reference/product-api/pay-links/createpaylink>`_
4545
4646
product_id appears to be required:
47-
Paddle error 108 - Unable to find requested product
47+
48+
Paddle error 108 - Unable to find requested product
49+
50+
4851
Even though the docs states:
49-
"If no product_id is set, custom non-subscription product checkouts
50-
can be generated instead by specifying title, webhook_url and prices."
51-
https://developer.paddle.com/api-reference/product-api/coupons/createcoupon # NOQA: E501
52+
53+
"If no product_id is set, custom non-subscription product checkouts
54+
can be generated instead by specifying title, webhook_url and prices."
5255
""" # NOQA: E501
5356
url = urljoin(self.vendors_v2, 'product/generate_license')
5457

paddle/_plans.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,15 @@ def list_plans(self, plan: int = None) -> List[dict]:
1919
return self.post(url=url)
2020

2121

22-
# def get_plan(self, plan: int) -> dict:
23-
# """
24-
# `List Plans Paddle docs <https://developer.paddle.com/api-reference/subscription-api/plans/listplans>`_ # NOQA: E501
22+
def get_plan(self, plan: int) -> dict:
23+
"""
24+
`List Plans Paddle docs <https://developer.paddle.com/api-reference/subscription-api/plans/listplans>`_
2525
26-
# There is no get_plan endpoint in Paddle's API. This is a convenient
27-
# alias of the list plans endpoint where the Plan ID is required
28-
# """ # NOQA: E501
29-
# return self.list_plans(plan=plan)[0]
26+
There is no Get Plan endpoint in Paddle's API but list plans does support
27+
sending through a plan ID. This is a helper method to get a single plan
28+
where the plan parameter is required.
29+
""" # NOQA: E501
30+
return self.list_plans(plan=plan)[0]
3031

3132

3233
def create_plan(

paddle/_subscription_users.py

Lines changed: 16 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -36,30 +36,6 @@ def list_subscription_users(
3636
return self.post(url=url, json=json)
3737

3838

39-
# def list_subscriptions(self, **kwargs: dict) -> List[dict]:
40-
# """
41-
# `List Users (subscription) Paddle docs <https://developer.paddle.com/api-reference/subscription-api/subscription-users/listusers>`_ # NOQA: E501
42-
43-
# This is a convenient alias for list_subscription_users as while the
44-
# other name matches the API name, it's not particularly guessable
45-
# """ # NOQA: E501
46-
# return self.list_subscription_users(**kwargs)
47-
48-
49-
# def get_subscription(self, subscription_id: int) -> dict:
50-
# """
51-
# `List Users (subscription) Paddle docs <https://developer.paddle.com/api-reference/subscription-api/subscription-users/listusers>`_ # NOQA: E501
52-
53-
# There is no get_subscription endpoint in Paddle's API, This is a
54-
# convenient alias
55-
# """ # NOQA: E501
56-
# for subscription in self.list_subscription_users():
57-
# if subscription['subscription_id'] == subscription_id:
58-
# return subscription
59-
# error = 'Unable to find subscription with id {0}'.format(subscription_id)
60-
# raise ValueError(error)
61-
62-
6339
def cancel_subscription(
6440
self,
6541
subscription_id: int,
@@ -108,26 +84,26 @@ def update_subscription(
10884
return self.post(url=url, json=json)
10985

11086

111-
# def pause_subscription(self, subscription_id: int) -> dict:
112-
# """
113-
# `Update Subscription Paddle docs <https://developer.paddle.com/api-reference/subscription-api/subscription-users/updateuser`_ # NOQA: E501
87+
def pause_subscription(self, subscription_id: int) -> dict:
88+
"""
89+
`Update Subscription Paddle docs <https://developer.paddle.com/api-reference/subscription-api/subscription-users/updateuser>`_
11490
115-
# There is no resume_subscription endpoint in Paddle's API. This is a
116-
# convenient alias for update_subscription as no extra data can be sent
117-
# when pausing/resuming subscriptions
118-
# """ # NOQA: E501
119-
# return self.update_subscription(subscription_id=subscription_id, pause=True) # NOQA: E501
91+
There is no Pause Subscription endpoint in Paddle's API. This is a
92+
convenient helper method for update_subscription as no extra data can be
93+
sent when pausing/resuming subscriptions
94+
""" # NOQA: E501
95+
return self.update_subscription(subscription_id=subscription_id, pause=True) # NOQA: E501
12096

12197

122-
# def resume_subscription(self, subscription_id: int) -> dict:
123-
# """
124-
# `Update Subscription Paddle docs <https://developer.paddle.com/api-reference/subscription-api/subscription-users/updateuser`_ # NOQA: E501
98+
def resume_subscription(self, subscription_id: int) -> dict:
99+
"""
100+
`Update Subscription Paddle docs <https://developer.paddle.com/api-reference/subscription-api/subscription-users/updateuser>`_
125101
126-
# There is no resume_subscription endpoint in Paddle's API. This is a
127-
# convenient alias for update_subscription as no extra data can be sent
128-
# when pausing/resuming subscriptions
129-
# """ # NOQA: E501
130-
# return self.update_subscription(subscription_id=subscription_id, pause=False) # NOQA: E501
102+
There is no Resume Subscription endpoint in Paddle's API. This is a
103+
convenient helper method for update_subscription as no extra data can be
104+
sent when pausing/resuming subscriptions
105+
""" # NOQA: E501
106+
return self.update_subscription(subscription_id=subscription_id, pause=False) # NOQA: E501
131107

132108

133109
def preview_subscription_update(

paddle/paddle.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,12 +179,15 @@ def post(self, url, **kwargs):
179179
from ._product_payments import refund_product_payment
180180

181181
from ._plans import list_plans
182-
# from ._plans import get_plan
182+
from ._plans import get_plan
183183
from ._plans import create_plan
184184

185185
from ._subscription_users import list_subscription_users
186+
from ._subscription_users import list_subscription_users as list_subscriptions # NOQA: E501
186187
from ._subscription_users import cancel_subscription
187188
from ._subscription_users import update_subscription
189+
from ._subscription_users import pause_subscription
190+
from ._subscription_users import resume_subscription
188191
from ._subscription_users import preview_subscription_update
189192
# Alias to better match update_subscription
190193
from ._subscription_users import preview_subscription_update as preview_update_subscription # NOQA: E501

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name = "paddle-client"
33
packages = [
44
{include = "paddle"}
55
]
6-
version = "0.7.1"
6+
version = "0.8.0"
77
description = "Python wrapper around the Paddle.com API"
88
license = "MIT"
99
authors = ["Matt Pye <pyematt@gmail.com>"]

tests/test_one_off_charges.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ def test_create_one_off_charge(mocker, paddle_client): # NOQA: F811
1414
This test is mocked as creating a one off charge against Paddle will
1515
actually create a one of charge
1616
17-
If the below test fails it means a change has been made which has affected
18-
the refund payment endpoint.
17+
If this test fails it means a change has been made which has affected
18+
the one-off charge endpoint.
1919
2020
The code now needs to be run directly against Paddle's API at least once to
2121
ensure the new code is working as expected.

tests/test_plans.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,17 @@ def test_list_plans_with_plan(paddle_client): # NOQA: F811
3434
assert isinstance(plan['trial_days'], int)
3535

3636

37-
# def test_get_plan(paddle_client): # NOQA: F811
38-
# # ToDo: Create plan when API exists for it here
39-
# plan_id = int(os.environ['PADDLE_TEST_DEFAULT_PLAN_ID'])
40-
# plan = paddle_client.get_plan(plan=plan_id)
41-
# assert plan['id'] == plan_id
42-
# assert isinstance(plan['billing_period'], int)
43-
# assert isinstance(plan['billing_type'], str)
44-
# assert isinstance(plan['initial_price'], dict)
45-
# assert isinstance(plan['name'], str)
46-
# assert isinstance(plan['recurring_price'], dict)
47-
# assert isinstance(plan['trial_days'], int)
37+
def test_get_plan(paddle_client): # NOQA: F811
38+
# ToDo: Create plan when API exists for it here
39+
plan_id = int(os.environ['PADDLE_TEST_DEFAULT_PLAN_ID'])
40+
plan = paddle_client.get_plan(plan=plan_id)
41+
assert plan['id'] == plan_id
42+
assert isinstance(plan['billing_period'], int)
43+
assert isinstance(plan['billing_type'], str)
44+
assert isinstance(plan['initial_price'], dict)
45+
assert isinstance(plan['name'], str)
46+
assert isinstance(plan['recurring_price'], dict)
47+
assert isinstance(plan['trial_days'], int)
4848

4949

5050
@pytest.mark.manual_cleanup

tests/test_product_payments.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ def test_refund_product_payment(mocker, paddle_client): # NOQA: F811
1111
This test is mocked as creating a refund is not something you want to
1212
happen against a live system.
1313
14-
If the below test fails it means a change has been made which has affected
15-
the refund payment endpoint.
14+
If this test fails it means a change has been made which has affected
15+
the refund product payment endpoint.
1616
1717
The code now needs to be run directly against Paddle's API at least once to
1818
ensure the new code is working as expected.

0 commit comments

Comments
 (0)