amazon-mws-plus 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.project +12 -0
  4. data/Gemfile +13 -0
  5. data/README.markdown +30 -0
  6. data/Rakefile +50 -0
  7. data/amazon-mws-plus.gemspec +23 -0
  8. data/amazon-mws.tmproj +27 -0
  9. data/examples/xml/cancel_feed_submissions.xml +16 -0
  10. data/examples/xml/cancel_fulfillment_order.xml +6 -0
  11. data/examples/xml/cancel_report_requests.xml +18 -0
  12. data/examples/xml/create_fulfillment_order.xml +6 -0
  13. data/examples/xml/error.xml +10 -0
  14. data/examples/xml/get_feed_submission_count.xml +10 -0
  15. data/examples/xml/get_feed_submission_list.xml +18 -0
  16. data/examples/xml/get_feed_submission_list_by_next_token.xml +16 -0
  17. data/examples/xml/get_feed_submission_result.xml +30 -0
  18. data/examples/xml/get_fulfillment_order.xml +113 -0
  19. data/examples/xml/get_fulfillment_preview.xml +148 -0
  20. data/examples/xml/get_matching_product.xml +115 -0
  21. data/examples/xml/get_matching_product_for_id.xml +119 -0
  22. data/examples/xml/get_report.xml +237 -0
  23. data/examples/xml/get_report_count.xml +9 -0
  24. data/examples/xml/get_report_list.xml +17 -0
  25. data/examples/xml/get_report_request_count.xml +8 -0
  26. data/examples/xml/get_report_request_list.xml +120 -0
  27. data/examples/xml/get_report_request_list_by_next_token.xml +20 -0
  28. data/examples/xml/get_report_schedule_count.xml +10 -0
  29. data/examples/xml/get_report_schedule_list.xml +15 -0
  30. data/examples/xml/get_report_schedule_list_by_next_token.xml +15 -0
  31. data/examples/xml/list_all_fulfillment_orders.xml +69 -0
  32. data/examples/xml/list_all_fulfillment_orders_by_next_token.xml +61 -0
  33. data/examples/xml/manage_report_schedule.xml +14 -0
  34. data/examples/xml/orders_request.xml +39 -0
  35. data/examples/xml/request_order_items.xml +51 -0
  36. data/examples/xml/request_order_items_by_next_token.xml +51 -0
  37. data/examples/xml/request_orders.xml +43 -0
  38. data/examples/xml/request_orders_by_next_token.xml +69 -0
  39. data/examples/xml/request_report.xml +17 -0
  40. data/examples/xml/submit_feed.xml +14 -0
  41. data/examples/xml/update_report_acknowledgements.xml +18 -0
  42. data/examples/xsd/Inventory.xsd +49 -0
  43. data/examples/xsd/Item.xsd +285 -0
  44. data/examples/xsd/Listings.xsd +32 -0
  45. data/examples/xsd/OrderAcknowledgement.xsd +55 -0
  46. data/examples/xsd/OrderAdjustment.xsd +94 -0
  47. data/examples/xsd/OrderFulfillment.xsd +57 -0
  48. data/examples/xsd/Override.xsd +48 -0
  49. data/examples/xsd/Price.xsd +59 -0
  50. data/examples/xsd/ProcessingReport.xsd +87 -0
  51. data/examples/xsd/Product.xsd +220 -0
  52. data/examples/xsd/Product/AutoAccessory.xsd +807 -0
  53. data/examples/xsd/Product/Beauty.xsd +114 -0
  54. data/examples/xsd/Product/CE.xsd +544 -0
  55. data/examples/xsd/Product/CameraPhoto.xsd +2410 -0
  56. data/examples/xsd/Product/FoodAndBeverages.xsd +270 -0
  57. data/examples/xsd/Product/Gourmet.xsd +85 -0
  58. data/examples/xsd/Product/Health.xsd +189 -0
  59. data/examples/xsd/Product/Home.xsd +654 -0
  60. data/examples/xsd/Product/Jewelry.xsd +603 -0
  61. data/examples/xsd/Product/Miscellaneous.xsd +157 -0
  62. data/examples/xsd/Product/MusicalInstruments.xsd +853 -0
  63. data/examples/xsd/Product/Office.xsd +550 -0
  64. data/examples/xsd/Product/PetSupplies.xsd +40 -0
  65. data/examples/xsd/Product/ProductClothing.xsd +197 -0
  66. data/examples/xsd/Product/SWVG.xsd +238 -0
  67. data/examples/xsd/Product/Sports.xsd +308 -0
  68. data/examples/xsd/Product/TiresAndWheels.xsd +159 -0
  69. data/examples/xsd/Product/Tools.xsd +62 -0
  70. data/examples/xsd/Product/ToysBaby.xsd +241 -0
  71. data/examples/xsd/Product/Wireless.xsd +77 -0
  72. data/examples/xsd/ProductImage.xsd +39 -0
  73. data/examples/xsd/Relationship.xsd +47 -0
  74. data/examples/xsd/SettlementReport.xsd +158 -0
  75. data/examples/xsd/amzn-base.xsd +1600 -0
  76. data/examples/xsd/amzn-envelope.xsd +98 -0
  77. data/examples/xsd/amzn-header.xsd +45 -0
  78. data/lib/amazon-mws.rb +6 -0
  79. data/lib/amazon/mws.rb +69 -0
  80. data/lib/amazon/mws/authentication.rb +10 -0
  81. data/lib/amazon/mws/authentication/query_string.rb +36 -0
  82. data/lib/amazon/mws/authentication/signature.rb +43 -0
  83. data/lib/amazon/mws/base.rb +74 -0
  84. data/lib/amazon/mws/connection.rb +107 -0
  85. data/lib/amazon/mws/connection/management.rb +95 -0
  86. data/lib/amazon/mws/connection/request_builder.rb +67 -0
  87. data/lib/amazon/mws/exceptions.rb +55 -0
  88. data/lib/amazon/mws/lib/extensions.rb +178 -0
  89. data/lib/amazon/mws/lib/memoizable.rb +10 -0
  90. data/lib/amazon/mws/request/feed.rb +276 -0
  91. data/lib/amazon/mws/request/feed_builder.rb +83 -0
  92. data/lib/amazon/mws/request/fulfillment.rb +50 -0
  93. data/lib/amazon/mws/request/orders.rb +107 -0
  94. data/lib/amazon/mws/request/products.rb +38 -0
  95. data/lib/amazon/mws/request/report.rb +330 -0
  96. data/lib/amazon/mws/response.rb +43 -0
  97. data/lib/amazon/mws/response/feed/cancel_feed_submissions_response.rb +15 -0
  98. data/lib/amazon/mws/response/feed/get_feed_submission_count_response.rb +13 -0
  99. data/lib/amazon/mws/response/feed/get_feed_submission_list_by_next_token_response.rb +17 -0
  100. data/lib/amazon/mws/response/feed/get_feed_submission_list_response.rb +16 -0
  101. data/lib/amazon/mws/response/feed/get_feed_submission_result_response.rb +54 -0
  102. data/lib/amazon/mws/response/feed/models/feed_submission.rb +16 -0
  103. data/lib/amazon/mws/response/feed/submit_feed_response.rb +15 -0
  104. data/lib/amazon/mws/response/fulfillment_order/cancel_fulfillment_order_response.rb +11 -0
  105. data/lib/amazon/mws/response/fulfillment_order/create_fulfillment_order_response.rb +12 -0
  106. data/lib/amazon/mws/response/fulfillment_order/get_fulfillment_order_response.rb +19 -0
  107. data/lib/amazon/mws/response/fulfillment_order/list_all_fulfillment_orders_by_next_token_response.rb +16 -0
  108. data/lib/amazon/mws/response/fulfillment_order/list_all_fulfillment_orders_response.rb +15 -0
  109. data/lib/amazon/mws/response/fulfillment_order/models/fulfillment_address.rb +18 -0
  110. data/lib/amazon/mws/response/fulfillment_order/models/fulfillment_order.rb +24 -0
  111. data/lib/amazon/mws/response/fulfillment_order/models/fulfillment_order_item.rb +20 -0
  112. data/lib/amazon/mws/response/fulfillment_order/models/fulfillment_shipment.rb +18 -0
  113. data/lib/amazon/mws/response/fulfillment_order/models/fulfillment_shipment_item.rb +14 -0
  114. data/lib/amazon/mws/response/order/models/order.rb +43 -0
  115. data/lib/amazon/mws/response/order/models/order_item.rb +48 -0
  116. data/lib/amazon/mws/response/order/models/promotion_id.rb +9 -0
  117. data/lib/amazon/mws/response/order/request_get_order_response.rb +15 -0
  118. data/lib/amazon/mws/response/order/request_order_items_response.rb +25 -0
  119. data/lib/amazon/mws/response/order/request_orders_response.rb +28 -0
  120. data/lib/amazon/mws/response/product/get_matching_proudct.rb +31 -0
  121. data/lib/amazon/mws/response/product/models/product.rb +36 -0
  122. data/lib/amazon/mws/response/report/cancel_report_requests_response.rb +16 -0
  123. data/lib/amazon/mws/response/report/get_report_count_response.rb +13 -0
  124. data/lib/amazon/mws/response/report/get_report_list_response.rb +17 -0
  125. data/lib/amazon/mws/response/report/get_report_request_count_response.rb +13 -0
  126. data/lib/amazon/mws/response/report/get_report_request_list_by_next_token_response.rb +17 -0
  127. data/lib/amazon/mws/response/report/get_report_request_list_response.rb +17 -0
  128. data/lib/amazon/mws/response/report/get_report_schedule_count_response.rb +13 -0
  129. data/lib/amazon/mws/response/report/get_report_schedule_list_by_next_token_response.rb +17 -0
  130. data/lib/amazon/mws/response/report/get_report_schedule_list_response.rb +17 -0
  131. data/lib/amazon/mws/response/report/manage_report_schedule_response.rb +16 -0
  132. data/lib/amazon/mws/response/report/models/report_info.rb +16 -0
  133. data/lib/amazon/mws/response/report/models/report_request.rb +20 -0
  134. data/lib/amazon/mws/response/report/models/report_schedule.rb +13 -0
  135. data/lib/amazon/mws/response/report/request_report_response.rb +15 -0
  136. data/lib/amazon/mws/response/report/update_reports_acknowledgements_response.rb +16 -0
  137. data/lib/amazon/mws/response/response.rb +43 -0
  138. data/lib/amazon/mws/response/response_error.rb +21 -0
  139. data/test/connection_test.rb +14 -0
  140. data/test/feed_builder_test.rb +74 -0
  141. data/test/feed_test.rb +144 -0
  142. data/test/fulfillment_order.rb +49 -0
  143. data/test/orders_test.rb +78 -0
  144. data/test/products_test.rb +28 -0
  145. data/test/query_string_test.rb +18 -0
  146. data/test/report_test.rb +88 -0
  147. data/test/response_test.rb +172 -0
  148. data/test/signature_test.rb +32 -0
  149. data/test/test_config.yml +6 -0
  150. data/test/test_helper.rb +33 -0
  151. metadata +335 -0
