Skip to content

Commit

Permalink
Handle JSONDecodeError on empty responses (#276)
Browse files Browse the repository at this point in the history
* Handle JSONDecodeError

* Support code 202
  • Loading branch information
michaelpaul committed Nov 17, 2023
1 parent 72bd797 commit b536679
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 90 deletions.
2 changes: 0 additions & 2 deletions Adyen/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#!/bin/python

from __future__ import absolute_import, division, unicode_literals

from . import util
Expand Down
89 changes: 30 additions & 59 deletions Adyen/client.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#!/bin/python

from __future__ import absolute_import, division, unicode_literals

import json as json_lib
Expand Down Expand Up @@ -266,18 +264,18 @@ def _set_platform(self, **kwargs):

def _set_url_version(self, service, endpoint):
version_lookup = {"binlookup": self.api_bin_lookup_version,
"checkout": self.api_checkout_version,
"management": self.api_management_version,
"payments": self.api_payment_version,
"payouts": self.api_payout_version,
"recurring": self.api_recurring_version,
"terminal": self.api_terminal_version,
"legalEntityManagement": self.api_legal_entity_management_version,
"dataProtection": self.api_data_protection_version,
"transfers": self.api_transfers_version,
"storedValue": self.api_stored_value_version,
"balancePlatform": self.api_balance_platform_version,
"disputes": self.api_disputes_version
"checkout": self.api_checkout_version,
"management": self.api_management_version,
"payments": self.api_payment_version,
"payouts": self.api_payout_version,
"recurring": self.api_recurring_version,
"terminal": self.api_terminal_version,
"legalEntityManagement": self.api_legal_entity_management_version,
"dataProtection": self.api_data_protection_version,
"transfers": self.api_transfers_version,
"storedValue": self.api_stored_value_version,
"balancePlatform": self.api_balance_platform_version,
"disputes": self.api_disputes_version
}

new_version = f"v{version_lookup[service]}"
Expand Down Expand Up @@ -383,66 +381,39 @@ def _init_http_client(self):
def _handle_response(self, url, raw_response, raw_request,
status_code, headers):
"""This parses the content from raw communication, raising an error if
anything other than 200 was returned.
anything other than 2xx was returned.
Args:
url (str): URL where request was made
raw_response (str): The raw communication sent to Adyen
raw_request (str): The raw response returned by Adyen
status_code (int): The HTTP status code
headers (dict): Key/Value of the headers.
request_dict (dict): The original request dictionary that was given
to the HTTPClient.
Returns:
AdyenResult: Result object if successful.
"""

if status_code not in [200, 201, 204]:
try:
response = json_lib.loads(raw_response)
except json_lib.JSONDecodeError:
response = {}
# If the result can't be parsed into json, most likely is raw html.
# Some response are neither json or raw html, handle them here:
if raw_response:
response = json_lib.loads(raw_response)
# Pass raised error to error handler.
self._handle_http_error(url, response, status_code,
headers.get('pspReference'),
raw_request, raw_response,
headers)

try:
if response['errorCode']:
raise AdyenAPICommunicationError(
"Unexpected error while communicating with Adyen."
" Received the response data:'{}', HTTP Code:'{}'. "
"Please reach out to support@adyen.com if the "
"problem persists with the psp:{}".format(
raw_response,
status_code,
headers.get('pspReference')),
status_code=status_code,
raw_request=raw_request,
raw_response=raw_response,
url=url,
psp=headers.get('pspReference'),
headers=headers,
error_code=response['errorCode'])
except KeyError:
erstr = 'KeyError: errorCode'
raise AdyenAPICommunicationError(erstr)

if status_code not in [200, 201, 202, 204]:
self._raise_http_error(url, response, status_code,
headers.get('pspReference'),
raw_request, raw_response,
headers)
else:
if status_code != 204:
response = json_lib.loads(raw_response)
else:
response = {}
psp = self._get_psp(response, headers)
return AdyenResult(message=response, status_code=status_code,
psp=psp, raw_request=raw_request,
raw_response=raw_response)

def _handle_http_error(self, url, response_obj, status_code, psp_ref,
raw_request, raw_response, headers):
"""This function handles the non 200 responses from Adyen, raising an
@staticmethod
def _raise_http_error(url, response_obj, status_code, psp_ref,
raw_request, raw_response, headers):
"""This function handles the non 2xx responses from Adyen, raising an
error that should provide more information.
Args:
Expand All @@ -456,7 +427,7 @@ def _handle_http_error(self, url, response_obj, status_code, psp_ref,
headers(dict): headers of the response
Returns:
None
None: It never returns
"""

if response_obj == {}:
Expand Down Expand Up @@ -484,9 +455,9 @@ def _handle_http_error(self, url, response_obj, status_code, psp_ref,
elif status_code == 500:
raise AdyenAPICommunicationError(message, raw_request, raw_response, url, psp_ref, headers, status_code,
error_code)
else:
raise AdyenAPIResponseError(message, raw_request, raw_response, url, psp_ref, headers, status_code,
error_code)

raise AdyenAPIResponseError(message, raw_request, raw_response, url, psp_ref, headers, status_code,
error_code)

@staticmethod
def _get_psp(response, headers):
Expand Down
3 changes: 0 additions & 3 deletions Adyen/httpclient.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#!/bin/python

from __future__ import absolute_import, division, unicode_literals

try:
Expand Down Expand Up @@ -49,7 +47,6 @@ def __init__(

self.timeout = timeout


def _pycurl_request(
self,
method,
Expand Down
24 changes: 22 additions & 2 deletions test/ConfigurationTest.py → test/BalancePlatformTest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Adyen
import unittest

import Adyen
from Adyen import settings

try:
Expand All @@ -8,7 +9,7 @@
from .BaseTest import BaseTest


class TestManagement(unittest.TestCase):
class TestBalancePlatform(unittest.TestCase):
adyen = Adyen.Adyen()

client = adyen.client
Expand Down Expand Up @@ -117,3 +118,22 @@ def test_get_transaction_rule(self):
json=None,
xapikey="YourXapikey"
)

def test_update_network_token(self):
request = {
"status": "closed"
}
self.adyen.client = self.test.create_client_from_file(202, request)

result = self.adyen.balancePlatform.network_tokens_api.update_network_token(request, 'TK123ABC')

self.assertEqual(202, result.status_code)
self.assertEqual({}, result.message)
self.assertEqual("", result.raw_response)
self.adyen.client.http_client.request.assert_called_once_with(
'PATCH',
f'{self.balance_platform_url}/networkTokens/TK123ABC',
headers={'adyen-library-name': 'adyen-python-api-library', 'adyen-library-version': settings.LIB_VERSION},
json=request,
xapikey="YourXapikey"
)
2 changes: 1 addition & 1 deletion test/BaseTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from Adyen import httpclient


class BaseTest():
class BaseTest:
def __init__(self, adyen):
self.ady = adyen

Expand Down
74 changes: 51 additions & 23 deletions test/ManagementTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,19 @@ class TestManagement(unittest.TestCase):

def test_get_company_account(self):
request = None
id = "YOUR_COMPANY_ACCOUNT"
company_id = "YOUR_COMPANY_ACCOUNT"
self.adyen.client = self.test.create_client_from_file(200, request,
"test/mocks/"
"management/"
"get_company_account"
".json")

result = self.adyen.management.account_company_level_api.get_company_account(companyId=id)
self.assertEqual(id, result.message['id'])
result = self.adyen.management.account_company_level_api.get_company_account(companyId=company_id)

self.assertEqual(company_id, result.message['id'])
self.adyen.client.http_client.request.assert_called_once_with(
'GET',
f'{self.management_url}/companies/{id}',
f'{self.management_url}/companies/{company_id}',
headers={'adyen-library-name': 'adyen-python-api-library', 'adyen-library-version': settings.LIB_VERSION},
json=None,
xapikey="YourXapikey"
Expand All @@ -43,23 +44,29 @@ def test_my_api_credential_api(self):
"management/"
"post_me_allowed"
"_origins.json")

result = self.adyen.management.my_api_credential_api.add_allowed_origin(request)
originId = result.message['id']

self.assertEqual("YOUR_DOMAIN", result.message['domain'])

def test_no_content(self):
self.adyen.client = self.test.create_client_from_file(204, {},
"test/mocks/"
"management/"
"no_content.json")
result = self.adyen.management.my_api_credential_api.remove_allowed_origin(originId)
origin_id = 'YOUR_DOMAIN_ID'

self.adyen.management.my_api_credential_api.remove_allowed_origin(origin_id)

self.adyen.client.http_client.request.assert_called_once_with(
'DELETE',
f'{self.management_url}/me/allowedOrigins/{originId}',
f'{self.management_url}/me/allowedOrigins/{origin_id}',
headers={'adyen-library-name': 'adyen-python-api-library', 'adyen-library-version': settings.LIB_VERSION},
json=None,
xapikey="YourXapikey"
)

def test_update_a_store(self):
def test_update_store(self):
request = {
"address": {
"line1": "1776 West Pinewood Avenue",
Expand All @@ -73,19 +80,34 @@ def test_update_a_store(self):
"management/"
"update_a_store"
".json")
storeId = "YOUR_STORE_ID"
merchantId = "YOUR_MERCHANT_ACCOUNT_ID"
result = self.adyen.management.account_store_level_api.update_store(request, merchantId, storeId)
store_id = "YOUR_STORE_ID"
merchant_id = "YOUR_MERCHANT_ACCOUNT_ID"

result = self.adyen.management.account_store_level_api.update_store(request, merchant_id, store_id)

self.adyen.client.http_client.request.assert_called_once_with(
'PATCH',
f'{self.management_url}/merchants/{merchantId}/stores/{storeId}',
f'{self.management_url}/merchants/{merchant_id}/stores/{store_id}',
headers={'adyen-library-name': 'adyen-python-api-library', 'adyen-library-version': settings.LIB_VERSION},
json=request,
xapikey="YourXapikey"
)
self.assertEqual(storeId, result.message['id'])
self.assertEqual(store_id, result.message['id'])
self.assertEqual("1776 West Pinewood Avenue", result.message['address']['line1'])

def test_reassign_terminal(self):
request = {
'storeId': 'ST123ABC',
'inventory': False,
}
self.adyen.client = self.test.create_client_from_file(200, request)

result = self.adyen.management.terminals_terminal_level_api.reassign_terminal(request, 'AMS1-2345')

self.assertEqual(200, result.status_code)
self.assertEqual({}, result.message)
self.assertEqual("", result.raw_response)

def test_create_a_user(self):
request = {
"name": {
Expand All @@ -108,12 +130,14 @@ def test_create_a_user(self):
"management/"
"create_a_user"
".json")
companyId = "YOUR_COMPANY_ACCOUNT"
result = self.adyen.management.users_company_level_api.create_new_user(request, companyId)
company_id = "YOUR_COMPANY_ACCOUNT"

result = self.adyen.management.users_company_level_api.create_new_user(request, company_id)

self.assertEqual(request['name']['firstName'], result.message['name']['firstName'])
self.adyen.client.http_client.request.assert_called_once_with(
'POST',
f'{self.management_url}/companies/{companyId}/users',
f'{self.management_url}/companies/{company_id}/users',
json=request,
headers={'adyen-library-name': 'adyen-python-api-library', 'adyen-library-version': settings.LIB_VERSION},
xapikey="YourXapikey"
Expand All @@ -127,13 +151,15 @@ def test_get_list_of_android_apps(self):
"get_list_of"
"_android_apps"
".json")
companyId = "YOUR_COMPANY_ACCOUNT"
result = self.adyen.management.android_files_company_level_api.list_android_apps(companyId)
company_id = "YOUR_COMPANY_ACCOUNT"

result = self.adyen.management.android_files_company_level_api.list_android_apps(company_id)

self.assertEqual("ANDA422LZ223223K5F694GCCF732K8", result.message['androidApps'][0]['id'])

def test_query_paramaters(self):
def test_query_parameters(self):
request = {}
companyId = "YOUR_COMPANY_ACCOUNT"
company_id = "YOUR_COMPANY_ACCOUNT"
query_parameters = {
'pageNumber': 1,
'pageSize': 10
Expand All @@ -143,11 +169,13 @@ def test_query_paramaters(self):
"test/mocks/"
"management/"
"get_list_of_merchant_accounts.json")
result = self.adyen.management.account_company_level_api. \
list_merchant_accounts(companyId, query_parameters=query_parameters)

self.adyen.management.account_company_level_api. \
list_merchant_accounts(company_id, query_parameters=query_parameters)

self.adyen.client.http_client.request.assert_called_once_with(
'GET',
f'{self.management_url}/companies/{companyId}/merchants?pageNumber=1&pageSize=10',
f'{self.management_url}/companies/{company_id}/merchants?pageNumber=1&pageSize=10',
headers={'adyen-library-name': 'adyen-python-api-library', 'adyen-library-version': settings.LIB_VERSION},
json=None,
xapikey="YourXapikey"
Expand Down

0 comments on commit b536679

Please sign in to comment.