active_fulfillment 2.1.9 → 3.0.0.pre2

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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +68 -0
  3. data/lib/active_fulfillment.rb +5 -5
  4. data/lib/active_fulfillment/base.rb +10 -0
  5. data/lib/active_fulfillment/response.rb +26 -0
  6. data/lib/active_fulfillment/service.rb +56 -0
  7. data/lib/active_fulfillment/services.rb +5 -0
  8. data/lib/active_fulfillment/services/amazon_mws.rb +473 -0
  9. data/lib/active_fulfillment/services/james_and_james.rb +122 -0
  10. data/lib/active_fulfillment/services/shipwire.rb +266 -0
  11. data/lib/active_fulfillment/services/shopify_api.rb +125 -0
  12. data/lib/active_fulfillment/services/webgistix.rb +334 -0
  13. data/lib/active_fulfillment/version.rb +4 -0
  14. data/test/remote/amazon_mws_test.rb +20 -17
  15. data/test/remote/james_and_james_test.rb +77 -0
  16. data/test/remote/shipwire_test.rb +25 -25
  17. data/test/remote/webgistix_test.rb +21 -21
  18. data/test/test_helper.rb +27 -52
  19. data/test/unit/base_test.rb +4 -4
  20. data/test/unit/services/amazon_mws_test.rb +56 -26
  21. data/test/unit/services/james_and_james_test.rb +90 -0
  22. data/test/unit/services/shipwire_test.rb +18 -18
  23. data/test/unit/services/shopify_api_test.rb +7 -20
  24. data/test/unit/services/webgistix_test.rb +35 -35
  25. metadata +32 -114
  26. data/CHANGELOG +0 -62
  27. data/lib/active_fulfillment/fulfillment/base.rb +0 -12
  28. data/lib/active_fulfillment/fulfillment/response.rb +0 -28
  29. data/lib/active_fulfillment/fulfillment/service.rb +0 -58
  30. data/lib/active_fulfillment/fulfillment/services.rb +0 -5
  31. data/lib/active_fulfillment/fulfillment/services/amazon.rb +0 -389
  32. data/lib/active_fulfillment/fulfillment/services/amazon_mws.rb +0 -454
  33. data/lib/active_fulfillment/fulfillment/services/shipwire.rb +0 -268
  34. data/lib/active_fulfillment/fulfillment/services/shopify_api.rb +0 -125
  35. data/lib/active_fulfillment/fulfillment/services/webgistix.rb +0 -338
  36. data/lib/active_fulfillment/fulfillment/version.rb +0 -6
  37. data/test/fixtures.yml +0 -16
  38. data/test/fixtures/xml/amazon/inventory_get_response.xml +0 -17
  39. data/test/fixtures/xml/amazon/inventory_list_response.xml +0 -29
  40. data/test/fixtures/xml/amazon/inventory_list_response_with_next_1.xml +0 -30
  41. data/test/fixtures/xml/amazon/inventory_list_response_with_next_2.xml +0 -29
  42. data/test/fixtures/xml/amazon/tracking_response_1.xml +0 -56
  43. data/test/fixtures/xml/amazon/tracking_response_2.xml +0 -38
  44. data/test/fixtures/xml/amazon/tracking_response_error.xml +0 -13
  45. data/test/fixtures/xml/amazon/tracking_response_not_found.xml +0 -13
  46. data/test/fixtures/xml/amazon_mws/fulfillment_get_fulfillment_order.xml +0 -114
  47. data/test/fixtures/xml/amazon_mws/fulfillment_get_fulfillment_order_2.xml +0 -90
  48. data/test/fixtures/xml/amazon_mws/fulfillment_get_fullfillment_order_with_multiple_tracking_numbers.xml +0 -121
  49. data/test/fixtures/xml/amazon_mws/fulfillment_list_all_fulfillment_orders.xml +0 -70
  50. data/test/fixtures/xml/amazon_mws/inventory_list_inventory_item_supply.xml +0 -32
  51. data/test/fixtures/xml/amazon_mws/inventory_list_inventory_supply.xml +0 -75
  52. data/test/fixtures/xml/amazon_mws/inventory_list_inventory_supply_by_next_token.xml +0 -38
  53. data/test/fixtures/xml/amazon_mws/tracking_response_error.xml +0 -9
  54. data/test/fixtures/xml/amazon_mws/tracking_response_not_found.xml +0 -9
  55. data/test/fixtures/xml/shipwire/fulfillment_failure_response.xml +0 -7
  56. data/test/fixtures/xml/shipwire/invalid_login_response.xml +0 -7
  57. data/test/fixtures/xml/shipwire/inventory_get_response.xml +0 -44
  58. data/test/fixtures/xml/shipwire/successful_empty_tracking_response.xml +0 -8
  59. data/test/fixtures/xml/shipwire/successful_live_tracking_response.xml +0 -53
  60. data/test/fixtures/xml/shipwire/successful_tracking_response.xml +0 -16
  61. data/test/fixtures/xml/shipwire/successful_tracking_response_with_tracking_urls.xml +0 -31
  62. data/test/fixtures/xml/webgistix/multiple_tracking_response.xml +0 -21
  63. data/test/fixtures/xml/webgistix/tracking_response.xml +0 -14
  64. data/test/remote/amazon_test.rb +0 -124
  65. data/test/unit/services/amazon_test.rb +0 -271
