active_shipping 0.12.6 → 1.0.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|