Skip to content

Commit 6889c54

Browse files
authored
Merge pull request #60 from XeroAPI/app-store-subscriptions
app store subscriptions added
2 parents ec94bbe + 238678c commit 6889c54

38 files changed

+38900
-44489
lines changed

docs/v1/accounting/index.html

Lines changed: 37067 additions & 44202 deletions
Large diffs are not rendered by default.

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,5 @@ def read_file(filename):
4848
keywords="xero python sdk API oAuth",
4949
name="xero_python",
5050
packages=find_packages(include=["xero_python", "xero_python.*"]),
51-
version="1.8.1",
51+
version="1.9.0",
5252
)

xero_python/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22

33
__author__ = """Xero Developer API"""
44
__email__ = "api@xero.com"
5-
__version__ = "1.8.1"
5+
__version__ = "1.9.0"

xero_python/accounting/api/accounting_api.py

Lines changed: 110 additions & 110 deletions
Large diffs are not rendered by default.

xero_python/accounting/docs/Payment.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Name | Type | Description | Notes
1414
**date** | **date** | Date the payment is being made (YYYY-MM-DD) e.g. 2009-09-06 | [optional]
1515
**currency_rate** | **float** | Exchange rate when payment is received. Only used for non base currency invoices and credit notes e.g. 0.7500 | [optional]
1616
**amount** | **float** | The amount of the payment. Must be less than or equal to the outstanding amount owing on the invoice e.g. 200.00 | [optional]
17+
**bank_amount** | **float** | The amount of the payment in the currency of the bank account. | [optional]
1718
**reference** | **str** | An optional description for the payment e.g. Direct Debit | [optional]
1819
**is_reconciled** | **bool** | An optional parameter for the payment. A boolean indicating whether you would like the payment to be created as reconciled when using PUT, or whether a payment has been reconciled when using GET | [optional]
1920
**status** | **str** | The status of the payment. | [optional]