data/CHANGELOG DELETED
@@ -1,62 +0,0 @@
1
- = ActiveFulfillment CHANGELOG
2
-
3
- == Version 2.1.7
4
-
5
- * Add shopify_api service
6
- * Drop Ruby 1.9.3 support
7
-
8
- == Version 2.1.0
9
-
10
- * Added fetch_tracking_data methods which returns tracking_companies and tracking_urls if available in addition to tracking_numbers for each service
11
-
12
- == Version 2.0.0 (Jan 5, 2013)
13
-
14
- * API Change on tracking numbers, returns array instead of single string [csaunders]
15
-
16
- == Version 1.0.3 (Jan 21, 2010)
17
-
18
- * Include "pending" counts in stock levels for Shipwire [wisq]
19
- * Add option to include pending stock in Shipwire inventory calculations [jessehk]
20
-
21
- == Version 1.0.2 (Jan 12, 2010)
22
-
23
- * Include "pending" counts in stock levels for Shipwire [wisq]
24
-
25
- == Version 1.0.1 (Dec 13, 2010)
26
-
27
- * Updated common files with changes from activemerchant [Dennis Theisen]
28
- * Updated Webgistix USPS shipping methods (4 added, 1 removed) [Dennis Theisen]
29
- * Changed Webgistix to treat a duplicate response as success instead of failure and to retry failed connection errors. [Dennis Theisen]
30
-
31
- == Version 1.0.0 (July 12, 2010)
32
-
33
- * Add inventory support to Amazon and Webgistix [wisq]
34
-
35
- == Version 0.10.0 (July 6, 2010)
36
-
37
- * Remove DHL from Webgistix shipping methods [Dennis Thiesen]
38
- * Update Amazon FBA to use AWS credentials [John Tajima]
39
- * Use new connection code from ActiveMerchant [cody]
40
- * Add #valid_credentials? support to all fulfillment services [cody]
41
- * Return 'Access Denied' message when Webgistix credenentials are invalid [cody]
42
- * Update Shipwire endpoint hostname [cody]
43
- * Add missing ISO countries [Edward Ocampo-Gooding]
44
- * Add support for Guernsey to country.rb [cody]
45
- * Use a Rails 2.3 compatible OrderedHash [cody]
46
- * Use :words_connector instead of connector in RequiresParameters [cody]
47
- * Provide Webgistix with a valid test sku to keep remote tests passing
48
- * Update PostsData to support get requests
49
- * Update Shipwire to latest version of dtd.
50
- * Use real addresses for Shipwire remote fulfillment tests
51
- * Pass Shipwire the ISO country code instead of the previous name and country combo. Always add the country element to the document
52
- * Update Shipwire warehouses and don't send unneeded Content-Type header
53
- * Add configurable timeouts from Active Merchant
54
- * Shipwire: Send the company in address1 if present. Otherwise send address1 in address1.
55
- * Always send address to Shipwire
56
- * Map company to address1 with Shipwire
57
- * Sync posts_data.rb with ActiveMerchant
58
- * Add support for fetching tracking numbers to Shipwire
59
- * Move email to the options hash. Refactor Shipwire commit method.
60
- * Package for initial upload to Google Code
61
- * Fix remote Webgistix test
62
- * Add support for Fulfillment by Amazon Basic Fulfillment
@@ -1,12 +0,0 @@
1
- module ActiveMerchant
2
- module Fulfillment
3
- module Base
4
- mattr_accessor :mode
5
- self.mode = :production
6
-
7
- def self.service(name)
8
- ActiveMerchant::Fulfillment.const_get("#{name.to_s.downcase}_service".camelize)
9
- end
10
- end
11
- end
12
- end
@@ -1,28 +0,0 @@
1
- module ActiveMerchant
2
- module Fulfillment
3
- class Response
4
- attr_reader :params
5
- attr_reader :message
6
- attr_reader :test
7
-
8
- def success?
9
- @success
10
- end
11
-
12
- def test?
13
- @test
14
- end
15
-
16
- def initialize(success, message, params = {}, options = {})
17
- @success, @message, @params = success, message, params.stringify_keys
18
- @test = options[:test] || false
19
- end
20
-
21
- private
22
- def method_missing(method, *args)
23
- @params[method.to_s] || super
24
- end
25
- end
26
-
27
- end
28
- end
@@ -1,58 +0,0 @@
1
- module ActiveMerchant
2
- module Fulfillment
3
- class Service
4
-
5
- include RequiresParameters
6
- include PostsData
7
-
8
- cattr_accessor :logger
9
-
10
- def initialize(options = {})
11
- check_test_mode(options)
12
-
13
- @options = {}
14
- @options.update(options)
15
- end
16
-
17
- def test_mode?
18
- false
19
- end
20
-
21
- def test?
22
- @options[:test] || Base.mode == :test
23
- end
24
-
25
- def valid_credentials?
26
- true
27
- end
28
-
29
- # API Requirements for Implementors
30
- def fulfill(order_id, shipping_address, line_items, options = {})
31
- raise NotImplementedError.new("Subclasses must implement")
32
- end
33
-
34
- def fetch_stock_levels(options = {})
35
- raise NotImplementedError.new("Subclasses must implement")
36
- end
37
-
38
- def fetch_tracking_numbers(order_ids, options = {})
39
- response = fetch_tracking_data(order_ids, options)
40
- response.params.delete('tracking_companies')
41
- response.params.delete('tracking_urls')
42
- response
43
- end
44
-
45
- def fetch_tracking_data(order_ids, options = {})
46
- raise NotImplementedError.new("Subclasses must implement")
47
- end
48
-
49
- private
50
-
51
- def check_test_mode(options)
52
- if options[:test] and not test_mode?
53
- raise ArgumentError, 'Test mode is not supported by this gateway'
54
- end
55
- end
56
- end
57
- end
58
- end
@@ -1,5 +0,0 @@
1
- require 'active_fulfillment/fulfillment/services/shopify_api'
2
- require 'active_fulfillment/fulfillment/services/shipwire'
3
- require 'active_fulfillment/fulfillment/services/webgistix'
4
- require 'active_fulfillment/fulfillment/services/amazon'
5
- require 'active_fulfillment/fulfillment/services/amazon_mws'
@@ -1,389 +0,0 @@
1
- require 'base64'
2
- require 'openssl'
3
-
4
- module ActiveMerchant
5
- module Fulfillment
6
- class AmazonService < Service
7
- SERVICES = {
8
- :outbound => {
9
- :url => 'https://fba-outbound.amazonaws.com',
10
- :xmlns => 'http://fba-outbound.amazonaws.com/doc/2007-08-02/',
11
- :version => '2007-08-02'
12
- },
13
- :inventory => {
14
- :url => 'https://fba-inventory.amazonaws.com',
15
- :xmlns => 'http://fba-inventory.amazonaws.com/doc/2009-07-31/',
16
- :version => '2009-07-31'
17
- }
18
- }
19
-
20
- SUCCESS, FAILURE, ERROR = 'Accepted', 'Failure', 'Error'
21
- MESSAGES = {
22
- :status => {
23
- 'Accepted' => 'Success',
24
- 'Failure' => 'Failed',
25
- 'Error' => 'An error occurred'
26
- },
27
- :create => {
28
- 'Accepted' => 'Successfully submitted the order',
29
- 'Failure' => 'Failed to submit the order',
30
- 'Error' => 'An error occurred while submitting the order'
31
- },
32
- :list => {
33
- 'Accepted' => 'Successfully submitted request',
34
- 'Failure' => 'Failed to submit request',
35
- 'Error' => 'An error occurred while submitting request'
36
-
37
- }
38
- }
39
-
40
- ENV_NAMESPACES = { 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
41
- 'xmlns:env' => 'http://schemas.xmlsoap.org/soap/envelope/',
42
- 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance'
43
- }
44
-
45
- AWS_SECURITY_ATTRIBUTES = {
46
- "env:actor" => "http://schemas.xmlsoap.org/soap/actor/next",
47
- "env:mustUnderstand" => "0",
48
- "xmlns:aws" => "http://security.amazonaws.com/doc/2007-01-01/"
49
- }
50
-
51
- @@digest = OpenSSL::Digest.new("sha1")
52
-
53
- OPERATIONS = {
54
- :outbound => {
55
- :status => 'GetServiceStatus',
56
- :create => 'CreateFulfillmentOrder',
57
- :list => 'ListAllFulfillmentOrders',
58
- :tracking => 'GetFulfillmentOrder'
59
- },
60
- :inventory => {
61
- :get => 'GetInventorySupply',
62
- :list => 'ListUpdatedInventorySupply',
63
- :list_next => 'ListUpdatedInventorySupplyByNextToken'
64
- }
65
- }
66
-
67
- # The first is the label, and the last is the code
68
- # Standard: 3-5 business days
69
- # Expedited: 2 business days
70
- # Priority: 1 business day
71
- def self.shipping_methods
72
- [
73
- [ 'Standard Shipping', 'Standard' ],
74
- [ 'Expedited Shipping', 'Expedited' ],
75
- [ 'Priority Shipping', 'Priority' ]
76
- ].inject(ActiveSupport::OrderedHash.new){|h, (k,v)| h[k] = v; h}
77
- end
78
-
79
- def self.sign(aws_secret_access_key, auth_string)
80
- Base64.encode64(OpenSSL::HMAC.digest(@@digest, aws_secret_access_key, auth_string)).strip
81
- end
82
-
83
- def initialize(options = {})
84
- requires!(options, :login, :password)
85
- super
86
- end
87
-
88
- def status
89
- commit :outbound, :status, build_status_request
90
- end
91
-
92
- def fulfill(order_id, shipping_address, line_items, options = {})
93
- requires!(options, :order_date, :comment, :shipping_method)
94
- commit :outbound, :create, build_fulfillment_request(order_id, shipping_address, line_items, options)
95
- end
96
-
97
- def fetch_current_orders
98
- commit :outbound, :list, build_get_current_fulfillment_orders_request
99
- end
100
-
101
- def fetch_stock_levels(options = {})
102
- if options[:sku]
103
- commit :inventory, :get, build_inventory_get_request(options)
104
- else
105
- response = commit :inventory, :list, build_inventory_list_request(options)
106
-
107
- while token = response.params['next_token'] do
108
- next_page = commit :inventory, :list_next, build_next_inventory_list_request(token)
109
-
110
- next_page.stock_levels.merge!(response.stock_levels)
111
- response = next_page
112
- end
113
-
114
- response
115
- end
116
- end
117
-
118
- def fetch_tracking_data(order_ids, options = {})
119
- order_ids.inject(nil) do |previous, o_id|
120
- response = commit :outbound, :tracking, build_tracking_request(o_id, options)
121
- return response unless response.success?
122
-
123
- if previous
124
- response.tracking_numbers.merge!(previous.tracking_numbers)
125
- response.tracking_companies.merge!(previous.tracking_companies)
126
- response.tracking_urls.merge!(previous.tracking_urls)
127
- end
128
-
129
- response
130
- end
131
- end
132
-
133
- def valid_credentials?
134
- status.success?
135
- end
136
-
137
- def test_mode?
138
- false
139
- end
140
-
141
- private
142
- def soap_request(request)
143
- xml = Builder::XmlMarkup.new :indent => 2
144
- xml.instruct!
145
- xml.tag! "env:Envelope", ENV_NAMESPACES do
146
- xml.tag! "env:Header" do
147
- add_credentials(xml, request)
148
- end
149
- xml.tag! "env:Body" do
150
- yield xml
151
- end
152
- end
153
- xml.target!
154
- end
155
-
156
- def build_status_request
157
- request = OPERATIONS[:outbound][:status]
158
- soap_request(request) do |xml|
159
- xml.tag! request, { 'xmlns' => SERVICES[:outbound][:xmlns] }
160
- end
161
- end
162
-
163
- def build_get_current_fulfillment_orders_request
164
- request = OPERATIONS[:outbound][:list]
165
- soap_request(request) do |xml|
166
- xml.tag! request, { 'xmlns' => SERVICES[:outbound][:xmlns] } do
167
- xml.tag! "NumberOfResultsRequested", 5
168
- xml.tag! "QueryStartDateTime", Time.now.utc.yesterday.strftime("%Y-%m-%dT%H:%M:%SZ")
169
- end
170
- end
171
- end
172
-
173
- def build_fulfillment_request(order_id, shipping_address, line_items, options)
174
- request = OPERATIONS[:outbound][:create]
175
- soap_request(request) do |xml|
176
- xml.tag! request, { 'xmlns' => SERVICES[:outbound][:xmlns] } do
177
- xml.tag! "MerchantFulfillmentOrderId", order_id
178
- xml.tag! "DisplayableOrderId", order_id
179
- xml.tag! "DisplayableOrderDateTime", options[:order_date].strftime("%Y-%m-%dT%H:%M:%SZ")
180
- xml.tag! "DisplayableOrderComment", options[:comment]
181
- xml.tag! "ShippingSpeedCategory", options[:shipping_method]
182
-
183
- add_address(xml, shipping_address)
184
- add_items(xml, line_items)
185
- end
186
- end
187
- end
188
-
189
- def build_inventory_get_request(options)
190
- request = OPERATIONS[:inventory][:get]
191
- soap_request(request) do |xml|
192
- xml.tag! request, { 'xmlns' => SERVICES[:inventory][:xmlns] } do
193
- xml.tag! "MerchantSKU", options[:sku]
194
- xml.tag! "ResponseGroup", "Basic"
195
- end
196
- end
197
- end
198
-
199
- def build_inventory_list_request(options)
200
- start_time = options[:start_time] || 1.day.ago
201
-
202
- request = OPERATIONS[:inventory][:list]
203
- soap_request(request) do |xml|
204
- xml.tag! request, { 'xmlns' => SERVICES[:inventory][:xmlns] } do
205
- xml.tag! "NumberOfResultsRequested", 50
206
- xml.tag! "QueryStartDateTime", start_time.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
207
- xml.tag! "ResponseGroup", "Basic"
208
- end
209
- end
210
- end
211
-
212
- def build_next_inventory_list_request(token)
213
- request = OPERATIONS[:inventory][:list_next]
214
- soap_request(request) do |xml|
215
- xml.tag! request, { 'xmlns' => SERVICES[:inventory][:xmlns] } do
216
- xml.tag! "NextToken", token
217
- end
218
- end
219
- end
220
-
221
- def build_tracking_request(order_id, options)
222
- request = OPERATIONS[:outbound][:tracking]
223
- soap_request(request) do |xml|
224
- xml.tag! request, { 'xmlns' => SERVICES[:outbound][:xmlns] } do
225
- xml.tag! "MerchantFulfillmentOrderId", order_id
226
- end
227
- end
228
- end
229
-
230
- def add_credentials(xml, request)
231
- login = @options[:login]
232
- timestamp = "#{Time.now.utc.strftime("%Y-%m-%dT%H:%M:%S")}Z"
233
- signature = self.class.sign(@options[:password], "#{request}#{timestamp}")
234
-
235
- xml.tag! 'aws:AWSAccessKeyId', login, AWS_SECURITY_ATTRIBUTES
236
- xml.tag! 'aws:Signature', signature, AWS_SECURITY_ATTRIBUTES
237
- xml.tag! 'aws:Timestamp', timestamp, AWS_SECURITY_ATTRIBUTES
238
- end
239
-
240
- def add_items(xml, line_items)
241
- Array(line_items).each_with_index do |item, index|
242
- xml.tag! 'Item' do
243
- xml.tag! 'MerchantSKU', item[:sku]
244
- xml.tag! "MerchantFulfillmentOrderItemId", index
245
- xml.tag! "Quantity", item[:quantity]
246
- xml.tag! "GiftMessage", item[:gift_message] unless item[:gift_message].blank?
247
- xml.tag! "DisplayableComment", item[:comment] unless item[:comment].blank?
248
- end
249
- end
250
- end
251
-
252
- def add_address(xml, address)
253
- xml.tag! 'DestinationAddress' do
254
- xml.tag! 'Name', address[:name]
255
- xml.tag! 'Line1', address[:address1]
256
- xml.tag! 'Line2', address[:address2] unless address[:address2].blank?
257
- xml.tag! 'Line3', address[:address3] unless address[:address3].blank?
258
- xml.tag! 'City', address[:city]
259
- xml.tag! 'StateOrProvinceCode', address[:state]
260
- xml.tag! 'CountryCode', address[:country]
261
- xml.tag! 'PostalCode', address[:zip]
262
- xml.tag! 'PhoneNumber', address[:phone] unless address[:phone].blank?
263
- end
264
- end
265
-
266
- def commit(service, op, body)
267
- data = ssl_post(SERVICES[service][:url], body, 'Content-Type' => 'application/soap+xml; charset=utf-8')
268
- response = parse_response(service, op, data)
269
- Response.new(success?(response), message_from(response), response)
270
- rescue ActiveMerchant::ResponseError => e
271
- handle_error(e)
272
- end
273
-
274
- def handle_error(e)
275
- response = parse_error(e.response)
276
- if response.fetch(:faultstring, "") =~ /Reason: requested order not found./
277
- Response.new(true, nil, {:status => SUCCESS, :tracking_numbers => {}, :tracking_companies => {}, :tracking_urls => {}})
278
- else
279
- Response.new(false, message_from(response), response)
280
- end
281
- end
282
-
283
- def success?(response)
284
- response[:response_status] == SUCCESS
285
- end
286
-
287
- def message_from(response)
288
- response[:response_comment]
289
- end
290
-
291
- def parse_response(service, op, xml)
292
- begin
293
- document = REXML::Document.new(xml)
294
- rescue REXML::ParseException
295
- return {:success => FAILURE}
296
- end
297
-
298
- case service
299
- when :outbound
300
- case op
301
- when :tracking
302
- parse_tracking_response(document)
303
- else
304
- parse_fulfillment_response(op, document)
305
- end
306
- when :inventory
307
- parse_inventory_response(document)
308
- else
309
- raise ArgumentError, "Unknown service #{service}"
310
- end
311
- end
312
-
313
- def parse_fulfillment_response(op, document)
314
- response = {}
315
- action = OPERATIONS[:outbound][op]
316
- node = REXML::XPath.first(document, "//ns1:#{action}Response")
317
-
318
- response[:response_status] = SUCCESS
319
- response[:response_comment] = MESSAGES[op][SUCCESS]
320
- response
321
- end
322
-
323
- def parse_inventory_response(document)
324
- response = {}
325
- response[:stock_levels] = {}
326
-
327
- document.each_element('//ns1:MerchantSKUSupply') do |node|
328
- # {MerchantSKU => 'SOME-ID', InStockSupplyQuantity => '101', ...}
329
- params = node.elements.to_a.each_with_object({}) {|elem, hash| hash[elem.name] = elem.text}
330
-
331
- response[:stock_levels][params['MerchantSKU']] = params['InStockSupplyQuantity'].to_i
332
- end
333
-
334
- next_token = REXML::XPath.first(document, '//ns1:NextToken')
335
- response[:next_token] = (next_token ? next_token.text : nil)
336
-
337
- response[:response_status] = SUCCESS
338
- response
339
- end
340
-
341
- def parse_tracking_response(document)
342
- response = {}
343
- response[:tracking_numbers] = {}
344
- response[:tracking_companies] = {}
345
- response[:tracking_urls] = {}
346
-
347
- track_node = REXML::XPath.first(document, '//ns1:FulfillmentShipmentPackage/ns1:TrackingNumber')
348
- if track_node
349
- id_node = REXML::XPath.first(document, '//ns1:MerchantFulfillmentOrderId')
350
- response[:tracking_numbers][id_node.text] = [track_node.text]
351
- end
352
-
353
- company_node = REXML::XPath.first(document, '//ns1:FulfillmentShipmentPackage/ns1:CarrierCode')
354
- if company_node
355
- id_node = REXML::XPath.first(document, '//ns1:MerchantFulfillmentOrderId')
356
- response[:tracking_companies][id_node.text] = [company_node.text]
357
- end
358
-
359
- response[:response_status] = SUCCESS
360
- response
361
- end
362
-
363
- def parse_error(http_response)
364
- response = {}
365
- response[:http_code] = http_response.code
366
- response[:http_message] = http_response.message
367
-
368
- document = REXML::Document.new(http_response.body)
369
-
370
- node = REXML::XPath.first(document, "//env:Fault")
371
-
372
- failed_node = node.find_first_recursive {|sib| sib.name == "Fault" }
373
- faultcode_node = node.find_first_recursive {|sib| sib.name == "faultcode" }
374
- faultstring_node = node.find_first_recursive {|sib| sib.name == "faultstring" }
375
-
376
- response[:response_status] = FAILURE
377
- response[:faultcode] = faultcode_node ? faultcode_node.text : ""
378
- response[:faultstring] = faultstring_node ? faultstring_node.text : ""
379
- response[:response_comment] = "#{response[:faultcode]} #{response[:faultstring]}"
380
- response
381
- rescue REXML::ParseException => e
382
- response[:http_body] = http_response.body
383
- response[:response_status] = FAILURE
384
- response[:response_comment] = "#{response[:http_code]}: #{response[:http_message]}"
385
- response
386
- end
387
- end
388
- end
389
- end