ruby_omx 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +3 -0
- data/Rakefile +51 -0
- data/lib/ruby_omx/base.rb +62 -0
- data/lib/ruby_omx/connection.rb +49 -0
- data/lib/ruby_omx/exceptions.rb +84 -0
- data/lib/ruby_omx/items.rb +66 -0
- data/lib/ruby_omx/orders.rb +122 -0
- data/lib/ruby_omx/response/append_order_response.rb +12 -0
- data/lib/ruby_omx/response/item_info_response.rb +28 -0
- data/lib/ruby_omx/response/response_error.rb +13 -0
- data/lib/ruby_omx/response.rb +30 -0
- data/lib/ruby_omx/version.rb +3 -0
- data/lib/ruby_omx.rb +44 -0
- data/test/ruby_omx_test.rb +7 -0
- data/test/test_helper.rb +27 -0
- metadata +111 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2011 YOURNAME
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
Rake::TestTask.new do |t|
|
6
|
+
t.libs << 'test'
|
7
|
+
t.pattern = 'test/**/*_test.rb'
|
8
|
+
end
|
9
|
+
|
10
|
+
task :default => :test
|
11
|
+
|
12
|
+
namespace :whitespace do
|
13
|
+
FIND_FILE_BLACKLIST = "find . -type f | grep -v -e '.git/'"
|
14
|
+
|
15
|
+
desc 'Runs all whitespace tasks'
|
16
|
+
task :all do
|
17
|
+
Rake::Task["whitespace:remove_trailing"].invoke
|
18
|
+
Rake::Task["whitespace:covert_to_soft_tabs"].invoke
|
19
|
+
Rake::Task["whitespace:remove_blank_lines"].invoke
|
20
|
+
end
|
21
|
+
|
22
|
+
desc 'Removes trailing whitespace'
|
23
|
+
task :remove_trailing do
|
24
|
+
system %{
|
25
|
+
echo Removing trailing whitespace
|
26
|
+
for f in `#{FIND_FILE_BLACKLIST}`;
|
27
|
+
do cat $f | sed 's/[ \t]*$//' > .whitespace; cp .whitespace $f; rm .whitespace; echo $f;
|
28
|
+
done
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
desc 'Converts hard-tabs into two-space soft-tabs'
|
33
|
+
task :covert_to_soft_tabs do
|
34
|
+
system %{
|
35
|
+
echo Converting hard-tabs into two-space soft-tabs
|
36
|
+
for f in `#{FIND_FILE_BLACKLIST}`;
|
37
|
+
do cat $f | sed 's/\t/ /g' > .soft_tabs; cp .soft_tabs $f; rm .soft_tabs; echo $f;
|
38
|
+
done
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
desc 'Remove consecutive blank lines'
|
43
|
+
task :remove_blank_lines do
|
44
|
+
system %{
|
45
|
+
echo Removing consecutive blank lines
|
46
|
+
for f in `#{FIND_FILE_BLACKLIST}`;
|
47
|
+
do cat $f | sed '/./,/^$/!d' > .blank_lines; cp .blank_lines $f; rm .blank_lines; echo $f;
|
48
|
+
done
|
49
|
+
}
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module RubyOmx
|
2
|
+
DEFAULT_HOST = 'https://api.omx.ordermotion.com/hdde/xml/udi.asp'
|
3
|
+
|
4
|
+
class Base
|
5
|
+
attr_accessor :connection
|
6
|
+
|
7
|
+
def self.debug; @@debug ||= false end
|
8
|
+
def self.debug=(bool); @@debug = bool end
|
9
|
+
|
10
|
+
def initialize(options ={})
|
11
|
+
@http_biz_id = options['http_biz_id']
|
12
|
+
@udi_auth_token = options['udi_auth_token']
|
13
|
+
raise "Must supply udi auth token" unless @udi_auth_token
|
14
|
+
raise "Must supply http biz ID" unless @http_biz_id
|
15
|
+
@connection = RubyOmx::Connection.connect(options)
|
16
|
+
end
|
17
|
+
|
18
|
+
def connection
|
19
|
+
raise RubyOmx::NoConnectionEstablished.new if !connected?
|
20
|
+
@connection
|
21
|
+
end
|
22
|
+
|
23
|
+
def connected?
|
24
|
+
!@connection.nil?
|
25
|
+
end
|
26
|
+
|
27
|
+
def disconnect
|
28
|
+
@connection.http.finish if @connection.persistent?
|
29
|
+
@connection = nil
|
30
|
+
end
|
31
|
+
|
32
|
+
# Wraps the current connection's request method and picks the appropriate response class to wrap the response in.
|
33
|
+
# If the response is an error, it will raise that error as an exception. All such exceptions can be caught by rescuing
|
34
|
+
# their superclass, the ResponseError exception class.
|
35
|
+
#
|
36
|
+
# It is unlikely that you would call this method directly. Subclasses of Base have convenience methods for each http request verb
|
37
|
+
# that wrap calls to request.
|
38
|
+
def request(verb, body = nil, attempts = 0, &block)
|
39
|
+
# Find the connection method in connection/management.rb which is evaled into Amazon::MWS::Base
|
40
|
+
response = @connection.request(verb, body, attempts, &block)
|
41
|
+
|
42
|
+
# Each calling class is responsible for formatting the result
|
43
|
+
return response
|
44
|
+
rescue InternalError, RequestTimeout
|
45
|
+
if attempts == 3
|
46
|
+
raise
|
47
|
+
else
|
48
|
+
attempts += 1
|
49
|
+
retry
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Make some convenience methods
|
54
|
+
[:get, :post, :put, :delete, :head].each do |verb|
|
55
|
+
class_eval(<<-EVAL, __FILE__, __LINE__)
|
56
|
+
def #{verb}(body = nil, &block)
|
57
|
+
request(:#{verb}, body, &block)
|
58
|
+
end
|
59
|
+
EVAL
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module RubyOmx
|
2
|
+
|
3
|
+
class Connection
|
4
|
+
# Static/Class methods
|
5
|
+
class << self
|
6
|
+
def connect(options = {})
|
7
|
+
new(options)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(params = {})
|
12
|
+
|
13
|
+
# These values are essential to establishing a connection
|
14
|
+
@udi_auth_token = params['udi_auth_token']
|
15
|
+
@server = params['server'] || RubyOmx::DEFAULT_HOST + "?UDIAuthToken=#{@udi_auth_token}"
|
16
|
+
@persistent = params['persistent'] || false
|
17
|
+
@http_biz_id = params['http_biz_id']
|
18
|
+
@path = URI.parse(@server).request_uri
|
19
|
+
|
20
|
+
raise MissingConnectionOptions if [@udi_auth_token, @http_biz_id].any? {|option| option.nil?}
|
21
|
+
@http = connect
|
22
|
+
end
|
23
|
+
|
24
|
+
# Create the Net::HTTP object to use for this connection
|
25
|
+
def connect
|
26
|
+
uri = URI.parse(@server)
|
27
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
28
|
+
http.use_ssl = true
|
29
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
30
|
+
return http
|
31
|
+
end
|
32
|
+
|
33
|
+
# Make the request, based on the appropriate request object
|
34
|
+
# Called from RubyOmx::Base
|
35
|
+
def request(verb, body = nil, attempts = 0, &block)
|
36
|
+
request = Net::HTTP.const_get(verb.to_s.capitalize).new(@path)
|
37
|
+
request.body = body
|
38
|
+
request.content_length = request.body.size
|
39
|
+
request.content_type = "text/xml; charset=utf-8"
|
40
|
+
@http.request(request)
|
41
|
+
|
42
|
+
rescue Errno::EPIPE, Timeout::Error, Errno::EINVAL, EOFError
|
43
|
+
@http = connect
|
44
|
+
attempts == 3 ? raise : (attempts += 1; retry)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module RubyOmx
|
2
|
+
|
3
|
+
# Abstract super class of all Amazon::MWS exceptions
|
4
|
+
class RubyOmxException < StandardError
|
5
|
+
end
|
6
|
+
|
7
|
+
# Abstract super class for all invalid options.
|
8
|
+
class InvalidOption < RubyOmxException
|
9
|
+
end
|
10
|
+
|
11
|
+
class InvalidMessageType < RubyOmxException
|
12
|
+
end
|
13
|
+
|
14
|
+
class InvalidReportType < RubyOmxException
|
15
|
+
end
|
16
|
+
|
17
|
+
class InvalidSchedule < RubyOmxException
|
18
|
+
end
|
19
|
+
|
20
|
+
class MissingConnectionOptions < RubyOmxException
|
21
|
+
end
|
22
|
+
|
23
|
+
class MissingOrderOptions < RubyOmxException
|
24
|
+
end
|
25
|
+
|
26
|
+
class MissingItemOptions < RubyOmxException
|
27
|
+
end
|
28
|
+
|
29
|
+
# All responses with a code between 300 and 599 that contain an <Error></Error> body are wrapped in an
|
30
|
+
# ErrorResponse which contains an Error object. This Error class generates a custom exception with the name
|
31
|
+
# of the xml Error and its message. All such runtime generated exception classes descend from ResponseError
|
32
|
+
# and contain the ErrorResponse object so that all code that makes a request can rescue ResponseError and get
|
33
|
+
# access to the ErrorResponse.
|
34
|
+
# class ResponseError < RubyOmxException
|
35
|
+
# def initialize(formatted_response)
|
36
|
+
# instance_eval(<<-EVAL, __FILE__, __LINE__)
|
37
|
+
# def request_id
|
38
|
+
# '#{formatted_response["RequestID"]}'
|
39
|
+
# end
|
40
|
+
# EVAL
|
41
|
+
#
|
42
|
+
# formatted_response["Error"].each do |key, value|
|
43
|
+
# instance_eval(<<-EVAL, __FILE__, __LINE__)
|
44
|
+
# def #{key.underscore}
|
45
|
+
# '#{value}'
|
46
|
+
# end
|
47
|
+
# EVAL
|
48
|
+
# end
|
49
|
+
# end
|
50
|
+
# end
|
51
|
+
|
52
|
+
class RequestTimeout < ResponseError
|
53
|
+
end
|
54
|
+
|
55
|
+
# Most ResponseError's are created just time on a need to have basis, but we explicitly define the
|
56
|
+
# InternalError exception because we want to explicitly rescue InternalError in some cases.
|
57
|
+
class InternalError < ResponseError
|
58
|
+
end
|
59
|
+
|
60
|
+
# Raised if an unrecognized option is passed when establishing a connection.
|
61
|
+
class InvalidConnectionOption < InvalidOption
|
62
|
+
def initialize(invalid_options)
|
63
|
+
message = "The following connection options are invalid: #{invalid_options.join(', ')}. " +
|
64
|
+
"The valid connection options are: #{Connection::Options::VALID_OPTIONS.join(', ')}."
|
65
|
+
super(message)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Raised if either the access key id or secret access key arguments are missing when establishing a connection.
|
70
|
+
class MissingAccessKey < InvalidOption
|
71
|
+
def initialize(missing_keys)
|
72
|
+
key_list = missing_keys.map {|key| key.to_s}.join(' and the ')
|
73
|
+
super("You did not provide both required access keys. Please provide the #{key_list}.")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Raised if a request is attempted before any connections have been established.
|
78
|
+
class NoConnectionEstablished < RubyOmxException
|
79
|
+
def initialize
|
80
|
+
super("\nPlease use Amazon::MWS::Base.establish_connection! before making API calls.")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module RubyOmx
|
2
|
+
module Items
|
3
|
+
|
4
|
+
# ItemInformationRequest (ITIR100) This request type lists the name, default prices, inventory availability, sub-items, cross-sell items, substitution items, and bundle items for a given item code.
|
5
|
+
def get_item_info(params ={})
|
6
|
+
required_fields = [
|
7
|
+
params[:item_code]
|
8
|
+
]
|
9
|
+
raise MissingOrderOptions if required_fields.any? {|option| option.nil?}
|
10
|
+
item_code = params[:item_code]
|
11
|
+
raw_xml = params[:raw_xml] ||= 0
|
12
|
+
|
13
|
+
doc = Nokogiri::XML::Document.new
|
14
|
+
root_tag = RubyOmx.add_child_helper(doc,'ItemInformationRequest','version','1.00',nil)
|
15
|
+
udi_parameter = RubyOmx.add_child_helper(root_tag,'UDIParameter',nil,nil,nil)
|
16
|
+
RubyOmx.add_child_helper(udi_parameter,'Parameter','key','HTTPBizID',@http_biz_id)
|
17
|
+
RubyOmx.add_child_helper(udi_parameter,'Parameter','key','ItemCode',item_code)
|
18
|
+
RubyOmx.add_child_helper(udi_parameter,'Parameter','key','OutputSubItemAttributes','True')
|
19
|
+
response = post(doc.to_xml)
|
20
|
+
if raw_xml==1
|
21
|
+
return response
|
22
|
+
else
|
23
|
+
ItemInfoResponse.format(response)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
#CustomItemAttributeInformationRequest (CIAIR200) This request type lists all the custom item attributes names and values for a given item code or list of item codes, in one or all custom item attribute groups.
|
29
|
+
def get_custom_item_info(params ={})
|
30
|
+
required_fields = [
|
31
|
+
params[:item_code]
|
32
|
+
]
|
33
|
+
raise MissingOrderOptions if required_fields.any? {|option| option.nil?}
|
34
|
+
item_code = params[:item_code]
|
35
|
+
raw_xml = params[:raw_xml] ||= 0
|
36
|
+
|
37
|
+
doc = Nokogiri::XML::Document.new
|
38
|
+
root_tag = RubyOmx.add_child_helper(doc,'CustomItemAttributeInformationRequest','version','2.00',nil)
|
39
|
+
udi_parameter = RubyOmx.add_child_helper(root_tag,'UDIParameter',nil,nil,nil)
|
40
|
+
RubyOmx.add_child_helper(udi_parameter,'Parameter','key','HTTPBizID',@http_biz_id)
|
41
|
+
RubyOmx.add_child_helper(udi_parameter,'Parameter','key','ItemCode',item_code)
|
42
|
+
RubyOmx.add_child_helper(udi_parameter,'Parameter','key','AttributeGroupID','All')
|
43
|
+
response = post(doc.to_xml)
|
44
|
+
if raw_xml==1
|
45
|
+
return response
|
46
|
+
else
|
47
|
+
ItemInfoResponse.format(response)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
#CustomItemAttributeUpdateRequest (CIAUR100) This request type is used to set or update the custom item attribute values for a given item code.
|
52
|
+
#ItemCategoryUpdateRequest (ITCATUR100) This request type is used to set the categories for an item. Categories can be used as the basis for webstore sections, or other classification needs in the application.
|
53
|
+
#ItemCustomizationGroupAssignmentRequest (ICGAR200) This request type allows for assigning a shared customization group to an item, by name or by ID.
|
54
|
+
#ItemCustomizationGroupUpdateRequest (ICGUR200) This request type is used to update shared item customization groups in the account.
|
55
|
+
#ItemCustomizationUpdateRequest (ICUR200) This request type is used to add and update individual item customizations by item, rather than shared customization groups.
|
56
|
+
#ItemListRequest (ILR100) This command returns a list of items.
|
57
|
+
#ItemLocationUpdateRequest (ILUR100) This command enables you to update item location information.
|
58
|
+
#ItemLocatorRequest (ITLR100) This request type lists possible matches for an item given search information.
|
59
|
+
#ItemPriceUpdateRequest (IPUR100) This request type is used to update item default prices or keycode prices.
|
60
|
+
#ItemUpdateRequest (ITUR200) This command enables you to create items, or update item information (with selective partial updates).
|
61
|
+
#LocationUpdateRequest (LUR100) This command enables you to update location information.
|
62
|
+
#SubItemUpdateRequest (SITUR100) This request type is used to update parent/sub-item associations, or to create new sub-items for a given parent item.
|
63
|
+
#SupplierItemUpdateRequest (SUPITUR100) This request type is used to create or update a supplier-item association.
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
module RubyOmx
|
2
|
+
module Orders
|
3
|
+
|
4
|
+
#UniversalDirectOrderAppending (UDOA200) This request type is used to create orders in the application.
|
5
|
+
def append_order(params ={})
|
6
|
+
|
7
|
+
required_fields = [
|
8
|
+
params[:keycode],
|
9
|
+
params[:queue_flag],
|
10
|
+
params[:verify_flag],
|
11
|
+
params[:order_date],
|
12
|
+
params[:order_id],
|
13
|
+
params[:last_name],
|
14
|
+
params[:line_items],
|
15
|
+
params[:method_code],
|
16
|
+
params[:total_amount]
|
17
|
+
]
|
18
|
+
#raise MissingOrderOptions if required_fields.any? {|option| option.nil?}
|
19
|
+
|
20
|
+
raw_xml = params[:raw_xml] ||= 0
|
21
|
+
|
22
|
+
doc = Nokogiri::XML::Document.new
|
23
|
+
root_tag = RubyOmx.add_child_helper(doc,'UDOARequest','version','2.00',nil)
|
24
|
+
|
25
|
+
udi_parameter = RubyOmx.add_child_helper(root_tag,'UDIParameter',nil,nil,nil)
|
26
|
+
RubyOmx.add_child_helper(udi_parameter,'Parameter','key','HTTPBizID',@http_biz_id)
|
27
|
+
RubyOmx.add_child_helper(udi_parameter,'Parameter','key','UDIAuthToken',@udi_auth_token)
|
28
|
+
RubyOmx.add_child_helper(udi_parameter,'Parameter','key','QueueFlag',params[:queue_flag] ||= 'False') # Determines whether any orders with errors will be stored in the OrderMotion "Outside Order Queue", to be corrected by an OrderMotion user before resubmission. If set to "True", almost all orders will be accepted by OrderMotion, but additional order information will only be returned in the response if the order is successfully placed. Otherwise, any order with any error (eg invalid ZIP code) will be rejected.
|
29
|
+
RubyOmx.add_child_helper(udi_parameter,'Parameter','key','Keycode',params[:keycode])
|
30
|
+
RubyOmx.add_child_helper(udi_parameter,'Parameter','key','VerifyFlag',params[:verify_flag] ||= 'True') # Determines whether a successful order should be saved, or only verified/calculated. When set to "True", OrderMotion will behave as if the order was placed, but not return an Order Number in the response.
|
31
|
+
RubyOmx.add_child_helper(udi_parameter,'Parameter','key','Vendor',params[:vendor] ||= nil)
|
32
|
+
|
33
|
+
header = RubyOmx.add_child_helper(root_tag,'Header',nil,nil,nil)
|
34
|
+
RubyOmx.add_child_helper(header,'StoreCode',nil,nil,params[:store_code] ||= '')
|
35
|
+
RubyOmx.add_child_helper(header,'OrderID',nil,nil,params[:order_id])
|
36
|
+
RubyOmx.add_child_helper(header,'OrderDate',nil,nil,params[:order_date]) # Dates are almost the same as the W3C Schema "date" type, but with a space instead of the "T" separating the date from the time.
|
37
|
+
RubyOmx.add_child_helper(header,'OriginType',nil,nil,params[:origin_type] ||= '2') # 2 = phone order, 3 = internet order
|
38
|
+
|
39
|
+
customer = RubyOmx.add_child_helper(root_tag,'Customer',nil,nil,nil)
|
40
|
+
address = RubyOmx.add_child_helper(customer,'Address','type','BillTo',nil)
|
41
|
+
RubyOmx.add_child_helper(address,'TitleCode',nil,nil,params[:title_code] ||= '0')
|
42
|
+
RubyOmx.add_child_helper(address,'Firstname',nil,nil,params[:first_name] ||= 'Test')
|
43
|
+
RubyOmx.add_child_helper(address,'Lastname',nil,nil,params[:last_name] ||= 'Test')
|
44
|
+
RubyOmx.add_child_helper(address,'Address1',nil,nil,params[:address1] ||= nil)
|
45
|
+
RubyOmx.add_child_helper(address,'Address2',nil,nil,params[:address2] ||= nil)
|
46
|
+
RubyOmx.add_child_helper(address,'City',nil,nil,params[:city] ||=nil)
|
47
|
+
RubyOmx.add_child_helper(address,'State',nil,nil,params[:state] ||= nil)
|
48
|
+
RubyOmx.add_child_helper(address,'ZIP',nil,nil,params[:zip] ||=nil)
|
49
|
+
RubyOmx.add_child_helper(address,'TLD',nil,nil,params[:tld] ||=nil)
|
50
|
+
RubyOmx.add_child_helper(address,'PhoneNumber',nil,nil,params[:phone] ||= nil)
|
51
|
+
RubyOmx.add_child_helper(address,'Email',nil,nil,params[:email] ||= nil)
|
52
|
+
|
53
|
+
shipping_info = RubyOmx.add_child_helper(root_tag,'ShippingInformation',nil,nil,nil)
|
54
|
+
RubyOmx.add_child_helper(shipping_info,'MethodCode',nil,nil,params[:method_code])
|
55
|
+
# address = RubyOmx.add_child_helper(shipping_info,'Address','type','ShipTo',nil)
|
56
|
+
# RubyOmx.add_child_helper(address,'TitleCode',nil,nil,'0')
|
57
|
+
# RubyOmx.add_child_helper(address,'Firstname',nil,nil,'Test') #TODO capture the first and last name for billing, not just shipping
|
58
|
+
# RubyOmx.add_child_helper(address,'Lastname',nil,nil,'Test')
|
59
|
+
# RubyOmx.add_child_helper(address,'Address1',nil,nil,'251 West 30th St')
|
60
|
+
# RubyOmx.add_child_helper(address,'Address2',nil,nil,'Apt 12E')
|
61
|
+
# RubyOmx.add_child_helper(address,'City',nil,nil,'New York')
|
62
|
+
# RubyOmx.add_child_helper(address,'State',nil,nil,'NY')
|
63
|
+
# RubyOmx.add_child_helper(address,'ZIP',nil,nil,'10001')
|
64
|
+
# RubyOmx.add_child_helper(address,'TLD',nil,nil,'US')
|
65
|
+
# RubyOmx.add_child_helper(address,'PhoneNumber',nil,nil,nil)
|
66
|
+
# RubyOmx.add_child_helper(address,'Email',nil,nil,nil)
|
67
|
+
RubyOmx.add_child_helper(shipping_info,'ShippingAmount',nil,nil,params[:shipping_amount] ||= '0.00')
|
68
|
+
#RubyOmx.add_child_helper(shipping_info,'HandlingAmount',nil,nil,'0')
|
69
|
+
#RubyOmx.add_child_helper(shipping_info,'SpecialInstructions',nil,nil,'0')
|
70
|
+
RubyOmx.add_child_helper(shipping_info,'GiftWrapping',nil,nil,params[:gift_wrapping] ||= 'False')
|
71
|
+
RubyOmx.add_child_helper(shipping_info,'GiftMessage',nil,nil,params[:gift_message] ||= nil)
|
72
|
+
|
73
|
+
payment_type = RubyOmx.add_child_helper(root_tag,'Payment','type',params[:payment_type] ||= '6',nil) #6 for open invoice
|
74
|
+
# RubyOmx.add_child_helper(payment_type,'CardNumber',nil,nil,'4111111111111111')
|
75
|
+
# RubyOmx.add_child_helper(payment_type,'CardVerification',nil,nil,'222')
|
76
|
+
# RubyOmx.add_child_helper(payment_type,'CardExpDateMonth',nil,nil,'09')
|
77
|
+
# RubyOmx.add_child_helper(payment_type,'CardExpDateYear',nil,nil,'2011')
|
78
|
+
# RubyOmx.add_child_helper(payment_type,'CardStatus',nil,nil,'11')
|
79
|
+
# RubyOmx.add_child_helper(payment_type,'CardAuthCode',nil,nil,'11')
|
80
|
+
# RubyOmx.add_child_helper(payment_type,'CardTransactionID',nil,nil,'123456789')
|
81
|
+
|
82
|
+
order_detail = RubyOmx.add_child_helper(root_tag,'OrderDetail',nil,nil,nil)
|
83
|
+
|
84
|
+
i=1
|
85
|
+
params[:line_items].each do |item|
|
86
|
+
raise MissingItemOptions if item[:item_code].nil?
|
87
|
+
line_item = RubyOmx.add_child_helper(order_detail,'LineItem','lineNumber',i.to_s,nil)
|
88
|
+
RubyOmx.add_child_helper(line_item,'ItemCode',nil,nil,item[:item_code])
|
89
|
+
RubyOmx.add_child_helper(line_item,'Quantity',nil,nil,item[:quantity] ||= '1')
|
90
|
+
if !item[:unit_price].nil?
|
91
|
+
RubyOmx.add_child_helper(line_item,'UnitPrice',nil,nil,item[:unit_price])
|
92
|
+
end
|
93
|
+
#RubyOmx.add_child_helper(line_item,'StandingOrder','configurationID','5',nil)
|
94
|
+
#customization = RubyOmx.add_child_helper(line_item,'ItemCustomizationData',nil,nil,nil)
|
95
|
+
#field = RubyOmx.add_child_helper(customization,'CustomizationField','fieldID','127',nil)
|
96
|
+
#RubyOmx.add_child_helper(field,'Value',nil,nil,'demoText')
|
97
|
+
i+=1
|
98
|
+
end
|
99
|
+
|
100
|
+
check = RubyOmx.add_child_helper(root_tag,'Check',nil,nil,nil)
|
101
|
+
RubyOmx.add_child_helper(check,'TotalAmount',nil,nil,params[:total_amount])
|
102
|
+
|
103
|
+
response = post(doc.to_xml)
|
104
|
+
if raw_xml==1
|
105
|
+
return response
|
106
|
+
else
|
107
|
+
AppendOrderResponse.format(response)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
#OrderDetailUpdateRequest (ODUR100) This request type enables you to update certain data for orders.
|
112
|
+
|
113
|
+
|
114
|
+
#CancellationHistoryRequest (CHR100) This request type lists all the cancellations that have occurred between two dates.
|
115
|
+
#InvoiceProcessRequest (IPR100) This command takes an order number, and runs the invoicing and credit memo processes against the order if there are any order lines that can be subject to an invoice or credit memo, or if there are returns on the order.
|
116
|
+
#OrderCancellationRequest (OCR100) This request type enables you to cancel some or all the line items in an order.
|
117
|
+
#OrderInformationRequest (OIR200) This request type provides the ShippingInformationRequest (SIR) result for the order as a whole.
|
118
|
+
#OrderSecondaryStatusUpdateRequest (OSSUR100) This request type enables you to set the secondary status of the OrderLines.
|
119
|
+
#OrderUpdateRequest (OUR200) This request type enables you to change the Payment Plan of an order, as well as the basis date for payment plan calculation, and also update the "Alt ID 2" (a.k.a "Reference") field of the order.
|
120
|
+
#OrderWaitDateUpdateRequest (OWDUR100) This request type enables you to change the Wait Date of an existing order.
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module RubyOmx
|
2
|
+
|
3
|
+
class ItemInfoResponse < Response
|
4
|
+
#xml_name "Item"
|
5
|
+
xml_name "ItemInformationResponse"
|
6
|
+
#result = "Item"
|
7
|
+
|
8
|
+
xml_reader :item_code, :from => '@itemCode', :in => "Item"
|
9
|
+
xml_reader :active, :from => '@active', :in => "Item"
|
10
|
+
xml_reader :incomplete, :from => '@incomplete', :in => "Item"
|
11
|
+
xml_reader :parent_item_code, :from => '@parentItemCode', :in => "Item"
|
12
|
+
|
13
|
+
|
14
|
+
xml_reader :product_name, :in => "Item"
|
15
|
+
xml_reader :available_inventory, :as => Integer, :in => "Item"
|
16
|
+
xml_reader :sub_item_count, :as => Integer, :in => "Item"
|
17
|
+
xml_reader :last_updated_date, :as => DateTime, :in => "Item"
|
18
|
+
xml_reader :weight, :as => Float, :in => "Item"
|
19
|
+
|
20
|
+
xml_reader :price_type, :from => '@priceType', :in => 'Item/PriceData'
|
21
|
+
xml_reader :price_quantity, :from => '@quantity', :in => 'Item/PriceData/Price', :as => Integer
|
22
|
+
xml_reader :price_amount, :from => 'Amount', :in => 'Item/PriceData/Price', :as => Float
|
23
|
+
xml_reader :price_addl_sh, :from => 'AdditionalSH', :in => 'Item/PriceData/Price', :as => Float
|
24
|
+
xml_reader :bonus, :in => 'Item/PriceData/Price', :as => Float
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module RubyOmx
|
2
|
+
|
3
|
+
class ResponseError < Response
|
4
|
+
xml_name "ErrorResponse"
|
5
|
+
|
6
|
+
xml_reader :type, :in => "Error"
|
7
|
+
xml_reader :code, :in => "Error"
|
8
|
+
xml_reader :message, :in => "Error"
|
9
|
+
xml_reader :detail, :in => "Error"
|
10
|
+
xml_reader :request_id
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module RubyOmx
|
2
|
+
|
3
|
+
class Response
|
4
|
+
include ROXML
|
5
|
+
xml_convention :camelcase
|
6
|
+
|
7
|
+
# This is the factoryish method that is called!, not new
|
8
|
+
def self.format(response)
|
9
|
+
if response.content_type =~ /xml/ || response.body =~ /<?xml/
|
10
|
+
parse_xml(response)
|
11
|
+
else
|
12
|
+
response.body
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.parse_xml(response)
|
17
|
+
if [Net::HTTPClientError, Net::HTTPServerError].any? {|error| response.is_a? error }
|
18
|
+
puts "ERROR: #{response} -- #{response.body}"
|
19
|
+
return ResponseError.from_xml(response.body)
|
20
|
+
else
|
21
|
+
return self.from_xml(response.body)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def accessors
|
26
|
+
roxml_references.map {|r| r.accessor}
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
data/lib/ruby_omx.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
#require 'rubygems'
|
2
|
+
require 'cgi'
|
3
|
+
require 'uri'
|
4
|
+
require 'openssl'
|
5
|
+
require 'net/https'
|
6
|
+
require 'time'
|
7
|
+
require 'date'
|
8
|
+
require 'base64'
|
9
|
+
require 'builder'
|
10
|
+
require "rexml/document"
|
11
|
+
require 'roxml'
|
12
|
+
|
13
|
+
$:.unshift(File.dirname(__FILE__))
|
14
|
+
|
15
|
+
module RubyOmx
|
16
|
+
|
17
|
+
module_function
|
18
|
+
def add_child_helper(parent_node,child_name,key,value,content)
|
19
|
+
new_node = parent_node.add_child(Nokogiri::XML::Node.new child_name, parent_node)
|
20
|
+
if !key.nil? && !value.nil?
|
21
|
+
new_node[key] = value
|
22
|
+
end
|
23
|
+
if !content.nil?
|
24
|
+
new_node.content = content
|
25
|
+
end
|
26
|
+
return new_node
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
require 'ruby_omx/response'
|
32
|
+
require 'ruby_omx/orders'
|
33
|
+
require 'ruby_omx/items'
|
34
|
+
Dir.glob(File.join(File.dirname(__FILE__), 'ruby_omx/response/*.rb')).each {|f| require f }
|
35
|
+
|
36
|
+
require 'ruby_omx/base'
|
37
|
+
require 'ruby_omx/version'
|
38
|
+
require 'ruby_omx/exceptions'
|
39
|
+
require 'ruby_omx/connection'
|
40
|
+
|
41
|
+
RubyOmx::Base.class_eval do
|
42
|
+
include RubyOmx::Orders
|
43
|
+
include RubyOmx::Items
|
44
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
if RUBY_VERSION.match("1.9")
|
2
|
+
require 'simplecov'
|
3
|
+
SimpleCov.start do
|
4
|
+
add_filter 'test'
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'minitest/autorun'
|
9
|
+
require 'pathname'
|
10
|
+
require 'yaml'
|
11
|
+
require 'mocha'
|
12
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'ruby_omx')
|
13
|
+
|
14
|
+
def xml_for(name, code)
|
15
|
+
file = File.open(Pathname.new(File.dirname(__FILE__)).expand_path.dirname.join("examples/xml/#{name}.xml"),'rb')
|
16
|
+
mock_response(code, {:content_type=>'text/xml', :body=>file.read})
|
17
|
+
end
|
18
|
+
|
19
|
+
def mock_response(code, options={})
|
20
|
+
body = options[:body]
|
21
|
+
content_type = options[:content_type]
|
22
|
+
response = Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, "message")
|
23
|
+
response.instance_variable_set(:@body, body)
|
24
|
+
response.instance_variable_set(:@read, true)
|
25
|
+
response.content_type = content_type
|
26
|
+
return response
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruby_omx
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- A. Edward Wible
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-04-19 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: roxml
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.3.1
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 3.3.1
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: xml-simple
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 1.1.1
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.1.1
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: builder
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 3.0.0
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 3.0.0
|
62
|
+
description: Ruby wrapper for OrderMotion (OMX) developer API
|
63
|
+
email:
|
64
|
+
- aewiblee@gmail.com
|
65
|
+
executables: []
|
66
|
+
extensions: []
|
67
|
+
extra_rdoc_files: []
|
68
|
+
files:
|
69
|
+
- lib/ruby_omx/base.rb
|
70
|
+
- lib/ruby_omx/connection.rb
|
71
|
+
- lib/ruby_omx/exceptions.rb
|
72
|
+
- lib/ruby_omx/items.rb
|
73
|
+
- lib/ruby_omx/orders.rb
|
74
|
+
- lib/ruby_omx/response/append_order_response.rb
|
75
|
+
- lib/ruby_omx/response/item_info_response.rb
|
76
|
+
- lib/ruby_omx/response/response_error.rb
|
77
|
+
- lib/ruby_omx/response.rb
|
78
|
+
- lib/ruby_omx/version.rb
|
79
|
+
- lib/ruby_omx.rb
|
80
|
+
- MIT-LICENSE
|
81
|
+
- Rakefile
|
82
|
+
- README.rdoc
|
83
|
+
- test/ruby_omx_test.rb
|
84
|
+
- test/test_helper.rb
|
85
|
+
homepage: http://github.com/aew/ruby_omx
|
86
|
+
licenses: []
|
87
|
+
post_install_message:
|
88
|
+
rdoc_options: []
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
none: false
|
93
|
+
requirements:
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
99
|
+
requirements:
|
100
|
+
- - ! '>='
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
requirements: []
|
104
|
+
rubyforge_project:
|
105
|
+
rubygems_version: 1.8.22
|
106
|
+
signing_key:
|
107
|
+
specification_version: 3
|
108
|
+
summary: Ruby wrapper for OrderMotion (OMX)
|
109
|
+
test_files:
|
110
|
+
- test/ruby_omx_test.rb
|
111
|
+
- test/test_helper.rb
|