-
Notifications
You must be signed in to change notification settings - Fork 545
adds address validation to usps.rb #410
base: master
Are you sure you want to change the base?
Changes from all commits
7411f9a
67f439a
3014629
05ab9ff
f0a6e68
e6c2b11
61d832a
7ec09e0
63b38ec
5421ee6
095af09
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
module ActiveShipping | ||
|
||
# The `AddressStandarizationResponse` object is returned by the {ActiveShipping::Carrier#????} | ||
# call. The most important method is {#standardize_addresses}, which will return a list of | ||
# standardized, correctly-spelled, validated, full addresses. | ||
# | ||
# @note This only works for USPS and in the US | ||
# | ||
# @!attribute addresses | ||
# The correct addresses returned from USPS | ||
class AddressStandardizationResponse < Response | ||
|
||
attr_reader :locations | ||
|
||
# Initializes a new AddressStandarizationResponse instance. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indentation a little off here. |
||
# | ||
# @param success (see ActiveShipping::Response#initialize) | ||
# @param message (see ActiveShipping::Response#initialize) | ||
# @param params (see ActiveShipping::Response#initialize) | ||
# @option options (see ActiveShipping::Response#initialize) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could summarize it in one line like https://github.com/Shopify/active_shipping/blob/master/lib/active_shipping/tracking_response.rb#L59 |
||
def initialize(success, message, params = {}, options = {}) | ||
@locations = options[:locations] | ||
super | ||
end | ||
end | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A newline is preferred at the end of all files. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,7 +29,8 @@ class USPS < Carrier | |
:us_rates => 'RateV4', | ||
:world_rates => 'IntlRateV2', | ||
:test => 'CarrierPickupAvailability', | ||
:track => 'TrackV2' | ||
:track => 'TrackV2', | ||
:address_standarization => 'Verify' | ||
} | ||
USE_SSL = { | ||
:us_rates => false, | ||
|
@@ -229,6 +230,12 @@ def find_rates(origin, destination, packages, options = {}) | |
end | ||
end | ||
|
||
def standardize_addresses(addresses, options = {}) | ||
request = build_address_standardization_request(addresses) | ||
|
||
parse_address_standardize_response(commit(:address_standarization, request, false), addresses, options) | ||
end | ||
|
||
def valid_credentials? | ||
# Cannot test with find_rates because USPS doesn't allow that in test mode | ||
test_mode? ? canned_address_verification_works? : super | ||
|
@@ -607,7 +614,6 @@ def parse_tracking_response(response, options = {}) | |
end | ||
end | ||
|
||
|
||
def parse_tracking_info(response, node) | ||
success = !has_error?(node) | ||
message = response_message(node) | ||
|
@@ -654,6 +660,71 @@ def parse_tracking_info(response, node) | |
) | ||
end | ||
|
||
def build_address_standardization_request(addresses) | ||
xml_builder = Nokogiri::XML::Builder.new do |xml| | ||
xml.AddressValidateRequest('USERID' => @options[:login]) do | ||
xml.IncludeOptionalElements(true) | ||
xml.ReturnCarrierRoute(true) | ||
Array(addresses).each_with_index do |address, id| | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't believe you need to wrap |
||
xml.Address('ID' => id) do | ||
xml.FirmName(address[:firm_name]) | ||
xml.Address1(address[:address1]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From the documentation, it looks like We use |
||
xml.Address2(address[:address2]) | ||
xml.City(address[:city]) | ||
xml.State(address[:state]) | ||
xml.Urbanization(address[:urbanization]) | ||
xml.Zip5(address[:postal_code]) | ||
xml.Zip4(address[:zip4]) | ||
end | ||
end | ||
end | ||
end | ||
save_request(xml_builder.to_xml) | ||
end | ||
|
||
def parse_address_standardize_response(response, addresses, options = {}) | ||
success = true | ||
message = '' | ||
address_hash = {} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks unused to me. |
||
locations = [] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you use the |
||
|
||
xml = Nokogiri.XML(response) | ||
|
||
if error = xml.at_xpath('/Error | //ServiceErrors/ServiceError') | ||
success = false | ||
message = error.at('Description').text | ||
else | ||
xml.root.xpath('Address').each do |address| | ||
if address.at('Error') | ||
success = false | ||
message = address.at('Error/Description').text | ||
break | ||
end | ||
end | ||
end | ||
|
||
if success | ||
addresses = Hash.from_xml(response)["AddressValidateResponse"]["Address"] | ||
if addresses.is_a?(Array) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Took a look at the response, you should be able to do this to avoid the
|
||
addresses.each do |address| | ||
locations << Location.new(:address1 => address["Address1"], | ||
:address2 => address["Address2"], | ||
:postal_code => address["Zip5"], | ||
:city => address["City"], | ||
:state => address["State"]) | ||
end | ||
else | ||
locations << Location.new(:address1 => addresses["Address1"], | ||
:address2 => addresses["Address2"], | ||
:postal_code => addresses["Zip5"], | ||
:city => addresses["City"], | ||
:state => addresses["State"]) | ||
end | ||
end | ||
|
||
AddressStandardizationResponse.new(success, message, Hash.from_xml(response), :locations => locations, :addresses => addresses, :xml => response, :request => last_request) | ||
end | ||
|
||
def error_description_node(node) | ||
node.xpath('Error/Description') | ||
end | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'll need an
attr_reader
for:addresses
too.