From 8c1182203d6d50b7f0a5ea76ce24da66dc5ccf54 Mon Sep 17 00:00:00 2001 From: Abhishek Srikanth Date: Mon, 27 Jan 2020 15:14:55 +0530 Subject: [PATCH] Add requirements.txt - Added requirements.txt - Updated README.md - PEP8 formatting --- README.md | 11 +++- amazon_pay/client.py | 103 +++++++++++++++++----------------- amazon_pay/ipn_handler.py | 18 +++--- amazon_pay/payment_request.py | 33 ++++++----- requirements.txt | 2 + test/test_ap.py | 48 ++++++++-------- 6 files changed, 113 insertions(+), 102 deletions(-) create mode 100644 requirements.txt 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