From 14eea65671a7062c92f7b0e01dece692ccd0a1e1 Mon Sep 17 00:00:00 2001 From: radlws Date: Tue, 1 Dec 2015 02:01:42 -0500 Subject: [PATCH 1/2] added address validation v4 --- examples/address_validation.py | 101 ++- fedex/services/address_validation_service.py | 25 +- fedex/wsdl/AddressValidationService_v2.wsdl | 603 ------------------ .../AddressValidationService_v2.wsdl | 603 ------------------ 4 files changed, 80 insertions(+), 1252 deletions(-) delete mode 100755 fedex/wsdl/AddressValidationService_v2.wsdl delete mode 100755 fedex/wsdl/test_server_wsdl/AddressValidationService_v2.wsdl diff --git a/examples/address_validation.py b/examples/address_validation.py index 783dfc6..859b3d1 100755 --- a/examples/address_validation.py +++ b/examples/address_validation.py @@ -7,51 +7,92 @@ class can handle up to 100 addresses for validation. from example_config import CONFIG_OBJ from fedex.services.address_validation_service import FedexAddressValidationRequest +# NOTE: TO USE ADDRESS VALIDATION SERVICES, YOU NEED TO REQUEST FEDEX TO ENABLE THIS SERVICE FOR YOUR ACCOUNT. +# BY DEFAULT, THE SERVICE IS DISABLED AND YOU WILL RECEIVE AUTHENTICATION FAILED, 1000 RESPONSE. + # Set this to the INFO level to see the response from Fedex printed in stdout. logging.basicConfig(level=logging.INFO) # This is the object that will be handling our tracking request. # We're using the FedexConfig object from example_config.py in this dir. -connection = FedexAddressValidationRequest(CONFIG_OBJ) - -# The AddressValidationOptions are created with default values of None, which -# will cause WSDL validation errors. To make things work, each option needs to -# be explicitly set or deleted. - -## Set the flags we want to True (or a value). -connection.AddressValidationOptions.CheckResidentialStatus = True -connection.AddressValidationOptions.VerifyAddresses = True -connection.AddressValidationOptions.RecognizeAlternateCityNames = True -connection.AddressValidationOptions.MaximumNumberOfMatches = 3 - -## Delete the flags we don't want. -del connection.AddressValidationOptions.ConvertToUpperCase -del connection.AddressValidationOptions.ReturnParsedElements - -## *Accuracy fields can be TIGHT, EXACT, MEDIUM, or LOOSE. Or deleted. -connection.AddressValidationOptions.StreetAccuracy = 'LOOSE' -del connection.AddressValidationOptions.DirectionalAccuracy -del connection.AddressValidationOptions.CompanyNameAccuracy - -## Create some addresses to validate -address1 = connection.create_wsdl_object_of_type('AddressToValidate') -address1.CompanyName = 'International Paper' +customer_transaction_id = "*** AddressValidation Request v4 using Python ***" # Optional transaction_id +# Optional locale & language client data +client_language_code = 'EN' +client_locale_code = 'US' +avs_request = FedexAddressValidationRequest(CONFIG_OBJ, customer_transaction_id=customer_transaction_id, + client_locale_code=client_locale_code, + client_language_code=client_language_code) + +# Create some addresses to validate +address1 = avs_request.create_wsdl_object_of_type('AddressToValidate') +address1.ClientReferenceId = "Your ID for the Recipient" address1.Address.StreetLines = ['155 Old Greenville Hwy', 'Suite 103'] address1.Address.City = 'Clemson' address1.Address.StateOrProvinceCode = 'SC' address1.Address.PostalCode = 29631 address1.Address.CountryCode = 'US' address1.Address.Residential = False -connection.add_address(address1) -address2 = connection.create_wsdl_object_of_type('AddressToValidate') +address1.Contact.PersonName = 'Recipient Name' +address1.Contact.CompanyName = 'Company Name' +address1.Contact.PhoneNumber = '999-123-5343' +address1.Contact.EMailAddress = 'example_recipient@email.com' +avs_request.add_address(address1) + +address2 = avs_request.create_wsdl_object_of_type('AddressToValidate') address2.Address.StreetLines = ['320 S Cedros', '#200'] address2.Address.City = 'Solana Beach' address2.Address.StateOrProvinceCode = 'CA' address2.Address.PostalCode = 92075 address2.Address.CountryCode = 'US' -connection.add_address(address2) +avs_request.add_address(address2) + + +# If you'd like to see some documentation on the ship service WSDL, un-comment +# this line. (Spammy). +#print avs_request.client + +# Un-comment this to see your complete, ready-to-send request as it stands +# before it is actually sent. This is useful for seeing what values you can +# change. +#print avs_request.AddressesToValidate +#print avs_request.ClientDetail +#print avs_request.TransactionDetail + +# Fires off the request, sets the 'response' attribute on the object. +avs_request.send_request() + +# good to un-comment to see the variables returned by the Fedex reply. +print avs_request.response +#print avs_request.client.last_received() + +# See the request printed out. +#print avs_request.client.last_sent() + +# Overall end result of the query +for i in range(len(avs_request.response.AddressResults)): + + print "Details for Address", i + 1 + print "The validated street is:", avs_request.response.AddressResults[i].EffectiveAddress.StreetLines + print "The validated city is:", avs_request.response.AddressResults[i].EffectiveAddress.City + print "The validated state code is:", avs_request.response.AddressResults[i].EffectiveAddress.StateOrProvinceCode + print "The validated postal code is:", avs_request.response.AddressResults[i].EffectiveAddress.PostalCode + print "The validated country code is:", avs_request.response.AddressResults[i].EffectiveAddress.CountryCode + + # Can be used to determine the address classification to figure out if Residential fee should apply. + # MIXED, RESIDENTIAL, UNKNOWN, BUSINESS + print "The validated address is residential:", avs_request.response.AddressResults[i].Classification != 'BUSINESS' -## Send the request and print the response -connection.send_request() -print connection.response + # Getting the optional attributes if available + for j in range(len(avs_request.response.AddressResults[i].Attributes)): + cur_attribute = avs_request.response.AddressResults[i].Attributes[j] + if cur_attribute.Name == "CountrySupported": + print "Supported Country:", cur_attribute.Value == 'true' + if cur_attribute.Name == "SuiteRequiredButMissing": + print "Missing Suite:", cur_attribute.Value == 'true' + if cur_attribute.Name == "CountrySupported": + print "Invalid Suite:", cur_attribute.Value == 'true' + if cur_attribute.Name == "MultipleMatches": + print "Multiple Matches:", cur_attribute.Value == 'true' + if cur_attribute.Name == "POBox": + print "Is POBox:", cur_attribute.Value == 'true' diff --git a/fedex/services/address_validation_service.py b/fedex/services/address_validation_service.py index f566731..8d0ec31 100644 --- a/fedex/services/address_validation_service.py +++ b/fedex/services/address_validation_service.py @@ -28,30 +28,24 @@ def __init__(self, config_obj, *args, **kwargs): # Holds version info for the VersionId SOAP object. self._version_info = { 'service_id': 'aval', - 'major': '2', + 'major': '4', 'intermediate': '0', 'minor': '0' } - self.AddressValidationOptions = None + # self.AddressValidationOptions = None """@ivar: Holds the AddressValidationOptions WSDL object.""" - self.addresses_to_validate = [] + self.AddressesToValidate = [] """@ivar: Holds the AddressToValidate WSDL object.""" # Call the parent FedexBaseService class for basic setup work. super(FedexAddressValidationRequest, self).__init__( - self._config_obj, 'AddressValidationService_v2.wsdl', *args, **kwargs) + self._config_obj, 'AddressValidationService_v4.wsdl', *args, **kwargs) def _prepare_wsdl_objects(self): """ Create the data structure and get it ready for the WSDL request. """ - - # This holds some optional options for the request.. - self.AddressValidationOptions = self.client.factory.create('AddressValidationOptions') - - # This is good to review if you'd like to see what the data structure - # looks like. - self.logger.debug(self.AddressValidationOptions) + pass def _assemble_and_send_request(self): """ @@ -75,13 +69,12 @@ def _assemble_and_send_request(self): ClientDetail=self.ClientDetail, TransactionDetail=self.TransactionDetail, Version=self.VersionId, - RequestTimestamp=datetime.now(), - Options=self.AddressValidationOptions, - AddressesToValidate=self.addresses_to_validate) + InEffectAsOfTimestamp=datetime.now(), + AddressesToValidate=self.AddressesToValidate) def add_address(self, address_item): """ - Adds an address to self.addresses_to_validate. + Adds an address to self.AddressesToValidate. @type address_item: WSDL object, type of AddressToValidate WSDL object. @keyword address_item: A AddressToValidate, created by @@ -90,4 +83,4 @@ def add_address(self, address_item): See examples/create_shipment.py for more details. """ - self.addresses_to_validate.append(address_item) + self.AddressesToValidate.append(address_item) diff --git a/fedex/wsdl/AddressValidationService_v2.wsdl b/fedex/wsdl/AddressValidationService_v2.wsdl deleted file mode 100755 index 44c89e7..0000000 --- a/fedex/wsdl/AddressValidationService_v2.wsdl +++ /dev/null @@ -1,603 +0,0 @@ - - - - - - - - - - - The descriptive data to be used in authentication of the sender's identity (and right to use FedEx web services). - - - - - Descriptive data identifying the client submitting the transaction. - - - - - Descriptive data for this customer transaction. The TransactionDetail from the request is echoed back to the caller in the corresponding reply. - - - - - Identifies the version/level of a service operation expected by a caller (in each request) and performed by the callee (in each reply). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Used in authentication of the sender's identity. - - - - - Credential used to authenticate a specific software application. This value is provided by FedEx after registration. - - - - - - - Two part authentication string used for the sender's identity. - - - - - Identifying part of the authentication key. This value is provided by FedEx after registration. - - 16 - - - - - - Secret part of authentication key used for authentication. This value is provided by FedEx after registration. - - 25 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (EAS 100) Apartment number not found for this address. - - - - - - - (EAS 101) Address requires apartment number. - - - - - - - (EAS 102) Address normalized - abbreviations applied. - - - - - - - (EAS 103) Dropped data. - - - - - - - (EAS 104) Address requires box number. - - - - - - - (EAS 200) Match - no changes applied to input address. - - - - - - - (EAS 201) Address modified to achieve match. - - - - - - - (EAS 202) Match to street range. - - - - - - - (EAS 203) Match to box number. - - - - - - - (EAS 204) Match to Rural Route (RR) / Highway Contract (HC) address. - - - - - - - (EAS 205) Match to city (non-US, non-Canada). - - - - - - - (EAS 206) Match to postal code only (non-street) - - - - - - - (EAS 207) Need box number for Rural Route / Highway Contract (HC) match. - - - - - - - (EAS 208) Formatting performed for country (non-US, non-Canada). - - - - - - - (EAS 209) Match to military address (e.g. APO/FPO). - - - - - - - (EAS 210) Match to general delivery. - - - - - - - (EAS 211) Address exceeded 35 character plug-in limit. - - - - - - - (EAS 212) Unable to append non-address; data 35 character limit imposed. - - - - - - - (EAS 300) Insufficient data for address verification. - - - - - - - (EAS 301) Address (house or box number) not found. - - - - - - - (EAS 303) Postal code not found. - - - - - - - (EAS 305) Invalid country. - - - - - - - (EAS 400) Service unavailable for request address. - - - - - - - - The descriptive data identifying the client submitting the transaction. - - - - - The FedEx account number assigned to the customer initiating the request. - - 12 - - - - - - Identifies the unique client device submitting the request. This number is assigned by FedEx and identifies the unique device from which the request is originating. - - 10 - - - - - - Governs any future language/translations used for human-readable Notification.localizedMessages in responses to the request containing this ClientDetail object. Different requests from the same client may contain different Localization data. (Contrast with TransactionDetail.localization, which governs data payload language/translation.) - - - - - - - Governs any future language/translations used for human-readable text. - - - - - Identifies the language to use for human-readable messages. - - 2 - - - - - - Identifies the locale (i.e. country code) associated with the language. - - 2 - - - - - - - - Descriptive data for this customer transaction. The TransactionDetail from the request is echoed back to the caller in the corresponding reply. - - - - - Identifies a customer-supplied unique identifier for this transaction. It is returned in the reply message to aid in matching requests to replies. - - 40 - - - - - - Governs any future language/translations applied to the data payload(contrasted with ClientDetail.localization, which governs Notification.localizedMessage language selection). - - - - - - - Identifies the version/level of a service operation expected by a caller (in each request) and performed by the callee (in each reply). - - - - - Identifies a system or sub-system which performs an operation. - - - - - Identifies the service business level. For the initial FedEx Web Service release this value should be set to 1. - - - - - Identifies the service interface level. For the initial FedEx Web Service release this value should be set to 0. - - - - - Identifies the service code level. For the initial FedEx Web Service release this value should be set to 0. - - - - - - - Identifies the set of severity values for a Notification. - - - - - - - - - - - - The descriptive data regarding the results of the submitted transaction. - - - - - The severity of this notification. this can indicate success or failure or some other information about the request such as errors or notes. - - - - - Indicates the source of the notification. Combined with Code, it uniqely identifies this message. - - - - - A code that represents this notification. Combined with Source, it uniqely identifies this message. - - 8 - - - - - - Text that explains this notification. - - 255 - - - - - - A translated message. The translation is based on the Localization element of the ClientDetail element of the request. - - TBD - - - - - - If the message used parameter replacement to be specific as to the meaning of the message, this is the list of parameters that were used. - - TBD - - - - - - - - - - Name identifiying the type of the data in the element 'Value' - - - - - The value that was used as the replacement parameter. - - - - - - - The descriptive data for a physical location. - - - - - Combination of number, street name, etc. At least one line is required for a valid physical address; empty lines should not be included. - - 35 - - - - - - Name of city, town, etc. - - - 35 - 20 - - - - - - - Identifying abbreviation for US state, Canada province, etc. Format and presence of this field will vary, depending on country. - - 14 - - - - - - Identification of a region (usually small) for mail/package delivery. Format and presence of this field will vary, depending on country. This element is required if both the City and StateOrProvinceCode are not present. - - 16 - - - - - - Relevant only to addresses in Puerto Rico. In Puerto Rico, multiple addresses within the same ZIP code can have the same house number and street name. When this is the case, the urbanization code is needed to distinguish them. - - 100 - - - - - - Identification of a country. - - 2 - - - - - - Indicates whether this address is residential (as opposed to commercial). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/fedex/wsdl/test_server_wsdl/AddressValidationService_v2.wsdl b/fedex/wsdl/test_server_wsdl/AddressValidationService_v2.wsdl deleted file mode 100755 index baedf0f..0000000 --- a/fedex/wsdl/test_server_wsdl/AddressValidationService_v2.wsdl +++ /dev/null @@ -1,603 +0,0 @@ - - - - - - - - - - - The descriptive data to be used in authentication of the sender's identity (and right to use FedEx web services). - - - - - Descriptive data identifying the client submitting the transaction. - - - - - Descriptive data for this customer transaction. The TransactionDetail from the request is echoed back to the caller in the corresponding reply. - - - - - Identifies the version/level of a service operation expected by a caller (in each request) and performed by the callee (in each reply). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Used in authentication of the sender's identity. - - - - - Credential used to authenticate a specific software application. This value is provided by FedEx after registration. - - - - - - - Two part authentication string used for the sender's identity. - - - - - Identifying part of the authentication key. This value is provided by FedEx after registration. - - 16 - - - - - - Secret part of authentication key used for authentication. This value is provided by FedEx after registration. - - 25 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (EAS 100) Apartment number not found for this address. - - - - - - - (EAS 101) Address requires apartment number. - - - - - - - (EAS 102) Address normalized - abbreviations applied. - - - - - - - (EAS 103) Dropped data. - - - - - - - (EAS 104) Address requires box number. - - - - - - - (EAS 200) Match - no changes applied to input address. - - - - - - - (EAS 201) Address modified to achieve match. - - - - - - - (EAS 202) Match to street range. - - - - - - - (EAS 203) Match to box number. - - - - - - - (EAS 204) Match to Rural Route (RR) / Highway Contract (HC) address. - - - - - - - (EAS 205) Match to city (non-US, non-Canada). - - - - - - - (EAS 206) Match to postal code only (non-street) - - - - - - - (EAS 207) Need box number for Rural Route / Highway Contract (HC) match. - - - - - - - (EAS 208) Formatting performed for country (non-US, non-Canada). - - - - - - - (EAS 209) Match to military address (e.g. APO/FPO). - - - - - - - (EAS 210) Match to general delivery. - - - - - - - (EAS 211) Address exceeded 35 character plug-in limit. - - - - - - - (EAS 212) Unable to append non-address; data 35 character limit imposed. - - - - - - - (EAS 300) Insufficient data for address verification. - - - - - - - (EAS 301) Address (house or box number) not found. - - - - - - - (EAS 303) Postal code not found. - - - - - - - (EAS 305) Invalid country. - - - - - - - (EAS 400) Service unavailable for request address. - - - - - - - - The descriptive data identifying the client submitting the transaction. - - - - - The FedEx account number assigned to the customer initiating the request. - - 12 - - - - - - Identifies the unique client device submitting the request. This number is assigned by FedEx and identifies the unique device from which the request is originating. - - 10 - - - - - - Governs any future language/translations used for human-readable Notification.localizedMessages in responses to the request containing this ClientDetail object. Different requests from the same client may contain different Localization data. (Contrast with TransactionDetail.localization, which governs data payload language/translation.) - - - - - - - Governs any future language/translations used for human-readable text. - - - - - Identifies the language to use for human-readable messages. - - 2 - - - - - - Identifies the locale (i.e. country code) associated with the language. - - 2 - - - - - - - - Descriptive data for this customer transaction. The TransactionDetail from the request is echoed back to the caller in the corresponding reply. - - - - - Identifies a customer-supplied unique identifier for this transaction. It is returned in the reply message to aid in matching requests to replies. - - 40 - - - - - - Governs any future language/translations applied to the data payload(contrasted with ClientDetail.localization, which governs Notification.localizedMessage language selection). - - - - - - - Identifies the version/level of a service operation expected by a caller (in each request) and performed by the callee (in each reply). - - - - - Identifies a system or sub-system which performs an operation. - - - - - Identifies the service business level. For the initial FedEx Web Service release this value should be set to 1. - - - - - Identifies the service interface level. For the initial FedEx Web Service release this value should be set to 0. - - - - - Identifies the service code level. For the initial FedEx Web Service release this value should be set to 0. - - - - - - - Identifies the set of severity values for a Notification. - - - - - - - - - - - - The descriptive data regarding the results of the submitted transaction. - - - - - The severity of this notification. this can indicate success or failure or some other information about the request such as errors or notes. - - - - - Indicates the source of the notification. Combined with Code, it uniqely identifies this message. - - - - - A code that represents this notification. Combined with Source, it uniqely identifies this message. - - 8 - - - - - - Text that explains this notification. - - 255 - - - - - - A translated message. The translation is based on the Localization element of the ClientDetail element of the request. - - TBD - - - - - - If the message used parameter replacement to be specific as to the meaning of the message, this is the list of parameters that were used. - - TBD - - - - - - - - - - Name identifiying the type of the data in the element 'Value' - - - - - The value that was used as the replacement parameter. - - - - - - - The descriptive data for a physical location. - - - - - Combination of number, street name, etc. At least one line is required for a valid physical address; empty lines should not be included. - - 35 - - - - - - Name of city, town, etc. - - - 35 - 20 - - - - - - - Identifying abbreviation for US state, Canada province, etc. Format and presence of this field will vary, depending on country. - - 14 - - - - - - Identification of a region (usually small) for mail/package delivery. Format and presence of this field will vary, depending on country. This element is required if both the City and StateOrProvinceCode are not present. - - 16 - - - - - - Relevant only to addresses in Puerto Rico. In Puerto Rico, multiple addresses within the same ZIP code can have the same house number and street name. When this is the case, the urbanization code is needed to distinguish them. - - 100 - - - - - - Identification of a country. - - 2 - - - - - - Indicates whether this address is residential (as opposed to commercial). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 1d438f0b71848a34e0f48aebc4adb66d3f106387 Mon Sep 17 00:00:00 2001 From: radlws Date: Tue, 1 Dec 2015 02:47:00 -0500 Subject: [PATCH 2/2] added test for avs --- tests/test_address_validation_service.py | 41 ++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 tests/test_address_validation_service.py diff --git a/tests/test_address_validation_service.py b/tests/test_address_validation_service.py new file mode 100644 index 0000000..2320fe6 --- /dev/null +++ b/tests/test_address_validation_service.py @@ -0,0 +1,41 @@ +""" +Test module for the Fedex AddressValidationService WSDL. +""" + +import unittest + +import sys +sys.path.insert(0, '..') +from fedex.services.address_validation_service import FedexAddressValidationRequest + +# Common global config object for testing. +from common import get_test_config +CONFIG_OBJ = get_test_config() + + +class AddressValidationServiceTests(unittest.TestCase): + """ + These tests verify that the address validation service WSDL is in good shape. + """ + def test_avs(self): + + avs_request = FedexAddressValidationRequest(CONFIG_OBJ) + + address1 = avs_request.create_wsdl_object_of_type('AddressToValidate') + address1.Address.StreetLines = ['155 Old Greenville Hwy', 'Suite 103'] + address1.Address.City = 'Clemson' + address1.Address.StateOrProvinceCode = 'SC' + address1.Address.PostalCode = 29631 + address1.Address.CountryCode = 'US' + address1.Address.Residential = False + avs_request.add_address(address1) + + avs_request.send_request() + + assert avs_request.response + + + +if __name__ == "__main__": + + unittest.main()