xero_python/accounting/models/payment.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class Payment(BaseModel):
4141
"date": "date[ms-format]",
4242
"currency_rate": "float",
4343
"amount": "float",
44+
"bank_amount": "float",
4445
"reference": "str",
4546
"is_reconciled": "bool",
4647
"status": "str",
@@ -69,6 +70,7 @@ class Payment(BaseModel):
6970
"date": "Date",
7071
"currency_rate": "CurrencyRate",
7172
"amount": "Amount",
73+
"bank_amount": "BankAmount",
7274
"reference": "Reference",
7375
"is_reconciled": "IsReconciled",
7476
"status": "Status",
@@ -98,6 +100,7 @@ def __init__(
98100
date=None,
99101
currency_rate=None,
100102
amount=None,
103+
bank_amount=None,
101104
reference=None,
102105
is_reconciled=None,
103106
status=None,
@@ -126,6 +129,7 @@ def __init__(
126129
self._date = None
127130
self._currency_rate = None
128131
self._amount = None
132+
self._bank_amount = None
129133
self._reference = None
130134
self._is_reconciled = None
131135
self._status = None
@@ -164,6 +168,8 @@ def __init__(
164168
self.currency_rate = currency_rate
165169
if amount is not None:
166170
self.amount = amount
171+
if bank_amount is not None:
172+
self.bank_amount = bank_amount
167173
if reference is not None:
168174
self.reference = reference
169175
if is_reconciled is not None:
@@ -436,6 +442,29 @@ def amount(self, amount):
436442

437443
self._amount = amount
438444

445+
@property
446+
def bank_amount(self):
447+
"""Gets the bank_amount of this Payment. # noqa: E501
448+
449+
The amount of the payment in the currency of the bank account. # noqa: E501
450+
451+
:return: The bank_amount of this Payment. # noqa: E501
452+
:rtype: float
453+
"""
454+
return self._bank_amount
455+
456+
@bank_amount.setter
457+
def bank_amount(self, bank_amount):
458+
"""Sets the bank_amount of this Payment.
459+
460+
The amount of the payment in the currency of the bank account. # noqa: E501
461+
462+
:param bank_amount: The bank_amount of this Payment. # noqa: E501
463+
:type: float
464+
"""
465+
466+
self._bank_amount = bank_amount
467+
439468
@property
440469
def reference(self):
441470
"""Gets the reference of this Payment. # noqa: E501

xero_python/accounting/models/time_zone.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,4 @@ class TimeZone(Enum):
132132
HAWAIIANSTANDARDTIME = "HAWAIIANSTANDARDTIME"
133133
UTC11 = "UTC11"
134134
DATELINESTANDARDTIME = "DATELINESTANDARDTIME"
135+
EASTERISLANDSTANDARDTIME = "EASTERISLANDSTANDARDTIME"

xero_python/api_client/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -758,13 +758,13 @@ def revoke_oauth2_token(self):
758758
if oauth2_token.revoke_access_token(self):
759759
return self.get_oauth2_token()
760760

761-
def get_client_credentials_token(self):
761+
def get_client_credentials_token(self, app_store_billing=False):
762762
"""
763763
Obtain oauth2 token using client credentials grant type
764764
:return: oauth2 token
765765
"""
766766
oauth2_token = self.configuration.oauth2_token
767-
if oauth2_token.get_client_credentials_access_token(self):
767+
if oauth2_token.get_client_credentials_access_token(self, app_store_billing):
768768
return self.get_oauth2_token()
769769

770770
def oauth2_token_getter(self, token_getter):

xero_python/api_client/deserializer.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
MS_DATETIME_RE = re.compile(r"/Date\((?P<timestamp>-?\d+)(?P<tzinfo>[+-]\d{2,4})?\)/$")
2525
DATE_WITH_NO_DAY_RE = re.compile("(\d\d\d\d)-(\d\d)")
2626

27+
2728
def deserialize_routing(data_type, data, model_finder):
2829
"""Custom logic to find matching deserialize implementation and
2930
returns it's unique registration string key
@@ -210,16 +211,17 @@ def deserialize_datetime(data_type, data, model_finder):
210211
:return: deserialized datetime.datetime
211212
212213
"""
213-
try:
214-
dt = isoparse(data)
215-
except (ValueError, TypeError):
216-
raise ValueError("Invalid datetime value {!r}".format(data))
214+
if data is not None:
215+
try:
216+
dt = isoparse(data)
217+
except (ValueError, TypeError):
218+
raise ValueError("Invalid datetime value {!r}".format(data))
217219

218-
if not dt.tzinfo:
219-
# timezone naive datetime from Xero API response always in UTC
220-
dt = dt.replace(tzinfo=tz.UTC)
220+
if not dt.tzinfo:
221+
# timezone naive datetime from Xero API response always in UTC
222+
dt = dt.replace(tzinfo=tz.UTC)
221223

222-
return dt
224+
return dt
223225

224226

225227
@deserialize.register("datetime[ms-format]")
@@ -251,7 +253,7 @@ def deserialize_datetime_ms(data_type, data, model_finder):
251253
timestamp_s = timestamp_ms / 1000
252254
return datetime.datetime.fromtimestamp(timestamp_s, tz=tz_info)
253255
elif DATE_WITH_NO_DAY_RE.match(str(data)):
254-
return datetime.datetime.strptime(data + '-01', '%Y-%m-%d')
256+
return datetime.datetime.strptime(data + "-01", "%Y-%m-%d")
255257
else:
256258
raise ValueError("Invalid datetime value {!r}".format(data))
257259

xero_python/api_client/oauth2.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def revoke_token(self, refresh_token):
8181
)
8282
return status
8383

84-
def get_client_credentials_token(self):
84+
def get_client_credentials_token(self, app_store_billing):
8585
"""
8686
Call Xero Identity API to obtain an access token via OAuth2 Client Credentails grant type
8787
:return: dictionary with new auth2 token
@@ -91,6 +91,8 @@ def get_client_credentials_token(self):
9191
"client_secret": self.client_secret,
9292
"grant_type": "client_credentials",
9393
}
94+
if app_store_billing:
95+
post_data["scope"] = "marketplace.billing"
9496
response, status, headers = self.api_client.call_api(
9597
self.client_credentials_token_url,
9698
"POST",
@@ -231,14 +233,14 @@ def refresh_access_token(self, api_client):
231233
api_client.set_oauth2_token(new_token)
232234
return True
233235

234-
def get_client_credentials_access_token(self, api_client):
236+
def get_client_credentials_access_token(self, api_client, app_store_billing):
235237
"""
236238
Perform OAuth2 Client Credentials grant token request.
237239
:param api_client: ApiClient instance used to perform refresh token API call.
238240
:return: bool - True if success
239241
"""
240242
token_api = TokenApi(api_client, self.client_id, self.client_secret)
241-
new_token = token_api.get_client_credentials_token()
243+
new_token = token_api.get_client_credentials_token(app_store_billing)
242244
self.update_token(**new_token)
243245
api_client.set_oauth2_token(new_token)
244246
return True

xero_python/appstore/__init__.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# coding: utf-8
2+
3+
# flake8: noqa
4+
5+
"""
6+
Xero AppStore API
7+
8+
These endpoints are for Xero Partners to interact with the App Store Billing platform # noqa: E501
9+
10+
Contact: api@xero.com
11+
Generated by: https://openapi-generator.tech
12+
"""
13+
14+
15+
# import apis into sdk package
16+
from xero_python.appstore.api.app_store_api import AppStoreApi
17+
18+
19+
# import models into sdk package
20+
from xero_python.appstore.models.plan import Plan
21+
from xero_python.appstore.models.price import Price
22+
from xero_python.appstore.models.problem_details import ProblemDetails
23+
from xero_python.appstore.models.product import Product
24+
from xero_python.appstore.models.subscription import Subscription
25+
from xero_python.appstore.models.subscription_item import SubscriptionItem

xero_python/appstore/api/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# flake8: noqa
2+
3+
# import apis into api package
4+
from xero_python.appstore.api.app_store_api import AppStoreApi
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# coding: utf-8
2+
3+
"""
4+
Xero AppStore API
5+
6+
These endpoints are for Xero Partners to interact with the App Store Billing platform # noqa: E501
7+
8+
Contact: api@xero.com
9+
Generated by: https://openapi-generator.tech
10+
"""
11+
12+
"""
13+
OpenAPI spec version: 2.16.1
14+
"""
15+
16+
import importlib
17+
import re # noqa: F401
18+
19+
from xero_python import exceptions
20+
from xero_python.api_client import ApiClient, ModelFinder
21+
22+
try:
23+
from .exception_handler import translate_status_exception
24+
except ImportError:
25+
translate_status_exception = exceptions.translate_status_exception
26+
27+
28+
class empty:
29+
"""empty object to mark optional parameter not set"""
30+
31+
32+
class AppStoreApi(object):
33+
"""NOTE: This class is auto generated by OpenAPI Generator
34+
Ref: https://openapi-generator.tech
35+
36+
Do not edit the class manually.
37+
"""
38+
39+
base_url = "https://api.xero.com/appstore/2.0"
40+
models_module = importlib.import_module("xero_python.appstore.models")
41+
42+
def __init__(self, api_client=None, base_url=None):
43+
if api_client is None:
44+
api_client = ApiClient()
45+
self.api_client = api_client
46+
self.base_url = base_url or self.base_url
47+
48+
def get_resource_url(self, resource_path):
49+
"""
50+
Combine API base url with resource specific path
51+
:param str resource_path: API endpoint specific path
52+
:return: str full resource path
53+
"""
54+
return self.base_url + resource_path
55+
56+
def get_model_finder(self):
57+
return ModelFinder(self.models_module)
58+
59+
def get_subscription(
60+
self,
61+
subscription_id,
62+
_return_http_data_only=True,
63+
_preload_content=True,
64+
_request_timeout=None,
65+
):
66+
"""Retrieves a subscription for a given subscriptionId # noqa: E501
67+
OAuth2 scope: marketplace.billing
68+
:param str subscription_id: Unique identifier for Subscription object (required)
69+
:param bool _return_http_data_only: return received data only
70+
:param bool _preload_content: load received data in models
71+
:param bool _request_timeout: maximum wait time for response
72+
:return: Subscription
73+
"""
74+
75+
# verify the required parameter 'subscription_id' is set
76+
if subscription_id is None:
77+
raise ValueError(
78+
"Missing the required parameter `subscription_id` "
79+
"when calling `get_subscription`"
80+
)
81+
82+
collection_formats = {}
83+
path_params = {
84+
"subscriptionId": subscription_id,
85+
}
86+
87+
query_params = []
88+
89+
header_params = {}
90+
91+
local_var_files = {}
92+
form_params = []
93+
94+
body_params = None
95+
# HTTP header `Accept`
96+
header_params["Accept"] = self.api_client.select_header_accept(
97+
["application/json"]
98+
)
99+
100+
# Authentication setting
101+
auth_settings = ["OAuth2"]
102+
url = self.get_resource_url("/subscriptions/{subscriptionId}")
103+
104+
try:
105+
return self.api_client.call_api(
106+
url,
107+
"GET",
108+
path_params,
109+
query_params,
110+
header_params,
111+
body=body_params,
112+
post_params=form_params,
113+
files=local_var_files,
114+
response_type="Subscription",
115+
response_model_finder=self.get_model_finder(),
116+
auth_settings=auth_settings,
117+
_return_http_data_only=_return_http_data_only,
118+
_preload_content=_preload_content,
119+
_request_timeout=_request_timeout,
120+
collection_formats=collection_formats,
121+
)
122+
except exceptions.HTTPStatusException as error:
123+
raise translate_status_exception(error, self, "get_subscription")

0 commit comments

Comments
 (0)