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
@@ -0,0 +1,122 @@
1
+ require 'json'
2
+
3
+ module ActiveFulfillment
4
+ class JamesAndJamesService < Service
5
+
6
+ SERVICE_URLS = {
7
+ fulfillment: 'https://%{subdomain}.sixworks.co.uk/api/1/',
8
+ inventory: 'https://%{subdomain}.sixworks.co.uk/api/1/stock'
9
+ }
10
+
11
+ def initialize(options = {})
12
+ requires!(options, :subdomain, :key)
13
+ super
14
+ end
15
+
16
+ def fulfill(order_id, shipping_address, line_items, options = {})
17
+ requires!(options, :billing_address)
18
+ commit :fulfillment, build_fulfillment_request(order_id, shipping_address, line_items, options)
19
+ end
20
+
21
+ def fetch_stock_levels(options = {})
22
+ get :inventory, build_inventory_request(options)
23
+ end
24
+
25
+ def test_mode?
26
+ true
27
+ end
28
+
29
+ private
30
+
31
+ def build_fulfillment_request(order_id, shipping_address, line_items, options)
32
+ data = {
33
+ order: {
34
+ client_ref: order_id,
35
+ ShippingContact: format_address(shipping_address),
36
+ BillingContact: format_address(options[:billing_address]),
37
+ items: format_line_items(line_items)
38
+ }
39
+ }
40
+ data[:allow_preorder] = options[:allow_preorder] unless options[:allow_preorder].blank?
41
+ data[:update_stock] = options[:update_stock] unless options[:update_stock].blank?
42
+ data[:order][:po_number] = options[:po_number] unless options[:po_number].blank?
43
+ data[:order][:date_placed] = options[:date_placed] unless options[:po_number].blank?
44
+ data[:order][:postage_speed] = options[:postage_speed] unless options[:postage_speed].blank?
45
+ data[:order][:postage_cost] = options[:postage_cost] unless options[:postage_cost].blank?
46
+ data[:order][:total_value] = options[:total_value] unless options[:total_value].blank?
47
+ data[:order][:days_before_bbe] = options[:days_before_bbe] unless options[:days_before_bbe].blank?
48
+ data[:order][:callback_url] = options[:callback_url] unless options[:callback_url].blank?
49
+ return data
50
+ end
51
+
52
+ def build_inventory_request(options)
53
+ {}
54
+ end
55
+
56
+ def commit(action, request)
57
+ request = request.merge({api_key: @options[:key], test: test? })
58
+ data = ssl_post(SERVICE_URLS[action] % {subdomain: @options[:subdomain]}, JSON.generate(request))
59
+ response = parse_response(data)
60
+ Response.new(response["success"], "message", response, test: response["test"])
61
+ rescue ActiveUtils::ResponseError => e
62
+ handle_error(e)
63
+ rescue JSON::ParserError => e
64
+ Response.new(false, e.message)
65
+ end
66
+
67
+ def get(action, request)
68
+ request = request.merge({api_key: @options[:key], test: test? })
69
+ data = ssl_get(SERVICE_URLS[action] % {subdomain: @options[:subdomain]} + "?" + request.to_query)
70
+ response = parse_response(data)
71
+ Response.new(response["success"], "message", response, test: response["test"])
72
+ rescue ActiveUtils::ResponseError => e
73
+ handle_error(e)
74
+ rescue JSON::ParserError => e
75
+ Response.new(false, e.message)
76
+ end
77
+
78
+ def parse_response(json)
79
+ JSON.parse(json)
80
+ end
81
+
82
+ def handle_error(e)
83
+ response = parse_error(e.response)
84
+ Response.new(false, response[:http_message], response)
85
+ end
86
+
87
+ def parse_error(http_response)
88
+ response = {}
89
+ response[:http_code] = http_response.code
90
+ response[:http_message] = http_response.message
91
+ response
92
+ end
93
+
94
+ def format_address(address)
95
+ data = {
96
+ name: address[:name],
97
+ address: address[:address1],
98
+ city: address[:city],
99
+ country: address[:country],
100
+ postcode: address[:zip].blank? ? "-" : address[:zip]
101
+ }
102
+ data[:company] = address[:company] unless address[:company].blank?
103
+ data[:email] = address[:email] unless address[:email].blank?
104
+ data[:address_contd] = address[:address2] unless address[:address2].blank?
105
+ data[:county] = address[:state] unless address[:state].blank?
106
+ return data
107
+ end
108
+
109
+ def format_line_items(items)
110
+ data = []
111
+ items.each do |item|
112
+ data << {
113
+ client_ref: item[:sku],
114
+ quantity: item[:quantity],
115
+ price: item[:price]
116
+ }
117
+ end
118
+ return data
119
+ end
120
+
121
+ end
122
+ end
@@ -0,0 +1,266 @@
1
+ require 'cgi'
2
+
3
+ module ActiveFulfillment
4
+ class ShipwireService < Service
5
+
6
+ SERVICE_URLS = { :fulfillment => 'https://api.shipwire.com/exec/FulfillmentServices.php',
7
+ :inventory => 'https://api.shipwire.com/exec/InventoryServices.php',
8
+ :tracking => 'https://api.shipwire.com/exec/TrackingServices.php'
9
+ }
10
+
11
+ SCHEMA_URLS = { :fulfillment => 'http://www.shipwire.com/exec/download/OrderList.dtd',
12
+ :inventory => 'http://www.shipwire.com/exec/download/InventoryUpdate.dtd',
13
+ :tracking => 'http://www.shipwire.com/exec/download/TrackingUpdate.dtd'
14
+ }
15
+
16
+ POST_VARS = { :fulfillment => 'OrderListXML',
17
+ :inventory => 'InventoryUpdateXML',
18
+ :tracking => 'TrackingUpdateXML'
19
+ }
20
+
21
+ WAREHOUSES = { 'CHI' => 'Chicago',
22
+ 'LAX' => 'Los Angeles',
23
+ 'REN' => 'Reno',
24
+ 'VAN' => 'Vancouver',
25
+ 'TOR' => 'Toronto',
26
+ 'UK' => 'United Kingdom'
27
+ }
28
+
29
+ INVALID_LOGIN = /(Error with Valid Username\/EmailAddress and Password Required)|(Could not verify Username\/EmailAddress and Password combination)/
30
+
31
+ class_attribute :affiliate_id
32
+
33
+ # The first is the label, and the last is the code
34
+ def self.shipping_methods
35
+ [ ['1 Day Service', '1D'],
36
+ ['2 Day Service', '2D'],
37
+ ['Ground Service', 'GD'],
38
+ ['Freight Service', 'FT'],
39
+ ['International', 'INTL']
40
+ ].inject({}){|h, (k,v)| h[k] = v; h}
41
+ end
42
+
43
+ # Pass in the login and password for the shipwire account.
44
+ # Optionally pass in the :test => true to force test mode
45
+ def initialize(options = {})
46
+ requires!(options, :login, :password)
47
+
48
+ super
49
+ end
50
+
51
+ def fulfill(order_id, shipping_address, line_items, options = {})
52
+ commit :fulfillment, build_fulfillment_request(order_id, shipping_address, line_items, options)
53
+ end
54
+
55
+ def fetch_stock_levels(options = {})
56
+ commit :inventory, build_inventory_request(options)
57
+ end
58
+
59
+ def fetch_tracking_data(order_ids, options = {})
60
+ commit :tracking, build_tracking_request(order_ids)
61
+ end
62
+
63
+ def valid_credentials?
64
+ response = fetch_tracking_numbers([])
65
+ response.message !~ INVALID_LOGIN
66
+ end
67
+
68
+ def test_mode?
69
+ true
70
+ end
71
+
72
+ def include_pending_stock?
73
+ @options[:include_pending_stock]
74
+ end
75
+
76
+ def include_empty_stock?
77
+ @options[:include_empty_stock]
78
+ end
79
+
80
+ private
81
+ def build_fulfillment_request(order_id, shipping_address, line_items, options)
82
+ xml = Builder::XmlMarkup.new :indent => 2
83
+ xml.instruct!
84
+ xml.declare! :DOCTYPE, :OrderList, :SYSTEM, SCHEMA_URLS[:fulfillment]
85
+ xml.tag! 'OrderList' do
86
+ add_credentials(xml)
87
+ xml.tag! 'Referer', 'Active Fulfillment'
88
+ add_order(xml, order_id, shipping_address, line_items, options)
89
+ end
90
+ xml.target!
91
+ end
92
+
93
+ def build_inventory_request(options)
94
+ xml = Builder::XmlMarkup.new :indent => 2
95
+ xml.instruct!
96
+ xml.declare! :DOCTYPE, :InventoryStatus, :SYSTEM, SCHEMA_URLS[:inventory]
97
+ xml.tag! 'InventoryUpdate' do
98
+ add_credentials(xml)
99
+ xml.tag! 'Warehouse', WAREHOUSES[options[:warehouse]]
100
+ xml.tag! 'ProductCode', options[:sku]
101
+ xml.tag! 'IncludeEmpty' if include_empty_stock?
102
+ end
103
+ end
104
+
105
+ def build_tracking_request(order_ids)
106
+ xml = Builder::XmlMarkup.new
107
+ xml.instruct!
108
+ xml.declare! :DOCTYPE, :InventoryStatus, :SYSTEM, SCHEMA_URLS[:inventory]
109
+ xml.tag! 'TrackingUpdate' do
110
+ add_credentials(xml)
111
+ xml.tag! 'Server', test? ? 'Test' : 'Production'
112
+ order_ids.each do |o_id|
113
+ xml.tag! 'OrderNo', o_id
114
+ end
115
+ end
116
+ end
117
+
118
+ def add_credentials(xml)
119
+ xml.tag! 'EmailAddress', @options[:login]
120
+ xml.tag! 'Password', @options[:password]
121
+ xml.tag! 'Server', test? ? 'Test' : 'Production'
122
+ xml.tag! 'AffiliateId', affiliate_id if affiliate_id.present?
123
+ end
124
+
125
+ def add_order(xml, order_id, shipping_address, line_items, options)
126
+ xml.tag! 'Order', :id => order_id do
127
+ xml.tag! 'Warehouse', options[:warehouse] || '00'
128
+
129
+ add_address(xml, shipping_address, options)
130
+ xml.tag! 'Shipping', options[:shipping_method] unless options[:shipping_method].blank?
131
+
132
+ Array(line_items).each_with_index do |line_item, index|
133
+ add_item(xml, line_item, index)
134
+ end
135
+ xml.tag! 'Note' do
136
+ xml.cdata! options[:note] unless options[:note].blank?
137
+ end
138
+ end
139
+ end
140
+
141
+ def add_address(xml, address, options)
142
+ xml.tag! 'AddressInfo', :type => 'Ship' do
143
+ xml.tag! 'Name' do
144
+ xml.tag! 'Full', address[:name]
145
+ end
146
+
147
+ xml.tag! 'Address1', address[:address1]
148
+ xml.tag! 'Address2', address[:address2]
149
+
150
+ xml.tag! 'Company', address[:company]
151
+
152
+ xml.tag! 'City', address[:city]
153
+ xml.tag! 'State', address[:state] unless address[:state].blank?
154
+ xml.tag! 'Country', address[:country]
155
+
156
+ xml.tag! 'Zip', address[:zip]
157
+ xml.tag! 'Phone', address[:phone] unless address[:phone].blank?
158
+ xml.tag! 'Email', options[:email] unless options[:email].blank?
159
+ end
160
+ end
161
+
162
+ # Code is limited to 12 characters
163
+ def add_item(xml, item, index)
164
+ xml.tag! 'Item', :num => index do
165
+ xml.tag! 'Code', item[:sku]
166
+ xml.tag! 'Quantity', item[:quantity]
167
+ end
168
+ end
169
+
170
+ def commit(action, request)
171
+ data = ssl_post(SERVICE_URLS[action], "#{POST_VARS[action]}=#{CGI.escape(request)}")
172
+
173
+ response = parse_response(action, data)
174
+ Response.new(response[:success], response[:message], response, :test => test?)
175
+ end
176
+
177
+ def parse_response(action, data)
178
+ case action
179
+ when :fulfillment
180
+ parse_fulfillment_response(data)
181
+ when :inventory
182
+ parse_inventory_response(data)
183
+ when :tracking
184
+ parse_tracking_response(data)
185
+ else
186
+ raise ArgumentError, "Unknown action #{action}"
187
+ end
188
+ end
189
+
190
+ def parse_fulfillment_response(xml)
191
+ response = {}
192
+
193
+ document = REXML::Document.new(xml)
194
+ document.root.elements.each do |node|
195
+ response[node.name.underscore.to_sym] = text_content(node)
196
+ end
197
+
198
+ response[:success] = response[:status] == '0'
199
+ response[:message] = response[:success] ? "Successfully submitted the order" : message_from(response[:error_message])
200
+ response
201
+ end
202
+
203
+ def parse_inventory_response(xml)
204
+ response = {}
205
+ response[:stock_levels] = {}
206
+
207
+ document = REXML::Document.new(xml)
208
+ document.root.elements.each do |node|
209
+ if node.name == 'Product'
210
+ to_check = ['quantity']
211
+ to_check << 'pending' if include_pending_stock?
212
+
213
+ amount = to_check.sum { |a| node.attributes[a].to_i }
214
+ response[:stock_levels][node.attributes['code']] = amount
215
+ else
216
+ response[node.name.underscore.to_sym] = text_content(node)
217
+ end
218
+ end
219
+
220
+ response[:success] = test? ? response[:status] == 'Test' : response[:status] == '0'
221
+ response[:message] = response[:success] ? "Successfully received the stock levels" : message_from(response[:error_message])
222
+
223
+ response
224
+ end
225
+
226
+ def parse_tracking_response(xml)
227
+ response = {}
228
+ response[:tracking_numbers] = {}
229
+ response[:tracking_companies] = {}
230
+ response[:tracking_urls] = {}
231
+
232
+ document = REXML::Document.new(xml)
233
+ document.root.elements.each do |node|
234
+ if node.name == 'Order'
235
+ if node.attributes["shipped"] == "YES" && node.elements['TrackingNumber']
236
+ tracking_number = node.elements['TrackingNumber'].text.strip
237
+ response[:tracking_numbers][node.attributes['id']] = [tracking_number]
238
+
239
+ tracking_company = node.elements['TrackingNumber'].attributes['carrier']
240
+ response[:tracking_companies][node.attributes['id']] = [tracking_company.strip] if tracking_company
241
+
242
+ tracking_url = node.elements['TrackingNumber'].attributes['href']
243
+ response[:tracking_urls][node.attributes['id']] = [tracking_url.strip] if tracking_url
244
+ end
245
+ else
246
+ response[node.name.underscore.to_sym] = text_content(node)
247
+ end
248
+ end
249
+
250
+ response[:success] = test? ? (response[:status] == '0' || response[:status] == 'Test') : response[:status] == '0'
251
+ response[:message] = response[:success] ? "Successfully received the tracking numbers" : message_from(response[:error_message])
252
+ response
253
+ end
254
+
255
+ def message_from(string)
256
+ return if string.blank?
257
+ string.gsub("\n", '').squeeze(" ")
258
+ end
259
+
260
+ def text_content(xml_node)
261
+ text = xml_node.text
262
+ text = xml_node.cdatas.join if text.blank?
263
+ text
264
+ end
265
+ end
266
+ end
@@ -0,0 +1,125 @@
1
+ require 'active_support/core_ext/object/to_query'
2
+
3
+ module ActiveFulfillment
4
+ class ShopifyAPIService < Service
5
+
6
+ OrderIdCutoffDate = Date.iso8601("2015-03-01")
7
+
8
+ RESCUABLE_CONNECTION_ERRORS = [
9
+ Net::ReadTimeout,
10
+ Net::OpenTimeout,
11
+ TimeoutError,
12
+ Errno::ETIMEDOUT,
13
+ Timeout::Error,
14
+ IOError,
15
+ EOFError,
16
+ SocketError,
17
+ Errno::ECONNRESET,
18
+ Errno::ECONNABORTED,
19
+ Errno::EPIPE,
20
+ Errno::ECONNREFUSED,
21
+ Errno::EAGAIN,
22
+ Errno::EHOSTUNREACH,
23
+ Errno::ENETUNREACH,
24
+ Resolv::ResolvError,
25
+ Net::HTTPBadResponse,
26
+ Net::HTTPHeaderSyntaxError,
27
+ Net::ProtocolError,
28
+ ActiveUtils::ConnectionError,
29
+ ActiveUtils::ResponseError,
30
+ ActiveUtils::InvalidResponseError
31
+ ]
32
+
33
+ def initialize(options = {})
34
+ @name = options[:name]
35
+ @callback_url = options[:callback_url]
36
+ @format = options[:format]
37
+ end
38
+
39
+ def fulfill(order_id, shipping_address, line_items, options = {})
40
+ raise NotImplementedError.new("Shopify API Service must listen to fulfillment/create Webhooks")
41
+ end
42
+
43
+ def fetch_stock_levels(options = {})
44
+ response = send_app_request('fetch_stock', options.delete(:headers), options)
45
+ if response
46
+ stock_levels = parse_response(response, 'StockLevels', 'Product', 'Sku', 'Quantity') { |p| p.to_i }
47
+ Response.new(true, "API stock levels", {:stock_levels => stock_levels})
48
+ else
49
+ Response.new(false, "Unable to fetch remote stock levels")
50
+ end
51
+ end
52
+
53
+ def fetch_tracking_data(order_numbers, options = {})
54
+ options.merge!({:order_ids => order_numbers, :order_names => order_numbers})
55
+ response = send_app_request('fetch_tracking_numbers', options.delete(:headers), options)
56
+ if response
57
+ tracking_numbers = parse_response(response, 'TrackingNumbers', 'Order', 'ID', 'Tracking') { |o| o }
58
+ Response.new(true, "API tracking_numbers", {:tracking_numbers => tracking_numbers,
59
+ :tracking_companies => {},
60
+ :tracking_urls => {}})
61
+ else
62
+ Response.new(false, "Unable to fetch remote tracking numbers #{order_numbers.inspect}")
63
+ end
64
+ end
65
+
66
+ private
67
+
68
+ def request_uri(action, data)
69
+ URI.parse "#{@callback_url}/#{action}.#{@format}?#{data.to_query}"
70
+ end
71
+
72
+ def send_app_request(action, headers, data)
73
+ uri = request_uri(action, data)
74
+
75
+ logger.info "[" + @name.upcase + " APP] Post #{uri}"
76
+
77
+ response = nil
78
+ realtime = Benchmark.realtime do
79
+ begin
80
+ Timeout.timeout(20.seconds) do
81
+ response = ssl_get(uri, headers)
82
+ end
83
+ rescue *(RESCUABLE_CONNECTION_ERRORS) => e
84
+ logger.warn "[#{self}] Error while contacting fulfillment service error =\"#{e.message}\""
85
+ end
86
+ end
87
+
88
+ line = "[" + @name.upcase + "APP] Response from #{uri} --> "
89
+ line << "#{response} #{"%.4fs" % realtime}"
90
+ logger.info line
91
+
92
+ response
93
+ end
94
+
95
+ def parse_response(response, root, type, key, value)
96
+ case @format
97
+ when 'json'
98
+ response_data = ActiveSupport::JSON.decode(response)
99
+ return {} unless response_data.is_a?(Hash)
100
+ response_data[root.underscore] || response_data
101
+ when 'xml'
102
+ response_data = {}
103
+ document = REXML::Document.new(response)
104
+ document.elements[root].each do |node|
105
+ if node.name == type
106
+ response_data[node.elements[key].text] = node.elements[value].text
107
+ end
108
+ end
109
+ response_data
110
+ end
111
+
112
+ rescue ActiveSupport::JSON.parse_error, REXML::ParseException
113
+ {}
114
+ end
115
+
116
+ def encode_payload(payload, root)
117
+ case @format
118
+ when 'json'
119
+ {root => payload}.to_json
120
+ when 'xml'
121
+ payload.to_xml(:root => root)
122
+ end
123
+ end
124
+ end
125
+ end