amazon-mws-plus 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.project +12 -0
- data/Gemfile +13 -0
- data/README.markdown +30 -0
- data/Rakefile +50 -0
- data/amazon-mws-plus.gemspec +23 -0
- data/amazon-mws.tmproj +27 -0
- data/examples/xml/cancel_feed_submissions.xml +16 -0
- data/examples/xml/cancel_fulfillment_order.xml +6 -0
- data/examples/xml/cancel_report_requests.xml +18 -0
- data/examples/xml/create_fulfillment_order.xml +6 -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 +18 -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_fulfillment_order.xml +113 -0
- data/examples/xml/get_fulfillment_preview.xml +148 -0
- data/examples/xml/get_matching_product.xml +115 -0
- data/examples/xml/get_matching_product_for_id.xml +119 -0
- data/examples/xml/get_report.xml +237 -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/list_all_fulfillment_orders.xml +69 -0
- data/examples/xml/list_all_fulfillment_orders_by_next_token.xml +61 -0
- data/examples/xml/manage_report_schedule.xml +14 -0
- data/examples/xml/orders_request.xml +39 -0
- data/examples/xml/request_order_items.xml +51 -0
- data/examples/xml/request_order_items_by_next_token.xml +51 -0
- data/examples/xml/request_orders.xml +43 -0
- data/examples/xml/request_orders_by_next_token.xml +69 -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 +62 -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 +1600 -0
- data/examples/xsd/amzn-envelope.xsd +98 -0
- data/examples/xsd/amzn-header.xsd +45 -0
- data/lib/amazon-mws.rb +6 -0
- data/lib/amazon/mws.rb +69 -0
- data/lib/amazon/mws/authentication.rb +10 -0
- data/lib/amazon/mws/authentication/query_string.rb +36 -0
- data/lib/amazon/mws/authentication/signature.rb +43 -0
- data/lib/amazon/mws/base.rb +74 -0
- data/lib/amazon/mws/connection.rb +107 -0
- data/lib/amazon/mws/connection/management.rb +95 -0
- data/lib/amazon/mws/connection/request_builder.rb +67 -0
- data/lib/amazon/mws/exceptions.rb +55 -0
- data/lib/amazon/mws/lib/extensions.rb +178 -0
- data/lib/amazon/mws/lib/memoizable.rb +10 -0
- data/lib/amazon/mws/request/feed.rb +276 -0
- data/lib/amazon/mws/request/feed_builder.rb +83 -0
- data/lib/amazon/mws/request/fulfillment.rb +50 -0
- data/lib/amazon/mws/request/orders.rb +107 -0
- data/lib/amazon/mws/request/products.rb +38 -0
- data/lib/amazon/mws/request/report.rb +330 -0
- data/lib/amazon/mws/response.rb +43 -0
- data/lib/amazon/mws/response/feed/cancel_feed_submissions_response.rb +15 -0
- data/lib/amazon/mws/response/feed/get_feed_submission_count_response.rb +13 -0
- data/lib/amazon/mws/response/feed/get_feed_submission_list_by_next_token_response.rb +17 -0
- data/lib/amazon/mws/response/feed/get_feed_submission_list_response.rb +16 -0
- data/lib/amazon/mws/response/feed/get_feed_submission_result_response.rb +54 -0
- data/lib/amazon/mws/response/feed/models/feed_submission.rb +16 -0
- data/lib/amazon/mws/response/feed/submit_feed_response.rb +15 -0
- data/lib/amazon/mws/response/fulfillment_order/cancel_fulfillment_order_response.rb +11 -0
- data/lib/amazon/mws/response/fulfillment_order/create_fulfillment_order_response.rb +12 -0
- data/lib/amazon/mws/response/fulfillment_order/get_fulfillment_order_response.rb +19 -0
- data/lib/amazon/mws/response/fulfillment_order/list_all_fulfillment_orders_by_next_token_response.rb +16 -0
- data/lib/amazon/mws/response/fulfillment_order/list_all_fulfillment_orders_response.rb +15 -0
- data/lib/amazon/mws/response/fulfillment_order/models/fulfillment_address.rb +18 -0
- data/lib/amazon/mws/response/fulfillment_order/models/fulfillment_order.rb +24 -0
- data/lib/amazon/mws/response/fulfillment_order/models/fulfillment_order_item.rb +20 -0
- data/lib/amazon/mws/response/fulfillment_order/models/fulfillment_shipment.rb +18 -0
- data/lib/amazon/mws/response/fulfillment_order/models/fulfillment_shipment_item.rb +14 -0
- data/lib/amazon/mws/response/order/models/order.rb +43 -0
- data/lib/amazon/mws/response/order/models/order_item.rb +48 -0
- data/lib/amazon/mws/response/order/models/promotion_id.rb +9 -0
- data/lib/amazon/mws/response/order/request_get_order_response.rb +15 -0
- data/lib/amazon/mws/response/order/request_order_items_response.rb +25 -0
- data/lib/amazon/mws/response/order/request_orders_response.rb +28 -0
- data/lib/amazon/mws/response/product/get_matching_proudct.rb +31 -0
- data/lib/amazon/mws/response/product/models/product.rb +36 -0
- data/lib/amazon/mws/response/report/cancel_report_requests_response.rb +16 -0
- data/lib/amazon/mws/response/report/get_report_count_response.rb +13 -0
- data/lib/amazon/mws/response/report/get_report_list_response.rb +17 -0
- data/lib/amazon/mws/response/report/get_report_request_count_response.rb +13 -0
- data/lib/amazon/mws/response/report/get_report_request_list_by_next_token_response.rb +17 -0
- data/lib/amazon/mws/response/report/get_report_request_list_response.rb +17 -0
- data/lib/amazon/mws/response/report/get_report_schedule_count_response.rb +13 -0
- data/lib/amazon/mws/response/report/get_report_schedule_list_by_next_token_response.rb +17 -0
- data/lib/amazon/mws/response/report/get_report_schedule_list_response.rb +17 -0
- data/lib/amazon/mws/response/report/manage_report_schedule_response.rb +16 -0
- data/lib/amazon/mws/response/report/models/report_info.rb +16 -0
- data/lib/amazon/mws/response/report/models/report_request.rb +20 -0
- data/lib/amazon/mws/response/report/models/report_schedule.rb +13 -0
- data/lib/amazon/mws/response/report/request_report_response.rb +15 -0
- data/lib/amazon/mws/response/report/update_reports_acknowledgements_response.rb +16 -0
- data/lib/amazon/mws/response/response.rb +43 -0
- data/lib/amazon/mws/response/response_error.rb +21 -0
- data/test/connection_test.rb +14 -0
- data/test/feed_builder_test.rb +74 -0
- data/test/feed_test.rb +144 -0
- data/test/fulfillment_order.rb +49 -0
- data/test/orders_test.rb +78 -0
- data/test/products_test.rb +28 -0
- data/test/query_string_test.rb +18 -0
- data/test/report_test.rb +88 -0
- data/test/response_test.rb +172 -0
- data/test/signature_test.rb +32 -0
- data/test/test_config.yml +6 -0
- data/test/test_helper.rb +33 -0
- metadata +335 -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
data/lib/amazon/mws.rb
ADDED
@@ -0,0 +1,69 @@
|
|
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
|
+
require 'roxml'
|
14
|
+
|
15
|
+
$:.unshift(File.dirname(__FILE__))
|
16
|
+
require 'mws/lib/extensions'
|
17
|
+
require 'builder'
|
18
|
+
#require_library_or_gem 'mime/types', 'mime-types' unless defined? MIME::Types
|
19
|
+
|
20
|
+
require 'mws/lib/memoizable'
|
21
|
+
|
22
|
+
require 'mws/request/feed_builder'
|
23
|
+
require 'mws/request/feed'
|
24
|
+
require 'mws/request/report'
|
25
|
+
require 'mws/request/products'
|
26
|
+
require 'mws/request/fulfillment'
|
27
|
+
require 'mws/request/orders'
|
28
|
+
|
29
|
+
require 'mws/response/response'
|
30
|
+
Dir.glob(File.join(File.dirname(__FILE__), 'mws/response/**/*.rb')).each {|f| require f }
|
31
|
+
|
32
|
+
require 'mws/base'
|
33
|
+
require 'mws/exceptions'
|
34
|
+
require 'mws/connection'
|
35
|
+
require 'mws/connection/request_builder'
|
36
|
+
require 'mws/authentication'
|
37
|
+
require 'mws/authentication/query_string'
|
38
|
+
require 'mws/authentication/signature'
|
39
|
+
|
40
|
+
Amazon::MWS::Base.class_eval do
|
41
|
+
include Amazon::MWS::Feed
|
42
|
+
include Amazon::MWS::Report
|
43
|
+
include Amazon::MWS::Orders
|
44
|
+
include Amazon::MWS::Products
|
45
|
+
include Amazon::MWS::Fulfillment
|
46
|
+
end
|
47
|
+
|
48
|
+
#AWS = Amazon
|
49
|
+
|
50
|
+
#require_library_or_gem 'xmlsimple', 'xml-simple' unless defined? XmlSimple
|
51
|
+
gem 'xml-simple'
|
52
|
+
|
53
|
+
=begin
|
54
|
+
# If libxml is installed, we use the FasterXmlSimple library, that provides most of the functionality of XmlSimple
|
55
|
+
# except it uses the xml/libxml library for xml parsing (rather than REXML). If libxml isn't installed, we just fall back on
|
56
|
+
# XmlSimple.
|
57
|
+
AWS::S3::Parsing.parser =
|
58
|
+
begin
|
59
|
+
require_library_or_gem 'xml/libxml'
|
60
|
+
# Older version of libxml aren't stable (bus error when requesting attributes that don't exist) so we
|
61
|
+
# have to use a version greater than '0.3.8.2'.
|
62
|
+
raise LoadError unless XML::Parser::VERSION > '0.3.8.2'
|
63
|
+
$:.push(File.join(File.dirname(__FILE__), '..', '..', 'support', 'faster-xml-simple', 'lib'))
|
64
|
+
require_library_or_gem 'faster_xml_simple'
|
65
|
+
FasterXmlSimple
|
66
|
+
rescue LoadError
|
67
|
+
XmlSimple
|
68
|
+
end
|
69
|
+
=end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class Amazon::MWS::Authentication
|
2
|
+
|
3
|
+
class QueryString < String
|
4
|
+
def initialize(params = {})
|
5
|
+
query_params = {
|
6
|
+
'AWSAccessKeyId' => params[:access_key],
|
7
|
+
'SignatureMethod' => Signature::METHOD,
|
8
|
+
'SignatureVersion' => Signature::VERSION,
|
9
|
+
'Timestamp' => Time.now.iso8601
|
10
|
+
}
|
11
|
+
|
12
|
+
if params[:path].include? 'Orders'
|
13
|
+
query_params['SellerId'] = params[:merchant_id]
|
14
|
+
query_params['Version'] = Amazon::MWS::Authentication::ORDERS_VERSION
|
15
|
+
elsif params[:path].include? 'Products'
|
16
|
+
query_params['SellerId'] = params[:merchant_id]
|
17
|
+
query_params['Version'] = Amazon::MWS::Authentication::PRODUCTS_VERSION
|
18
|
+
else
|
19
|
+
query_params['Merchant'] = params[:merchant_id]
|
20
|
+
query_params['Version'] = Amazon::MWS::Authentication::VERSION
|
21
|
+
end
|
22
|
+
|
23
|
+
# Add any params that are passed in via uri before calculating the signature
|
24
|
+
query_params = query_params.merge(params[:query_params] || {})
|
25
|
+
# Calculate the signature
|
26
|
+
query_params['Signature'] = Signature.new(query_params, params)
|
27
|
+
|
28
|
+
self << formatted_querystring(query_params)
|
29
|
+
end
|
30
|
+
|
31
|
+
def formatted_querystring(query_params)
|
32
|
+
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
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
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), params[:server], params[:path])
|
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, server, path)
|
28
|
+
verb = verb.to_s.upcase
|
29
|
+
string = "#{verb}\n#{server}\n#{path}\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,74 @@
|
|
1
|
+
module Amazon
|
2
|
+
module MWS
|
3
|
+
HOSTS = {
|
4
|
+
:ca => "mws.amazonservices.ca",
|
5
|
+
:cn => "mws.amazonservices.com.cn",
|
6
|
+
:de => "mws-eu.amazonservices.com",
|
7
|
+
:es => "mws-eu.amazonservices.com",
|
8
|
+
:fr => "mws-eu.amazonservices.com",
|
9
|
+
:in => "mws.amazonservices.in",
|
10
|
+
:it => "mws-eu.amazonservices.com",
|
11
|
+
:jp => "mws.amazonservices.jp",
|
12
|
+
:uk => "mws-eu.amazonservices.com",
|
13
|
+
:us => "mws.amazonservices.com"
|
14
|
+
}
|
15
|
+
|
16
|
+
class Base
|
17
|
+
attr_accessor :connection
|
18
|
+
|
19
|
+
def self.debug; @@debug ||= false end
|
20
|
+
def self.debug=(bool); @@debug = bool end
|
21
|
+
|
22
|
+
def initialize(options ={})
|
23
|
+
@merchant_id = options['merchant_id']
|
24
|
+
raise "Must supply merchant_id" unless @merchant_id
|
25
|
+
@connection = Amazon::MWS::Connection.connect(options)
|
26
|
+
end
|
27
|
+
|
28
|
+
def connection
|
29
|
+
raise Amazon::MWS::NoConnectionEstablished.new if !connected?
|
30
|
+
@connection
|
31
|
+
end
|
32
|
+
|
33
|
+
def connected?
|
34
|
+
!@connection.nil?
|
35
|
+
end
|
36
|
+
|
37
|
+
#def disconnect
|
38
|
+
# @connection.http.finish if @connection.persistent?
|
39
|
+
# @connection = nil
|
40
|
+
#end
|
41
|
+
|
42
|
+
# Wraps the current connection's request method and picks the appropriate response class to wrap the response in.
|
43
|
+
# If the response is an error, it will raise that error as an exception. All such exceptions can be caught by rescuing
|
44
|
+
# their superclass, the ResponseError exception class.
|
45
|
+
#
|
46
|
+
# It is unlikely that you would call this method directly. Subclasses of Base have convenience methods for each http request verb
|
47
|
+
# that wrap calls to request.
|
48
|
+
def request(verb, path, query_params = {}, body = nil, attempts = 0, &block)
|
49
|
+
# Find the connection method in connection/management.rb which is evaled into Amazon::MWS::Base
|
50
|
+
response = @connection.request(verb, path, query_params, body, attempts, &block)
|
51
|
+
|
52
|
+
# Each calling class is responsible for formatting the result
|
53
|
+
return response
|
54
|
+
rescue InternalError, RequestTimeout
|
55
|
+
if attempts == 3
|
56
|
+
raise
|
57
|
+
else
|
58
|
+
attempts += 1
|
59
|
+
retry
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Make some convenience methods
|
64
|
+
[:get, :post, :put, :delete, :head].each do |verb|
|
65
|
+
class_eval(<<-EVAL, __FILE__, __LINE__)
|
66
|
+
def #{verb}(path, query_params = {}, body = nil, &block)
|
67
|
+
request(:#{verb}, path, query_params, body, &block)
|
68
|
+
end
|
69
|
+
EVAL
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
module Amazon
|
2
|
+
module MWS
|
3
|
+
|
4
|
+
class Connection
|
5
|
+
|
6
|
+
attr_reader :server, :access_key, :merchant_id, :marketplace_id, :locale
|
7
|
+
|
8
|
+
# Static/Class methods
|
9
|
+
class << self
|
10
|
+
def connect(options = {})
|
11
|
+
new(options)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(params = {})
|
16
|
+
# These values are essential to establishing a connection
|
17
|
+
@locale = (params['locale'] || "us").downcase.to_sym
|
18
|
+
@server = HOSTS[locale]
|
19
|
+
#@persistent = params['persistent'] || false
|
20
|
+
# These values are essential to signing requests
|
21
|
+
@access_key = params['access_key']
|
22
|
+
@secret_access_key = params['secret_access_key']
|
23
|
+
@merchant_id = params['merchant_id']
|
24
|
+
@marketplace_id = params['marketplace_id']
|
25
|
+
@path = '/'
|
26
|
+
|
27
|
+
raise MissingConnectionOptions if [@access_key, @secret_access_key, @merchant_id, @marketplace_id].any? {|option| option.nil?}
|
28
|
+
|
29
|
+
@http = connect
|
30
|
+
end
|
31
|
+
|
32
|
+
# Create the Net::HTTP object to use for this connection
|
33
|
+
def connect
|
34
|
+
http = Net::HTTP.new(@server, 443)
|
35
|
+
http.use_ssl = true
|
36
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
37
|
+
return http
|
38
|
+
end
|
39
|
+
|
40
|
+
# Make the request, based on the appropriate request object
|
41
|
+
# Called from Amazon::MWS::Base
|
42
|
+
def request(verb, path, query_params, body = nil, attempts = 0, &block)
|
43
|
+
@path = path
|
44
|
+
# presumably this is for files
|
45
|
+
body.rewind if body.respond_to?(:rewind) unless attempts.zero?
|
46
|
+
# Prepare the Proc to be called by Net::HTTP
|
47
|
+
proc = requester(verb, path, query_params, body)
|
48
|
+
|
49
|
+
#if @persistent
|
50
|
+
# @http.start unless @http.started?
|
51
|
+
# proc.call
|
52
|
+
#else
|
53
|
+
@http.start(&proc)
|
54
|
+
#end
|
55
|
+
rescue Errno::EPIPE, Timeout::Error, Errno::EINVAL, EOFError
|
56
|
+
@http = connect
|
57
|
+
attempts == 3 ? raise : (attempts += 1; retry)
|
58
|
+
end
|
59
|
+
|
60
|
+
# A Proc used by the request method
|
61
|
+
def requester(verb, path, query_params, body)
|
62
|
+
Proc.new do |http|
|
63
|
+
path = prepare_path(verb, path, query_params)
|
64
|
+
puts "#{path}\n\n" if Amazon::MWS::Base.debug
|
65
|
+
request = build_request(verb, path, body)
|
66
|
+
|
67
|
+
@http.request(request)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Create the signed authentication query string.
|
72
|
+
# Add this query string to the path WITHOUT prepending the server address.
|
73
|
+
def prepare_path(verb, path, query_params)
|
74
|
+
query_string = authenticate_query_string(verb, query_params)
|
75
|
+
return "#{path}?#{query_string}"
|
76
|
+
end
|
77
|
+
|
78
|
+
# Generates the authentication query string used by Amazon.
|
79
|
+
# Takes the http method and the query string of the request and returns the authenticated query string
|
80
|
+
def authenticate_query_string(verb, query_params = {})
|
81
|
+
Authentication::QueryString.new(
|
82
|
+
:verb => verb,
|
83
|
+
:query_params => query_params,
|
84
|
+
:access_key => @access_key,
|
85
|
+
:secret_access_key => @secret_access_key,
|
86
|
+
:merchant_id => @merchant_id,
|
87
|
+
:marketplace_id => @marketplace_id,
|
88
|
+
:server => @server,
|
89
|
+
:path => @path
|
90
|
+
)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Builds up a Net::HTTP request object
|
94
|
+
def build_request(verb, path, body = nil)
|
95
|
+
builder = RequestBuilder.new(verb, path, body)
|
96
|
+
builder.add_user_agent
|
97
|
+
builder.add_content_type
|
98
|
+
builder.add_content_md5(body) unless body.nil?
|
99
|
+
|
100
|
+
return builder.request
|
101
|
+
end
|
102
|
+
end
|
103
|
+
# Connection
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|