paymentsgate 1.5.0__py3-none-any.whl → 1.5.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.
Potentially problematic release.
This version of paymentsgate might be problematic. Click here for more details.
- paymentsgate/__init__.py +14 -14
- paymentsgate/cache.py +9 -7
- paymentsgate/client.py +270 -110
- paymentsgate/enums.py +60 -59
- paymentsgate/exceptions.py +29 -12
- paymentsgate/logger.py +0 -1
- paymentsgate/mappers.py +0 -1
- paymentsgate/models.py +234 -197
- paymentsgate/signature.py +91 -0
- paymentsgate/tokens.py +7 -4
- paymentsgate/transport.py +12 -6
- paymentsgate/types.py +3 -5
- {paymentsgate-1.5.0.dist-info → paymentsgate-1.5.2.dist-info}/METADATA +5 -4
- paymentsgate-1.5.2.dist-info/RECORD +16 -0
- paymentsgate-1.5.0.dist-info/RECORD +0 -15
- {paymentsgate-1.5.0.dist-info → paymentsgate-1.5.2.dist-info}/LICENSE +0 -0
- {paymentsgate-1.5.0.dist-info → paymentsgate-1.5.2.dist-info}/WHEEL +0 -0
paymentsgate/__init__.py
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
from paymentsgate.client import ApiClient
|
|
2
2
|
from paymentsgate.enums import (
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
3
|
+
AuthenticationRealms,
|
|
4
|
+
ApiPaths,
|
|
5
|
+
Currencies,
|
|
6
|
+
Languages,
|
|
7
|
+
Statuses,
|
|
8
|
+
CurrencyTypes,
|
|
9
|
+
InvoiceTypes,
|
|
10
|
+
CredentialsTypes,
|
|
11
|
+
RiskScoreLevels,
|
|
12
|
+
CancellationReason,
|
|
13
|
+
FeesStrategy,
|
|
14
|
+
InvoiceDirection,
|
|
15
|
+
TTLUnits,
|
|
16
16
|
)
|
|
17
|
-
from paymentsgate.models import Credentials
|
|
17
|
+
from paymentsgate.models import Credentials
|
paymentsgate/cache.py
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
from abc import ABC, abstractmethod
|
|
2
2
|
from dataclasses import dataclass, field
|
|
3
3
|
|
|
4
|
-
from paymentsgate.tokens import
|
|
5
|
-
|
|
6
|
-
RefreshToken
|
|
7
|
-
)
|
|
4
|
+
from paymentsgate.tokens import AccessToken, RefreshToken
|
|
5
|
+
|
|
8
6
|
|
|
9
7
|
class AbstractCache(ABC):
|
|
10
8
|
"""
|
|
@@ -19,15 +17,19 @@ class AbstractCache(ABC):
|
|
|
19
17
|
...
|
|
20
18
|
|
|
21
19
|
@abstractmethod
|
|
22
|
-
def set_token(self,token: AccessToken | RefreshToken) -> None:
|
|
20
|
+
def set_token(self, token: AccessToken | RefreshToken) -> None:
|
|
23
21
|
"""
|
|
24
22
|
Save the token to the cache under the specified key
|
|
25
23
|
"""
|
|
26
24
|
...
|
|
27
|
-
|
|
25
|
+
|
|
26
|
+
|
|
28
27
|
@dataclass
|
|
29
28
|
class DefaultCache(AbstractCache):
|
|
30
|
-
tokens: dict[str, AccessToken | RefreshToken] = field(
|
|
29
|
+
tokens: dict[str, AccessToken | RefreshToken] = field(
|
|
30
|
+
default_factory=dict, init=False
|
|
31
|
+
)
|
|
32
|
+
|
|
31
33
|
def get_token(self, key: str) -> AccessToken | RefreshToken | None:
|
|
32
34
|
return self.tokens.get(key)
|
|
33
35
|
|
paymentsgate/client.py
CHANGED
|
@@ -1,26 +1,20 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
import logging
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
import json
|
|
5
5
|
from urllib.parse import urlencode
|
|
6
6
|
from pydantic import Field, BaseModel
|
|
7
7
|
|
|
8
8
|
from .types import TokenResponse
|
|
9
|
-
from .tokens import
|
|
10
|
-
|
|
11
|
-
RefreshToken
|
|
12
|
-
)
|
|
13
|
-
from .exceptions import (
|
|
14
|
-
APIResponseError,
|
|
15
|
-
APIAuthenticationError
|
|
16
|
-
)
|
|
9
|
+
from .tokens import AccessToken, RefreshToken
|
|
10
|
+
from .exceptions import APIResponseError, APIAuthenticationError
|
|
17
11
|
from .models import (
|
|
18
|
-
Credentials,
|
|
19
|
-
GetQuoteModel,
|
|
20
|
-
GetQuoteResponseModel,
|
|
21
|
-
PayInModel,
|
|
22
|
-
PayInResponseModel,
|
|
23
|
-
PayOutModel,
|
|
12
|
+
Credentials,
|
|
13
|
+
GetQuoteModel,
|
|
14
|
+
GetQuoteResponseModel,
|
|
15
|
+
PayInModel,
|
|
16
|
+
PayInResponseModel,
|
|
17
|
+
PayOutModel,
|
|
24
18
|
PayOutResponseModel,
|
|
25
19
|
InvoiceModel,
|
|
26
20
|
GetQuoteTlv,
|
|
@@ -28,32 +22,240 @@ from .models import (
|
|
|
28
22
|
QuoteTlvResponse,
|
|
29
23
|
)
|
|
30
24
|
from .enums import ApiPaths
|
|
31
|
-
from .transport import
|
|
32
|
-
Request,
|
|
33
|
-
Response
|
|
34
|
-
)
|
|
25
|
+
from .transport import Request, Response
|
|
35
26
|
from .logger import Logger
|
|
36
|
-
from .cache import
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
)
|
|
27
|
+
from .cache import AbstractCache, DefaultCache
|
|
28
|
+
|
|
29
|
+
import httpx
|
|
40
30
|
|
|
41
|
-
import requests
|
|
42
31
|
|
|
32
|
+
class BaseClient:
|
|
43
33
|
|
|
44
|
-
|
|
45
|
-
def __init__(self, config: Credentials, baseUrl: str, debug: bool=False):
|
|
34
|
+
def __init__(self, config: Credentials, baseUrl: str, timeout: int = 20, debug: bool=False):
|
|
46
35
|
self.config = config
|
|
47
36
|
self.cache = DefaultCache()
|
|
48
37
|
self.baseUrl = baseUrl
|
|
49
|
-
|
|
50
|
-
self.REQUEST_DEBUG = False
|
|
51
|
-
self.RESPONSE_DEBUG = False
|
|
52
|
-
self.timeout = 180
|
|
53
|
-
|
|
38
|
+
self.timeout = timeout
|
|
54
39
|
if debug:
|
|
55
40
|
logging.basicConfig(level=logging.DEBUG)
|
|
56
41
|
|
|
42
|
+
|
|
43
|
+
class ApiAsyncClient(BaseClient):
|
|
44
|
+
async def PayIn(self, request: PayInModel) -> PayInResponseModel:
|
|
45
|
+
# Prepare request
|
|
46
|
+
request = Request(
|
|
47
|
+
method="post",
|
|
48
|
+
path=ApiPaths.invoices_payin,
|
|
49
|
+
content_type='application/json',
|
|
50
|
+
noAuth=False,
|
|
51
|
+
body=request.model_dump(exclude_none=True),
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
# Handle response
|
|
55
|
+
response = await self._send_request(request)
|
|
56
|
+
if (response.success):
|
|
57
|
+
return response.cast(PayInResponseModel, APIResponseError)
|
|
58
|
+
else:
|
|
59
|
+
raise APIResponseError(response)
|
|
60
|
+
|
|
61
|
+
async def PayOut(self, request: PayOutModel) -> PayOutResponseModel:
|
|
62
|
+
# Prepare request
|
|
63
|
+
request = Request(
|
|
64
|
+
method="post",
|
|
65
|
+
path=ApiPaths.invoices_payout,
|
|
66
|
+
content_type='application/json',
|
|
67
|
+
noAuth=False,
|
|
68
|
+
signature=True,
|
|
69
|
+
body=request.model_dump(exclude_none=True)
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
# Handle response
|
|
73
|
+
response = await self._send_request(request)
|
|
74
|
+
if (response.success):
|
|
75
|
+
return response.cast(PayOutResponseModel, APIResponseError)
|
|
76
|
+
else:
|
|
77
|
+
raise APIResponseError(response)
|
|
78
|
+
|
|
79
|
+
async def PayOutTlv(self, request: PayOutTlvRequest) -> PayOutResponseModel:
|
|
80
|
+
request = Request(
|
|
81
|
+
method="post",
|
|
82
|
+
path=ApiPaths.invoices_payout_tlv,
|
|
83
|
+
content_type="application/json",
|
|
84
|
+
noAuth=False,
|
|
85
|
+
signature=False,
|
|
86
|
+
body=request.model_dump(exclude_none=True),
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
# Handle response
|
|
90
|
+
response = await self._send_request(request)
|
|
91
|
+
if not response.success:
|
|
92
|
+
raise APIResponseError(response)
|
|
93
|
+
|
|
94
|
+
return response.cast(PayOutResponseModel, APIResponseError)
|
|
95
|
+
|
|
96
|
+
async def Quote(self, params: GetQuoteModel) -> GetQuoteResponseModel:
|
|
97
|
+
# Prepare request
|
|
98
|
+
request = Request(
|
|
99
|
+
method="get",
|
|
100
|
+
path=ApiPaths.fx_quote,
|
|
101
|
+
content_type='application/json',
|
|
102
|
+
noAuth=False,
|
|
103
|
+
signature=False,
|
|
104
|
+
body=params.model_dump(exclude_none=True)
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
# Handle response
|
|
108
|
+
response = await self._send_request(request)
|
|
109
|
+
if not response.success:
|
|
110
|
+
raise APIResponseError(response)
|
|
111
|
+
|
|
112
|
+
return response.cast(GetQuoteResponseModel, APIResponseError)
|
|
113
|
+
|
|
114
|
+
async def QuoteQr(self, params: GetQuoteTlv) -> QuoteTlvResponse:
|
|
115
|
+
request = Request(
|
|
116
|
+
method="post",
|
|
117
|
+
path=ApiPaths.fx_quote_tlv,
|
|
118
|
+
content_type="application/json",
|
|
119
|
+
noAuth=False,
|
|
120
|
+
signature=False,
|
|
121
|
+
body=params.model_dump(exclude_none=True),
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
# Handle response
|
|
125
|
+
response = await self._send_request(request)
|
|
126
|
+
if not response.success:
|
|
127
|
+
raise APIResponseError(response)
|
|
128
|
+
|
|
129
|
+
return response.cast(QuoteTlvResponse, APIResponseError)
|
|
130
|
+
|
|
131
|
+
async def Status(self, id: str) -> InvoiceModel:
|
|
132
|
+
# Prepare request
|
|
133
|
+
request = Request(
|
|
134
|
+
method="get",
|
|
135
|
+
path=ApiPaths.invoices_info.replace(':id', id),
|
|
136
|
+
content_type='application/json',
|
|
137
|
+
noAuth=False,
|
|
138
|
+
signature=False,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
# Handle response
|
|
142
|
+
response = await self._send_request(request)
|
|
143
|
+
if not response.success:
|
|
144
|
+
raise APIResponseError(response)
|
|
145
|
+
return response.cast(InvoiceModel, APIResponseError)
|
|
146
|
+
|
|
147
|
+
async def get_token(self) -> AccessToken | None:
|
|
148
|
+
# First check if valid token is cached
|
|
149
|
+
token = self.cache.get_token("AccessToken")
|
|
150
|
+
refresh = self.cache.get_token("RefreshToken")
|
|
151
|
+
|
|
152
|
+
if token is not None and not token.is_expired:
|
|
153
|
+
return token
|
|
154
|
+
else:
|
|
155
|
+
# try to refresh token
|
|
156
|
+
if refresh is not None and not refresh.is_expired:
|
|
157
|
+
refreshed = await self._refresh_token(token, refresh)
|
|
158
|
+
|
|
159
|
+
if refreshed.success:
|
|
160
|
+
access = AccessToken(refreshed.json_body["access_token"])
|
|
161
|
+
refresh = RefreshToken(
|
|
162
|
+
refreshed.json_body["refresh_token"],
|
|
163
|
+
int(refreshed.json_body["expires_in"]),
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
self.cache.set_token(access)
|
|
167
|
+
self.cache.set_token(refresh)
|
|
168
|
+
|
|
169
|
+
return access
|
|
170
|
+
|
|
171
|
+
# try to issue token
|
|
172
|
+
response = await self._fetch_token()
|
|
173
|
+
if response.success:
|
|
174
|
+
access = AccessToken(response.json_body["access_token"])
|
|
175
|
+
refresh = RefreshToken(
|
|
176
|
+
response.json_body["refresh_token"],
|
|
177
|
+
int(response.json_body["expires_in"]),
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
self.cache.set_token(access)
|
|
181
|
+
self.cache.set_token(refresh)
|
|
182
|
+
|
|
183
|
+
return access
|
|
184
|
+
else:
|
|
185
|
+
raise APIAuthenticationError(response)
|
|
186
|
+
|
|
187
|
+
async def _send_request(self, request: Request) -> Response:
|
|
188
|
+
"""
|
|
189
|
+
Send a specified Request to the GoPay REST API and process the response
|
|
190
|
+
"""
|
|
191
|
+
dict_factory = lambda l: {k: v for k, v in l if v is not None}
|
|
192
|
+
body = request.body
|
|
193
|
+
# Add Bearer authentication to headers if needed
|
|
194
|
+
headers = request.headers or {}
|
|
195
|
+
if not request.noAuth:
|
|
196
|
+
auth = await self.get_token()
|
|
197
|
+
if auth is not None:
|
|
198
|
+
headers["Authorization"] = f"Bearer {auth.token}"
|
|
199
|
+
|
|
200
|
+
client = httpx.AsyncClient(timeout=self.timeout)
|
|
201
|
+
if request.method == 'get':
|
|
202
|
+
url = f'{self.baseUrl}{request.path}'
|
|
203
|
+
if body:
|
|
204
|
+
params = urlencode(body)
|
|
205
|
+
url = f'{url}?{params}'
|
|
206
|
+
r = await client.request(
|
|
207
|
+
method=request.method,
|
|
208
|
+
url=url,
|
|
209
|
+
headers=headers,
|
|
210
|
+
timeout=self.timeout
|
|
211
|
+
)
|
|
212
|
+
else:
|
|
213
|
+
r = await client.request(
|
|
214
|
+
method=request.method,
|
|
215
|
+
url=f"{self.baseUrl}{request.path}",
|
|
216
|
+
headers=headers,
|
|
217
|
+
json=body,
|
|
218
|
+
timeout=self.timeout
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
# Build Response instance, try to decode body as JSON
|
|
222
|
+
response = Response(raw_body=r.content, json={}, status_code=r.status_code)
|
|
223
|
+
|
|
224
|
+
try:
|
|
225
|
+
response.json_body = r.json()
|
|
226
|
+
except json.JSONDecodeError:
|
|
227
|
+
pass
|
|
228
|
+
|
|
229
|
+
return response
|
|
230
|
+
|
|
231
|
+
async def _fetch_token(self) -> Response:
|
|
232
|
+
# Prepare request
|
|
233
|
+
request = Request(
|
|
234
|
+
method="post",
|
|
235
|
+
path=ApiPaths.token_issue,
|
|
236
|
+
content_type='application/json',
|
|
237
|
+
noAuth=True,
|
|
238
|
+
body={"account_id": self.config.account_id, "public_key": self.config.public_key},
|
|
239
|
+
)
|
|
240
|
+
# Handle response
|
|
241
|
+
response = await self._send_request(request)
|
|
242
|
+
return response
|
|
243
|
+
|
|
244
|
+
async def _refresh_token(self) -> Response:
|
|
245
|
+
# Prepare request
|
|
246
|
+
request = Request(
|
|
247
|
+
method="post",
|
|
248
|
+
path=ApiPaths.token_refresh,
|
|
249
|
+
content_type='application/json',
|
|
250
|
+
body={"refresh_token": self.refreshToken},
|
|
251
|
+
)
|
|
252
|
+
# Handle response
|
|
253
|
+
response = await self._send_request(request)
|
|
254
|
+
return response
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
class ApiClient(BaseClient):
|
|
258
|
+
|
|
57
259
|
def PayIn(self, request: PayInModel) -> PayInResponseModel:
|
|
58
260
|
# Prepare request
|
|
59
261
|
request = Request(
|
|
@@ -61,12 +263,11 @@ class ApiClient:
|
|
|
61
263
|
path=ApiPaths.invoices_payin,
|
|
62
264
|
content_type='application/json',
|
|
63
265
|
noAuth=False,
|
|
64
|
-
body=request,
|
|
266
|
+
body=request.model_dump(exclude_none=True),
|
|
65
267
|
)
|
|
66
268
|
|
|
67
269
|
# Handle response
|
|
68
270
|
response = self._send_request(request)
|
|
69
|
-
self.log(request, response)
|
|
70
271
|
if (response.success):
|
|
71
272
|
return response.cast(PayInResponseModel, APIResponseError)
|
|
72
273
|
else:
|
|
@@ -80,12 +281,11 @@ class ApiClient:
|
|
|
80
281
|
content_type='application/json',
|
|
81
282
|
noAuth=False,
|
|
82
283
|
signature=True,
|
|
83
|
-
body=request
|
|
284
|
+
body=request.model_dump(exclude_none=True)
|
|
84
285
|
)
|
|
85
286
|
|
|
86
287
|
# Handle response
|
|
87
288
|
response = self._send_request(request)
|
|
88
|
-
self.log(request, response)
|
|
89
289
|
if (response.success):
|
|
90
290
|
return response.cast(PayOutResponseModel, APIResponseError)
|
|
91
291
|
else:
|
|
@@ -95,52 +295,48 @@ class ApiClient:
|
|
|
95
295
|
request = Request(
|
|
96
296
|
method="post",
|
|
97
297
|
path=ApiPaths.invoices_payout_tlv,
|
|
98
|
-
content_type=
|
|
298
|
+
content_type="application/json",
|
|
99
299
|
noAuth=False,
|
|
100
300
|
signature=False,
|
|
101
|
-
body=request
|
|
301
|
+
body=request.model_dump(exclude_none=True),
|
|
102
302
|
)
|
|
103
303
|
|
|
104
304
|
# Handle response
|
|
105
305
|
response = self._send_request(request)
|
|
106
|
-
self.log(request, response)
|
|
107
306
|
if not response.success:
|
|
108
307
|
raise APIResponseError(response)
|
|
109
|
-
|
|
110
308
|
return response.cast(PayOutResponseModel, APIResponseError)
|
|
111
309
|
|
|
112
310
|
def Quote(self, params: GetQuoteModel) -> GetQuoteResponseModel:
|
|
113
311
|
# Prepare request
|
|
114
312
|
request = Request(
|
|
115
|
-
method="
|
|
313
|
+
method="get",
|
|
116
314
|
path=ApiPaths.fx_quote,
|
|
117
315
|
content_type='application/json',
|
|
118
316
|
noAuth=False,
|
|
119
317
|
signature=False,
|
|
120
|
-
body=params
|
|
318
|
+
body=params.model_dump(exclude_none=True)
|
|
121
319
|
)
|
|
122
320
|
|
|
123
321
|
# Handle response
|
|
124
322
|
response = self._send_request(request)
|
|
125
|
-
self.log(request, response)
|
|
126
323
|
if not response.success:
|
|
127
324
|
raise APIResponseError(response)
|
|
128
325
|
|
|
129
326
|
return response.cast(GetQuoteResponseModel, APIResponseError)
|
|
130
|
-
|
|
327
|
+
|
|
131
328
|
def QuoteQr(self, params: GetQuoteTlv) -> QuoteTlvResponse:
|
|
132
329
|
request = Request(
|
|
133
330
|
method="post",
|
|
134
331
|
path=ApiPaths.fx_quote_tlv,
|
|
135
|
-
content_type=
|
|
332
|
+
content_type="application/json",
|
|
136
333
|
noAuth=False,
|
|
137
334
|
signature=False,
|
|
138
|
-
body=params
|
|
335
|
+
body=params.model_dump(exclude_none=True),
|
|
139
336
|
)
|
|
140
337
|
|
|
141
338
|
# Handle response
|
|
142
339
|
response = self._send_request(request)
|
|
143
|
-
self.log(request, response)
|
|
144
340
|
if not response.success:
|
|
145
341
|
raise APIResponseError(response)
|
|
146
342
|
|
|
@@ -158,41 +354,37 @@ class ApiClient:
|
|
|
158
354
|
|
|
159
355
|
# Handle response
|
|
160
356
|
response = self._send_request(request)
|
|
161
|
-
self.log(request, response)
|
|
162
357
|
if not response.success:
|
|
163
358
|
raise APIResponseError(response)
|
|
164
359
|
|
|
165
360
|
return response.cast(InvoiceModel, APIResponseError)
|
|
166
361
|
|
|
167
|
-
|
|
168
|
-
def token(self) -> AccessToken | None:
|
|
362
|
+
def get_token(self) -> AccessToken | None:
|
|
169
363
|
# First check if valid token is cached
|
|
170
|
-
token = self.cache.get_token('
|
|
171
|
-
refresh = self.cache.get_token('
|
|
172
|
-
|
|
364
|
+
token = self.cache.get_token('access')
|
|
365
|
+
refresh = self.cache.get_token('refresh')
|
|
173
366
|
if token is not None and not token.is_expired:
|
|
174
367
|
return token
|
|
175
368
|
else:
|
|
176
369
|
# try to refresh token
|
|
177
370
|
if refresh is not None and not refresh.is_expired:
|
|
178
|
-
refreshed = self._refresh_token(
|
|
371
|
+
refreshed = self._refresh_token()
|
|
179
372
|
|
|
180
373
|
if (refreshed.success):
|
|
181
374
|
access = AccessToken(
|
|
182
|
-
|
|
375
|
+
response.json_body["access_token"]
|
|
183
376
|
)
|
|
184
377
|
refresh = RefreshToken(
|
|
185
|
-
|
|
186
|
-
int(
|
|
378
|
+
response.json_body["refresh_token"],
|
|
379
|
+
int(response.json_body["expires_in"]),
|
|
187
380
|
)
|
|
188
|
-
|
|
189
381
|
self.cache.set_token(access)
|
|
190
382
|
self.cache.set_token(refresh)
|
|
191
383
|
|
|
192
384
|
return access
|
|
193
385
|
|
|
194
|
-
# try to issue token
|
|
195
|
-
response = self.
|
|
386
|
+
# try to issue token
|
|
387
|
+
response = self._fetch_token()
|
|
196
388
|
if response.success:
|
|
197
389
|
|
|
198
390
|
access = AccessToken(
|
|
@@ -202,7 +394,6 @@ class ApiClient:
|
|
|
202
394
|
response.json_body["refresh_token"],
|
|
203
395
|
int(response.json_body["expires_in"]),
|
|
204
396
|
)
|
|
205
|
-
|
|
206
397
|
self.cache.set_token(access)
|
|
207
398
|
self.cache.set_token(refresh)
|
|
208
399
|
|
|
@@ -214,60 +405,40 @@ class ApiClient:
|
|
|
214
405
|
"""
|
|
215
406
|
Send a specified Request to the GoPay REST API and process the response
|
|
216
407
|
"""
|
|
217
|
-
# body = asdict(request.body) if is_dataclass(request.body) else request.body
|
|
218
|
-
body = request.body
|
|
219
408
|
# Add Bearer authentication to headers if needed
|
|
220
409
|
headers = request.headers or {}
|
|
221
410
|
if not request.noAuth:
|
|
222
|
-
auth = self.
|
|
411
|
+
auth = self.get_token()
|
|
223
412
|
if auth is not None:
|
|
224
413
|
headers["Authorization"] = f"Bearer {auth.token}"
|
|
225
414
|
|
|
226
415
|
if (request.method == 'get'):
|
|
227
416
|
params = urlencode(body)
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
)
|
|
235
|
-
except:
|
|
236
|
-
print('Error')
|
|
237
|
-
pass
|
|
417
|
+
r = httpx.request(
|
|
418
|
+
method=request.method,
|
|
419
|
+
url=f"{self.baseUrl}{request.path}?{params}",
|
|
420
|
+
headers=headers,
|
|
421
|
+
timeout=self.timeout
|
|
422
|
+
)
|
|
238
423
|
else:
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
)
|
|
247
|
-
except KeyError:
|
|
248
|
-
print('Error')
|
|
249
|
-
pass
|
|
250
|
-
|
|
251
|
-
# if r == None:
|
|
424
|
+
r = httpx.request(
|
|
425
|
+
method=request.method,
|
|
426
|
+
url=f"{self.baseUrl}{request.path}",
|
|
427
|
+
headers=headers,
|
|
428
|
+
json=body,
|
|
429
|
+
timeout=self.timeout
|
|
430
|
+
)
|
|
252
431
|
|
|
253
432
|
# Build Response instance, try to decode body as JSON
|
|
254
|
-
response = Response(raw_body=r.content,
|
|
433
|
+
response = Response(raw_body=r.content, json={}, status_code=r.status_code)
|
|
255
434
|
|
|
256
|
-
if (self.REQUEST_DEBUG):
|
|
257
|
-
print(f"{request.method} => {self.baseUrl}{request.path} => {response.status_code}")
|
|
258
|
-
|
|
259
435
|
try:
|
|
260
436
|
response.json_body = r.json()
|
|
261
437
|
except json.JSONDecodeError:
|
|
262
438
|
pass
|
|
263
|
-
|
|
264
|
-
self.log(request, response)
|
|
265
439
|
return response
|
|
266
440
|
|
|
267
|
-
def
|
|
268
|
-
Logger(self, request, response)
|
|
269
|
-
|
|
270
|
-
def _get_token(self) -> Response:
|
|
441
|
+
def _fetch_token(self) -> Response:
|
|
271
442
|
# Prepare request
|
|
272
443
|
request = Request(
|
|
273
444
|
method="post",
|
|
@@ -278,27 +449,16 @@ class ApiClient:
|
|
|
278
449
|
)
|
|
279
450
|
# Handle response
|
|
280
451
|
response = self._send_request(request)
|
|
281
|
-
self.log(request, response)
|
|
282
452
|
return response
|
|
283
|
-
|
|
284
|
-
def _refresh_token(self
|
|
453
|
+
|
|
454
|
+
def _refresh_token(self) -> Response:
|
|
285
455
|
# Prepare request
|
|
286
456
|
request = Request(
|
|
287
457
|
method="post",
|
|
288
458
|
path=ApiPaths.token_refresh,
|
|
289
459
|
content_type='application/json',
|
|
290
|
-
|
|
291
|
-
headers={"Authorization": f"Bearer {access.token}" },
|
|
292
|
-
body={"refresh_token": refresh.token},
|
|
460
|
+
body={"refresh_token": self.refreshToken},
|
|
293
461
|
)
|
|
294
462
|
# Handle response
|
|
295
463
|
response = self._send_request(request)
|
|
296
|
-
self.log(request, response)
|
|
297
464
|
return response
|
|
298
|
-
|
|
299
|
-
def loadToken(self, params: TokenResponse):
|
|
300
|
-
access = AccessToken(params.access_token)
|
|
301
|
-
refresh = RefreshToken(params.refresh_token, int(params.expires_in))
|
|
302
|
-
self.cache.set_token(access)
|
|
303
|
-
self.cache.set_token(refresh)
|
|
304
|
-
|