Skip to content

Commit b536679

Browse files
authored
Handle JSONDecodeError on empty responses (#276)
* Handle JSONDecodeError * Support code 202
1 parent 72bd797 commit b536679

File tree

6 files changed

+104
-90
lines changed

6 files changed

+104
-90
lines changed

Adyen/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#!/bin/python
2-
31
from __future__ import absolute_import, division, unicode_literals
42

53
from . import util

Adyen/client.py

Lines changed: 30 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#!/bin/python
2-
31
from __future__ import absolute_import, division, unicode_literals
42

53
import json as json_lib
@@ -266,18 +264,18 @@ def _set_platform(self, **kwargs):
266264

267265
def _set_url_version(self, service, endpoint):
268266
version_lookup = {"binlookup": self.api_bin_lookup_version,
269-
"checkout": self.api_checkout_version,
270-
"management": self.api_management_version,
271-
"payments": self.api_payment_version,
272-
"payouts": self.api_payout_version,
273-
"recurring": self.api_recurring_version,
274-
"terminal": self.api_terminal_version,
275-
"legalEntityManagement": self.api_legal_entity_management_version,
276-
"dataProtection": self.api_data_protection_version,
277-
"transfers": self.api_transfers_version,
278-
"storedValue": self.api_stored_value_version,
279-
"balancePlatform": self.api_balance_platform_version,
280-
"disputes": self.api_disputes_version
267+
"checkout": self.api_checkout_version,
268+
"management": self.api_management_version,
269+
"payments": self.api_payment_version,
270+
"payouts": self.api_payout_version,
271+
"recurring": self.api_recurring_version,
272+
"terminal": self.api_terminal_version,
273+
"legalEntityManagement": self.api_legal_entity_management_version,
274+
"dataProtection": self.api_data_protection_version,
275+
"transfers": self.api_transfers_version,
276+
"storedValue": self.api_stored_value_version,
277+
"balancePlatform": self.api_balance_platform_version,
278+
"disputes": self.api_disputes_version
281279
}
282280

283281
new_version = f"v{version_lookup[service]}"
@@ -383,66 +381,39 @@ def _init_http_client(self):
383381
def _handle_response(self, url, raw_response, raw_request,
384382
status_code, headers):
385383
"""This parses the content from raw communication, raising an error if
386-
anything other than 200 was returned.
384+
anything other than 2xx was returned.
387385
388386
Args:
389387
url (str): URL where request was made
390388
raw_response (str): The raw communication sent to Adyen
391389
raw_request (str): The raw response returned by Adyen
392390
status_code (int): The HTTP status code
393391
headers (dict): Key/Value of the headers.
394-
request_dict (dict): The original request dictionary that was given
395-
to the HTTPClient.
396392
397393
Returns:
398394
AdyenResult: Result object if successful.
399395
"""
400396

401-
if status_code not in [200, 201, 204]:
397+
try:
398+
response = json_lib.loads(raw_response)
399+
except json_lib.JSONDecodeError:
402400
response = {}
403-
# If the result can't be parsed into json, most likely is raw html.
404-
# Some response are neither json or raw html, handle them here:
405-
if raw_response:
406-
response = json_lib.loads(raw_response)
407-
# Pass raised error to error handler.
408-
self._handle_http_error(url, response, status_code,
409-
headers.get('pspReference'),
410-
raw_request, raw_response,
411-
headers)
412-
413-
try:
414-
if response['errorCode']:
415-
raise AdyenAPICommunicationError(
416-
"Unexpected error while communicating with Adyen."
417-
" Received the response data:'{}', HTTP Code:'{}'. "
418-
"Please reach out to support@adyen.com if the "
419-
"problem persists with the psp:{}".format(
420-
raw_response,
421-
status_code,
422-
headers.get('pspReference')),
423-
status_code=status_code,
424-
raw_request=raw_request,
425-
raw_response=raw_response,
426-
url=url,
427-
psp=headers.get('pspReference'),
428-
headers=headers,
429-
error_code=response['errorCode'])
430-
except KeyError:
431-
erstr = 'KeyError: errorCode'
432-
raise AdyenAPICommunicationError(erstr)
401+
402+
if status_code not in [200, 201, 202, 204]:
403+
self._raise_http_error(url, response, status_code,
404+
headers.get('pspReference'),
405+
raw_request, raw_response,
406+
headers)
433407
else:
434-
if status_code != 204:
435-
response = json_lib.loads(raw_response)
436-
else:
437-
response = {}
438408
psp = self._get_psp(response, headers)
439409
return AdyenResult(message=response, status_code=status_code,
440410
psp=psp, raw_request=raw_request,
441411
raw_response=raw_response)
442412

443-
def _handle_http_error(self, url, response_obj, status_code, psp_ref,
444-
raw_request, raw_response, headers):
445-
"""This function handles the non 200 responses from Adyen, raising an
413+
@staticmethod
414+
def _raise_http_error(url, response_obj, status_code, psp_ref,
415+
raw_request, raw_response, headers):
416+
"""This function handles the non 2xx responses from Adyen, raising an
446417
error that should provide more information.
447418
448419
Args:
@@ -456,7 +427,7 @@ def _handle_http_error(self, url, response_obj, status_code, psp_ref,
456427
headers(dict): headers of the response
457428
458429
Returns:
459-
None
430+
None: It never returns
460431
"""
461432

462433
if response_obj == {}:
@@ -484,9 +455,9 @@ def _handle_http_error(self, url, response_obj, status_code, psp_ref,
484455
elif status_code == 500:
485456
raise AdyenAPICommunicationError(message, raw_request, raw_response, url, psp_ref, headers, status_code,
486457
error_code)
487-
else:
488-
raise AdyenAPIResponseError(message, raw_request, raw_response, url, psp_ref, headers, status_code,
489-
error_code)
458+
459+
raise AdyenAPIResponseError(message, raw_request, raw_response, url, psp_ref, headers, status_code,
460+
error_code)
490461

491462
@staticmethod
492463
def _get_psp(response, headers):

Adyen/httpclient.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#!/bin/python
2-
31
from __future__ import absolute_import, division, unicode_literals
42

53
try:
@@ -49,7 +47,6 @@ def __init__(
4947

5048
self.timeout = timeout
5149

52-
5350
def _pycurl_request(
5451
self,
5552
method,

test/ConfigurationTest.py renamed to test/BalancePlatformTest.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import Adyen
21
import unittest
2+
3+
import Adyen
34
from Adyen import settings
45

56
try:
@@ -8,7 +9,7 @@
89
from .BaseTest import BaseTest
910

1011

11-
class TestManagement(unittest.TestCase):
12+
class TestBalancePlatform(unittest.TestCase):
1213
adyen = Adyen.Adyen()
1314

1415
client = adyen.client
@@ -117,3 +118,22 @@ def test_get_transaction_rule(self):
117118
json=None,
118119
xapikey="YourXapikey"
119120
)
121+
122+
def test_update_network_token(self):
123+
request = {
124+
"status": "closed"
125+
}
126+
self.adyen.client = self.test.create_client_from_file(202, request)
127+
128+
result = self.adyen.balancePlatform.network_tokens_api.update_network_token(request, 'TK123ABC')
129+
130+
self.assertEqual(202, result.status_code)
131+
self.assertEqual({}, result.message)
132+
self.assertEqual("", result.raw_response)
133+
self.adyen.client.http_client.request.assert_called_once_with(
134+
'PATCH',
135+
f'{self.balance_platform_url}/networkTokens/TK123ABC',
136+
headers={'adyen-library-name': 'adyen-python-api-library', 'adyen-library-version': settings.LIB_VERSION},
137+
json=request,
138+
xapikey="YourXapikey"
139+
)

test/BaseTest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from Adyen import httpclient
88

99

10-
class BaseTest():
10+
class BaseTest:
1111
def __init__(self, adyen):
1212
self.ady = adyen
1313

test/ManagementTest.py

Lines changed: 51 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,19 @@ class TestManagement(unittest.TestCase):
1919

2020
def test_get_company_account(self):
2121
request = None
22-
id = "YOUR_COMPANY_ACCOUNT"
22+
company_id = "YOUR_COMPANY_ACCOUNT"
2323
self.adyen.client = self.test.create_client_from_file(200, request,
2424
"test/mocks/"
2525
"management/"
2626
"get_company_account"
2727
".json")
2828

29-
result = self.adyen.management.account_company_level_api.get_company_account(companyId=id)
30-
self.assertEqual(id, result.message['id'])
29+
result = self.adyen.management.account_company_level_api.get_company_account(companyId=company_id)
30+
31+
self.assertEqual(company_id, result.message['id'])
3132
self.adyen.client.http_client.request.assert_called_once_with(
3233
'GET',
33-
f'{self.management_url}/companies/{id}',
34+
f'{self.management_url}/companies/{company_id}',
3435
headers={'adyen-library-name': 'adyen-python-api-library', 'adyen-library-version': settings.LIB_VERSION},
3536
json=None,
3637
xapikey="YourXapikey"
@@ -43,23 +44,29 @@ def test_my_api_credential_api(self):
4344
"management/"
4445
"post_me_allowed"
4546
"_origins.json")
47+
4648
result = self.adyen.management.my_api_credential_api.add_allowed_origin(request)
47-
originId = result.message['id']
49+
4850
self.assertEqual("YOUR_DOMAIN", result.message['domain'])
51+
52+
def test_no_content(self):
4953
self.adyen.client = self.test.create_client_from_file(204, {},
5054
"test/mocks/"
5155
"management/"
5256
"no_content.json")
53-
result = self.adyen.management.my_api_credential_api.remove_allowed_origin(originId)
57+
origin_id = 'YOUR_DOMAIN_ID'
58+
59+
self.adyen.management.my_api_credential_api.remove_allowed_origin(origin_id)
60+
5461
self.adyen.client.http_client.request.assert_called_once_with(
5562
'DELETE',
56-
f'{self.management_url}/me/allowedOrigins/{originId}',
63+
f'{self.management_url}/me/allowedOrigins/{origin_id}',
5764
headers={'adyen-library-name': 'adyen-python-api-library', 'adyen-library-version': settings.LIB_VERSION},
5865
json=None,
5966
xapikey="YourXapikey"
6067
)
6168

62-
def test_update_a_store(self):
69+
def test_update_store(self):
6370
request = {
6471
"address": {
6572
"line1": "1776 West Pinewood Avenue",
@@ -73,19 +80,34 @@ def test_update_a_store(self):
7380
"management/"
7481
"update_a_store"
7582
".json")
76-
storeId = "YOUR_STORE_ID"
77-
merchantId = "YOUR_MERCHANT_ACCOUNT_ID"
78-
result = self.adyen.management.account_store_level_api.update_store(request, merchantId, storeId)
83+
store_id = "YOUR_STORE_ID"
84+
merchant_id = "YOUR_MERCHANT_ACCOUNT_ID"
85+
86+
result = self.adyen.management.account_store_level_api.update_store(request, merchant_id, store_id)
87+
7988
self.adyen.client.http_client.request.assert_called_once_with(
8089
'PATCH',
81-
f'{self.management_url}/merchants/{merchantId}/stores/{storeId}',
90+
f'{self.management_url}/merchants/{merchant_id}/stores/{store_id}',
8291
headers={'adyen-library-name': 'adyen-python-api-library', 'adyen-library-version': settings.LIB_VERSION},
8392
json=request,
8493
xapikey="YourXapikey"
8594
)
86-
self.assertEqual(storeId, result.message['id'])
95+
self.assertEqual(store_id, result.message['id'])
8796
self.assertEqual("1776 West Pinewood Avenue", result.message['address']['line1'])
8897

98+
def test_reassign_terminal(self):
99+
request = {
100+
'storeId': 'ST123ABC',
101+
'inventory': False,
102+
}
103+
self.adyen.client = self.test.create_client_from_file(200, request)
104+
105+
result = self.adyen.management.terminals_terminal_level_api.reassign_terminal(request, 'AMS1-2345')
106+
107+
self.assertEqual(200, result.status_code)
108+
self.assertEqual({}, result.message)
109+
self.assertEqual("", result.raw_response)
110+
89111
def test_create_a_user(self):
90112
request = {
91113
"name": {
@@ -108,12 +130,14 @@ def test_create_a_user(self):
108130
"management/"
109131
"create_a_user"
110132
".json")
111-
companyId = "YOUR_COMPANY_ACCOUNT"
112-
result = self.adyen.management.users_company_level_api.create_new_user(request, companyId)
133+
company_id = "YOUR_COMPANY_ACCOUNT"
134+
135+
result = self.adyen.management.users_company_level_api.create_new_user(request, company_id)
136+
113137
self.assertEqual(request['name']['firstName'], result.message['name']['firstName'])
114138
self.adyen.client.http_client.request.assert_called_once_with(
115139
'POST',
116-
f'{self.management_url}/companies/{companyId}/users',
140+
f'{self.management_url}/companies/{company_id}/users',
117141
json=request,
118142
headers={'adyen-library-name': 'adyen-python-api-library', 'adyen-library-version': settings.LIB_VERSION},
119143
xapikey="YourXapikey"
@@ -127,13 +151,15 @@ def test_get_list_of_android_apps(self):
127151
"get_list_of"
128152
"_android_apps"
129153
".json")
130-
companyId = "YOUR_COMPANY_ACCOUNT"
131-
result = self.adyen.management.android_files_company_level_api.list_android_apps(companyId)
154+
company_id = "YOUR_COMPANY_ACCOUNT"
155+
156+
result = self.adyen.management.android_files_company_level_api.list_android_apps(company_id)
157+
132158
self.assertEqual("ANDA422LZ223223K5F694GCCF732K8", result.message['androidApps'][0]['id'])
133159

134-
def test_query_paramaters(self):
160+
def test_query_parameters(self):
135161
request = {}
136-
companyId = "YOUR_COMPANY_ACCOUNT"
162+
company_id = "YOUR_COMPANY_ACCOUNT"
137163
query_parameters = {
138164
'pageNumber': 1,
139165
'pageSize': 10
@@ -143,11 +169,13 @@ def test_query_paramaters(self):
143169
"test/mocks/"
144170
"management/"
145171
"get_list_of_merchant_accounts.json")
146-
result = self.adyen.management.account_company_level_api. \
147-
list_merchant_accounts(companyId, query_parameters=query_parameters)
172+
173+
self.adyen.management.account_company_level_api. \
174+
list_merchant_accounts(company_id, query_parameters=query_parameters)
175+
148176
self.adyen.client.http_client.request.assert_called_once_with(
149177
'GET',
150-
f'{self.management_url}/companies/{companyId}/merchants?pageNumber=1&pageSize=10',
178+
f'{self.management_url}/companies/{company_id}/merchants?pageNumber=1&pageSize=10',
151179
headers={'adyen-library-name': 'adyen-python-api-library', 'adyen-library-version': settings.LIB_VERSION},
152180
json=None,
153181
xapikey="YourXapikey"

0 commit comments

Comments
 (0)