usps-ruby-client 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitattributes +2 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.rubocop.yml +41 -0
- data/.rubocop_todo.yml +0 -0
- data/.travis.yml +6 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +21 -0
- data/README.md +77 -0
- data/Rakefile +9 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/data/api/address-information-api.htm +8229 -0
- data/lib/data/api/domestic-mail-service-standards-api.htm +11016 -0
- data/lib/data/api/evs-international-label-api.htm +33291 -0
- data/lib/data/api/evs-label-api.htm +18895 -0
- data/lib/data/api/hold-for-pickup-facilities-lookup-api.htm +5530 -0
- data/lib/data/api/package-pickup-api.htm +19157 -0
- data/lib/data/api/rate-calculator-api.htm +16355 -0
- data/lib/data/api/scan-api.htm +5934 -0
- data/lib/data/api/service-delivery-calculator-get-locations-api.htm +12548 -0
- data/lib/data/api/track-and-confirm-api.htm +21288 -0
- data/lib/data/api/uspsreturnslabel-api.htm +9474 -0
- data/lib/helpers/erubis_helper.rb +10 -0
- data/lib/tasks/api.rake +246 -0
- data/lib/usps-ruby-client.rb +30 -0
- data/lib/usps/api/endpoints.rb +70 -0
- data/lib/usps/api/endpoints/carrier_pickup_schedule.rb +117 -0
- data/lib/usps/api/endpoints/city_state_lookup.rb +50 -0
- data/lib/usps/api/endpoints/e_vs_express_mail_intl.rb +359 -0
- data/lib/usps/api/endpoints/e_vs_first_class_mail_intl.rb +323 -0
- data/lib/usps/api/endpoints/e_vs_priority_mail_intl.rb +366 -0
- data/lib/usps/api/endpoints/e_vsgxg_get_label.rb +366 -0
- data/lib/usps/api/endpoints/e_vsi_cancel.rb +55 -0
- data/lib/usps/api/endpoints/hfp_facility_info.rb +71 -0
- data/lib/usps/api/endpoints/intl_rate_v2.rb +135 -0
- data/lib/usps/api/endpoints/pts_email.rb +73 -0
- data/lib/usps/api/endpoints/pts_pod.rb +86 -0
- data/lib/usps/api/endpoints/pts_rre.rb +72 -0
- data/lib/usps/api/endpoints/ptst_pod.rb +75 -0
- data/lib/usps/api/endpoints/rate_v4.rb +140 -0
- data/lib/usps/api/endpoints/scan.rb +121 -0
- data/lib/usps/api/endpoints/track_v2.rb +62 -0
- data/lib/usps/api/endpoints/usps_returns_label.rb +149 -0
- data/lib/usps/api/endpoints/verify.rb +75 -0
- data/lib/usps/api/endpoints/zip_code_lookup.rb +69 -0
- data/lib/usps/api/error.rb +6 -0
- data/lib/usps/api/errors/too_many_requests_error.rb +22 -0
- data/lib/usps/api/errors/usps_error.rb +30 -0
- data/lib/usps/api/templates/_build_xml.erb +7 -0
- data/lib/usps/api/templates/_options.erb +6 -0
- data/lib/usps/api/templates/_throw_argument_error.erb +3 -0
- data/lib/usps/api/templates/endpoints.erb +22 -0
- data/lib/usps/api/templates/method.erb +49 -0
- data/lib/usps/api/templates/method_spec.erb +22 -0
- data/lib/usps/api/xml.rb +8 -0
- data/lib/usps/client.rb +37 -0
- data/lib/usps/config.rb +50 -0
- data/lib/usps/faraday/connection.rb +34 -0
- data/lib/usps/faraday/request.rb +39 -0
- data/lib/usps/faraday/response/raise_error.rb +16 -0
- data/lib/usps/logger.rb +14 -0
- data/lib/usps/version.rb +4 -0
- data/usps-ruby-client.gemspec +46 -0
- metadata +307 -0
data/lib/tasks/api.rake
ADDED
@@ -0,0 +1,246 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'amazing_print'
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'erubis'
|
5
|
+
require 'active_support'
|
6
|
+
require 'active_support/core_ext'
|
7
|
+
require 'pry'
|
8
|
+
require 'helpers/erubis_helper'
|
9
|
+
|
10
|
+
namespace :usps do
|
11
|
+
namespace :api do
|
12
|
+
task :update do
|
13
|
+
def dig_set(obj, keys, value)
|
14
|
+
key = keys.first
|
15
|
+
if keys.length == 1
|
16
|
+
obj[key] = value
|
17
|
+
else
|
18
|
+
obj[key] = {} unless obj[key]
|
19
|
+
dig_set(obj[key], keys.slice(1..-1), value)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def table_array_to_hash_array(columns, rows)
|
24
|
+
rows.map do |row|
|
25
|
+
row_data = {}
|
26
|
+
columns.each_with_index do |k, i|
|
27
|
+
row_data[k.to_s.gsub(/[[:space:]]+/, ' ').strip] =
|
28
|
+
row[i].is_a? String ? row[i].to_s.gsub(/[[:space:]]+/, ' ').strip : row[i]
|
29
|
+
end
|
30
|
+
row_data
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def standardize_table_hash_array(arr)
|
35
|
+
arr.map do |option|
|
36
|
+
next if option['Tag Name'].split('/').pop.strip.casecmp('userid').zero?
|
37
|
+
|
38
|
+
{
|
39
|
+
type: option['Type'],
|
40
|
+
name: option['Tag Name'].split('/').pop.strip,
|
41
|
+
required: option['Occurs'] == 'Required',
|
42
|
+
description: option['Description'],
|
43
|
+
}
|
44
|
+
end.compact
|
45
|
+
end
|
46
|
+
|
47
|
+
def table_hash_array_to_shape(arr)
|
48
|
+
shape = {}
|
49
|
+
|
50
|
+
nesting = []
|
51
|
+
arr[0][:type] = '(Alias)' unless arr[0][:type].casecmp('(alias)').zero?
|
52
|
+
arr.each do |tag|
|
53
|
+
if tag[:type].casecmp('(alias)').zero?
|
54
|
+
if nesting.last == tag[:name]
|
55
|
+
nesting.pop
|
56
|
+
else
|
57
|
+
nesting.push(tag[:name])
|
58
|
+
dig_set(shape, nesting, tag.merge(children: {}))
|
59
|
+
end
|
60
|
+
elsif tag[:type].casecmp('(group)').zero?
|
61
|
+
if nesting.last == tag[:name]
|
62
|
+
nesting.pop(2)
|
63
|
+
else
|
64
|
+
nesting.push(:children)
|
65
|
+
nesting.push(tag[:name])
|
66
|
+
dig_set(shape, nesting, tag.merge(children: {}))
|
67
|
+
end
|
68
|
+
elsif nesting.length.positive?
|
69
|
+
nesting_with_children = nesting + [:children]
|
70
|
+
dig_set(shape, nesting_with_children,
|
71
|
+
shape.dig(*nesting_with_children).merge({ tag[:name] => tag.merge(children: {}) }))
|
72
|
+
else
|
73
|
+
shape[tag[:name]] = tag
|
74
|
+
end
|
75
|
+
end
|
76
|
+
shape
|
77
|
+
end
|
78
|
+
|
79
|
+
def pp_xml(xml = '')
|
80
|
+
doc = Nokogiri.XML(xml) do |config|
|
81
|
+
config.default_xml.noblanks
|
82
|
+
end
|
83
|
+
doc.to_xml(indent: 2)
|
84
|
+
end
|
85
|
+
|
86
|
+
@failed_methods = []
|
87
|
+
|
88
|
+
@endpoint_files = []
|
89
|
+
|
90
|
+
def parse_doc(path)
|
91
|
+
doc = Nokogiri::HTML(File.open(path))
|
92
|
+
|
93
|
+
table_of_contents = {}
|
94
|
+
raw_table_of_contents = doc.search('sdt[docparttype="Table of Contents"] p a').map do |link|
|
95
|
+
full_title = link.content.tr("\n", ' ')
|
96
|
+
next if full_title.blank?
|
97
|
+
|
98
|
+
full_version = full_title.match(/^[\d.]+/)[0]
|
99
|
+
major, minor, tiny = full_version.split('.')
|
100
|
+
|
101
|
+
title = full_title.match(/\s+[A-Za-z\s\t.:]*\s+/)[0].gsub(/[[:space:]]+/,
|
102
|
+
' ').strip.chomp('.')
|
103
|
+
|
104
|
+
data = {
|
105
|
+
# full_title: full_title,
|
106
|
+
# link: link['href'],
|
107
|
+
anchor: link['href'].split('#')[1],
|
108
|
+
version: full_version,
|
109
|
+
major: major,
|
110
|
+
minor: minor,
|
111
|
+
tiny: tiny,
|
112
|
+
title: title,
|
113
|
+
}
|
114
|
+
|
115
|
+
table_of_contents[major] ||= []
|
116
|
+
table_of_contents[major] << data
|
117
|
+
|
118
|
+
data
|
119
|
+
end
|
120
|
+
|
121
|
+
data = table_of_contents.map do |section_number, section|
|
122
|
+
section_data = {}
|
123
|
+
section.each do |subsection|
|
124
|
+
header_node = doc.search("a[name=#{subsection[:anchor]}]")[0].parent
|
125
|
+
header_node = header_node.next_element if header_node.content.blank? && header_node.next_element
|
126
|
+
|
127
|
+
content_node = if header_node.next_element && header_node.next_element.content.present?
|
128
|
+
header_node.next_element
|
129
|
+
elsif header_node.parent.next_element && header_node.parent.next_element.content.present?
|
130
|
+
header_node.parent.next_element
|
131
|
+
else
|
132
|
+
header_node.parent.parent.next_element
|
133
|
+
end
|
134
|
+
next unless content_node # For section 1
|
135
|
+
|
136
|
+
section_data[:link] = subsection[:link]
|
137
|
+
|
138
|
+
if subsection[:version] == "#{section_number}.0"
|
139
|
+
section_data[:title] = subsection[:title]
|
140
|
+
elsif subsection[:title] == 'Overview'
|
141
|
+
section_data[:description] = content_node.content.tr("\n", ' ')
|
142
|
+
elsif subsection[:title] == 'API Signature'
|
143
|
+
columns, *rows = content_node.search('tr').map do |tr|
|
144
|
+
tr.search('td').map do |td|
|
145
|
+
td.content.gsub(/\n\s/, '').strip
|
146
|
+
end
|
147
|
+
end
|
148
|
+
section_data[:signature] = table_array_to_hash_array(columns, rows)
|
149
|
+
section_data[:url] =
|
150
|
+
"#{section_data[:signature][0]['Scheme']}#{section_data[:signature][0]['Host']}#{section_data[:signature][0]['Path'].chomp('?')}"
|
151
|
+
section_data[:group] =
|
152
|
+
section_data[:signature][0]['API'].sub('API=', '').gsub(/[[:space:]]+/,
|
153
|
+
' ').strip
|
154
|
+
# ap section_data[:signature]
|
155
|
+
# ap section_data[:signature].map{|s| s[]}
|
156
|
+
# elsif subsection[:title] == "Request Descriptions"
|
157
|
+
# columns, *rows = content_node.search('tr').map{|tr| tr.search('td').map{|td| td.content.gsub(/\n\s/, '').strip}}
|
158
|
+
# section_data[:request_descriptions] = table_hash_array_to_shape(standardize_table_hash_array(table_array_to_hash_array(columns, rows)))
|
159
|
+
elsif subsection[:title] == 'Sample Request'
|
160
|
+
title, xml = content_node.content.gsub(/[[:space:]]+/, ' ').strip.split('<', 2)
|
161
|
+
xml = pp_xml("<#{xml}")
|
162
|
+
section_data[:sample_request] = <<~XML
|
163
|
+
#{title}
|
164
|
+
#{xml}
|
165
|
+
XML
|
166
|
+
elsif subsection[:title] == 'Response Descriptions' || subsection[:title] == 'Request Descriptions'
|
167
|
+
columns, *rows = content_node.search('tr').map do |tr|
|
168
|
+
next if tr.ancestors('table').length > 1
|
169
|
+
|
170
|
+
tr.search('td').map do |td|
|
171
|
+
has_table = td.search('table').length.positive?
|
172
|
+
if !has_table
|
173
|
+
td.content.gsub(/\n\s/, '').strip
|
174
|
+
else
|
175
|
+
table = td.search('table')[0]
|
176
|
+
c, *r = table.search('tr').map do |tr|
|
177
|
+
tr.search('td').map do |td|
|
178
|
+
td.content.gsub(/\n\s/, '').strip
|
179
|
+
end
|
180
|
+
end
|
181
|
+
table_array_to_hash_array(c, r)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end.compact
|
185
|
+
binding.pry if rows.blank?
|
186
|
+
section_data[subsection[:title].downcase.gsub(/\s+/, '_').to_sym] =
|
187
|
+
table_hash_array_to_shape(standardize_table_hash_array(table_array_to_hash_array(
|
188
|
+
columns, rows
|
189
|
+
)))
|
190
|
+
elsif subsection[:title] == 'Sample Response'
|
191
|
+
title, xml = content_node.content.gsub(/[[:space:]]+/, ' ').strip.split('<', 2)
|
192
|
+
xml = pp_xml("<#{xml}")
|
193
|
+
section_data[:sample_response] = <<~XML
|
194
|
+
#{title}
|
195
|
+
#{xml}
|
196
|
+
XML
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
section_data
|
201
|
+
end
|
202
|
+
|
203
|
+
method_template = Erubis::Eruby.new(File.read('lib/usps/api/templates/method.erb'))
|
204
|
+
method_spec_template = Erubis::Eruby.new(File.read('lib/usps/api/templates/method_spec.erb'))
|
205
|
+
data.each do |api|
|
206
|
+
next if api[:group].nil? || api[:group].empty?
|
207
|
+
|
208
|
+
# begin
|
209
|
+
rendered_method = method_template.result(group: api[:group], data: api)
|
210
|
+
File.write("lib/usps/api/endpoints/#{api[:group].underscore}.rb", rendered_method)
|
211
|
+
|
212
|
+
rendered_method_spec = method_spec_template.result(group: api[:group], data: api)
|
213
|
+
File.write("spec/usps/api/endpoints/#{api[:group].underscore}_spec.rb",
|
214
|
+
rendered_method_spec)
|
215
|
+
|
216
|
+
@endpoint_files << {
|
217
|
+
file: api[:group].underscore,
|
218
|
+
module: api[:group].camelize,
|
219
|
+
}
|
220
|
+
# rescue => e
|
221
|
+
# @failed_methods << {
|
222
|
+
# file: path,
|
223
|
+
# api: api[:group],
|
224
|
+
# }
|
225
|
+
# end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
failed_docs = []
|
230
|
+
Dir.glob('lib/data/api/*.htm').each do |f|
|
231
|
+
ap f
|
232
|
+
# begin
|
233
|
+
parse_doc(f)
|
234
|
+
# rescue => e
|
235
|
+
# failed_docs << f
|
236
|
+
# end
|
237
|
+
end
|
238
|
+
|
239
|
+
endpoints_template = Erubis::Eruby.new(File.read('lib/usps/api/templates/endpoints.erb'))
|
240
|
+
File.write(
|
241
|
+
'lib/usps/api/endpoints.rb',
|
242
|
+
endpoints_template.result(files: @endpoint_files.sort_by { |f| f[:file] })
|
243
|
+
)
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'usps/version'
|
3
|
+
require 'usps/logger'
|
4
|
+
require 'usps/config'
|
5
|
+
|
6
|
+
require 'active_support'
|
7
|
+
require 'active_support/core_ext'
|
8
|
+
require 'builder'
|
9
|
+
require 'faraday'
|
10
|
+
require 'faraday_middleware'
|
11
|
+
require 'json'
|
12
|
+
require 'logger'
|
13
|
+
|
14
|
+
require_relative 'usps/api/errors/usps_error'
|
15
|
+
require_relative 'usps/api/errors/too_many_requests_error'
|
16
|
+
# require_relative 'usps/api/error'
|
17
|
+
# require_relative 'usps/api/errors'
|
18
|
+
require_relative 'usps/faraday/response/raise_error'
|
19
|
+
require_relative 'usps/faraday/connection'
|
20
|
+
require_relative 'usps/faraday/request'
|
21
|
+
# require_relative 'usps/api/mixins'
|
22
|
+
require_relative 'usps/api/xml'
|
23
|
+
require_relative 'usps/api/endpoints'
|
24
|
+
# require_relative 'usps/pagination/cursor'
|
25
|
+
require_relative 'usps/client'
|
26
|
+
|
27
|
+
# module Usps
|
28
|
+
# class Error < StandardError; end
|
29
|
+
# # Your code goes here...
|
30
|
+
# end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# This file was auto-generated by lib/tasks/web.rake
|
3
|
+
|
4
|
+
require_relative 'endpoints/carrier_pickup_schedule'
|
5
|
+
require_relative 'endpoints/city_state_lookup'
|
6
|
+
require_relative 'endpoints/e_vs_express_mail_intl'
|
7
|
+
require_relative 'endpoints/e_vs_first_class_mail_intl'
|
8
|
+
require_relative 'endpoints/e_vs_priority_mail_intl'
|
9
|
+
require_relative 'endpoints/e_vsgxg_get_label'
|
10
|
+
require_relative 'endpoints/e_vsi_cancel'
|
11
|
+
require_relative 'endpoints/hfp_facility_info'
|
12
|
+
require_relative 'endpoints/intl_rate_v2'
|
13
|
+
require_relative 'endpoints/pts_email'
|
14
|
+
require_relative 'endpoints/pts_pod'
|
15
|
+
require_relative 'endpoints/pts_rre'
|
16
|
+
require_relative 'endpoints/ptst_pod'
|
17
|
+
require_relative 'endpoints/rate_v4'
|
18
|
+
require_relative 'endpoints/scan'
|
19
|
+
require_relative 'endpoints/track_v2'
|
20
|
+
require_relative 'endpoints/usps_returns_label'
|
21
|
+
require_relative 'endpoints/verify'
|
22
|
+
require_relative 'endpoints/zip_code_lookup'
|
23
|
+
|
24
|
+
module Usps
|
25
|
+
module Api
|
26
|
+
module Endpoints
|
27
|
+
include CarrierPickupSchedule
|
28
|
+
include CityStateLookup
|
29
|
+
include EVSExpressMailIntl
|
30
|
+
include EVSFirstClassMailIntl
|
31
|
+
include EVSPriorityMailIntl
|
32
|
+
include EVSGXGGetLabel
|
33
|
+
include EVSICancel
|
34
|
+
include HFPFacilityInfo
|
35
|
+
include IntlRateV2
|
36
|
+
include PTSEmail
|
37
|
+
include PTSPod
|
38
|
+
include PTSRre
|
39
|
+
include PTSTPod
|
40
|
+
include RateV4
|
41
|
+
include SCAN
|
42
|
+
include TrackV2
|
43
|
+
include USPSReturnsLabel
|
44
|
+
include Verify
|
45
|
+
include ZipCodeLookup
|
46
|
+
|
47
|
+
ACTIONS = {
|
48
|
+
carrier_pickup_schedule: 'CarrierPickupSchedule',
|
49
|
+
city_state_lookup: 'CityStateLookup',
|
50
|
+
e_vs_express_mail_intl: 'EVSExpressMailIntl',
|
51
|
+
e_vs_first_class_mail_intl: 'EVSFirstClassMailIntl',
|
52
|
+
e_vs_priority_mail_intl: 'EVSPriorityMailIntl',
|
53
|
+
e_vsgxg_get_label: 'EVSGXGGetLabel',
|
54
|
+
e_vsi_cancel: 'EVSICancel',
|
55
|
+
hfp_facility_info: 'HFPFacilityInfo',
|
56
|
+
intl_rate_v2: 'IntlRateV2',
|
57
|
+
pts_email: 'PTSEmail',
|
58
|
+
pts_pod: 'PTSPod',
|
59
|
+
pts_rre: 'PTSRre',
|
60
|
+
ptst_pod: 'PTSTPod',
|
61
|
+
rate_v4: 'RateV4',
|
62
|
+
scan: 'SCAN',
|
63
|
+
track_v2: 'TrackV2',
|
64
|
+
usps_returns_label: 'USPSReturnsLabel',
|
65
|
+
verify: 'Verify',
|
66
|
+
zip_code_lookup: 'ZipCodeLookup',
|
67
|
+
}.freeze
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This file was auto-generated by lib/tasks/api.rake
|
4
|
+
|
5
|
+
module Usps
|
6
|
+
module Api
|
7
|
+
module Endpoints
|
8
|
+
module CarrierPickupSchedule
|
9
|
+
#
|
10
|
+
# Package Pickup Schedule API
|
11
|
+
#
|
12
|
+
# The Package Pickup Schedule API schedules a
|
13
|
+
# Package Pickup and provides the user a confirmation number for the scheduled
|
14
|
+
# pickup. Prior to making a Pickup Schedule call, it is recommended to use
|
15
|
+
# the Pickup Availability API to confirm that service is available.
|
16
|
+
#
|
17
|
+
# @option option [(Alias)] :CarrierPickupScheduleRequest (Required)
|
18
|
+
# @option option [String] :FirstName (Required)
|
19
|
+
# - Only alpha characters, apostrophes, spaces, periods, and hyphens "-" may be used. For example: <FirstName>John</FirstName>
|
20
|
+
# @option option [String] :LastName (Required)
|
21
|
+
# - Only alpha characters, apostrophes, spaces, periods and hyphens "-" may be used. For example: <LastName>Doe</LastName>
|
22
|
+
# @option option [String] :FirmName (Optional)
|
23
|
+
# - Only alpha and numeric characters, apostrophes, spaces, hyphens "-" and ampersands "&" may be used. Use this tag for a firm or company name. Some firms/companies that have their own ZIP codes require the use of firm name to properly identify their address. Note: FirmName is Optional except if the First Name and Last Name tags are null. For example: <FirmName>ABC Company</FirmName>
|
24
|
+
# @option option [String] :SuiteOrApt (Required)
|
25
|
+
# - Apartment or suite number. Optional except if needed to uniquely identify an address at a multiple dwelling address, for example, an apartment building. For example: <SuiteOrApt>Suite 777</SuiteOrApt>
|
26
|
+
# @option option [String] :Address2 (Required)
|
27
|
+
# - Street address. For example: <Address2>1390 Market Street</Address2>
|
28
|
+
# @option option [String] :Urbanization (Required)
|
29
|
+
# - Use this tag for Urbanization (for Puerto Rico only). ZIP Code prefixes 006 to 009, if area is so designated.
|
30
|
+
# @option option [String] :City (Required)
|
31
|
+
# - City name. Either ZIP5 or City and State are required. For example: <City>Houston</City>
|
32
|
+
# @option option [String] :State (Required)
|
33
|
+
# - State abbreviation. Either ZIP5 or City and State are required. For example: <State>TX</State>
|
34
|
+
# @option option [String] :ZIP5 (Required)
|
35
|
+
# - 5-digit ZIP Code. Either ZIP5 or City and State are required. For example: <ZIP5>77058</ZIP5>
|
36
|
+
# @option option [String] :ZIP4 (Required)
|
37
|
+
# - Use this tag for a 4 digit ZIP Code. For example: <ZIP4>1234</ZIP4>
|
38
|
+
# @option option [String] :Phone (Required)
|
39
|
+
# - Two formats are allowed: (###) 123-4567 or ###-123-4567. For example: <Phone>5555551234</Phone> or <Phone>555-555-1234</Phone>
|
40
|
+
# @option option [String] :Extension (Optional)
|
41
|
+
# - Optional value for Phone Extension. For example: <Extension>201</Extension>
|
42
|
+
# @option option [(Group)] :Package (Required)
|
43
|
+
# - No values entered with this tag. <ServiceType> and <Count> tags are embedded under this. Refer to the XML request example section, below, to see how these embedded tags are formatted. If the <Count> for a service type is zero, you do not need to encode a <Package> but you must have at least one <Package> with embedded <ServiceType> and <Count> tags.
|
44
|
+
# @option option [String] :ServiceType (Required)
|
45
|
+
# - This tag is embedded under the <Package> tag. If your pickup contains more than one Service Type, use additional <Package> tags for each service type with the accompanying <ServiceType> and <Count> tags. Refer to the XML Request Example below to see how these embedded tags are formatted. For example: <ServiceType>PriorityMailExpress</ServiceType>
|
46
|
+
# @option option [String] :Count (Required)
|
47
|
+
# - This tag is embedded under the <Package> tag. Enter the number of packages for the accompanying <ServiceType> tag. Maximum characters allowed: 3 or 999 packages. If your pickup contains more than one Service Type, use additional <Package> tags for each service type with the accompanying <ServiceType> and <Count> tags. Refer to the XML request example section, below, to see how these embedded tags are formatted. For example: <Count>2</Count>
|
48
|
+
# @option option [String] :EstimatedWeight (Required)
|
49
|
+
# - Enter the estimated aggregate weight (in pounds) of all packages being picked up. For example: <EstimatedWeight>14</EstimatedWeight>
|
50
|
+
# @option option [String] :PackageLocation (Required)
|
51
|
+
# - Enter one of the following values: Note: "Other" requires information in the value for the <SpecialInstructions> tag. For example: <PackageLocation>Front Door</PackageLocation>
|
52
|
+
# @option option [String] :SpecialInstructions (Optional)
|
53
|
+
# - Value Required when PackageLocation is “Other”. Only alpha, numeric, commas, periods, apostrophes, _, &, -, ( ), ?, #, / +, @ and space characters may be used. For example: <SpecialInstructions>Packages are behind the screen door.</SpecialInstructions>
|
54
|
+
# @option option [String] :EmailAddress (Optional)
|
55
|
+
# - If provided, email notifications will be sent confirming package pickup, or request changes and cancellations. Maximum characters allowed: 50. For example: <EmailAddress>cpapple@email.com</EmailAddress>
|
56
|
+
|
57
|
+
#
|
58
|
+
# @see
|
59
|
+
def carrier_pickup_schedule(options = {})
|
60
|
+
throw ArgumentError.new('Required arguments :carrier_pickup_schedule_request missing') if options[:carrier_pickup_schedule_request].nil?
|
61
|
+
throw ArgumentError.new('Required arguments :carrier_pickup_schedule_request, :first_name missing') if options[:carrier_pickup_schedule_request][:first_name].nil?
|
62
|
+
throw ArgumentError.new('Required arguments :carrier_pickup_schedule_request, :last_name missing') if options[:carrier_pickup_schedule_request][:last_name].nil?
|
63
|
+
throw ArgumentError.new('Required arguments :carrier_pickup_schedule_request, :suite_or_apt missing') if options[:carrier_pickup_schedule_request][:suite_or_apt].nil?
|
64
|
+
throw ArgumentError.new('Required arguments :carrier_pickup_schedule_request, :address2 missing') if options[:carrier_pickup_schedule_request][:address2].nil?
|
65
|
+
throw ArgumentError.new('Required arguments :carrier_pickup_schedule_request, :urbanization missing') if options[:carrier_pickup_schedule_request][:urbanization].nil?
|
66
|
+
throw ArgumentError.new('Required arguments :carrier_pickup_schedule_request, :city missing') if options[:carrier_pickup_schedule_request][:city].nil?
|
67
|
+
throw ArgumentError.new('Required arguments :carrier_pickup_schedule_request, :state missing') if options[:carrier_pickup_schedule_request][:state].nil?
|
68
|
+
throw ArgumentError.new('Required arguments :carrier_pickup_schedule_request, :zip5 missing') if options[:carrier_pickup_schedule_request][:zip5].nil?
|
69
|
+
throw ArgumentError.new('Required arguments :carrier_pickup_schedule_request, :zip4 missing') if options[:carrier_pickup_schedule_request][:zip4].nil?
|
70
|
+
throw ArgumentError.new('Required arguments :carrier_pickup_schedule_request, :phone missing') if options[:carrier_pickup_schedule_request][:phone].nil?
|
71
|
+
throw ArgumentError.new('Required arguments :carrier_pickup_schedule_request, :package missing') if options[:carrier_pickup_schedule_request][:package].nil?
|
72
|
+
throw ArgumentError.new('Required arguments :carrier_pickup_schedule_request, :package, :service_type missing') if options[:carrier_pickup_schedule_request][:package][:service_type].nil?
|
73
|
+
throw ArgumentError.new('Required arguments :carrier_pickup_schedule_request, :package, :count missing') if options[:carrier_pickup_schedule_request][:package][:count].nil?
|
74
|
+
throw ArgumentError.new('Required arguments :carrier_pickup_schedule_request, :package, :estimated_weight missing') if options[:carrier_pickup_schedule_request][:package][:estimated_weight].nil?
|
75
|
+
throw ArgumentError.new('Required arguments :carrier_pickup_schedule_request, :package, :package_location missing') if options[:carrier_pickup_schedule_request][:package][:package_location].nil?
|
76
|
+
|
77
|
+
request = build_request(:carrier_pickup_schedule, options)
|
78
|
+
get('https://secure.shippingapis.com/ShippingAPI.dll', {
|
79
|
+
API: 'CarrierPickupSchedule',
|
80
|
+
XML: request,
|
81
|
+
})
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def tag_unless_blank(xml, tag_name, data)
|
87
|
+
xml.tag!(tag_name, data) unless data.blank? || data.nil?
|
88
|
+
end
|
89
|
+
|
90
|
+
def build_carrier_pickup_schedule_request(xml, options = {})
|
91
|
+
xml.tag!('FirstName', options[:carrier_pickup_schedule_request][:first_name])
|
92
|
+
xml.tag!('LastName', options[:carrier_pickup_schedule_request][:last_name])
|
93
|
+
tag_unless_blank(xml, 'FirmName', options[:carrier_pickup_schedule_request][:firm_name])
|
94
|
+
xml.tag!('SuiteOrApt', options[:carrier_pickup_schedule_request][:suite_or_apt])
|
95
|
+
xml.tag!('Address2', options[:carrier_pickup_schedule_request][:address2])
|
96
|
+
xml.tag!('Urbanization', options[:carrier_pickup_schedule_request][:urbanization])
|
97
|
+
xml.tag!('City', options[:carrier_pickup_schedule_request][:city])
|
98
|
+
xml.tag!('State', options[:carrier_pickup_schedule_request][:state])
|
99
|
+
xml.tag!('ZIP5', options[:carrier_pickup_schedule_request][:zip5])
|
100
|
+
xml.tag!('ZIP4', options[:carrier_pickup_schedule_request][:zip4])
|
101
|
+
xml.tag!('Phone', options[:carrier_pickup_schedule_request][:phone])
|
102
|
+
tag_unless_blank(xml, 'Extension', options[:carrier_pickup_schedule_request][:extension])
|
103
|
+
xml.tag!('Package') do
|
104
|
+
xml.tag!('ServiceType', options[:carrier_pickup_schedule_request][:package][:service_type])
|
105
|
+
xml.tag!('Count', options[:carrier_pickup_schedule_request][:package][:count])
|
106
|
+
xml.tag!('EstimatedWeight', options[:carrier_pickup_schedule_request][:package][:estimated_weight])
|
107
|
+
xml.tag!('PackageLocation', options[:carrier_pickup_schedule_request][:package][:package_location])
|
108
|
+
tag_unless_blank(xml, 'SpecialInstructions', options[:carrier_pickup_schedule_request][:package][:special_instructions])
|
109
|
+
tag_unless_blank(xml, 'EmailAddress', options[:carrier_pickup_schedule_request][:package][:email_address])
|
110
|
+
end
|
111
|
+
xml.target!
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|