amazon-mws 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/README.markdown +31 -0
- data/Rakefile +14 -0
- data/VERSION +1 -0
- data/amazon-mws.gemspec +164 -0
- data/examples/xml/cancel_feed_submissions.xml +16 -0
- data/examples/xml/cancel_report_requests.xml +18 -0
- data/examples/xml/error.xml +10 -0
- data/examples/xml/get_feed_submission_count.xml +10 -0
- data/examples/xml/get_feed_submission_list.xml +16 -0
- data/examples/xml/get_feed_submission_list_by_next_token.xml +16 -0
- data/examples/xml/get_feed_submission_result.xml +30 -0
- data/examples/xml/get_report_count.xml +9 -0
- data/examples/xml/get_report_list.xml +17 -0
- data/examples/xml/get_report_request_count.xml +8 -0
- data/examples/xml/get_report_request_list.xml +120 -0
- data/examples/xml/get_report_request_list_by_next_token.xml +20 -0
- data/examples/xml/get_report_schedule_count.xml +10 -0
- data/examples/xml/get_report_schedule_list.xml +15 -0
- data/examples/xml/get_report_schedule_list_by_next_token.xml +15 -0
- data/examples/xml/manage_report_schedule.xml +14 -0
- data/examples/xml/request_report.xml +17 -0
- data/examples/xml/submit_feed.xml +14 -0
- data/examples/xml/update_report_acknowledgements.xml +18 -0
- data/examples/xsd/Inventory.xsd +49 -0
- data/examples/xsd/Item.xsd +285 -0
- data/examples/xsd/Listings.xsd +32 -0
- data/examples/xsd/OrderAcknowledgement.xsd +55 -0
- data/examples/xsd/OrderAdjustment.xsd +94 -0
- data/examples/xsd/OrderFulfillment.xsd +57 -0
- data/examples/xsd/Override.xsd +48 -0
- data/examples/xsd/Price.xsd +59 -0
- data/examples/xsd/ProcessingReport.xsd +87 -0
- data/examples/xsd/Product.xsd +220 -0
- data/examples/xsd/Product/AutoAccessory.xsd +807 -0
- data/examples/xsd/Product/Beauty.xsd +114 -0
- data/examples/xsd/Product/CE.xsd +544 -0
- data/examples/xsd/Product/CameraPhoto.xsd +2410 -0
- data/examples/xsd/Product/FoodAndBeverages.xsd +270 -0
- data/examples/xsd/Product/Gourmet.xsd +85 -0
- data/examples/xsd/Product/Health.xsd +189 -0
- data/examples/xsd/Product/Home.xsd +654 -0
- data/examples/xsd/Product/Jewelry.xsd +603 -0
- data/examples/xsd/Product/Miscellaneous.xsd +157 -0
- data/examples/xsd/Product/MusicalInstruments.xsd +853 -0
- data/examples/xsd/Product/Office.xsd +550 -0
- data/examples/xsd/Product/PetSupplies.xsd +40 -0
- data/examples/xsd/Product/ProductClothing.xsd +197 -0
- data/examples/xsd/Product/SWVG.xsd +238 -0
- data/examples/xsd/Product/Sports.xsd +308 -0
- data/examples/xsd/Product/TiresAndWheels.xsd +159 -0
- data/examples/xsd/Product/Tools.xsd +66 -0
- data/examples/xsd/Product/ToysBaby.xsd +241 -0
- data/examples/xsd/Product/Wireless.xsd +77 -0
- data/examples/xsd/ProductImage.xsd +39 -0
- data/examples/xsd/Relationship.xsd +47 -0
- data/examples/xsd/SettlementReport.xsd +158 -0
- data/examples/xsd/amzn-base.xsd +1601 -0
- data/examples/xsd/amzn-envelope.xsd +98 -0
- data/examples/xsd/amzn-header.xsd +45 -0
- data/lib/amazon/mws.rb +86 -0
- data/lib/amazon/mws/authentication.rb +9 -0
- data/lib/amazon/mws/authentication/query_string.rb +28 -0
- data/lib/amazon/mws/authentication/signature.rb +43 -0
- data/lib/amazon/mws/base.rb +61 -0
- data/lib/amazon/mws/connection.rb +99 -0
- data/lib/amazon/mws/connection/management.rb +94 -0
- data/lib/amazon/mws/connection/request_builder.rb +67 -0
- data/lib/amazon/mws/exceptions.rb +80 -0
- data/lib/amazon/mws/feed.rb +223 -0
- data/lib/amazon/mws/feed_builder.rb +67 -0
- data/lib/amazon/mws/feed_enumerations.rb +46 -0
- data/lib/amazon/mws/feed_submission.rb +14 -0
- data/lib/amazon/mws/lib/extensions.rb +162 -0
- data/lib/amazon/mws/lib/memoizable.rb +10 -0
- data/lib/amazon/mws/orders.rb +9 -0
- data/lib/amazon/mws/report.rb +310 -0
- data/lib/amazon/mws/report_enumerations.rb +44 -0
- data/lib/amazon/mws/report_info.rb +16 -0
- data/lib/amazon/mws/report_request.rb +19 -0
- data/lib/amazon/mws/report_schedule.rb +13 -0
- data/lib/amazon/mws/response.rb +32 -0
- data/lib/amazon/mws/response/cancel_feed_submissions_response.rb +14 -0
- data/lib/amazon/mws/response/cancel_report_requests_response.rb +14 -0
- data/lib/amazon/mws/response/get_feed_submission_count_response.rb +13 -0
- data/lib/amazon/mws/response/get_feed_submission_list_by_next_token_response.rb +15 -0
- data/lib/amazon/mws/response/get_feed_submission_list_response.rb +15 -0
- data/lib/amazon/mws/response/get_feed_submission_result_response.rb +54 -0
- data/lib/amazon/mws/response/get_report_count_response.rb +13 -0
- data/lib/amazon/mws/response/get_report_list_response.rb +15 -0
- data/lib/amazon/mws/response/get_report_request_count_response.rb +13 -0
- data/lib/amazon/mws/response/get_report_request_list_by_next_token_response.rb +15 -0
- data/lib/amazon/mws/response/get_report_request_list_response.rb +15 -0
- data/lib/amazon/mws/response/get_report_schedule_count_response.rb +13 -0
- data/lib/amazon/mws/response/get_report_schedule_list_by_next_token_response.rb +15 -0
- data/lib/amazon/mws/response/get_report_schedule_list_response.rb +15 -0
- data/lib/amazon/mws/response/manage_report_schedule_response.rb +14 -0
- data/lib/amazon/mws/response/request_report_response.rb +14 -0
- data/lib/amazon/mws/response/response_error.rb +15 -0
- data/lib/amazon/mws/response/submit_feed_response.rb +13 -0
- data/lib/amazon/mws/response/update_reports_acknowledgements_response.rb +14 -0
- data/lib/amazon/mws/version.rb +12 -0
- data/pkg/amazon-mws-0.1.0.gem +0 -0
- data/test/authentication_test.rb +15 -0
- data/test/connection_test.rb +5 -0
- data/test/feed_builder_test.rb +15 -0
- data/test/feed_submission_test.rb +32 -0
- data/test/feed_test.rb +64 -0
- data/test/query_string_test.rb +21 -0
- data/test/report_test.rb +29 -0
- data/test/request_test.rb +18 -0
- data/test/response_test.rb +197 -0
- data/test/signature_test.rb +30 -0
- data/test/test_config.yml +5 -0
- data/test/test_helper.rb +22 -0
- metadata +179 -0
@@ -0,0 +1,98 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<!-- Revision="$Revision: #6 $" -->
|
3
|
+
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
|
4
|
+
<!--
|
5
|
+
$Date: 2007/01/18 $
|
6
|
+
|
7
|
+
AMAZON.COM CONFIDENTIAL. This document and the information contained in it are
|
8
|
+
confidential and proprietary information of Amazon.com and may not be reproduced,
|
9
|
+
distributed or used, in whole or in part, for any purpose other than as necessary
|
10
|
+
to list products for sale on the www.amazon.com web site pursuant to an agreement
|
11
|
+
with Amazon.com.
|
12
|
+
-->
|
13
|
+
<xsd:include schemaLocation="amzn-base.xsd"/>
|
14
|
+
<xsd:include schemaLocation="amzn-header.xsd"/>
|
15
|
+
<xsd:include schemaLocation="FulfillmentCenter.xsd"/>
|
16
|
+
<xsd:include schemaLocation="Inventory.xsd"/>
|
17
|
+
<xsd:include schemaLocation="Listings.xsd"/>
|
18
|
+
<xsd:include schemaLocation="OrderAcknowledgement.xsd"/>
|
19
|
+
<xsd:include schemaLocation="OrderAdjustment.xsd"/>
|
20
|
+
<xsd:include schemaLocation="OrderFulfillment.xsd"/>
|
21
|
+
|
22
|
+
<xsd:include schemaLocation="Override.xsd"/>
|
23
|
+
<xsd:include schemaLocation="Price.xsd"/>
|
24
|
+
<xsd:include schemaLocation="ProcessingReport.xsd"/>
|
25
|
+
<xsd:include schemaLocation="ProductImage.xsd"/>
|
26
|
+
<xsd:include schemaLocation="Product.xsd"/>
|
27
|
+
<xsd:include schemaLocation="Relationship.xsd"/>
|
28
|
+
<xsd:include schemaLocation="SettlementReport.xsd"/>
|
29
|
+
<xsd:element name="AmazonEnvelope">
|
30
|
+
<xsd:complexType>
|
31
|
+
<xsd:sequence>
|
32
|
+
<xsd:element ref="Header"/>
|
33
|
+
<xsd:element name="MessageType">
|
34
|
+
<xsd:simpleType>
|
35
|
+
<xsd:restriction base="xsd:string">
|
36
|
+
<xsd:enumeration value="FulfillmentCenter"/>
|
37
|
+
<xsd:enumeration value="Inventory"/>
|
38
|
+
<xsd:enumeration value="Listings"/>
|
39
|
+
<xsd:enumeration value="OrderAcknowledgement"/>
|
40
|
+
<xsd:enumeration value="OrderAdjustment"/>
|
41
|
+
<xsd:enumeration value="OrderFulfillment"/>
|
42
|
+
<xsd:enumeration value="Override"/>
|
43
|
+
<xsd:enumeration value="Price"/>
|
44
|
+
<xsd:enumeration value="ProcessingReport"/>
|
45
|
+
<xsd:enumeration value="Product"/>
|
46
|
+
<xsd:enumeration value="ProductImage"/>
|
47
|
+
<xsd:enumeration value="Relationship"/>
|
48
|
+
<xsd:enumeration value="SettlementReport"/>
|
49
|
+
</xsd:restriction>
|
50
|
+
</xsd:simpleType>
|
51
|
+
</xsd:element>
|
52
|
+
<xsd:element ref="MarketplaceName" minOccurs="0">
|
53
|
+
<xsd:annotation>
|
54
|
+
<xsd:documentation>
|
55
|
+
The MarketplaceName is only supported for
|
56
|
+
Override feeds.
|
57
|
+
If included here, the MarketplaceName will
|
58
|
+
apply to all messages in the feed.
|
59
|
+
</xsd:documentation>
|
60
|
+
</xsd:annotation>
|
61
|
+
</xsd:element>
|
62
|
+
<xsd:element name="PurgeAndReplace" type="xsd:boolean" minOccurs="0"/>
|
63
|
+
<xsd:element name="EffectiveDate" type="xsd:dateTime" minOccurs="0"/>
|
64
|
+
<xsd:element name="Message" maxOccurs="unbounded">
|
65
|
+
<xsd:complexType>
|
66
|
+
<xsd:sequence>
|
67
|
+
<xsd:element name="MessageID" type="IDNumber"/>
|
68
|
+
<xsd:element name="OperationType" minOccurs="0">
|
69
|
+
<xsd:simpleType>
|
70
|
+
<xsd:restriction base="xsd:string">
|
71
|
+
<xsd:enumeration value="Update"/>
|
72
|
+
<xsd:enumeration value="Delete"/>
|
73
|
+
<xsd:enumeration value="PartialUpdate"/>
|
74
|
+
</xsd:restriction>
|
75
|
+
</xsd:simpleType>
|
76
|
+
</xsd:element>
|
77
|
+
<xsd:choice>
|
78
|
+
<xsd:element ref="FulfillmentCenter"/>
|
79
|
+
<xsd:element ref="Inventory"/>
|
80
|
+
<xsd:element ref="Listings"/>
|
81
|
+
<xsd:element ref="OrderAcknowledgement"/>
|
82
|
+
<xsd:element ref="OrderAdjustment"/>
|
83
|
+
<xsd:element ref="OrderFulfillment"/>
|
84
|
+
<xsd:element ref="Override"/>
|
85
|
+
<xsd:element ref="Price"/>
|
86
|
+
<xsd:element ref="ProcessingReport"/>
|
87
|
+
<xsd:element ref="Product"/>
|
88
|
+
<xsd:element ref="ProductImage"/>
|
89
|
+
<xsd:element ref="Relationship"/>
|
90
|
+
<xsd:element ref="SettlementReport"/>
|
91
|
+
</xsd:choice>
|
92
|
+
</xsd:sequence>
|
93
|
+
</xsd:complexType>
|
94
|
+
</xsd:element>
|
95
|
+
</xsd:sequence>
|
96
|
+
</xsd:complexType>
|
97
|
+
</xsd:element>
|
98
|
+
</xsd:schema>
|
@@ -0,0 +1,45 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<!-- "$Revision: #3 $" -->
|
3
|
+
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
|
4
|
+
|
5
|
+
<!--
|
6
|
+
$Date: 2005/04/01 $
|
7
|
+
|
8
|
+
AMAZON.COM CONFIDENTIAL. This document and the information contained in it are
|
9
|
+
confidential and proprietary information of Amazon.com and may not be reproduced,
|
10
|
+
distributed or used, in whole or in part, for any purpose other than as necessary
|
11
|
+
to list products for sale on the www.amazon.com web site pursuant to an agreement
|
12
|
+
with Amazon.com.
|
13
|
+
-->
|
14
|
+
|
15
|
+
<xsd:include schemaLocation="amzn-base.xsd"/>
|
16
|
+
|
17
|
+
<xsd:element name="Header">
|
18
|
+
<xsd:complexType>
|
19
|
+
<xsd:sequence>
|
20
|
+
|
21
|
+
<xsd:element name="DocumentVersion">
|
22
|
+
<xsd:simpleType>
|
23
|
+
<xsd:restriction base="xsd:string">
|
24
|
+
<xsd:pattern value="\d{1,2}\.\d{1,2}"/>
|
25
|
+
</xsd:restriction>
|
26
|
+
</xsd:simpleType>
|
27
|
+
</xsd:element>
|
28
|
+
|
29
|
+
<xsd:element name="MerchantIdentifier" type="String"/>
|
30
|
+
|
31
|
+
<xsd:element name="OverrideReleaseId" minOccurs="0">
|
32
|
+
<xsd:simpleType>
|
33
|
+
<xsd:restriction base="xsd:string">
|
34
|
+
<xsd:pattern value="\d{1,4}\.\d{1,4}"/>
|
35
|
+
</xsd:restriction>
|
36
|
+
</xsd:simpleType>
|
37
|
+
</xsd:element>
|
38
|
+
|
39
|
+
</xsd:sequence>
|
40
|
+
</xsd:complexType>
|
41
|
+
</xsd:element>
|
42
|
+
|
43
|
+
</xsd:schema>
|
44
|
+
|
45
|
+
|
data/lib/amazon/mws.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'cgi'
|
3
|
+
require 'uri'
|
4
|
+
require 'openssl'
|
5
|
+
require 'net/https'
|
6
|
+
require 'time'
|
7
|
+
require 'date'
|
8
|
+
require 'hmac'
|
9
|
+
require 'hmac-sha2'
|
10
|
+
require 'base64'
|
11
|
+
require 'builder'
|
12
|
+
require "rexml/document"
|
13
|
+
|
14
|
+
# ROXML - nokogiri and roxml are the only dependencies
|
15
|
+
I_KNOW_I_AM_USING_AN_OLD_AND_BUGGY_VERSION_OF_LIBXML2 = true
|
16
|
+
# module ROXML
|
17
|
+
# XML_PARSER = 'nokogiri' # or 'libxml'
|
18
|
+
# end
|
19
|
+
require 'roxml'
|
20
|
+
# /ROXML
|
21
|
+
|
22
|
+
|
23
|
+
$:.unshift(File.dirname(__FILE__))
|
24
|
+
require 'mws/lib/extensions'
|
25
|
+
require 'builder'
|
26
|
+
#require_library_or_gem 'mime/types', 'mime-types' unless defined? MIME::Types
|
27
|
+
|
28
|
+
module Amazon
|
29
|
+
module MWS
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
require 'mws/lib/memoizable'
|
36
|
+
|
37
|
+
require 'mws/feed_builder'
|
38
|
+
require 'mws/feed_enumerations'
|
39
|
+
require 'mws/feed'
|
40
|
+
require 'mws/report_enumerations'
|
41
|
+
require 'mws/report'
|
42
|
+
|
43
|
+
|
44
|
+
require 'mws/response'
|
45
|
+
require 'mws/feed_submission'
|
46
|
+
require 'mws/report_request'
|
47
|
+
require 'mws/report_info'
|
48
|
+
require 'mws/report_schedule'
|
49
|
+
Dir.glob(File.join(File.dirname(__FILE__), 'mws/response/*.rb')).each {|f| require f }
|
50
|
+
|
51
|
+
require 'mws/base'
|
52
|
+
require 'mws/version'
|
53
|
+
require 'mws/exceptions'
|
54
|
+
require 'mws/connection'
|
55
|
+
require 'mws/connection/management'
|
56
|
+
require 'mws/connection/request_builder'
|
57
|
+
require 'mws/authentication'
|
58
|
+
require 'mws/authentication/query_string'
|
59
|
+
require 'mws/authentication/signature'
|
60
|
+
|
61
|
+
|
62
|
+
Amazon::MWS::Base.class_eval do
|
63
|
+
include Amazon::MWS::Feed
|
64
|
+
include Amazon::MWS::Report
|
65
|
+
end
|
66
|
+
|
67
|
+
AWS = Amazon
|
68
|
+
|
69
|
+
require_library_or_gem 'xmlsimple', 'xml-simple' unless defined? XmlSimple
|
70
|
+
=begin
|
71
|
+
# If libxml is installed, we use the FasterXmlSimple library, that provides most of the functionality of XmlSimple
|
72
|
+
# except it uses the xml/libxml library for xml parsing (rather than REXML). If libxml isn't installed, we just fall back on
|
73
|
+
# XmlSimple.
|
74
|
+
AWS::S3::Parsing.parser =
|
75
|
+
begin
|
76
|
+
require_library_or_gem 'xml/libxml'
|
77
|
+
# Older version of libxml aren't stable (bus error when requesting attributes that don't exist) so we
|
78
|
+
# have to use a version greater than '0.3.8.2'.
|
79
|
+
raise LoadError unless XML::Parser::VERSION > '0.3.8.2'
|
80
|
+
$:.push(File.join(File.dirname(__FILE__), '..', '..', 'support', 'faster-xml-simple', 'lib'))
|
81
|
+
require_library_or_gem 'faster_xml_simple'
|
82
|
+
FasterXmlSimple
|
83
|
+
rescue LoadError
|
84
|
+
XmlSimple
|
85
|
+
end
|
86
|
+
=end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class Amazon::MWS::Authentication
|
2
|
+
|
3
|
+
class QueryString < String
|
4
|
+
def initialize(params = {})
|
5
|
+
query_params = {
|
6
|
+
'AWSAccessKeyId' => params[:access_key],
|
7
|
+
'Marketplace' => params[:marketplace_id],
|
8
|
+
'Merchant' => params[:merchant_id],
|
9
|
+
'SignatureMethod' => Signature::METHOD,
|
10
|
+
'SignatureVersion' => Signature::VERSION,
|
11
|
+
'Timestamp' => Time.now.iso8601,
|
12
|
+
'Version' => Amazon::MWS::Authentication::VERSION
|
13
|
+
}
|
14
|
+
|
15
|
+
# Add any params that are passed in via uri before calculating the signature
|
16
|
+
query_params = query_params.merge(params[:query_params] || {})
|
17
|
+
# Calculate the signature
|
18
|
+
query_params['Signature'] = Signature.new(query_params, params)
|
19
|
+
|
20
|
+
self << formatted_querystring(query_params)
|
21
|
+
end
|
22
|
+
|
23
|
+
def formatted_querystring(query_params)
|
24
|
+
query_params.collect { |key, value| [CGI.escape(key.to_s), CGI.escape(value.to_s)].join('=') }.join('&') # order doesn't matter for the actual request
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class Amazon::MWS::Authentication
|
2
|
+
|
3
|
+
class Signature < String#:nodoc:
|
4
|
+
extend Memoizable
|
5
|
+
|
6
|
+
VERSION = '2'
|
7
|
+
METHOD = 'HmacSHA256'
|
8
|
+
|
9
|
+
def initialize(queryparams = {}, params = {})
|
10
|
+
verb = params[:verb]
|
11
|
+
secret = params[:secret_access_key]
|
12
|
+
# Create the string to sign
|
13
|
+
string = string_to_sign(verb, canonical_querystring(queryparams))
|
14
|
+
self << sign(string, secret)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns a signed string
|
18
|
+
def sign(string, secret_access_key)
|
19
|
+
hmac = HMAC::SHA256.new(secret_access_key)
|
20
|
+
hmac.update(string)
|
21
|
+
# chomp is important! the base64 encoded version will have a newline at the end
|
22
|
+
Base64.encode64(hmac.digest).chomp
|
23
|
+
end
|
24
|
+
|
25
|
+
memoize :sign
|
26
|
+
|
27
|
+
def string_to_sign(verb, querystring)
|
28
|
+
verb = verb.to_s.upcase
|
29
|
+
string = "#{verb}\n#{Amazon::MWS::DEFAULT_HOST}\n/\n#{querystring}"
|
30
|
+
end
|
31
|
+
|
32
|
+
memoize :string_to_sign
|
33
|
+
|
34
|
+
def canonical_querystring(params)
|
35
|
+
# Make sure we have string keys, otherwise the sort does not work
|
36
|
+
params = Hash.keys_to_s(params)
|
37
|
+
params.sort.collect { |key, value| [CGI.escape(key.to_s), CGI.escape(value.to_s)].join('=') }.join('&')
|
38
|
+
end
|
39
|
+
|
40
|
+
memoize :canonical_querystring
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Amazon
|
2
|
+
module MWS
|
3
|
+
DEFAULT_HOST = "mws.amazonaws.com"
|
4
|
+
|
5
|
+
class Base
|
6
|
+
attr_accessor :connection
|
7
|
+
|
8
|
+
def self.debug; @@debug ||= false end
|
9
|
+
def self.debug=(bool); @@debug = bool end
|
10
|
+
|
11
|
+
def initialize(options ={})
|
12
|
+
@connection = Amazon::MWS::Connection.connect(options)
|
13
|
+
end
|
14
|
+
|
15
|
+
def connection
|
16
|
+
raise Amazon::MWS::NoConnectionEstablished.new if !connected?
|
17
|
+
@connection
|
18
|
+
end
|
19
|
+
|
20
|
+
def connected?
|
21
|
+
!@connection.nil?
|
22
|
+
end
|
23
|
+
|
24
|
+
def disconnect
|
25
|
+
@connection.http.finish if @connection.persistent?
|
26
|
+
@connection = nil
|
27
|
+
end
|
28
|
+
|
29
|
+
# Wraps the current connection's request method and picks the appropriate response class to wrap the response in.
|
30
|
+
# If the response is an error, it will raise that error as an exception. All such exceptions can be caught by rescuing
|
31
|
+
# their superclass, the ResponseError exception class.
|
32
|
+
#
|
33
|
+
# It is unlikely that you would call this method directly. Subclasses of Base have convenience methods for each http request verb
|
34
|
+
# that wrap calls to request.
|
35
|
+
def request(verb, path, query_params = {}, body = nil, attempts = 0, &block)
|
36
|
+
# Find the connection method in connection/management.rb which is evaled into Amazon::MWS::Base
|
37
|
+
response = @connection.request(verb, path, query_params, body, attempts, &block)
|
38
|
+
|
39
|
+
# Each calling class is responsible for formatting the result
|
40
|
+
return response
|
41
|
+
rescue InternalError, RequestTimeout
|
42
|
+
if attempts == 3
|
43
|
+
raise
|
44
|
+
else
|
45
|
+
attempts += 1
|
46
|
+
retry
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Make some convenience methods
|
51
|
+
[:get, :post, :put, :delete, :head].each do |verb|
|
52
|
+
class_eval(<<-EVAL, __FILE__, __LINE__)
|
53
|
+
def #{verb}(path, query_params = {}, body = nil, &block)
|
54
|
+
request(:#{verb}, path, query_params, body, &block)
|
55
|
+
end
|
56
|
+
EVAL
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module Amazon
|
2
|
+
module MWS
|
3
|
+
|
4
|
+
class Connection
|
5
|
+
# Static/Class methods
|
6
|
+
class << self
|
7
|
+
def connect(options = {})
|
8
|
+
new(options)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(params = {})
|
13
|
+
# These values are essential to establishing a connection
|
14
|
+
@server = params['server'] || Amazon::MWS::DEFAULT_HOST
|
15
|
+
@persistent = params['persistent'] || false
|
16
|
+
# These values are essential to signing requests
|
17
|
+
@access_key = params['access_key']
|
18
|
+
@secret_access_key = params['secret_access_key']
|
19
|
+
@merchant_id = params['merchant_id']
|
20
|
+
@marketplace_id = params['marketplace_id']
|
21
|
+
|
22
|
+
raise MissingConnectionOptions if [@access_key, @secret_access_key, @merchant_id, @marketplace_id].any? {|option| option.nil?}
|
23
|
+
|
24
|
+
@http = connect
|
25
|
+
end
|
26
|
+
|
27
|
+
# Create the Net::HTTP object to use for this connection
|
28
|
+
def connect
|
29
|
+
http = Net::HTTP.new(@server, 443)
|
30
|
+
http.use_ssl = true
|
31
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
32
|
+
return http
|
33
|
+
end
|
34
|
+
|
35
|
+
# Make the request, based on the apropriate request object
|
36
|
+
# Called from Amazon::MWS::Base
|
37
|
+
def request(verb, path, query_params, body = nil, attempts = 0, &block)
|
38
|
+
# presumably this is for files
|
39
|
+
body.rewind if body.respond_to?(:rewind) unless attempts.zero?
|
40
|
+
# Prepare the Proc to be called by Net::HTTP
|
41
|
+
proc = requester(verb, path, query_params, body)
|
42
|
+
|
43
|
+
if @persistent
|
44
|
+
@http.start unless @http.started?
|
45
|
+
proc.call
|
46
|
+
else
|
47
|
+
@http.start(&proc)
|
48
|
+
end
|
49
|
+
rescue Errno::EPIPE, Timeout::Error, Errno::EINVAL, EOFError
|
50
|
+
@http = connect
|
51
|
+
attempts == 3 ? raise : (attempts += 1; retry)
|
52
|
+
end
|
53
|
+
|
54
|
+
# A Proc used by the request method
|
55
|
+
def requester(verb, path, query_params, body)
|
56
|
+
Proc.new do |http|
|
57
|
+
path = prepare_path(verb, path, query_params)
|
58
|
+
puts "#{path}\n\n" if AWS::MWS::Base.debug
|
59
|
+
request = build_request(verb, path, body)
|
60
|
+
|
61
|
+
@http.request(request)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Create the signed authentication query string.
|
66
|
+
# Add this query string to the path WITHOUT prepending the server address.
|
67
|
+
def prepare_path(verb, path, query_params)
|
68
|
+
query_string = authenticate_query_string(verb, query_params)
|
69
|
+
return "#{path}?#{query_string}"
|
70
|
+
end
|
71
|
+
|
72
|
+
# Generates the authentication query string used by Amazon.
|
73
|
+
# Takes the http method and the query string of the request and returns the authenticated query string
|
74
|
+
def authenticate_query_string(verb, query_params = {})
|
75
|
+
Authentication::QueryString.new(
|
76
|
+
:verb => verb,
|
77
|
+
:query_params => query_params,
|
78
|
+
:access_key => @access_key,
|
79
|
+
:secret_access_key => @secret_access_key,
|
80
|
+
:merchant_id => @merchant_id,
|
81
|
+
:marketplace_id => @marketplace_id
|
82
|
+
)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Builds up a Net::HTTP request object
|
86
|
+
def build_request(verb, path, body = nil)
|
87
|
+
builder = RequestBuilder.new(verb, path, body)
|
88
|
+
builder.add_user_agent
|
89
|
+
builder.add_content_type
|
90
|
+
builder.add_content_md5(body) unless body.nil?
|
91
|
+
|
92
|
+
return builder.request
|
93
|
+
end
|
94
|
+
end
|
95
|
+
# Connection
|
96
|
+
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|