@@ -0,0 +1,95 @@
1
+ class Amazon::MWS::Connection
2
+
3
+ module Management #:nodoc:
4
+ =begin
5
+ def self.included(base)
6
+ base.cattr_accessor :connections
7
+ base.connections = {}
8
+ base.extend ClassMethods
9
+ end
10
+
11
+ # Manage the creation and destruction of connections for Amazon::MWS::Base and its subclasses. Connections are
12
+ # created with establish_connection!.
13
+ module ClassMethods
14
+ # Creates a new connection with which to make requests to the S3 servers for the calling class.
15
+ #
16
+ # Amazon::MWS::Base.establish_connection!(
17
+ # :access_key_id => '...',
18
+ # :secret_access_key => '...',
19
+ # :merchant_id => '...',
20
+ # :marketplace_id => '...'
21
+ # )
22
+ #
23
+ # == Required arguments
24
+ #
25
+ # * <tt>:access_key_id</tt> - The access key id for your S3 account. Provided by Amazon.
26
+ # * <tt>:secret_access_key</tt> - The secret access key for your S3 account. Provided by Amazon.
27
+ # * <tt>:merchant_id</tt>
28
+ # * <tt>:marketplace_id</tt>
29
+ #
30
+ # If any of these required arguments is missing, a MissingAccessKey exception will be raised.
31
+ #
32
+ # == Optional arguments
33
+ #
34
+ # * <tt>:server</tt> - The server to make requests to. You can use this to specify your bucket in the subdomain,
35
+ # or your own domain's cname if you are using virtual hosted buckets. Defaults to <tt>mws.amazonaws.com</tt>.
36
+ # will be implicitly set to 443, unless specified otherwise. Defaults to false.
37
+ # * <tt>:persistent</tt> - Whether to use a persistent connection to the server. Having this on provides around a two fold
38
+ # performance increase but for long running processes some firewalls may find the long lived connection suspicious and close the connection.
39
+ # If you run into connection errors, try setting <tt>:persistent</tt> to false. Defaults to false.
40
+ #
41
+ def establish_connection!(options = {})
42
+ # After you've already established the default connection, just specify
43
+ # the difference for subsequent connections
44
+ #options = default_connection.options.merge(options) if connected?
45
+ connections[connection_name] = Amazon::MWS::Connection.connect(options)
46
+ end
47
+
48
+ # Returns the connection for the current class, or Base's default connection if the current class does not
49
+ # have its own connection.
50
+ #
51
+ # If not connection has been established yet, NoConnectionEstablished will be raised.
52
+ def connection
53
+ if connected?
54
+ connections[connection_name] || default_connection
55
+ else
56
+ raise Amazon::MWS::NoConnectionEstablished.new
57
+ end
58
+ end
59
+
60
+ # Returns true if a connection has been made yet.
61
+ def connected?
62
+ !connections.empty?
63
+ end
64
+
65
+ # Removes the connection for the current class. If there is no connection for the current class, the default
66
+ # connection will be removed.
67
+ def disconnect(name = connection_name)
68
+ name = default_connection unless connections.has_key?(name)
69
+ connection = connections[name]
70
+ connection.http.finish if connection.persistent?
71
+ connections.delete(name)
72
+ end
73
+
74
+ # Clears *all* connections, from all classes, with prejudice.
75
+ def disconnect!
76
+ connections.each_key {|connection| disconnect(connection)}
77
+ end
78
+
79
+ private
80
+ def connection_name
81
+ name
82
+ end
83
+
84
+ def default_connection_name
85
+ 'Amazon::MWS::Base'
86
+ end
87
+
88
+ def default_connection
89
+ connections[default_connection_name]
90
+ end
91
+ end
92
+ end
93
+
94
+ end
95
+ =end
@@ -0,0 +1,67 @@
1
+ class Amazon::MWS::Connection
2
+ class RequestBuilder
3
+ attr_accessor :request
4
+
5
+ def initialize(verb, path, body = nil)
6
+ # Create the request object
7
+ @request = request_method(verb).new(path)
8
+ process_body(body)
9
+ end
10
+
11
+ def request_method(verb)
12
+ Net::HTTP.const_get(verb.to_s.capitalize)
13
+ end
14
+
15
+ def process_body(body)
16
+ @request.content_length = 0 and return self if body.nil?
17
+
18
+ if body.respond_to?(:read)
19
+ @request.body_stream = body
20
+ else
21
+ @request.body = body
22
+ end
23
+
24
+ @request.content_length = body.respond_to?(:lstat) ? body.stat.size : body.size
25
+ return self
26
+ end
27
+
28
+ # For the SubmitFeed (p. 41) function, we require that you pass the Content-MD5 HTTP header,
29
+ # which contains the MD5 hash of the HTTP entity body (see Section 14.15 of RFC 2616, the HTTP/1.1
30
+ # specification), so we can check if the feed we stored for processing is bit for bit identical with what you
31
+ # sent, protecting you from corrupted descriptive or pricing product data appearing on Amazon.com.
32
+ #
33
+ #def add_host
34
+ # @request['Host'] = Amazon::MWS::DEFAULT_HOST
35
+ # return self
36
+ #end
37
+
38
+ def add_user_agent
39
+ @request['User-Agent'] = "Amazon::MWS (Language=Ruby)"
40
+ return self
41
+ end
42
+
43
+ def add_content_type
44
+ @request.content_type = "text/html; charset=iso-8859-1"
45
+ return self
46
+ end
47
+
48
+ def add_content_md5(body = "")
49
+ @request['Content-MD5'] = Base64.encode64(create_md5(body)).chomp
50
+ return self # chainable
51
+ end
52
+
53
+ # think about chaining this with process_body
54
+ def create_md5(body)
55
+ md5 = Digest::MD5.new
56
+
57
+ # stream from file or in memory?
58
+ if body.respond_to?(:read)
59
+ digest = body.each { |line| md5.update(line) }
60
+ else
61
+ digest = md5.update(body)
62
+ end
63
+
64
+ return digest.digest
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,55 @@
1
+ module Amazon
2
+ module MWS
3
+
4
+ # Abstract super class of all Amazon::MWS exceptions
5
+ class MWSException < StandardError
6
+ end
7
+
8
+ # Abstract super class for all invalid options.
9
+ class InvalidOption < MWSException
10
+ end
11
+
12
+ class InvalidMessageType < MWSException
13
+ end
14
+
15
+ class InvalidReportType < MWSException
16
+ end
17
+
18
+ class InvalidSchedule < MWSException
19
+ end
20
+
21
+ class MissingConnectionOptions < MWSException
22
+ end
23
+
24
+ # Raised if an unrecognized option is passed when establishing a connection.
25
+ class InvalidConnectionOption < InvalidOption
26
+ def initialize(invalid_options)
27
+ message = "The following connection options are invalid: #{invalid_options.join(', ')}. " +
28
+ "The valid connection options are: #{Connection::Options::VALID_OPTIONS.join(', ')}."
29
+ super(message)
30
+ end
31
+ end
32
+
33
+ # Raised if either the access key id or secret access key arguments are missing when establishing a connection.
34
+ class MissingAccessKey < InvalidOption
35
+ def initialize(missing_keys)
36
+ key_list = missing_keys.map {|key| key.to_s}.join(' and the ')
37
+ super("You did not provide both required access keys. Please provide the #{key_list}.")
38
+ end
39
+ end
40
+
41
+ # Raised if a request is attempted before any connections have been established.
42
+ class NoConnectionEstablished < MWSException
43
+ def initialize
44
+ super("\nPlease use Amazon::MWS::Base.establish_connection! before making API calls.")
45
+ end
46
+ end
47
+
48
+ class InvalidParams < MWSException
49
+ def initialize(params)
50
+ super("\nInvalid Params For The Request! Please Pass Correct Params #{params.inspect} to Build The Request.")
51
+ end
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,178 @@
1
+
2
+ class String
3
+
4
+ =begin
5
+ if RUBY_VERSION >= '1.9'
6
+ def valid_utf8?
7
+ dup.force_encoding('UTF-8').valid_encoding?
8
+ end
9
+ else
10
+ def valid_utf8?
11
+ scan(Regexp.new('[^\x00-\xa0]', nil, 'u')) { |s| s.unpack('U') }
12
+ true
13
+ rescue ArgumentError
14
+ false
15
+ end
16
+ end
17
+ =end
18
+
19
+ =begin
20
+ def to_boolean
21
+ (self == "true") ? true : false
22
+ end
23
+ =end
24
+
25
+ # By default, +camelize+ converts strings to UpperCamelCase. If the argument to +camelize+
26
+ # is set to <tt>:lower</tt> then +camelize+ produces lowerCamelCase.
27
+ #
28
+ # +camelize+ will also convert '/' to '::' which is useful for converting paths to namespaces.
29
+ #
30
+ # Examples:
31
+ # "active_record".camelize # => "ActiveRecord"
32
+ # "active_record".camelize(:lower) # => "activeRecord"
33
+ # "active_record/errors".camelize # => "ActiveRecord::Errors"
34
+ # "active_record/errors".camelize(:lower) # => "activeRecord::Errors"
35
+ def camelize(first_letter_in_uppercase = true)
36
+ if first_letter_in_uppercase
37
+ self.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
38
+ else
39
+ self.to_s.first.downcase + camelize(lower_case_and_underscored_word)[1..-1]
40
+ end
41
+ end
42
+
43
+ =begin
44
+ def underscore
45
+ self.gsub(/::/, '/').
46
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
47
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
48
+ tr("-", "_").
49
+ downcase
50
+ end
51
+ =end
52
+ end
53
+
54
+ class Hash
55
+
56
+ =begin
57
+ def self.from_query_string(string)
58
+ query = string.split(/\?/)[-1]
59
+ parts = query.split(/&|=/)
60
+ Hash[*parts]
61
+ end
62
+
63
+ def to_query_string
64
+ self.map { |k,v| "%s=%s" % [URI.encode(k.to_s), URI.encode(v.to_s)] }.join('&') unless self.empty?
65
+ end
66
+ =end
67
+
68
+ #take keys of hash and transform those to a symbols
69
+ def self.keys_to_s(value)
70
+ return value if not value.is_a?(Hash)
71
+ hash = value.inject({}){|memo,(k,v)| memo[k.to_s] = Hash.keys_to_s(v); memo}
72
+ return hash
73
+ end
74
+
75
+ end
76
+
77
+ class Array
78
+ def extract_options!
79
+ last.is_a?(::Hash) ? pop : {}
80
+ end
81
+
82
+ #def to_query_string
83
+ # self.map { |k| "%s=%s" % [URI.encode(k[0].to_s), URI.encode(k[1].to_s)] }.join('&') unless self.empty?
84
+ #end
85
+ end
86
+
87
+ =begin
88
+ class Object
89
+ def returning(value)
90
+ yield(value)
91
+ value
92
+ end
93
+ end
94
+ =end
95
+
96
+ =begin
97
+ module Kernel
98
+ def __method__(depth = 0)
99
+ caller[depth][/`([^']+)'/, 1]
100
+ end if RUBY_VERSION <= '1.8.7'
101
+
102
+ def __called_from__
103
+ caller[1][/`([^']+)'/, 1]
104
+ end if RUBY_VERSION > '1.8.7'
105
+
106
+ def expirable_memoize(reload = false, storage = nil)
107
+ current_method = RUBY_VERSION > '1.8.7' ? __called_from__ : __method__(1)
108
+ storage = "@#{storage || current_method}"
109
+ if reload
110
+ instance_variable_set(storage, nil)
111
+ else
112
+ if cache = instance_variable_get(storage)
113
+ return cache
114
+ end
115
+ end
116
+ instance_variable_set(storage, yield)
117
+ end
118
+
119
+ def require_library_or_gem(library, gem_name = nil)
120
+ if RUBY_VERSION >= '1.9'
121
+ gem(gem_name || library, '>=0')
122
+ end
123
+ require library
124
+ rescue LoadError => library_not_installed
125
+ begin
126
+ require 'rubygems'
127
+ require library
128
+ rescue LoadError
129
+ raise library_not_installed
130
+ end
131
+ end
132
+ end
133
+ =end
134
+
135
+ =begin
136
+ class Class # :nodoc:
137
+ def cattr_reader(*syms)
138
+ syms.flatten.each do |sym|
139
+ class_eval(<<-EOS, __FILE__, __LINE__)
140
+ unless defined? @@#{sym}
141
+ @@#{sym} = nil
142
+ end
143
+
144
+ def self.#{sym}
145
+ @@#{sym}
146
+ end
147
+
148
+ def #{sym}
149
+ @@#{sym}
150
+ end
151
+ EOS
152
+ end
153
+ end
154
+
155
+ def cattr_writer(*syms)
156
+ syms.flatten.each do |sym|
157
+ class_eval(<<-EOS, __FILE__, __LINE__)
158
+ unless defined? @@#{sym}
159
+ @@#{sym} = nil
160
+ end
161
+
162
+ def self.#{sym}=(obj)
163
+ @@#{sym} = obj
164
+ end
165
+
166
+ def #{sym}=(obj)
167
+ @@#{sym} = obj
168
+ end
169
+ EOS
170
+ end
171
+ end
172
+
173
+ def cattr_accessor(*syms)
174
+ cattr_reader(*syms)
175
+ cattr_writer(*syms)
176
+ end
177
+ end if Class.instance_methods(false).grep(/^cattr_(?:reader|writer|accessor)$/).empty?
178
+ =end
@@ -0,0 +1,10 @@
1
+ module Memoizable
2
+ def memoize( name, cache = Hash.new )
3
+ original = "__unmemoized_#{name}__"
4
+ ([Class, Module].include?(self.class) ? self : self.class).class_eval do
5
+ alias_method original, name
6
+ private original
7
+ define_method(name) { |*args| cache[args] ||= send(original, *args) }
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,276 @@
1
+ module Amazon
2
+ module MWS
3
+ module Feed
4
+
5
+ # Note: We do not handle flat file feed types
6
+ FEED_TYPES = {
7
+ :product_data => '_POST_PRODUCT_DATA_',
8
+ :product_relationship_data => '_POST_PRODUCT_RELATIONSHIP_DATA_',
9
+ :item_data => '_POST_ITEM_DATA_',
10
+ :product_overrides => '_POST_PRODUCT_OVERRIDES_DATA_',
11
+ :product_image_data => '_POST_PRODUCT_IMAGE_DATA_',
12
+ :product_pricing => '_POST_PRODUCT_PRICING_DATA_',
13
+ :inventory_availability => '_POST_INVENTORY_AVAILABILITY_DATA_',
14
+ :order_acknowledgement => '_POST_ORDER_ACKNOWLEDGEMENT_DATA_',
15
+ :order_fulfillment => '_POST_ORDER_FULFILLMENT_DATA_',
16
+ :payment_adjustment => '_POST_PAYMENT_ADJUSTMENT_DATA_',
17
+ :invoice_confirmation => '_POST_INVOICE_CONFIRMATION_DATA_'
18
+ # :flat_file_listings => '_POST_FLAT_FILE_LISTINGS_DATA_',
19
+ # :flat_file_order_acknowledgement => '_POST_FLAT_FILE_ORDER_ACKNOWLEDGEMENT_DATA_',
20
+ # :flat_file_fulfillment_data => '_POST_FLAT_FILE_FULFILLMENT_DATA_',
21
+ # :flat_file_payment_adjustment => '_POST_FLAT_FILE_PAYMENT_ADJUSTMENT_DATA_',
22
+ # :flat_file_invloader => '_POST_FLAT_FILE_INVLOADER_DATA_'
23
+ }
24
+
25
+ MESSAGE_TYPES = [
26
+ "FulfillmentCenter",
27
+ "Inventory",
28
+ "OrderAcknowledgement",
29
+ "OrderAdjustment",
30
+ "OrderFulfillment",
31
+ "OrderReport",
32
+ "Override",
33
+ "Price",
34
+ "ProcessingReport",
35
+ "Product",
36
+ "ProductImage",
37
+ "Relationship",
38
+ "SettlementReport",
39
+ "InvoiceConfirmation"
40
+ ]
41
+
42
+ PRODUCT_MESSAGE_TYPES = [
43
+ "Product",
44
+ "Price",
45
+ "ProductImage",
46
+ "Relationship",
47
+ "Inventory"
48
+ ]
49
+
50
+ PROCESSING_STATUSES = {
51
+ :submitted => '_SUBMITTED_',
52
+ :in_progress => '_IN_PROGRESS_',
53
+ :done => '_DONE_',
54
+ :completed => '_COMPLETED_'
55
+ }
56
+ # The SubmitFeed operation uploads a file for processing together with
57
+ # the necessary metadata to process the file.
58
+
59
+ # Amazon MWS limits calls to 1,000 total calls per hour per seller
60
+ # account. For best performance, you should limit your calls to
61
+ # SubmitFeed to no more than three feeds per hour per seller account,
62
+ # although you can successfully call SubmitFeed up to 30 times per
63
+ # hour. Feed size is limited to 2,147,483,647 bytes (2^32 -1) per
64
+ # feed.
65
+
66
+ def submit_flat_file_feed(records, purge_flag = false)
67
+ header = "sku\tproduct-id\tproduct-id-type\tprice\titem-condition\tquantity\tadd-delete\twill-ship-internationally\texpedited-shipping\titem-note\tfulfillment-center-id"
68
+ query_params = {"Action" => "SubmitFeed","FeedType" => "_POST_FLAT_FILE_INVLOADER_DATA_"}
69
+ query_params['PurgeAndReplace'] = 'true' if purge_flag
70
+ response = post("/", query_params, ([header] + records).join("\r"))
71
+ result = SubmitFeedResponse.format(response)
72
+ end
73
+
74
+ # params can only contain {:purge => true}
75
+ def submit_feed(feed_type, message_type, messages = [], params = {})
76
+ message_type= message_type.to_s.camelize
77
+ raise InvalidMessageType if !MESSAGE_TYPES.include?(message_type)
78
+ raise "Missing merchant_id" unless @merchant_id
79
+
80
+ body = Amazon::MWS::FeedBuilder.new(message_type, messages, params.merge({:merchant_id => @merchant_id})).render
81
+ puts body if Amazon::MWS::Base.debug
82
+
83
+ response =
84
+ post("/", {
85
+ "Action" => "SubmitFeed",
86
+ "FeedType" => FEED_TYPES[feed_type]
87
+ }, body)
88
+
89
+ result = SubmitFeedResponse.format(response)
90
+ end
91
+
92
+ alias_method :submit, :submit_feed
93
+
94
+ # The GetFeedSubmissionList operation returns the total list of feed
95
+ # submissions within the previous 90 days that match the query
96
+ # parameters. Amazon MWS limits calls to 1,000 total calls per hour
97
+ # per seller account, including calls to GetFeedSubmissionList.
98
+ #
99
+ # The maximum number of results that will be returned in one call is
100
+ # one hundred. If there are additional results to return, HasNext will
101
+ # be returned in the response with a true value. To retrieve all the
102
+ # results, you can use the value of the NextToken parameter to call
103
+ # GetFeedSubmissionListByNextToken until HasNext is false.
104
+
105
+ # Optional Request Parameters
106
+ # ------------------
107
+ # FeedSubmissionIdList
108
+ # A structured list of feed submission IDs. If you pass in explicit
109
+ # IDs in this call, the other conditions, if specified, will be
110
+ # ignored.
111
+
112
+ # MaxCount
113
+ # Maximum number of feed submissions to return in the list. If you
114
+ # specify a number greater than 100, the call will be rejected.
115
+
116
+ # FeedTypeList
117
+ # A structured list of one or more FeedType constants by which to
118
+ # filter feed submissions.
119
+
120
+ # FeedProcessingStatusList
121
+ # A structured list of one or more feed processing statuses by which
122
+ # to filter feed submissions. Valid values are:
123
+ #
124
+ # _SUBMITTED_
125
+ # _IN_PROGRESS_
126
+ # _CANCELLED_
127
+ # _DONE_
128
+
129
+ # SubmittedFromDate
130
+ # The earliest submission date you are looking for, in ISO8601 date
131
+ # format (for example, "2008-07-03T18:12:22Z" or
132
+ # "2008-07-03T18:12:22.093-07:00").
133
+
134
+ # SubmittedToDate
135
+ # The latest submission date you are looking for, in ISO8601 date
136
+ # format (for example, "2008-07-03T18:12:22Z" or
137
+ # "2008-07-03T18:12:22.093-07:00").
138
+
139
+ def get_feed_submission_list(params = {})
140
+ response = get("/", {"Action" => "GetFeedSubmissionList"}.merge(params))
141
+ result = GetFeedSubmissionListResponse.format(response)
142
+ end
143
+
144
+ alias_method :feed_submission_list, :get_feed_submission_list
145
+
146
+ # The GetFeedSubmissionListByNextToken operation returns a list of
147
+ # feed submissions that match the query parameters, using the
148
+ # NextToken, which was supplied by a previous call to either
149
+ # GetFeedSubmissionListByNextToken or a call to GetFeedSubmissionList,
150
+ # where the value of HasNext was true in that previous call.
151
+ #
152
+ # Request Parameters
153
+ # ------------------
154
+ # NextToken
155
+ # Token returned in a previous call to either GetFeedSubmissionList or
156
+ # GetFeedSubmissionListByNextToken when the value of HasNext was true.
157
+ def get_feed_submission_list_by_next_token(next_token)
158
+ response =
159
+ get("/", {
160
+ "Action" => "GetFeedSubmissionListByNextToken",
161
+ "NextToken" => next_token
162
+ })
163
+
164
+ GetFeedSubmissionListByNextTokenResponse.format(response)
165
+ end
166
+
167
+ alias_method :feed_submission_list_by_next_token, :get_feed_submission_list_by_next_token
168
+
169
+ # The GetFeedsubmissionCount operation returns a count of the total
170
+ # number of feed submissions within the previous 90 days.
171
+ #
172
+ # Optional Request Parameters
173
+ # ------------------
174
+ # FeedTypeList
175
+ # A structured list of one or more FeedType constants by which to
176
+ # filter feed submissions.
177
+
178
+ # FeedProcessingStatusList
179
+ # A structured list of one or more feed processing statuses by which
180
+ # to filter feed submissions. Valid values are:
181
+ #
182
+ # _SUBMITTED_
183
+ # _IN_PROGRESS_
184
+ # _CANCELLED_
185
+ # _DONE_
186
+
187
+ # SubmittedFromDate
188
+ # The earliest submission date you are looking for, in ISO8601 date
189
+ # format (for example, "2008-07-03T18:12:22Z" or
190
+ # "2008-07-03T18:12:22.093-07:00").
191
+
192
+ # SubmittedToDate
193
+ # The latest submission date you are looking for, in ISO8601 date
194
+ # format (for example, "2008-07-03T18:12:22Z" or
195
+ # "2008-07-03T18:12:22.093-07:00").
196
+
197
+ def get_feed_submission_count(params = {})
198
+ response = get("/", {"Action" => "GetFeedSubmissionCount"}.merge(params))
199
+ GetFeedSubmissionCountResponse.format(response)
200
+ end
201
+
202
+ alias_method :feed_submission_count, :get_feed_submission_count
203
+
204
+ # The CancelFeedSubmissions operation cancels one or more feed
205
+ # submissions, returning the count of the canceled feed submissions
206
+ # and the feed submission information. You can specify a number to
207
+ # cancel of greater than one hundred, but information will only be
208
+ # returned about the first one hundred feed submissions in the list.
209
+ # To return metadata about a greater number of canceled feed
210
+ # submissions, you can call GetFeedSubmissionList. If feeds have
211
+ # already begun processing, they cannot be canceled.
212
+
213
+ # Amazon MWS limits calls to 1,000 total calls per hour per seller
214
+ # account, including calls to CancelFeedSubmissions.
215
+
216
+ # Optional Request Parameters
217
+ # ------------------
218
+ # FeedSubmissionIdList
219
+ # A structured list of feed submission IDs. If you pass in explicit
220
+ # IDs in this call, the other conditions, if specified, will be
221
+ # ignored.
222
+
223
+ # FeedTypeList
224
+ # A structured list of one or more FeedType constants by which to
225
+ # filter feed submissions.
226
+
227
+ # SubmittedFromDate
228
+ # The earliest submission date you are looking for, in ISO8601 date
229
+ # format (for example, "2008-07-03T18:12:22Z" or
230
+ # "2008-07-03T18:12:22.093-07:00").
231
+
232
+ # SubmittedToDate
233
+ # The latest submission date you are looking for, in ISO8601 date
234
+ # format (for example, "2008-07-03T18:12:22Z" or
235
+ # "2008-07-03T18:12:22.093-07:00").
236
+
237
+ def cancel_feed_submissions(params = {})
238
+ response =
239
+ get("/", {"Action" => "CancelFeedSubmissions"}.merge(params))
240
+
241
+ CancelFeedSubmissionsResponse.format(response)
242
+ end
243
+
244
+ # The GetFeedSubmissionResult operation returns the feed processing
245
+ # report and the Content-MD5 header for the returned body.
246
+
247
+ # You should compute the MD5 hash of the HTTP body that we returned to
248
+ # you, and compare that with the Content-MD5 header value that we
249
+ # returned. If they do not match, which means the body was corrupted
250
+ # during transmission, you should discard the result and automatically
251
+ # retry the call for up to three more times. Please notify us if you
252
+ # ever see such a corrupted body. You can contact us by using the
253
+ # contact form at http://mws.amazon.com (http://mws.amazon.com). For
254
+ # more information on computing the MD5, see Using the Content-MD5
255
+ # Header with SubmitFeed.
256
+
257
+ # FeedSubmissionId
258
+ # The identifier of the feed submission to get results for. Obtained
259
+ # by a call to GetFeedSubmissionList.
260
+
261
+ def get_feed_submission_result(feed_submission_id, params = {})
262
+ response = get("/", {
263
+ "Action" => "GetFeedSubmissionResult",
264
+ "FeedSubmissionId" => feed_submission_id
265
+ }.merge(params))
266
+
267
+ GetFeedSubmissionResultResponse.format(response)
268
+ end
269
+
270
+ alias_method :feed_submission_result, :get_feed_submission_result
271
+ end
272
+
273
+ # Feed
274
+
275
+ end
276
+ end