diff --git a/README.md b/README.md
index 912a5da..6fec53f 100644
--- a/README.md
+++ b/README.md
@@ -4,9 +4,14 @@ The official Amazon Pay Python SDK.
## Requirements
-Python >= 3.2
-pyOpenSSL >= 0.11
-Requests >= 2.6.0
+- Python >= 3.2
+
+Install dependencies using requirements.txt
+
+```shell
+pip install -r requirements.txt
+```
+
## Documentation
diff --git a/amazon_pay/client.py b/amazon_pay/client.py
index c65e330..8de5990 100644
--- a/amazon_pay/client.py
+++ b/amazon_pay/client.py
@@ -9,6 +9,7 @@
from amazon_pay.payment_request import PaymentRequest
from fileinput import filename
+
class AmazonPayClient:
logger = logging.getLogger('__amazon_pay_sdk__')
@@ -34,9 +35,7 @@ def __init__(
log_enabled=False,
log_file_name=None,
log_level=None
- ):
-
-
+ ):
"""
Parameters
----------
@@ -143,22 +142,23 @@ def __init__(
ch = logging.StreamHandler(sys.stdout)
self.logger.addHandler(ch)
ch.setLevel(numeric_level)
-
+
app_name_and_ver = ''
-
+
if application_name not in ['', None]:
app_name_and_ver = app_name_and_ver + str(application_name)
if application_version not in ['', None]:
- app_name_and_ver = app_name_and_ver + '/' + str(application_version)
+ app_name_and_ver = app_name_and_ver + \
+ '/' + str(application_version)
elif application_version not in ['', None]:
app_name_and_ver = app_name_and_ver + str(application_version)
-
+
if ((application_name not in ['', None]) | (application_version not in ['', None])):
app_name_and_ver = app_name_and_ver + '; '
current_py_ver = ".".join(map(str, sys.version_info[:3]))
-
+
self._user_agent = 'amazon-pay-sdk-python/{0} ({1}Python/{2}; {3}/{4})'.format(
str(self._application_library_version),
str(app_name_and_ver),
@@ -166,7 +166,7 @@ def __init__(
str(platform.system()),
str(platform.release())
)
-
+
self.logger.debug('user agent: %s', self._user_agent)
self._headers = {
@@ -205,13 +205,13 @@ def get_login_profile(self, access_token, client_id):
sandbox=self._sandbox)
response = lwa_client.get_login_profile(access_token=access_token)
return response
-
+
def get_merchant_account_status(
self,
merchant_id=None,
mws_auth_token=None):
""" Check the account status of the merchant
-
+
Parameters
----------
merchant_id : string, optional
@@ -220,18 +220,18 @@ def get_merchant_account_status(
mws_auth_token: string, optional
Your marketplace web service auth token. Default: None
-
+
"""
parameters = {
'Action': 'GetMerchantAccountStatus'
- }
-
+ }
+
optionals = {
'SellerId': merchant_id,
'MWSAuthToken': mws_auth_token}
-
+
return self._operation(params=parameters, options=optionals)
-
+
def create_order_reference_for_id(
self,
object_id,
@@ -683,22 +683,22 @@ def set_order_reference_details(
return self._operation(params=parameters, options=optionals)
def set_order_attributes(
- self,
- amazon_order_reference_id,
- currency_code=None,
- amount=None,
- seller_order_id=None,
- payment_service_provider_id=None,
- payment_service_provider_order_id=None,
- platform_id=None,
- seller_note=None,
- request_payment_authorization=None,
- store_name=None,
- list_order_item_categories=None,
- custom_information=None,
- merchant_id=None,
- mws_auth_token=None,
- supplementary_data=None):
+ self,
+ amazon_order_reference_id,
+ currency_code=None,
+ amount=None,
+ seller_order_id=None,
+ payment_service_provider_id=None,
+ payment_service_provider_order_id=None,
+ platform_id=None,
+ seller_note=None,
+ request_payment_authorization=None,
+ store_name=None,
+ list_order_item_categories=None,
+ custom_information=None,
+ merchant_id=None,
+ mws_auth_token=None,
+ supplementary_data=None):
'''
Return and update the information of an order with missing
or updated information
@@ -806,7 +806,6 @@ def set_order_attributes(
return self._operation(params=parameters, options=optionals)
-
def get_order_reference_details(
self,
amazon_order_reference_id,
@@ -823,7 +822,7 @@ def get_order_reference_details(
The order reference identifier. This value is retrieved from the
amazon pay Button widget after the buyer has successfully authenticated
with Amazon.
-
+
access_token : string, optional
The access token. This value is retrieved from the
amazon pay Button widget after the buyer has successfully authenticated
@@ -901,8 +900,8 @@ def confirm_order_reference(
'SuccessUrl': success_url,
'FailureUrl': failure_url,
'AuthorizationAmount.Amount': authorization_amount,
- 'AuthorizationAmount.CurrencyCode': self.currency_code if currency_code is None else currency_code }
-
+ 'AuthorizationAmount.CurrencyCode': self.currency_code if currency_code is None else currency_code}
+
if authorization_amount == "0" or authorization_amount is None:
del optionals['AuthorizationAmount.Amount']
del optionals['AuthorizationAmount.CurrencyCode']
@@ -988,7 +987,6 @@ def list_order_reference(
order_reference_status_list_filter=None,
merchant_id=None,
mws_auth_token=None):
-
"""
Allows the search of any Amazon Pay order made using secondary
seller order IDs generated manually, a solution provider, or a custom
@@ -1004,7 +1002,7 @@ def list_order_reference(
The type of query the id is referencing.
Note: At this time, you can only use the query type (SellerOrderId).
More options will be available in the future. Default: SellerOrderId
-
+
payment_domain: string, optional
The region and currency that will be set to authorize and collect
payments from your customers. You can leave this blank for the
@@ -1048,9 +1046,9 @@ def list_order_reference(
of the orders on file. You can search for any valid status for orders
on file. Filters MUST be written out in English.
Example: "Open", "Closed", "Suspended", "Canceled"
- Default: None
+ Default: None
"""
-
+
if self.region is not None:
region_code = self.region.lower()
if region_code == 'na':
@@ -1058,18 +1056,19 @@ def list_order_reference(
elif region_code in ('uk', 'gb'):
payment_domain = 'EU_GBP'
elif region_code in ('jp', 'fe'):
- payment_domain = 'FE_JPY'
+ payment_domain = 'FE_JPY'
elif region_code in ('eu', 'de', 'fr', 'it', 'es', 'cy'):
payment_domain = 'EU_EUR'
else:
- raise ValueError("Error. The current region code does not match our records")
+ raise ValueError(
+ "Error. The current region code does not match our records")
parameters = {
'Action': 'ListOrderReference',
'QueryId': query_id,
'QueryIdType': query_id_type,
'PaymentDomain': payment_domain
- }
+ }
optionals = {
'CreatedTimeRange.StartTime': created_time_range_start,
'CreatedTimeRange.EndTime': created_time_range_end,
@@ -1120,7 +1119,6 @@ def get_payment_details(
amazon_order_reference_id,
merchant_id=None,
mws_auth_token=None):
-
'''
This is a convenience function that will return every authorization,
charge, and refund call of an Amazon Pay order ID.
@@ -1176,7 +1174,8 @@ def get_payment_details(
answer.append(response)
queryID = json.loads(response.to_json())
chargeID = queryID['GetAuthorizationDetailsResponse']\
- ['GetAuthorizationDetailsResult']['AuthorizationDetails']['IdList']
+ ['GetAuthorizationDetailsResult'][
+ 'AuthorizationDetails']['IdList']
if chargeID is not None:
chargeID = chargeID['member']
@@ -1194,7 +1193,7 @@ def get_payment_details(
if type(refundID['member']) is not list:
refundID = [refundID['member']]
else:
- refundID = refundID['member']
+ refundID = refundID['member']
for id in refundID:
parameters = {
@@ -1721,12 +1720,12 @@ def _operation(self, params, options=None):
request.send_post()
return request.response
-
+
def _enumerate(
- self,
- category,
- filter_types,
- optionals):
+ self,
+ category,
+ filter_types,
+ optionals):
def enumerate_param(param, values):
"""
@@ -1758,7 +1757,7 @@ def enumerate_param(param, values):
optionals.update(enumerate_param(category, filter_types))
else:
if ',' in filter_types:
- filter_types = filter_types.replace(' ','')
+ filter_types = filter_types.replace(' ', '')
filter_types = filter_types.split(',')
optionals.update(enumerate_param(category, filter_types))
else:
diff --git a/amazon_pay/ipn_handler.py b/amazon_pay/ipn_handler.py
index 5ed2b98..57c901f 100644
--- a/amazon_pay/ipn_handler.py
+++ b/amazon_pay/ipn_handler.py
@@ -74,8 +74,8 @@ def __init__(self, body, headers):
self._xml = self._notification_data.replace(
'\n',
'')
- self.logger.debug('IPN Response: %s',
- self._sanitize_response_data(self._xml))
+ self.logger.debug('IPN Response: %s',
+ self._sanitize_response_data(self._xml))
def authenticate(self):
"""Attempt to validate a SNS message received from Amazon
@@ -171,23 +171,25 @@ def _validate_signature(self):
return True
def to_json(self):
- """Retuns notification message as JSON"""
+ """Retuns notification message as JSON"""
return PaymentResponse(self._xml).to_json()
def to_xml(self):
"""Retuns notification message as XML"""
return PaymentResponse(self._xml).to_xml()
-
+
def _sanitize_response_data(self, text):
editText = text
patterns = []
patterns.append(r'(?s)().*(<\/SellerNote>)')
- patterns.append(r'(?s)().*(<\/AuthorizationBillingAddress>)')
- patterns.append(r'(?s)().*(<\/SellerAuthorizationNote>)')
+ patterns.append(
+ r'(?s)().*(<\/AuthorizationBillingAddress>)')
+ patterns.append(
+ r'(?s)().*(<\/SellerAuthorizationNote>)')
patterns.append(r'(?s)().*(<\/SellerCaptureNote>)')
patterns.append(r'(?s)().*(<\/SellerRefundNote>)')
replacement = r'\1 REMOVED \2'
-
+
for pattern in patterns:
editText = re.sub(pattern, replacement, editText)
- return editText
\ No newline at end of file
+ return editText
diff --git a/amazon_pay/payment_request.py b/amazon_pay/payment_request.py
index ee9e9df..969990e 100644
--- a/amazon_pay/payment_request.py
+++ b/amazon_pay/payment_request.py
@@ -115,9 +115,9 @@ def _querystring(self, params):
def _request(self, retry_time):
time.sleep(retry_time)
data = self._querystring(self._params)
-
- self.logger.debug('Request Header: %s',
- self._sanitize_request_data(str(self._headers)))
+
+ self.logger.debug('Request Header: %s',
+ self._sanitize_request_data(str(self._headers)))
r = requests.post(
url=self._mws_endpoint,
@@ -131,8 +131,8 @@ def _request(self, retry_time):
self.success = True
self._should_throttle = False
self.response = PaymentResponse(r.text)
- self.logger.debug('Response: %s',
- self._sanitize_response_data(r.text))
+ self.logger.debug('Response: %s',
+ self._sanitize_response_data(r.text))
elif (self._status_code == 500 or self._status_code ==
503) and self.handle_throttle:
self._should_throttle = True
@@ -140,8 +140,8 @@ def _request(self, retry_time):
'{}'.format(r.status_code))
else:
self.response = PaymentErrorResponse(r.text)
- self.logger.debug('Response: %s',
- self._sanitize_response_data(r.text))
+ self.logger.debug('Response: %s',
+ self._sanitize_response_data(r.text))
def send_post(self):
"""Call request to send to MWS endpoint and handle throttle if set."""
@@ -152,7 +152,7 @@ def send_post(self):
break
else:
self._request(0)
-
+
def _sanitize_request_data(self, text):
editText = text
patterns = []
@@ -161,24 +161,27 @@ def _sanitize_request_data(self, text):
patterns.append(r'(?s)(SellerCaptureNote).*(&)')
patterns.append(r'(?s)(SellerRefundNote).*(&)')
replacement = r'\1 REMOVED \2'
-
+
for pattern in patterns:
editText = re.sub(pattern, replacement, editText)
return editText
-
+
def _sanitize_response_data(self, text):
editText = text
patterns = []
patterns.append(r'(?s)().*()')
- patterns.append(r'(?s)().*()')
+ patterns.append(
+ r'(?s)().*()')
patterns.append(r'(?s)().*(<\/BillingAddress>)')
patterns.append(r'(?s)().*(<\/SellerNote>)')
- patterns.append(r'(?s)().*(<\/AuthorizationBillingAddress>)')
- patterns.append(r'(?s)().*(<\/SellerAuthorizationNote>)')
+ patterns.append(
+ r'(?s)().*(<\/AuthorizationBillingAddress>)')
+ patterns.append(
+ r'(?s)().*(<\/SellerAuthorizationNote>)')
patterns.append(r'(?s)().*(<\/SellerCaptureNote>)')
patterns.append(r'(?s)().*(<\/SellerRefundNote>)')
replacement = r'\1 REMOVED \2'
-
+
for pattern in patterns:
editText = re.sub(pattern, replacement, editText)
- return editText
\ No newline at end of file
+ return editText
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..1f3a870
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,2 @@
+requests==2.22.0
+pyOpenSSL==19.1.0
diff --git a/test/test_ap.py b/test/test_ap.py
index 3b5804b..468213c 100644
--- a/test/test_ap.py
+++ b/test/test_ap.py
@@ -12,6 +12,7 @@
from amazon_pay.payment_response import PaymentResponse, PaymentErrorResponse
from symbol import parameters
+
class AmazonPayClientTest(unittest.TestCase):
def setUp(self):
@@ -32,7 +33,7 @@ def setUp(self):
sandbox=True,
region='na',
currency_code='USD'
- )
+ )
self.request = PaymentRequest(
params={'test': 'test'},
@@ -94,7 +95,7 @@ def test_sandbox_setter(self):
self.assertEqual(
self.client._mws_endpoint,
'https://mws.amazonservices.com/OffAmazonPayments_Sandbox/2013-01-01')
-
+
def test_sanitize_response_data(self):
current_file_dir = os.path.dirname(__file__)
test_file_path = os.path.join(current_file_dir, "log.txt")
@@ -184,15 +185,15 @@ def test_headers(self, mock_urlopen):
self.client.get_service_status()
if sys.version_info[0] == 3 and sys.version_info[1] >= 2:
py_valid = True
-
+
header_expected = {
'Content-Type': 'application/x-www-form-urlencoded',
- "User-Agent":'amazon-pay-sdk-python/{0} ({1}Python/{2}; {3}/{4})'.format(
- str(ap_version.versions['application_version']),
- (''),
- py_version,
- str(platform.system()),
- str(platform.release())
+ "User-Agent": 'amazon-pay-sdk-python/{0} ({1}Python/{2}; {3}/{4})'.format(
+ str(ap_version.versions['application_version']),
+ (''),
+ py_version,
+ str(platform.system()),
+ str(platform.release())
)
}
self.assertEqual(mock_urlopen.call_args[1]['headers'], header_expected)
@@ -408,7 +409,7 @@ def test_set_order_reference_details(self, mock_urlopen):
'OrderReferenceAttributes.SellerOrderAttributes.SupplementaryData': self.supplementary_data}
data_expected = self.request._querystring(parameters)
self.assertEqual(mock_urlopen.call_args[1]['data'], data_expected)
-
+
@patch('requests.post')
def test_set_order_attributes(self, mock_urlopen):
mock_urlopen.side_effect = self.mock_requests_post
@@ -428,7 +429,7 @@ def test_set_order_attributes(self, mock_urlopen):
merchant_id='AGHJHHJKJHL',
mws_auth_token='amzn.mws.d8f2d-6a5f-b06a4628',
supplementary_data=self.supplementary_data)
-
+
parameters = {
'Action': 'SetOrderAttributes',
'AmazonOrderReferenceId': 'P01-1234567-4827348237',
@@ -449,7 +450,6 @@ def test_set_order_attributes(self, mock_urlopen):
data_expected = self.request._querystring(parameters)
self.assertEqual(mock_urlopen.call_args[1]['data'], data_expected)
-
@patch('requests.post')
def test_get_order_reference_details(self, mock_urlopen):
mock_urlopen.side_effect = self.mock_requests_post
@@ -466,7 +466,7 @@ def test_get_order_reference_details(self, mock_urlopen):
'AccessToken': 'AHJJOKJJHNJNJK',
'SellerId': 'ADGJUHJWKJKJ',
'MWSAuthToken': 'amzn.mws.d8f2d-6a5f-b427489234798'
- }
+ }
data_expected = self.request._querystring(parameters)
self.assertEqual(mock_urlopen.call_args[1]['data'], data_expected)
@@ -493,7 +493,7 @@ def test_confirm_order_reference(self, mock_urlopen):
'AuthorizationAmount.Amount': '5',
'AuthorizationAmount.CurrencyCode': 'USD'
}
-
+
data_expected = self.request._querystring(parameters)
self.assertEqual(mock_urlopen.call_args[1]['data'], data_expected)
@@ -545,18 +545,18 @@ def test_list_order_reference(self, mock_urlopen):
merchant_id='AFHRWKJEKJLJKL',
mws_auth_token='amzn.mws.d8f2d-6a5f-b42ryurueruio3uio87',
order_reference_status_list_filter=['test1', 'test2'])
-
+
if self.client.region in ('na'):
payment_domain = 'NA_USD'
elif self.client.region in ('uk', 'gb'):
payment_domain = 'EU_GBP'
elif self.client.region in ('jp', 'fe'):
- payment_domain = 'FE_JPY'
+ payment_domain = 'FE_JPY'
elif self.client.region in ('eu', 'de', 'fr', 'it', 'es', 'cy'):
payment_domain = 'EU_EUR'
else:
- raise ValueError("Error. The current region code does not match our records")
-
+ raise ValueError(
+ "Error. The current region code does not match our records")
parameters = {
'Action': 'ListOrderReference',
@@ -593,13 +593,13 @@ def test_list_order_reference_time_check_error(self, mock_urlopen):
elif self.client.region in ('uk', 'gb'):
payment_domain = 'EU_GBP'
elif self.client.region in ('jp', 'fe'):
- payment_domain = 'FE_JPY'
+ payment_domain = 'FE_JPY'
elif self.client.region in ('eu', 'de', 'fr', 'it', 'es', 'cy'):
payment_domain = 'EU_EUR'
else:
- raise ValueError("Error. The current region code does not match our records")
+ raise ValueError(
+ "Error. The current region code does not match our records")
-
parameters = {
'Action': 'ListOrderReference',
'QueryId': 'testSellerOrderId12444',
@@ -610,7 +610,7 @@ def test_list_order_reference_time_check_error(self, mock_urlopen):
'CreatedTimeRange.StartTime': 'testStart'}
data_expected = self.request._querystring(parameters)
self.assertEqual(mock_urlopen.call_args[1]['data'], data_expected)
-
+
@patch('requests.post')
def test_list_order_reference_by_next_token(self, mock_urlopen):
mock_urlopen.side_effect = self.mock_requests_post
@@ -618,14 +618,14 @@ def test_list_order_reference_by_next_token(self, mock_urlopen):
next_page_token='yrtewyy4823749329482394023940',
merchant_id='AHFUHWJELWJELEJW',
mws_auth_token='amzn.mws.d8f2d-6a5f-b42r23436248623748')
- parameters= {
+ parameters = {
'Action': 'ListOrderReferenceByNextToken',
'NextPageToken': 'yrtewyy4823749329482394023940',
'SellerId': 'AHFUHWJELWJELEJW',
'MWSAuthToken': 'amzn.mws.d8f2d-6a5f-b42r23436248623748'}
data_expected = self.request._querystring(parameters)
self.assertEqual(mock_urlopen.call_args[1]['data'], data_expected)
-
+
@patch('requests.post')
def test_authorize(self, mock_urlopen):
mock_urlopen.side_effect = self.mock_requests_post