awesome_usps 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +4 -0
- data/License.txt +20 -0
- data/Manifest.txt +38 -0
- data/PostInstall.txt +7 -0
- data/README.txt +48 -0
- data/Rakefile +4 -0
- data/config/hoe.rb +73 -0
- data/config/requirements.rb +15 -0
- data/lib/awesome_usps.rb +39 -0
- data/lib/awesome_usps/address_verification.rb +156 -0
- data/lib/awesome_usps/delivery_and_signature_confirmation.rb +160 -0
- data/lib/awesome_usps/electric_merchandis_return.rb +139 -0
- data/lib/awesome_usps/express_mail.rb +137 -0
- data/lib/awesome_usps/international_item.rb +43 -0
- data/lib/awesome_usps/international_mail_labels.rb +317 -0
- data/lib/awesome_usps/location.rb +97 -0
- data/lib/awesome_usps/open_distrubute_priority.rb +127 -0
- data/lib/awesome_usps/package.rb +132 -0
- data/lib/awesome_usps/service_standard.rb +143 -0
- data/lib/awesome_usps/shipping.rb +236 -0
- data/lib/awesome_usps/tracking.rb +88 -0
- data/lib/awesome_usps/version.rb +9 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +82 -0
- data/setup.rb +1585 -0
- data/tasks/deployment.rake +34 -0
- data/tasks/environment.rake +7 -0
- data/tasks/website.rake +17 -0
- data/test/test_awesome_usps.rb +11 -0
- data/test/test_helper.rb +2 -0
- data/website/index.html +145 -0
- data/website/index.txt +85 -0
- data/website/javascripts/rounded_corners_lite.inc.js +285 -0
- data/website/stylesheets/screen.css +138 -0
- data/website/template.html.erb +48 -0
- metadata +113 -0
@@ -0,0 +1,97 @@
|
|
1
|
+
module AwesomeUsps #:nodoc:
|
2
|
+
class Location
|
3
|
+
|
4
|
+
attr_reader :options,
|
5
|
+
:country,
|
6
|
+
:name,
|
7
|
+
:last_name,
|
8
|
+
:firm_name,
|
9
|
+
:zip5,
|
10
|
+
:zip4,
|
11
|
+
:state,
|
12
|
+
:city,
|
13
|
+
:address1,
|
14
|
+
:address2,
|
15
|
+
:address3,
|
16
|
+
:phone,
|
17
|
+
:facility_type,
|
18
|
+
:from_urbanization
|
19
|
+
#:fax,
|
20
|
+
#:address_type
|
21
|
+
|
22
|
+
alias_method :postal_code, :zip5
|
23
|
+
alias_method :postal, :postal_code
|
24
|
+
alias_method :zip, :postal
|
25
|
+
alias_method :province, :state
|
26
|
+
alias_method :territory, :province
|
27
|
+
alias_method :region, :province
|
28
|
+
alias_method :first_name, :name
|
29
|
+
|
30
|
+
def initialize(options = {})
|
31
|
+
@country = options[:country]
|
32
|
+
@name = options[:name] || options[:first_name]
|
33
|
+
@last_name= options[:last_name]
|
34
|
+
@firm_name = options[:firm_name]
|
35
|
+
@zip5 = options[:postal_code] || options[:postal] || options[:zip5]
|
36
|
+
@zip4 = options[:zip4]
|
37
|
+
@state = options[:province] || options[:state]
|
38
|
+
@city = options[:city]
|
39
|
+
@address1 = options[:address1]
|
40
|
+
@address2 = options[:address2]
|
41
|
+
@address3=options [:address3]
|
42
|
+
@phone = options[:phone]
|
43
|
+
@facility_type = options[:facility_type]
|
44
|
+
@from_urbanization =options[:from_urbanization]
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.from(object, options={})
|
48
|
+
return object if object.is_a? FotoVerite::Location
|
49
|
+
attr_mappings = {
|
50
|
+
:name => [:name, :first_name],
|
51
|
+
#:country => [:country_code, :country],
|
52
|
+
:zip5 => [:postal_code, :zip5, :postal],
|
53
|
+
:zip4 => [:zip4],
|
54
|
+
:state => [ :province, :state],
|
55
|
+
:city => [:city],
|
56
|
+
:address1 => [:address1],
|
57
|
+
:address2 => [:address2],
|
58
|
+
:facility_type => [:facility_type]
|
59
|
+
}
|
60
|
+
attributes = {}
|
61
|
+
hash_access = begin
|
62
|
+
object[:some_symbol]
|
63
|
+
true
|
64
|
+
rescue
|
65
|
+
false
|
66
|
+
end
|
67
|
+
attr_mappings.each do |pair|
|
68
|
+
pair[1].each do |sym|
|
69
|
+
if value = (object[sym] if hash_access) || (object.send(sym) if object.respond_to?(sym) && (!hash_access || !Hash.public_instance_methods.include?(sym.to_s)))
|
70
|
+
attributes[pair[0]] = value
|
71
|
+
break
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
self.new(attributes.update(options))
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
def to_s
|
80
|
+
prettyprint.gsub(/\n/, ' ')
|
81
|
+
end
|
82
|
+
|
83
|
+
def prettyprint
|
84
|
+
chunks = []
|
85
|
+
chunks << [@name,@firm_name].reject {|e| e.blank?}.join("\n")
|
86
|
+
chunks << [@address1,@address2].reject {|e| e.blank?}.join("\n")
|
87
|
+
chunks << [@city,@state,@zip5].reject {|e| e.blank?}.join(', ')
|
88
|
+
chunks.reject {|e| e.blank?}.join("\n")
|
89
|
+
end
|
90
|
+
|
91
|
+
def inspect
|
92
|
+
string = prettyprint
|
93
|
+
string
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
module AwesomeUsps
|
2
|
+
module OpenDistrubutePriority
|
3
|
+
|
4
|
+
MAX_RETRIES = 3
|
5
|
+
|
6
|
+
LIVE_DOMAIN = 'secure.shippingapis.com'
|
7
|
+
LIVE_RESOURCE = '/ShippingAPI.dll'
|
8
|
+
|
9
|
+
|
10
|
+
API_CODES = {:open_distrubute_priority => "OpenDistributePriority",
|
11
|
+
:open_distribute_priority_certify => "OpenDistributePriorityCertify"}
|
12
|
+
|
13
|
+
def open_distrubute_priority_label(orgin, destination, package_weight_in_ounces, mail_type, image_type, label_type=1, options={})
|
14
|
+
@package_weight_in_ounces = package_weight_in_ounces
|
15
|
+
@origin = origin
|
16
|
+
@destination = destination
|
17
|
+
@mail_type = mail_type
|
18
|
+
@image_type = image_type
|
19
|
+
@options =options
|
20
|
+
@api = "OpenDistributePriorityRequest"
|
21
|
+
request = open_distrubute_priority_xml
|
22
|
+
#YES THE API IS THAT STUPID THAT WE MUST PASS WHAT TYPE OF MIME TYPE!
|
23
|
+
commit_open_distrubute_priority_xml(:open_distrubute_priority, request, image_type, false)
|
24
|
+
end
|
25
|
+
|
26
|
+
def canned_open_distrubute_priority_label_test
|
27
|
+
@origin = Location.new( :name=> "John Smith", :address2 => "6406 Ivy Lane", :state => 'MD', :city => 'Greenbelt', :zip5 => '20770')
|
28
|
+
@destination =Location.new( :name=> "Fairfax Post Office", :address2 =>"10660 Page Ave", :state => 'VA', :city => 'Fairfax', :zip5 => "22030", :facility_type => "DDU")
|
29
|
+
@mail_type = "Letters"
|
30
|
+
@image_type = "PDF"
|
31
|
+
@package_weight_in_ounces = 1
|
32
|
+
@options = {:address_service => true, :permit_number => "21718", :permit_zip => "07204"}
|
33
|
+
@api = "OpenDistributePriorityCertifyRequest"
|
34
|
+
request= open_distrubute_priority_xml
|
35
|
+
commit_open_distrubute_priority_xml(:open_distribute_priority_certify, request, @image_type, true)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
def open_distrubute_priority_xml
|
40
|
+
xm = Builder::XmlMarkup.new
|
41
|
+
xm.tag!("#{@api}", "USERID"=>"#{@username}") do
|
42
|
+
xm.PermitNumber(@options[:permit_number])
|
43
|
+
xm.PermitIssuingPOZip5(@options[:permit_zip])
|
44
|
+
xm.FromName(@origin.name)
|
45
|
+
xm.FromFirm(@origin.firm_name)
|
46
|
+
xm.FromAddress1(@origin.address1) #Used for an apartment or suite number. Yes the API is a bit fucked.
|
47
|
+
xm.FromAddress2(@origin.address2)
|
48
|
+
xm.FromCity(@origin.city)
|
49
|
+
xm.FromState(@origin.state)
|
50
|
+
xm.FromZip5(@origin.zip5)
|
51
|
+
xm.FromZip4(@origin.zip4)
|
52
|
+
xm.POZipCode(@options[:po_zip_code])
|
53
|
+
xm.ToFacilityName(@destination.name)
|
54
|
+
xm.ToFacilityAddress1(@destination.address1)
|
55
|
+
xm.ToFacilityAddress2(@destination.address2)
|
56
|
+
xm.ToFacilityCity(@destination.city)
|
57
|
+
xm.ToFacilityState(@destination.state)
|
58
|
+
xm.ToFacilityZip5(@destination.zip5)
|
59
|
+
xm.ToFacilityZip4(@destination.zip4)
|
60
|
+
xm.FacilityType(@destination.facility_type)
|
61
|
+
xm.MailClassEnclosed(@mail_type)
|
62
|
+
xm.MailClassOther(@options[:other])
|
63
|
+
xm.WeightInPounds("0")
|
64
|
+
xm.WeightInOunces(@package_weight_in_ounces)
|
65
|
+
xm.ImageType(@image_type)
|
66
|
+
xm.SeparateReceiptPage(@options[:seperate])
|
67
|
+
xm.LabelDate(@options[:label_date])
|
68
|
+
xm.AllowNonCleansedFacilityAddr("false")
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def parse_open_distrubute_priority(xml, image_type)
|
73
|
+
if image_type == "TIF"
|
74
|
+
image_type = "image/tif"
|
75
|
+
else
|
76
|
+
image_type = "application/pdf"
|
77
|
+
end
|
78
|
+
parse = Hpricot.parse(xml)/:error
|
79
|
+
if parse != []
|
80
|
+
RAILS_DEFAULT_LOGGER.info "#{xml}"
|
81
|
+
return (Hpricot.parse(xml)/:description).inner_html
|
82
|
+
else
|
83
|
+
number = Hpricot.parse(xml)/:openDistributeprioritynumber
|
84
|
+
label = Hpricot.parse(xml)/:opendistributeprioritylabel
|
85
|
+
return {:image_type => image_type, :number => number.inner_html, :label => label.inner_html}
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def commit_open_distrubute_priority_xml(action, request, image_type, test=false)
|
90
|
+
retries = MAX_RETRIES
|
91
|
+
begin
|
92
|
+
#If and when their testing resource works again this will be useful tertiary command
|
93
|
+
url = URI.parse("https://#{LIVE_DOMAIN}#{LIVE_RESOURCE}")
|
94
|
+
req = Net::HTTP::Post.new(url.path)
|
95
|
+
req.set_form_data({'API' => API_CODES[action], 'XML' => request})
|
96
|
+
response = Net::HTTP.new(url.host, 443)
|
97
|
+
response.use_ssl
|
98
|
+
response.open_timeout = 5
|
99
|
+
response.read_timeout = 5
|
100
|
+
response.use_ssl = true
|
101
|
+
response.start
|
102
|
+
|
103
|
+
rescue Timeout::Error
|
104
|
+
if retries > 0
|
105
|
+
retries -= 1
|
106
|
+
retry
|
107
|
+
else
|
108
|
+
RAILS_DEFAULT_LOGGER.warn "The connection to the remote server timed out"
|
109
|
+
return "We appoligize for the inconvience but our USPS service is busy at the moment. To retry please refresh the browser"
|
110
|
+
end
|
111
|
+
rescue SocketError
|
112
|
+
RAILS_DEFAULT_LOGGER.error "There is a socket error with USPS plugin"
|
113
|
+
return "We appoligize for the inconvience but there is a problem with our server. To retry please refresh the browser"
|
114
|
+
end
|
115
|
+
|
116
|
+
response = response.request(req)
|
117
|
+
case response
|
118
|
+
when Net::HTTPSuccess
|
119
|
+
|
120
|
+
parse_open_distrubute_priority(response.body, image_type)
|
121
|
+
else
|
122
|
+
RAILS_DEFAULT_LOGGER.warn("USPS plugin settings are wrong #{response.body}")
|
123
|
+
return "USPS plugin settings are wrong #{response.body}"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
module AwesomeUsps #:nodoc:
|
2
|
+
class Package
|
3
|
+
GRAMS_IN_AN_OUNCE = 28.3495231
|
4
|
+
OUNCES_IN_A_GRAM = 0.0352739619
|
5
|
+
INCHES_IN_A_CM = 0.393700787
|
6
|
+
CM_IN_AN_INCH = 2.54
|
7
|
+
|
8
|
+
cattr_accessor :default_options
|
9
|
+
attr_reader :options, :value, :currency
|
10
|
+
|
11
|
+
# Package.new(100, [10, 20, 30], :units => :metric)
|
12
|
+
def initialize(grams_or_ounces, dimensions, options = {})
|
13
|
+
options = @@default_options.update(options) if @@default_options
|
14
|
+
options.symbolize_keys!
|
15
|
+
@options = options
|
16
|
+
|
17
|
+
imperial = options[:units] == :imperial
|
18
|
+
dimensions = Array(dimensions)
|
19
|
+
|
20
|
+
@ounces,@grams = nil
|
21
|
+
if grams_or_ounces.nil?
|
22
|
+
@grams = @ounces = 0
|
23
|
+
elsif imperial
|
24
|
+
@ounces = grams_or_ounces
|
25
|
+
else
|
26
|
+
@grams = grams_or_ounces
|
27
|
+
end
|
28
|
+
|
29
|
+
@inches,@centimetres = nil
|
30
|
+
if dimensions.empty?
|
31
|
+
@inches = @centimetres = [0,0,0]
|
32
|
+
else
|
33
|
+
process_dimensions(dimensions,imperial)
|
34
|
+
end
|
35
|
+
|
36
|
+
@value = Package.cents_from(options[:value])
|
37
|
+
@currency = options[:currency] || (options[:value].currency if options[:value].respond_to?(:currency))
|
38
|
+
@cylinder = (options[:cylinder] || options[:tube]) ? true : false
|
39
|
+
end
|
40
|
+
|
41
|
+
def cylinder?
|
42
|
+
@cylinder
|
43
|
+
end
|
44
|
+
alias_method :tube?, :cylinder?
|
45
|
+
|
46
|
+
def ounces(options={})
|
47
|
+
case options[:type]
|
48
|
+
when *[nil,:actual]: @ounces ||= grams(options) * OUNCES_IN_A_GRAM
|
49
|
+
when *[:volumetric,:dimensional]: @volumetric_ounces ||= grams(options) * OUNCES_IN_A_GRAM
|
50
|
+
when :billable: @billable_ounces ||= [ounces,ounces(:type => :volumetric)].max
|
51
|
+
end
|
52
|
+
end
|
53
|
+
alias_method :oz, :ounces
|
54
|
+
|
55
|
+
def grams(options={})
|
56
|
+
case options[:type]
|
57
|
+
when *[nil,:actual]: @grams ||= ounces(options) * GRAMS_IN_AN_OUNCE
|
58
|
+
when *[:volumetric,:dimensional]: @volumetric_grams ||= centimetres(:box_volume) / 6.0
|
59
|
+
when :billable: [grams,grams(:type => :volumetric)].max
|
60
|
+
end
|
61
|
+
end
|
62
|
+
alias_method :g, :grams
|
63
|
+
|
64
|
+
def pounds(options={})
|
65
|
+
ounces(options) / 16.0
|
66
|
+
end
|
67
|
+
alias_method :lb, :pounds
|
68
|
+
alias_method :lbs, :pounds
|
69
|
+
|
70
|
+
def kilograms(options={})
|
71
|
+
grams(options) / 1000.0
|
72
|
+
end
|
73
|
+
alias_method :kg, :kilograms
|
74
|
+
alias_method :kgs, :kilograms
|
75
|
+
|
76
|
+
def inches(measurement=nil)
|
77
|
+
@inches ||= @centimetres.map {|cm| cm * INCHES_IN_A_CM}
|
78
|
+
measurement.nil? ? @inches : measure(measurement, @inches)
|
79
|
+
end
|
80
|
+
alias_method :in, :inches
|
81
|
+
|
82
|
+
def centimetres(measurement=nil)
|
83
|
+
@centimetres ||= @inches.map {|inches| inches * CM_IN_AN_INCH}
|
84
|
+
measurement.nil? ? @centimetres : measure(measurement, @centimetres)
|
85
|
+
end
|
86
|
+
alias_method :cm, :centimetres
|
87
|
+
|
88
|
+
def self.cents_from(money)
|
89
|
+
return nil if money.nil?
|
90
|
+
if money.respond_to?(:cents)
|
91
|
+
return money.cents
|
92
|
+
else
|
93
|
+
return case money
|
94
|
+
when Float
|
95
|
+
(money * 100).to_i
|
96
|
+
when String
|
97
|
+
money =~ /\./ ? (money.to_f * 100).to_i : money.to_i
|
98
|
+
else
|
99
|
+
money.to_i
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def measure(measurement, ary)
|
108
|
+
case measurement
|
109
|
+
when Fixnum: ary[measurement]
|
110
|
+
when *[:x,:max,:length,:long]: ary[2]
|
111
|
+
when *[:y,:mid,:width,:wide]: ary[1]
|
112
|
+
when *[:z,:min,:height,:depth,:high,:deep]: ary[0]
|
113
|
+
when *[:girth,:around,:circumference]
|
114
|
+
self.cylinder? ? (Math::PI * (ary[0] + ary[1]) / 2) : (2 * ary[0]) + (2 * ary[1])
|
115
|
+
when :volume: self.cylinder? ? (Math::PI * (ary[0] + ary[1]) / 4)**2 * ary[2] : measure(:box_volume,ary)
|
116
|
+
when :box_volume: ary[0] * ary[1] * ary[2]
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def process_dimensions(dimensions, imperial_units)
|
121
|
+
units = imperial_units ? 'inches' : 'centimetres'
|
122
|
+
self.instance_variable_set("@#{units}", dimensions.sort)
|
123
|
+
units_array = self.instance_variable_get("@#{units}")
|
124
|
+
# [1,2] => [1,1,2]
|
125
|
+
# [5] => [5,5,5]
|
126
|
+
# etc..
|
127
|
+
2.downto(units_array.length) do |n|
|
128
|
+
units_array.unshift(units_array[0])
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
module AwesomeUsps
|
2
|
+
module ServiceStandard
|
3
|
+
MAX_RETRIES = 3
|
4
|
+
|
5
|
+
LIVE_DOMAIN = 'production.shippingapis.com'
|
6
|
+
LIVE_RESOURCE = '/ShippingAPI.dll'
|
7
|
+
|
8
|
+
TEST_DOMAIN ='testing.shippingapis.com'
|
9
|
+
TEST_RESOURCE = '/ShippingAPITest.dll'
|
10
|
+
|
11
|
+
API_CODES ={
|
12
|
+
:priority_mail => 'PriorityMail',
|
13
|
+
:standard => 'StandardB',
|
14
|
+
:express => 'ExpressMailCommitment'
|
15
|
+
}
|
16
|
+
|
17
|
+
# Takes your package tracking number and returns information for the USPS web API
|
18
|
+
def priority_mail_estimated_time(origin, destination)
|
19
|
+
@origin = orgin
|
20
|
+
@destination=destination
|
21
|
+
request = xml_for_estimated_time_for_delivery("PriorityMailRequest")
|
22
|
+
commit_service_standard_request(:priority_mail, request ,false)
|
23
|
+
end
|
24
|
+
|
25
|
+
def standard_mail_estimated_time(origin, destination)
|
26
|
+
@origin = orgin
|
27
|
+
@destination=destination
|
28
|
+
request = xml_for_estimated_time_for_delivery("StandardBRequest")
|
29
|
+
commit_service_standard_request(:standard, request ,false)
|
30
|
+
end
|
31
|
+
|
32
|
+
def express_mail_commitment(origin, destination, date=nil)
|
33
|
+
@origin = orgin
|
34
|
+
@destination=destination
|
35
|
+
@date = date
|
36
|
+
request = xml_for_estimated_time_for_delivery("ExpressMailCommitmentRequest")
|
37
|
+
commit_service_standard_request(:express, request ,false)
|
38
|
+
end
|
39
|
+
|
40
|
+
def canned_standard_mail_estimated_time_test
|
41
|
+
@origin = Location.new( :zip5 => '4')
|
42
|
+
@destination = Location.new( :zip5 => '4')
|
43
|
+
request = xml_for_estimated_time_for_delivery("PriorityMailRequest")
|
44
|
+
commit_service_standard_request(:priority_mail, request ,true)
|
45
|
+
end
|
46
|
+
|
47
|
+
def canned_priority_mail_estimated_time_test
|
48
|
+
@origin = Location.new( :zip5 => '4')
|
49
|
+
@destination = Location.new( :zip5 => '4')
|
50
|
+
request = xml_for_estimated_time_for_delivery("PriorityMailRequest")
|
51
|
+
commit_service_standard_request(:standard, request ,true)
|
52
|
+
end
|
53
|
+
|
54
|
+
def canned_express_mail_commitment_test
|
55
|
+
@origin= Location.new( :zip5 =>'20770')
|
56
|
+
@destination=Location.new( :zip5 =>'11210')
|
57
|
+
@date = '05-Aug-2004'
|
58
|
+
request = xml_for_estimated_time_for_delivery("ExpressMailCommitmentRequest")
|
59
|
+
commit_service_standard_request(:express, request ,true)
|
60
|
+
end
|
61
|
+
|
62
|
+
# XML from a straight string.
|
63
|
+
# "<TrackFieldRequest USERID='#{@username}'><TrackID ID='#{@tracking_number}'></TrackID></TrackFieldRequest>"
|
64
|
+
def xml_for_estimated_time_for_delivery(type_of_request)
|
65
|
+
xm = Builder::XmlMarkup.new
|
66
|
+
xm.tag!(type_of_request, "USERID"=>"#{@username}") do
|
67
|
+
xm.OriginZIP(@origin.zip5)
|
68
|
+
xm.DestinationZIP(@destination.zip5)
|
69
|
+
xm.Date(@date) if type_of_request == "ExpressMailCommitmentRequest"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Parses the XML into an array broken up by each event.
|
74
|
+
# Example of returned array
|
75
|
+
def parse_service(xml)
|
76
|
+
event_list = []
|
77
|
+
parse = Hpricot.parse(xml)/:error
|
78
|
+
if parse != []
|
79
|
+
RAILS_DEFAULT_LOGGER.info "#{xml}"
|
80
|
+
return (Hpricot.parse(xml)/:description).inner_html
|
81
|
+
else
|
82
|
+
return parse = (Hpricot.parse(xml)/:days).inner_html
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def parse_express(xml)
|
87
|
+
parse = Hpricot.parse(xml)/:error
|
88
|
+
if parse != []
|
89
|
+
RAILS_DEFAULT_LOGGER.info "#{xml}"
|
90
|
+
return (Hpricot.parse(xml)/:description).inner_html
|
91
|
+
else
|
92
|
+
i= 0
|
93
|
+
location_list = []
|
94
|
+
(Hpricot.parse(xml)/:location).each do |location|
|
95
|
+
i+=1
|
96
|
+
h = {}
|
97
|
+
location.children.each {|elem| h[elem.name.to_sym] = elem.inner_text unless elem.inner_text.blank?}
|
98
|
+
location_list << h
|
99
|
+
end
|
100
|
+
return location_list
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
private
|
105
|
+
def commit_service_standard_request(action, request, test = false)
|
106
|
+
retries = MAX_RETRIES
|
107
|
+
begin
|
108
|
+
url = URI.parse(test ? "http://#{TEST_DOMAIN}#{TEST_RESOURCE}" : "http://#{LIVE_DOMAIN}#{LIVE_RESOURCE}")
|
109
|
+
req = Net::HTTP::Post.new(url.path)
|
110
|
+
req.set_form_data({'API' => API_CODES[action], 'XML' => request})
|
111
|
+
response = Net::HTTP.new(url.host, url.port)
|
112
|
+
response.open_timeout = 5
|
113
|
+
response.read_timeout = 5
|
114
|
+
response.start
|
115
|
+
rescue Timeout::Error
|
116
|
+
if retries > 0
|
117
|
+
retries -= 1
|
118
|
+
retry
|
119
|
+
else
|
120
|
+
RAILS_DEFAULT_LOGGER.warn "The connection to the remote server timed out"
|
121
|
+
return "We appoligize for the inconvience but our USPS service is busy at the moment. To retry please refresh the browser"
|
122
|
+
|
123
|
+
end
|
124
|
+
rescue SocketError
|
125
|
+
RAILS_DEFAULT_LOGGER.error "There is a socket error with USPS plugin"
|
126
|
+
return "We appoligize for the inconvience but there is a problem with our server. To retry please refresh the browser"
|
127
|
+
end
|
128
|
+
|
129
|
+
response = response.request(req)
|
130
|
+
case response
|
131
|
+
when Net::HTTPSuccess
|
132
|
+
if action == :express
|
133
|
+
parse_express(response.body)
|
134
|
+
else
|
135
|
+
parse_service(response.body)
|
136
|
+
end
|
137
|
+
else
|
138
|
+
RAILS_DEFAULT_LOGGER.warn("USPS plugin settings are wrong #{response}")
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
end
|