active_shipping 0.12.6 → 1.0.0.pre1
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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +2 -0
- data.tar.gz.sig +0 -0
- data/{CHANGELOG → CHANGELOG.md} +6 -2
- data/CONTRIBUTING.md +32 -0
- data/{README.markdown → README.md} +45 -61
- data/lib/active_shipping.rb +20 -28
- data/lib/active_shipping/carrier.rb +82 -0
- data/lib/active_shipping/carriers.rb +33 -0
- data/lib/active_shipping/carriers/benchmark_carrier.rb +31 -0
- data/lib/active_shipping/carriers/bogus_carrier.rb +12 -0
- data/lib/active_shipping/carriers/canada_post.rb +253 -0
- data/lib/active_shipping/carriers/canada_post_pws.rb +870 -0
- data/lib/active_shipping/carriers/fedex.rb +579 -0
- data/lib/active_shipping/carriers/kunaki.rb +164 -0
- data/lib/active_shipping/carriers/new_zealand_post.rb +262 -0
- data/lib/active_shipping/carriers/shipwire.rb +181 -0
- data/lib/active_shipping/carriers/stamps.rb +861 -0
- data/lib/active_shipping/carriers/ups.rb +648 -0
- data/lib/active_shipping/carriers/usps.rb +642 -0
- data/lib/active_shipping/errors.rb +7 -0
- data/lib/active_shipping/label_response.rb +23 -0
- data/lib/active_shipping/location.rb +149 -0
- data/lib/active_shipping/package.rb +241 -0
- data/lib/active_shipping/rate_estimate.rb +64 -0
- data/lib/active_shipping/rate_response.rb +13 -0
- data/lib/active_shipping/response.rb +41 -0
- data/lib/active_shipping/shipment_event.rb +17 -0
- data/lib/active_shipping/shipment_packer.rb +73 -0
- data/lib/active_shipping/shipping_response.rb +12 -0
- data/lib/active_shipping/tracking_response.rb +52 -0
- data/lib/active_shipping/version.rb +1 -1
- data/lib/vendor/quantified/test/length_test.rb +2 -2
- data/lib/vendor/xml_node/test/test_parsing.rb +1 -1
- metadata +58 -36
- metadata.gz.sig +0 -0
- data/lib/active_shipping/shipping/base.rb +0 -13
- data/lib/active_shipping/shipping/carrier.rb +0 -84
- data/lib/active_shipping/shipping/carriers.rb +0 -23
- data/lib/active_shipping/shipping/carriers/benchmark_carrier.rb +0 -33
- data/lib/active_shipping/shipping/carriers/bogus_carrier.rb +0 -14
- data/lib/active_shipping/shipping/carriers/canada_post.rb +0 -257
- data/lib/active_shipping/shipping/carriers/canada_post_pws.rb +0 -874
- data/lib/active_shipping/shipping/carriers/fedex.rb +0 -581
- data/lib/active_shipping/shipping/carriers/kunaki.rb +0 -166
- data/lib/active_shipping/shipping/carriers/new_zealand_post.rb +0 -262
- data/lib/active_shipping/shipping/carriers/shipwire.rb +0 -184
- data/lib/active_shipping/shipping/carriers/stamps.rb +0 -864
- data/lib/active_shipping/shipping/carriers/ups.rb +0 -650
- data/lib/active_shipping/shipping/carriers/usps.rb +0 -649
- data/lib/active_shipping/shipping/errors.rb +0 -9
- data/lib/active_shipping/shipping/label_response.rb +0 -25
- data/lib/active_shipping/shipping/location.rb +0 -152
- data/lib/active_shipping/shipping/package.rb +0 -243
- data/lib/active_shipping/shipping/rate_estimate.rb +0 -66
- data/lib/active_shipping/shipping/rate_response.rb +0 -15
- data/lib/active_shipping/shipping/response.rb +0 -43
- data/lib/active_shipping/shipping/shipment_event.rb +0 -19
- data/lib/active_shipping/shipping/shipment_packer.rb +0 -75
- data/lib/active_shipping/shipping/shipping_response.rb +0 -14
- data/lib/active_shipping/shipping/tracking_response.rb +0 -54
@@ -1,166 +0,0 @@
|
|
1
|
-
require 'builder'
|
2
|
-
|
3
|
-
module ActiveMerchant
|
4
|
-
module Shipping
|
5
|
-
class Kunaki < Carrier
|
6
|
-
self.retry_safe = true
|
7
|
-
|
8
|
-
cattr_reader :name
|
9
|
-
@@name = "Kunaki"
|
10
|
-
|
11
|
-
URL = 'https://Kunaki.com/XMLService.ASP'
|
12
|
-
|
13
|
-
CARRIERS = ["UPS", "USPS", "FedEx", "Royal Mail", "Parcelforce", "Pharos", "Eurotrux", "Canada Post", "DHL"]
|
14
|
-
|
15
|
-
COUNTRIES = {
|
16
|
-
'AR' => 'Argentina',
|
17
|
-
'AU' => 'Australia',
|
18
|
-
'AT' => 'Austria',
|
19
|
-
'BE' => 'Belgium',
|
20
|
-
'BR' => 'Brazil',
|
21
|
-
'BG' => 'Bulgaria',
|
22
|
-
'CA' => 'Canada',
|
23
|
-
'CN' => 'China',
|
24
|
-
'CY' => 'Cyprus',
|
25
|
-
'CZ' => 'Czech Republic',
|
26
|
-
'DK' => 'Denmark',
|
27
|
-
'EE' => 'Estonia',
|
28
|
-
'FI' => 'Finland',
|
29
|
-
'FR' => 'France',
|
30
|
-
'DE' => 'Germany',
|
31
|
-
'GI' => 'Gibraltar',
|
32
|
-
'GR' => 'Greece',
|
33
|
-
'GL' => 'Greenland',
|
34
|
-
'HK' => 'Hong Kong',
|
35
|
-
'HU' => 'Hungary',
|
36
|
-
'IS' => 'Iceland',
|
37
|
-
'IE' => 'Ireland',
|
38
|
-
'IL' => 'Israel',
|
39
|
-
'IT' => 'Italy',
|
40
|
-
'JP' => 'Japan',
|
41
|
-
'LV' => 'Latvia',
|
42
|
-
'LI' => 'Liechtenstein',
|
43
|
-
'LT' => 'Lithuania',
|
44
|
-
'LU' => 'Luxembourg',
|
45
|
-
'MX' => 'Mexico',
|
46
|
-
'NL' => 'Netherlands',
|
47
|
-
'NZ' => 'New Zealand',
|
48
|
-
'NO' => 'Norway',
|
49
|
-
'PL' => 'Poland',
|
50
|
-
'PT' => 'Portugal',
|
51
|
-
'RO' => 'Romania',
|
52
|
-
'RU' => 'Russia',
|
53
|
-
'SG' => 'Singapore',
|
54
|
-
'SK' => 'Slovakia',
|
55
|
-
'SI' => 'Slovenia',
|
56
|
-
'ES' => 'Spain',
|
57
|
-
'SE' => 'Sweden',
|
58
|
-
'CH' => 'Switzerland',
|
59
|
-
'TW' => 'Taiwan',
|
60
|
-
'TR' => 'Turkey',
|
61
|
-
'UA' => 'Ukraine',
|
62
|
-
'GB' => 'United Kingdom',
|
63
|
-
'US' => 'United States',
|
64
|
-
'VA' => 'Vatican City',
|
65
|
-
'RS' => 'Yugoslavia',
|
66
|
-
'ME' => 'Yugoslavia'
|
67
|
-
}
|
68
|
-
|
69
|
-
def find_rates(origin, destination, packages, options = {})
|
70
|
-
requires!(options, :items)
|
71
|
-
commit(origin, destination, options)
|
72
|
-
end
|
73
|
-
|
74
|
-
def valid_credentials?
|
75
|
-
true
|
76
|
-
end
|
77
|
-
|
78
|
-
private
|
79
|
-
|
80
|
-
def build_request(destination, options)
|
81
|
-
xml = Builder::XmlMarkup.new
|
82
|
-
xml.instruct!
|
83
|
-
xml.tag! 'ShippingOptions' do
|
84
|
-
xml.tag! 'AddressInfo' do
|
85
|
-
xml.tag! 'Country', COUNTRIES[destination.country_code]
|
86
|
-
|
87
|
-
state = %w(US CA).include?(destination.country_code.to_s) ? destination.state : ''
|
88
|
-
|
89
|
-
xml.tag! 'State_Province', state
|
90
|
-
xml.tag! 'PostalCode', destination.zip
|
91
|
-
end
|
92
|
-
|
93
|
-
options[:items].each do |item|
|
94
|
-
xml.tag! 'Product' do
|
95
|
-
xml.tag! 'ProductId', item[:sku]
|
96
|
-
xml.tag! 'Quantity', item[:quantity]
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
xml.target!
|
101
|
-
end
|
102
|
-
|
103
|
-
def commit(origin, destination, options)
|
104
|
-
request = build_request(destination, options)
|
105
|
-
|
106
|
-
response = parse( ssl_post(URL, request, "Content-Type" => "text/xml") )
|
107
|
-
|
108
|
-
RateResponse.new(success?(response), message_from(response), response,
|
109
|
-
:rates => build_rate_estimates(response, origin, destination)
|
110
|
-
)
|
111
|
-
end
|
112
|
-
|
113
|
-
def build_rate_estimates(response, origin, destination)
|
114
|
-
response["Options"].collect do |quote|
|
115
|
-
RateEstimate.new(origin, destination, carrier_for(quote["Description"]), quote["Description"],
|
116
|
-
:total_price => quote["Price"],
|
117
|
-
:currency => "USD"
|
118
|
-
)
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
def carrier_for(service)
|
123
|
-
CARRIERS.dup.find { |carrier| service.to_s =~ /^#{carrier}/i } || service.to_s.split(" ").first
|
124
|
-
end
|
125
|
-
|
126
|
-
def parse(xml)
|
127
|
-
response = {}
|
128
|
-
response["Options"] = []
|
129
|
-
|
130
|
-
document = REXML::Document.new(sanitize(xml))
|
131
|
-
|
132
|
-
response["ErrorCode"] = parse_child_text(document.root, "ErrorCode")
|
133
|
-
response["ErrorText"] = parse_child_text(document.root, "ErrorText")
|
134
|
-
|
135
|
-
document.root.elements.each("Option") do |e|
|
136
|
-
rate = {}
|
137
|
-
rate["Description"] = parse_child_text(e, "Description")
|
138
|
-
rate["Price"] = parse_child_text(e, "Price")
|
139
|
-
response["Options"] << rate
|
140
|
-
end
|
141
|
-
response
|
142
|
-
end
|
143
|
-
|
144
|
-
def sanitize(response)
|
145
|
-
result = response.to_s
|
146
|
-
result.gsub!("\r\n", "")
|
147
|
-
result.gsub!(/<(\/)?(BODY|HTML)>/, '')
|
148
|
-
result
|
149
|
-
end
|
150
|
-
|
151
|
-
def parse_child_text(parent, name)
|
152
|
-
if element = parent.elements[name]
|
153
|
-
element.text
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
def success?(response)
|
158
|
-
response["ErrorCode"] == "0"
|
159
|
-
end
|
160
|
-
|
161
|
-
def message_from(response)
|
162
|
-
response["ErrorText"]
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
@@ -1,262 +0,0 @@
|
|
1
|
-
module ActiveMerchant
|
2
|
-
module Shipping
|
3
|
-
class NewZealandPost < Carrier
|
4
|
-
cattr_reader :name
|
5
|
-
@@name = "New Zealand Post"
|
6
|
-
|
7
|
-
URL = "http://api.nzpost.co.nz/ratefinder"
|
8
|
-
|
9
|
-
def requirements
|
10
|
-
[:key]
|
11
|
-
end
|
12
|
-
|
13
|
-
def find_rates(origin, destination, packages, options = {})
|
14
|
-
options = @options.merge(options)
|
15
|
-
request = RateRequest.from(origin, destination, packages, options)
|
16
|
-
request.raw_responses = commit(request.urls) if request.new_zealand_origin?
|
17
|
-
request.rate_response
|
18
|
-
end
|
19
|
-
|
20
|
-
protected
|
21
|
-
|
22
|
-
def commit(urls)
|
23
|
-
save_request(urls).map { |url| ssl_get(url) }
|
24
|
-
end
|
25
|
-
|
26
|
-
def self.default_location
|
27
|
-
Location.new(
|
28
|
-
:country => "NZ",
|
29
|
-
:city => "Wellington",
|
30
|
-
:address1 => "22 Waterloo Quay",
|
31
|
-
:address2 => "Pipitea",
|
32
|
-
:postal_code => "6011"
|
33
|
-
)
|
34
|
-
end
|
35
|
-
|
36
|
-
class NewZealandPostRateResponse < RateResponse
|
37
|
-
attr_reader :raw_responses
|
38
|
-
|
39
|
-
def initialize(success, message, params = {}, options = {})
|
40
|
-
@raw_responses = options[:raw_responses]
|
41
|
-
super
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
class RateRequest
|
46
|
-
attr_reader :urls
|
47
|
-
attr_writer :raw_responses
|
48
|
-
|
49
|
-
def self.from(*args)
|
50
|
-
return International.new(*args) unless domestic?(args[0..1])
|
51
|
-
Domestic.new(*args)
|
52
|
-
end
|
53
|
-
|
54
|
-
def initialize(origin, destination, packages, options)
|
55
|
-
@origin = Location.from(origin)
|
56
|
-
@destination = Location.from(destination)
|
57
|
-
@packages = Array(packages).map { |package| NewZealandPostPackage.new(package, api) }
|
58
|
-
@params = { :format => "json", :api_key => options[:key] }
|
59
|
-
@test = options[:test]
|
60
|
-
@rates = @responses = @raw_responses = []
|
61
|
-
@urls = @packages.map { |package| url(package) }
|
62
|
-
end
|
63
|
-
|
64
|
-
def rate_response
|
65
|
-
@rates = rates
|
66
|
-
NewZealandPostRateResponse.new(true, "success", response_params, response_options)
|
67
|
-
rescue => error
|
68
|
-
NewZealandPostRateResponse.new(false, error.message, response_params, response_options)
|
69
|
-
end
|
70
|
-
|
71
|
-
def new_zealand_origin?
|
72
|
-
self.class.new_zealand?(@origin)
|
73
|
-
end
|
74
|
-
|
75
|
-
protected
|
76
|
-
|
77
|
-
def self.new_zealand?(location)
|
78
|
-
['NZ', nil].include?(Location.from(location).country_code)
|
79
|
-
end
|
80
|
-
|
81
|
-
def self.domestic?(locations)
|
82
|
-
locations.select { |location| new_zealand?(location) }.size == 2
|
83
|
-
end
|
84
|
-
|
85
|
-
def response_options
|
86
|
-
{
|
87
|
-
:rates => @rates,
|
88
|
-
:raw_responses => @raw_responses,
|
89
|
-
:request => @urls,
|
90
|
-
:test => @test
|
91
|
-
}
|
92
|
-
end
|
93
|
-
|
94
|
-
def response_params
|
95
|
-
{ :responses => @responses }
|
96
|
-
end
|
97
|
-
|
98
|
-
def rate_options(products)
|
99
|
-
{
|
100
|
-
:total_price => products.sum { |product| price(product) },
|
101
|
-
:currency => "NZD",
|
102
|
-
:service_code => products.first["code"]
|
103
|
-
}
|
104
|
-
end
|
105
|
-
|
106
|
-
def rates
|
107
|
-
rates_hash.map do |service, products|
|
108
|
-
RateEstimate.new(@origin, @destination, NewZealandPost.name, service, rate_options(products))
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
def rates_hash
|
113
|
-
products_hash.select { |_service, products| products.size == @packages.size }
|
114
|
-
end
|
115
|
-
|
116
|
-
def products_hash
|
117
|
-
product_arrays.flatten.group_by { |product| service_name(product) }
|
118
|
-
end
|
119
|
-
|
120
|
-
def product_arrays
|
121
|
-
responses.map do |response|
|
122
|
-
raise(response["message"]) unless response["status"] == "success"
|
123
|
-
response["products"]
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
def responses
|
128
|
-
@responses = @raw_responses.map { |response| parse_response(response) }
|
129
|
-
end
|
130
|
-
|
131
|
-
def parse_response(response)
|
132
|
-
JSON.parse(response)
|
133
|
-
end
|
134
|
-
|
135
|
-
def url(package)
|
136
|
-
"#{URL}/#{api}?#{params(package).to_query}"
|
137
|
-
end
|
138
|
-
|
139
|
-
def params(package)
|
140
|
-
@params.merge(api_params).merge(package.params)
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
class Domestic < RateRequest
|
145
|
-
def service_name(product)
|
146
|
-
[product["service_group_description"], product["description"]].join(" ")
|
147
|
-
end
|
148
|
-
|
149
|
-
def api
|
150
|
-
:domestic
|
151
|
-
end
|
152
|
-
|
153
|
-
def api_params
|
154
|
-
{
|
155
|
-
:postcode_src => @origin.postal_code,
|
156
|
-
:postcode_dest => @destination.postal_code,
|
157
|
-
:carrier => "all"
|
158
|
-
}
|
159
|
-
end
|
160
|
-
|
161
|
-
def price(product)
|
162
|
-
product["cost"].to_f
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
class International < RateRequest
|
167
|
-
def rates
|
168
|
-
raise "New Zealand Post packages must originate in New Zealand" unless new_zealand_origin?
|
169
|
-
super
|
170
|
-
end
|
171
|
-
|
172
|
-
def service_name(product)
|
173
|
-
[product["group"], product["name"]].join(" ")
|
174
|
-
end
|
175
|
-
|
176
|
-
def api
|
177
|
-
:international
|
178
|
-
end
|
179
|
-
|
180
|
-
def api_params
|
181
|
-
{ :country_code => @destination.country_code }
|
182
|
-
end
|
183
|
-
|
184
|
-
def price(product)
|
185
|
-
product["price"].to_f
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
class NewZealandPostPackage
|
190
|
-
def initialize(package, api)
|
191
|
-
@package = package
|
192
|
-
@api = api
|
193
|
-
@params = { :weight => weight, :length => length }
|
194
|
-
end
|
195
|
-
|
196
|
-
def params
|
197
|
-
@params.merge(api_params).merge(shape_params)
|
198
|
-
end
|
199
|
-
|
200
|
-
protected
|
201
|
-
|
202
|
-
def weight
|
203
|
-
@package.kg
|
204
|
-
end
|
205
|
-
|
206
|
-
def length
|
207
|
-
mm(:length)
|
208
|
-
end
|
209
|
-
|
210
|
-
def height
|
211
|
-
mm(:height)
|
212
|
-
end
|
213
|
-
|
214
|
-
def width
|
215
|
-
mm(:width)
|
216
|
-
end
|
217
|
-
|
218
|
-
def shape
|
219
|
-
return :cylinder if @package.cylinder?
|
220
|
-
:cuboid
|
221
|
-
end
|
222
|
-
|
223
|
-
def api_params
|
224
|
-
send("#{@api}_params")
|
225
|
-
end
|
226
|
-
|
227
|
-
def international_params
|
228
|
-
{ :value => value }
|
229
|
-
end
|
230
|
-
|
231
|
-
def domestic_params
|
232
|
-
{}
|
233
|
-
end
|
234
|
-
|
235
|
-
def shape_params
|
236
|
-
send("#{shape}_params")
|
237
|
-
end
|
238
|
-
|
239
|
-
def cuboid_params
|
240
|
-
{ :height => height, :thickness => width }
|
241
|
-
end
|
242
|
-
|
243
|
-
def cylinder_params
|
244
|
-
{ :diameter => width }
|
245
|
-
end
|
246
|
-
|
247
|
-
def mm(measurement)
|
248
|
-
@package.cm(measurement) * 10
|
249
|
-
end
|
250
|
-
|
251
|
-
def value
|
252
|
-
return 0 unless @package.value && currency == "NZD"
|
253
|
-
@package.value / 100
|
254
|
-
end
|
255
|
-
|
256
|
-
def currency
|
257
|
-
@package.currency || "NZD"
|
258
|
-
end
|
259
|
-
end
|
260
|
-
end
|
261
|
-
end
|
262
|
-
end
|
@@ -1,184 +0,0 @@
|
|
1
|
-
require 'cgi'
|
2
|
-
require 'builder'
|
3
|
-
|
4
|
-
module ActiveMerchant
|
5
|
-
module Shipping
|
6
|
-
class Shipwire < Carrier
|
7
|
-
self.retry_safe = true
|
8
|
-
|
9
|
-
cattr_reader :name
|
10
|
-
@@name = "Shipwire"
|
11
|
-
|
12
|
-
URL = 'https://api.shipwire.com/exec/RateServices.php'
|
13
|
-
SCHEMA_URL = 'http://www.shipwire.com/exec/download/RateRequest.dtd'
|
14
|
-
WAREHOUSES = { 'CHI' => 'Chicago',
|
15
|
-
'LAX' => 'Los Angeles',
|
16
|
-
'REN' => 'Reno',
|
17
|
-
'VAN' => 'Vancouver',
|
18
|
-
'TOR' => 'Toronto',
|
19
|
-
'UK' => 'United Kingdom'
|
20
|
-
}
|
21
|
-
|
22
|
-
CARRIERS = ["UPS", "USPS", "FedEx", "Royal Mail", "Parcelforce", "Pharos", "Eurotrux", "Canada Post", "DHL"]
|
23
|
-
|
24
|
-
SUCCESS = "OK"
|
25
|
-
SUCCESS_MESSAGE = "Successfully received the shipping rates"
|
26
|
-
NO_RATES_MESSAGE = "No shipping rates could be found for the destination address"
|
27
|
-
REQUIRED_OPTIONS = [:login, :password].freeze
|
28
|
-
|
29
|
-
def find_rates(origin, destination, packages, options = {})
|
30
|
-
requires!(options, :items)
|
31
|
-
commit(origin, destination, options)
|
32
|
-
end
|
33
|
-
|
34
|
-
def valid_credentials?
|
35
|
-
location = self.class.default_location
|
36
|
-
find_rates(location, location, Package.new(100, [5, 15, 30]),
|
37
|
-
:items => [{ :sku => '', :quantity => 1 }]
|
38
|
-
)
|
39
|
-
rescue ActiveMerchant::Shipping::ResponseError
|
40
|
-
true
|
41
|
-
rescue ActiveMerchant::ResponseError => e
|
42
|
-
e.response.code != '401'
|
43
|
-
end
|
44
|
-
|
45
|
-
private
|
46
|
-
|
47
|
-
def requirements
|
48
|
-
REQUIRED_OPTIONS
|
49
|
-
end
|
50
|
-
|
51
|
-
def build_request(destination, options)
|
52
|
-
xml = Builder::XmlMarkup.new
|
53
|
-
xml.instruct!
|
54
|
-
xml.declare! :DOCTYPE, :RateRequest, :SYSTEM, SCHEMA_URL
|
55
|
-
xml.tag! 'RateRequest' do
|
56
|
-
add_credentials(xml)
|
57
|
-
add_order(xml, destination, options)
|
58
|
-
end
|
59
|
-
xml.target!
|
60
|
-
end
|
61
|
-
|
62
|
-
def add_credentials(xml)
|
63
|
-
xml.tag! 'EmailAddress', @options[:login]
|
64
|
-
xml.tag! 'Password', @options[:password]
|
65
|
-
end
|
66
|
-
|
67
|
-
def add_order(xml, destination, options)
|
68
|
-
xml.tag! 'Order', :id => options[:order_id] do
|
69
|
-
xml.tag! 'Warehouse', options[:warehouse] || '00'
|
70
|
-
|
71
|
-
add_address(xml, destination)
|
72
|
-
Array(options[:items]).each_with_index do |line_item, index|
|
73
|
-
add_item(xml, line_item, index)
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def add_address(xml, destination)
|
79
|
-
xml.tag! 'AddressInfo', :type => 'Ship' do
|
80
|
-
if destination.name.present?
|
81
|
-
xml.tag! 'Name' do
|
82
|
-
xml.tag! 'Full', destination.name
|
83
|
-
end
|
84
|
-
end
|
85
|
-
xml.tag! 'Address1', destination.address1
|
86
|
-
xml.tag! 'Address2', destination.address2 unless destination.address2.blank?
|
87
|
-
xml.tag! 'Address3', destination.address3 unless destination.address3.blank?
|
88
|
-
xml.tag! 'Company', destination.company unless destination.company.blank?
|
89
|
-
xml.tag! 'City', destination.city
|
90
|
-
xml.tag! 'State', destination.state unless destination.state.blank?
|
91
|
-
xml.tag! 'Country', destination.country_code
|
92
|
-
xml.tag! 'Zip', destination.zip unless destination.zip.blank?
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
# Code is limited to 12 characters
|
97
|
-
def add_item(xml, item, index)
|
98
|
-
xml.tag! 'Item', :num => index do
|
99
|
-
xml.tag! 'Code', item[:sku]
|
100
|
-
xml.tag! 'Quantity', item[:quantity]
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
def commit(origin, destination, options)
|
105
|
-
request = build_request(destination, options)
|
106
|
-
save_request(request)
|
107
|
-
|
108
|
-
response = parse( ssl_post(URL, "RateRequestXML=#{CGI.escape(request)}") )
|
109
|
-
|
110
|
-
RateResponse.new(response["success"], response["message"], response,
|
111
|
-
:xml => response,
|
112
|
-
:rates => build_rate_estimates(response, origin, destination),
|
113
|
-
:request => last_request
|
114
|
-
)
|
115
|
-
end
|
116
|
-
|
117
|
-
def build_rate_estimates(response, origin, destination)
|
118
|
-
response["rates"].collect do |quote|
|
119
|
-
RateEstimate.new(origin, destination, carrier_for(quote["service"]), quote["service"],
|
120
|
-
:service_code => quote["method"],
|
121
|
-
:total_price => quote["cost"],
|
122
|
-
:currency => quote["currency"],
|
123
|
-
:delivery_range => [timestamp_from_business_day(quote["delivery_min"]),
|
124
|
-
timestamp_from_business_day(quote["delivery_max"])]
|
125
|
-
)
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
def carrier_for(service)
|
130
|
-
CARRIERS.dup.find { |carrier| service.to_s =~ /^#{carrier}/i } || service.to_s.split(" ").first
|
131
|
-
end
|
132
|
-
|
133
|
-
def parse(xml)
|
134
|
-
response = {}
|
135
|
-
response["rates"] = []
|
136
|
-
|
137
|
-
document = REXML::Document.new(xml)
|
138
|
-
|
139
|
-
response["status"] = parse_child_text(document.root, "Status")
|
140
|
-
|
141
|
-
document.root.elements.each("Order/Quotes/Quote") do |e|
|
142
|
-
rate = {}
|
143
|
-
rate["method"] = e.attributes["method"]
|
144
|
-
rate["warehouse"] = parse_child_text(e, "Warehouse")
|
145
|
-
rate["service"] = parse_child_text(e, "Service")
|
146
|
-
rate["cost"] = parse_child_text(e, "Cost")
|
147
|
-
rate["currency"] = parse_child_attribute(e, "Cost", "currency")
|
148
|
-
if delivery_estimate = e.elements["DeliveryEstimate"]
|
149
|
-
rate["delivery_min"] = parse_child_text(delivery_estimate, "Minimum").to_i
|
150
|
-
rate["delivery_max"] = parse_child_text(delivery_estimate, "Maximum").to_i
|
151
|
-
end
|
152
|
-
response["rates"] << rate
|
153
|
-
end
|
154
|
-
|
155
|
-
if response["status"] == SUCCESS && response["rates"].any?
|
156
|
-
response["success"] = true
|
157
|
-
response["message"] = SUCCESS_MESSAGE
|
158
|
-
elsif response["status"] == SUCCESS && response["rates"].empty?
|
159
|
-
response["success"] = false
|
160
|
-
response["message"] = NO_RATES_MESSAGE
|
161
|
-
else
|
162
|
-
response["success"] = false
|
163
|
-
response["message"] = parse_child_text(document.root, "ErrorMessage")
|
164
|
-
end
|
165
|
-
|
166
|
-
response
|
167
|
-
rescue NoMethodError => e
|
168
|
-
raise ActiveMerchant::Shipping::ResponseContentError.new(e, xml)
|
169
|
-
end
|
170
|
-
|
171
|
-
def parse_child_text(parent, name)
|
172
|
-
if element = parent.elements[name]
|
173
|
-
element.text
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
def parse_child_attribute(parent, name, attribute)
|
178
|
-
if element = parent.elements[name]
|
179
|
-
element.attributes[attribute]
|
180
|
-
end
|
181
|
-
end
|
182
|
-
end
|
183
|
-
end
|
184
|
-
end
|