active_fulfillment 2.1.9 → 3.0.0.pre2

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