active_fulfillment 0.10.0
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.
- data/CHANGELOG +26 -0
- data/Rakefile +60 -0
- data/VERSION +1 -0
- data/active_fulfillment.gemspec +74 -0
- data/init.rb +1 -0
- data/lib/active_fulfillment/fulfillment/base.rb +12 -0
- data/lib/active_fulfillment/fulfillment/response.rb +32 -0
- data/lib/active_fulfillment/fulfillment/service.rb +31 -0
- data/lib/active_fulfillment/fulfillment/services/amazon.rb +230 -0
- data/lib/active_fulfillment/fulfillment/services/shipwire.rb +236 -0
- data/lib/active_fulfillment/fulfillment/services/webgistix.rb +207 -0
- data/lib/active_fulfillment/fulfillment/services.rb +3 -0
- data/lib/active_fulfillment.rb +50 -0
- data/lib/active_merchant/common/connection.rb +172 -0
- data/lib/active_merchant/common/country.rb +319 -0
- data/lib/active_merchant/common/error.rb +26 -0
- data/lib/active_merchant/common/post_data.rb +24 -0
- data/lib/active_merchant/common/posts_data.rb +47 -0
- data/lib/active_merchant/common/requires_parameters.rb +16 -0
- data/lib/active_merchant/common/utils.rb +18 -0
- data/lib/active_merchant/common/validateable.rb +76 -0
- data/lib/active_merchant/common.rb +14 -0
- data/lib/certs/cacert.pem +7815 -0
- data/test/fixtures.yml +11 -0
- data/test/remote/amazon_test.rb +93 -0
- data/test/remote/shipwire_test.rb +145 -0
- data/test/remote/webgistix_test.rb +80 -0
- data/test/test_helper.rb +60 -0
- data/test/unit/base_test.rb +17 -0
- data/test/unit/services/amazon_test.rb +187 -0
- data/test/unit/services/shipwire_test.rb +164 -0
- data/test/unit/services/webgistix_test.rb +145 -0
- metadata +106 -0
@@ -0,0 +1,236 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
3
|
+
module ActiveMerchant
|
4
|
+
module Fulfillment
|
5
|
+
class ShipwireService < Service
|
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 EmailAddress, valid email is required/
|
30
|
+
|
31
|
+
# The first is the label, and the last is the code
|
32
|
+
def self.shipping_methods
|
33
|
+
[ ['1 Day Service', '1D'],
|
34
|
+
['2 Day Service', '2D'],
|
35
|
+
['Ground Service', 'GD'],
|
36
|
+
['Freight Service', 'FT'],
|
37
|
+
['International', 'INTL']
|
38
|
+
].inject(ActiveSupport::OrderedHash.new){|h, (k,v)| h[k] = v; h}
|
39
|
+
end
|
40
|
+
|
41
|
+
# Pass in the login and password for the shipwire account.
|
42
|
+
# Optionally pass in the :test => true to force test mode
|
43
|
+
def initialize(options = {})
|
44
|
+
requires!(options, :login, :password)
|
45
|
+
|
46
|
+
super
|
47
|
+
end
|
48
|
+
|
49
|
+
def fulfill(order_id, shipping_address, line_items, options = {})
|
50
|
+
commit :fulfillment, build_fulfillment_request(order_id, shipping_address, line_items, options)
|
51
|
+
end
|
52
|
+
|
53
|
+
def fetch_stock_levels(options = {})
|
54
|
+
commit :inventory, build_inventory_request(options)
|
55
|
+
end
|
56
|
+
|
57
|
+
def fetch_tracking_numbers(options = {})
|
58
|
+
commit :tracking, build_tracking_request(options)
|
59
|
+
end
|
60
|
+
|
61
|
+
def valid_credentials?
|
62
|
+
response = fetch_tracking_numbers
|
63
|
+
response.message !~ INVALID_LOGIN
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_mode?
|
67
|
+
true
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
def build_fulfillment_request(order_id, shipping_address, line_items, options)
|
72
|
+
xml = Builder::XmlMarkup.new :indent => 2
|
73
|
+
xml.instruct!
|
74
|
+
xml.declare! :DOCTYPE, :OrderList, :SYSTEM, SCHEMA_URLS[:fulfillment]
|
75
|
+
xml.tag! 'OrderList' do
|
76
|
+
add_credentials(xml)
|
77
|
+
xml.tag! 'Referer', 'Active Fulfillment'
|
78
|
+
add_order(xml, order_id, shipping_address, line_items, options)
|
79
|
+
end
|
80
|
+
xml.target!
|
81
|
+
end
|
82
|
+
|
83
|
+
def build_inventory_request(options)
|
84
|
+
xml = Builder::XmlMarkup.new :indent => 2
|
85
|
+
xml.instruct!
|
86
|
+
xml.declare! :DOCTYPE, :InventoryStatus, :SYSTEM, SCHEMA_URLS[:inventory]
|
87
|
+
xml.tag! 'InventoryUpdate' do
|
88
|
+
add_credentials(xml)
|
89
|
+
xml.tag! 'Warehouse', WAREHOUSES[options[:warehouse]]
|
90
|
+
xml.tag! 'ProductCode', options[:sku]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def build_tracking_request(options)
|
95
|
+
xml = Builder::XmlMarkup.new
|
96
|
+
xml.instruct!
|
97
|
+
xml.declare! :DOCTYPE, :InventoryStatus, :SYSTEM, SCHEMA_URLS[:inventory]
|
98
|
+
xml.tag! 'TrackingUpdate' do
|
99
|
+
add_credentials(xml)
|
100
|
+
xml.tag! 'Server', test? ? 'Test' : 'Production'
|
101
|
+
xml.tag! 'Bookmark', '3'
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def add_credentials(xml)
|
106
|
+
xml.tag! 'EmailAddress', @options[:login]
|
107
|
+
xml.tag! 'Password', @options[:password]
|
108
|
+
xml.tag! 'Server', test? ? 'Test' : 'Production'
|
109
|
+
end
|
110
|
+
|
111
|
+
def add_order(xml, order_id, shipping_address, line_items, options)
|
112
|
+
xml.tag! 'Order', :id => order_id do
|
113
|
+
xml.tag! 'Warehouse', options[:warehouse] || '00'
|
114
|
+
|
115
|
+
add_address(xml, shipping_address, options)
|
116
|
+
xml.tag! 'Shipping', options[:shipping_method] unless options[:shipping_method].blank?
|
117
|
+
|
118
|
+
Array(line_items).each_with_index do |line_item, index|
|
119
|
+
add_item(xml, line_item, index)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def add_address(xml, address, options)
|
125
|
+
xml.tag! 'AddressInfo', :type => 'Ship' do
|
126
|
+
xml.tag! 'Name' do
|
127
|
+
xml.tag! 'Full', address[:name]
|
128
|
+
end
|
129
|
+
|
130
|
+
if address[:company].blank?
|
131
|
+
xml.tag! 'Address1', address[:address1]
|
132
|
+
xml.tag! 'Address2', address[:address2]
|
133
|
+
else
|
134
|
+
xml.tag! 'Address1', address[:company]
|
135
|
+
xml.tag! 'Address2', address[:address1]
|
136
|
+
xml.tag! 'Address3', address[:address2]
|
137
|
+
end
|
138
|
+
|
139
|
+
xml.tag! 'City', address[:city]
|
140
|
+
xml.tag! 'State', address[:state] unless address[:state].blank?
|
141
|
+
xml.tag! 'Country', address[:country]
|
142
|
+
|
143
|
+
xml.tag! 'Zip', address[:zip]
|
144
|
+
xml.tag! 'Phone', address[:phone] unless address[:phone].blank?
|
145
|
+
xml.tag! 'Email', options[:email] unless options[:email].blank?
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# Code is limited to 12 characters
|
150
|
+
def add_item(xml, item, index)
|
151
|
+
xml.tag! 'Item', :num => index do
|
152
|
+
xml.tag! 'Code', item[:sku]
|
153
|
+
xml.tag! 'Quantity', item[:quantity]
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def commit(action, request)
|
158
|
+
data = ssl_post(SERVICE_URLS[action], "#{POST_VARS[action]}=#{CGI.escape(request)}")
|
159
|
+
|
160
|
+
response = parse_response(action, data)
|
161
|
+
Response.new(response[:success], response[:message], response, :test => test?)
|
162
|
+
end
|
163
|
+
|
164
|
+
def parse_response(action, data)
|
165
|
+
case action
|
166
|
+
when :fulfillment
|
167
|
+
parse_fulfillment_response(data)
|
168
|
+
when :inventory
|
169
|
+
parse_inventory_response(data)
|
170
|
+
when :tracking
|
171
|
+
parse_tracking_response(data)
|
172
|
+
else
|
173
|
+
raise ArgumentError, "Unknown action #{action}"
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def parse_fulfillment_response(xml)
|
178
|
+
response = {}
|
179
|
+
|
180
|
+
document = REXML::Document.new(xml)
|
181
|
+
document.root.elements.each do |node|
|
182
|
+
response[node.name.underscore.to_sym] = node.text
|
183
|
+
end
|
184
|
+
|
185
|
+
response[:success] = response[:status] == '0'
|
186
|
+
response[:message] = response[:success] ? "Successfully submitted the order" : message_from(response[:error_message])
|
187
|
+
response
|
188
|
+
end
|
189
|
+
|
190
|
+
def parse_inventory_response(xml)
|
191
|
+
response = {}
|
192
|
+
response[:stock_levels] = {}
|
193
|
+
|
194
|
+
document = REXML::Document.new(xml)
|
195
|
+
document.root.elements.each do |node|
|
196
|
+
if node.name == 'Product'
|
197
|
+
response[:stock_levels][node.attributes['code']] = node.attributes['quantity'].to_i
|
198
|
+
else
|
199
|
+
response[node.name.underscore.to_sym] = node.text
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
response[:success] = test? ? response[:status] == 'Test' : response[:status] == '0'
|
204
|
+
response[:message] = response[:success] ? "Successfully received the stock levels" : message_from(response[:error_message])
|
205
|
+
|
206
|
+
response
|
207
|
+
end
|
208
|
+
|
209
|
+
def parse_tracking_response(xml)
|
210
|
+
response = {}
|
211
|
+
response[:tracking_numbers] = {}
|
212
|
+
|
213
|
+
document = REXML::Document.new(xml)
|
214
|
+
|
215
|
+
document.root.elements.each do |node|
|
216
|
+
if node.name == 'Order'
|
217
|
+
response[:tracking_numbers][node.attributes['id']] = node.attributes['trackingNumber'] if node.attributes["shipped"] == "YES"
|
218
|
+
else
|
219
|
+
response[node.name.underscore.to_sym] = node.text
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
response[:success] = test? ? (response[:status] == '0' || response[:status] == 'Test') : response[:status] == '0'
|
224
|
+
response[:message] = response[:success] ? "Successfully received the tracking numbers" : message_from(response[:error_message])
|
225
|
+
response
|
226
|
+
end
|
227
|
+
|
228
|
+
def message_from(string)
|
229
|
+
return if string.blank?
|
230
|
+
string.gsub("\n", '').squeeze(" ")
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
|
@@ -0,0 +1,207 @@
|
|
1
|
+
module ActiveMerchant
|
2
|
+
module Fulfillment
|
3
|
+
class WebgistixService < Service
|
4
|
+
TEST_URL = 'https://www.webgistix.com/XML/shippingTest.asp'
|
5
|
+
LIVE_URL = 'https://www.webgistix.com/XML/API.asp'
|
6
|
+
|
7
|
+
SUCCESS, FAILURE = 'True', 'False'
|
8
|
+
SUCCESS_MESSAGE = 'Successfully submitted the order'
|
9
|
+
FAILURE_MESSAGE = 'Failed to submit the order'
|
10
|
+
INVALID_LOGIN = 'Access Denied'
|
11
|
+
|
12
|
+
# The first is the label, and the last is the code
|
13
|
+
def self.shipping_methods
|
14
|
+
[
|
15
|
+
["UPS Ground Shipping", "Ground"],
|
16
|
+
["UPS Standard Shipping (Canada Only)", "Standard"],
|
17
|
+
["UPS 3-Business Day", "3-Day Select"],
|
18
|
+
["UPS 2-Business Day", "2nd Day Air"],
|
19
|
+
["UPS 2-Business Day AM", "2nd Day Air AM"],
|
20
|
+
["UPS Next Day", "Next Day Air"],
|
21
|
+
["UPS Next Day Saver", "Next Day Air Saver"],
|
22
|
+
["UPS Next Day Early AM", "Next Day Air Early AM"],
|
23
|
+
["UPS Worldwide Express (Next Day)", "Worldwide Express"],
|
24
|
+
["UPS Worldwide Expedited (2nd Day)", "Worldwide Expedited"],
|
25
|
+
["UPS Worldwide Express Saver", "Worldwide Express Saver"],
|
26
|
+
["FedEx Priority Overnight", "FedEx Priority Overnight"],
|
27
|
+
["FedEx Standard Overnight", "FedEx Standard Overnight"],
|
28
|
+
["FedEx First Overnight", "FedEx First Overnight"],
|
29
|
+
["FedEx 2nd Day", "FedEx 2nd Day"],
|
30
|
+
["FedEx Express Saver", "FedEx Express Saver"],
|
31
|
+
["FedEx International Priority", "FedEx International Priority"],
|
32
|
+
["FedEx International Economy", "FedEx International Economy"],
|
33
|
+
["FedEx International First", "FedEx International First"],
|
34
|
+
["FedEx Ground", "FedEx Ground"],
|
35
|
+
["USPS Priority Mail & Global Priority Mail", "Priority"],
|
36
|
+
["USPS Priority Mail & Global Priority Mail (flat rate)", "Flat Rate Priority"],
|
37
|
+
["USPS First Class Mail", "First Class"],
|
38
|
+
["USPS Express Mail & Global Express Mail", "Express"],
|
39
|
+
["USPS Flat Rate Global Express Mail", "Global Express Mail Flat Rate"],
|
40
|
+
["USPS Parcel Post", "Parcel"],
|
41
|
+
["USPS First Class International", "First Class International"],
|
42
|
+
["USPS Media Mail", "Media Mail"],
|
43
|
+
["USPS Economy Parcel Post", "Economy Parcel"],
|
44
|
+
["USPS Economy Air Letter Post", "Economy Letter"],
|
45
|
+
].inject(ActiveSupport::OrderedHash.new){|h, (k,v)| h[k] = v; h}
|
46
|
+
end
|
47
|
+
|
48
|
+
# Pass in the login and password for the shipwire account.
|
49
|
+
# Optionally pass in the :test => true to force test mode
|
50
|
+
def initialize(options = {})
|
51
|
+
requires!(options, :login, :password)
|
52
|
+
super
|
53
|
+
@url = test? ? TEST_URL : LIVE_URL
|
54
|
+
end
|
55
|
+
|
56
|
+
def fulfill(order_id, shipping_address, line_items, options = {})
|
57
|
+
requires!(options, :shipping_method)
|
58
|
+
commit build_fulfillment_request(order_id, shipping_address, line_items, options)
|
59
|
+
end
|
60
|
+
|
61
|
+
def valid_credentials?
|
62
|
+
response = fulfill('', {}, [], :shipping_method => '')
|
63
|
+
response.message != INVALID_LOGIN
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_mode?
|
67
|
+
true
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
#<?xml version="1.0"?>
|
72
|
+
# <OrderXML>
|
73
|
+
# <Password>Webgistix</Password>
|
74
|
+
# <CustomerID>3</CustomerID>
|
75
|
+
# <Order>
|
76
|
+
# <ReferenceNumber></ReferenceNumber>
|
77
|
+
# <Company>Test Company</Company>
|
78
|
+
# <Name>Joe Smith</Name>
|
79
|
+
# <Address1>123 Main St.</Address1>
|
80
|
+
# <Address2></Address2>
|
81
|
+
# <Address3></Address3>
|
82
|
+
# <City>Olean</City>
|
83
|
+
# <State>NY</State>
|
84
|
+
# <ZipCode>14760</ZipCode>
|
85
|
+
# <Country>United States</Country>
|
86
|
+
# <Email>info@webgistix.com</Email>
|
87
|
+
# <Phone>1-123-456-7890</Phone>
|
88
|
+
# <ShippingInstructions>Ground</ShippingInstructions>
|
89
|
+
# <OrderComments>Test Order</OrderComments>
|
90
|
+
# <Approve>0</Approve>
|
91
|
+
# <Item>
|
92
|
+
# <ItemID>testitem</ItemID>
|
93
|
+
# <ItemQty>2</ItemQty>
|
94
|
+
# </Item>
|
95
|
+
# </Order>
|
96
|
+
# </OrderXML>
|
97
|
+
def build_fulfillment_request(order_id, shipping_address, line_items, options)
|
98
|
+
xml = Builder::XmlMarkup.new :indent => 2
|
99
|
+
xml.instruct!
|
100
|
+
xml.tag! 'OrderXML' do
|
101
|
+
add_credentials(xml)
|
102
|
+
add_order(xml, order_id, shipping_address, line_items, options)
|
103
|
+
end
|
104
|
+
xml.target!
|
105
|
+
end
|
106
|
+
|
107
|
+
def add_credentials(xml)
|
108
|
+
xml.tag! 'CustomerID', @options[:login]
|
109
|
+
xml.tag! 'Password', @options[:password]
|
110
|
+
end
|
111
|
+
|
112
|
+
def add_order(xml, order_id, shipping_address, line_items, options)
|
113
|
+
xml.tag! 'Order' do
|
114
|
+
xml.tag! 'ReferenceNumber', order_id
|
115
|
+
xml.tag! 'ShippingInstructions', options[:shipping_method]
|
116
|
+
xml.tag! 'Approve', 1
|
117
|
+
xml.tag! 'OrderComments', options[:comment] unless options[:comment].blank?
|
118
|
+
|
119
|
+
add_address(xml, shipping_address, options)
|
120
|
+
|
121
|
+
Array(line_items).each_with_index do |line_item, index|
|
122
|
+
add_item(xml, line_item, index)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def add_address(xml, address, options)
|
128
|
+
xml.tag! 'Name', address[:name]
|
129
|
+
xml.tag! 'Address1', address[:address1]
|
130
|
+
xml.tag! 'Address2', address[:address2] unless address[:address2].blank?
|
131
|
+
xml.tag! 'Address3', address[:address3] unless address[:address3].blank?
|
132
|
+
xml.tag! 'City', address[:city]
|
133
|
+
xml.tag! 'State', address[:state]
|
134
|
+
xml.tag! 'ZipCode', address[:zip]
|
135
|
+
xml.tag! 'Company', address[:company]
|
136
|
+
|
137
|
+
unless address[:country].blank?
|
138
|
+
country = Country.find(address[:country])
|
139
|
+
xml.tag! 'Country', country.name
|
140
|
+
end
|
141
|
+
|
142
|
+
xml.tag! 'Phone', address[:phone]
|
143
|
+
xml.tag! 'Email', options[:email] unless options[:email].blank?
|
144
|
+
end
|
145
|
+
|
146
|
+
def add_item(xml, item, index)
|
147
|
+
xml.tag! 'Item' do
|
148
|
+
xml.tag! 'ItemID', item[:sku] unless item[:sku].blank?
|
149
|
+
xml.tag! 'ItemQty', item[:quantity] unless item[:quantity].blank?
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def commit(request)
|
154
|
+
@response = parse(ssl_post(@url, request,
|
155
|
+
'EndPointURL' => @url,
|
156
|
+
'Content-Type' => 'text/xml; charset="utf-8"')
|
157
|
+
)
|
158
|
+
|
159
|
+
Response.new(success?(@response), message_from(@response), @response,
|
160
|
+
:test => test?
|
161
|
+
)
|
162
|
+
end
|
163
|
+
|
164
|
+
def success?(response)
|
165
|
+
response[:success] == SUCCESS
|
166
|
+
end
|
167
|
+
|
168
|
+
def message_from(response)
|
169
|
+
return SUCCESS_MESSAGE if success?(response)
|
170
|
+
|
171
|
+
if response[:error_0] == INVALID_LOGIN
|
172
|
+
INVALID_LOGIN
|
173
|
+
else
|
174
|
+
FAILURE_MESSAGE
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def parse(xml)
|
179
|
+
response = {}
|
180
|
+
|
181
|
+
begin
|
182
|
+
document = REXML::Document.new("<response>#{xml}</response>")
|
183
|
+
rescue REXML::ParseException
|
184
|
+
response[:success] = FAILURE
|
185
|
+
return response
|
186
|
+
end
|
187
|
+
# Fetch the errors
|
188
|
+
document.root.elements.to_a("Error").each_with_index do |e, i|
|
189
|
+
response["error_#{i}".to_sym] = e.text
|
190
|
+
end
|
191
|
+
|
192
|
+
# Check if completed
|
193
|
+
if completed = REXML::XPath.first(document, '//Completed')
|
194
|
+
completed.elements.each do |e|
|
195
|
+
response[e.name.underscore.to_sym] = e.text
|
196
|
+
end
|
197
|
+
else
|
198
|
+
response[:success] = FAILURE
|
199
|
+
end
|
200
|
+
|
201
|
+
response
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2009 Jaded Pixel
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
$:.unshift File.dirname(__FILE__)
|
25
|
+
|
26
|
+
begin
|
27
|
+
require 'active_support'
|
28
|
+
rescue LoadError
|
29
|
+
require 'rubygems'
|
30
|
+
require 'active_support'
|
31
|
+
end
|
32
|
+
|
33
|
+
begin
|
34
|
+
require 'builder'
|
35
|
+
rescue LoadError
|
36
|
+
require 'rubygems'
|
37
|
+
require_gem 'builder'
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
require 'cgi'
|
42
|
+
require 'net/https'
|
43
|
+
require 'rexml/document'
|
44
|
+
require 'active_merchant/common'
|
45
|
+
|
46
|
+
require 'active_fulfillment/fulfillment/base'
|
47
|
+
require 'active_fulfillment/fulfillment/response'
|
48
|
+
require 'active_fulfillment/fulfillment/service'
|
49
|
+
require 'active_fulfillment/fulfillment/services'
|
50
|
+
|