mws_rb 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +2 -0
  5. data/.ruby-gemset +1 -0
  6. data/.travis.yml +9 -0
  7. data/CHANGELOG.md +43 -0
  8. data/Gemfile +3 -0
  9. data/Guardfile +12 -0
  10. data/LICENSE +20 -0
  11. data/README.markdown +73 -0
  12. data/Rakefile +1 -0
  13. data/lib/mws.rb +51 -0
  14. data/lib/mws/api/base.rb +55 -0
  15. data/lib/mws/api/feeds.rb +30 -0
  16. data/lib/mws/api/feeds/envelope.rb +84 -0
  17. data/lib/mws/api/feeds/xsd/AdditionalProductInformation.xsd +23 -0
  18. data/lib/mws/api/feeds/xsd/Amazon.xsd +94 -0
  19. data/lib/mws/api/feeds/xsd/Arts.xsd +144 -0
  20. data/lib/mws/api/feeds/xsd/AutoAccessory.xsd +1714 -0
  21. data/lib/mws/api/feeds/xsd/Baby.xsd +206 -0
  22. data/lib/mws/api/feeds/xsd/Beauty.xsd +170 -0
  23. data/lib/mws/api/feeds/xsd/Books.xsd +135 -0
  24. data/lib/mws/api/feeds/xsd/CE.xsd +2878 -0
  25. data/lib/mws/api/feeds/xsd/CameraPhoto.xsd +2612 -0
  26. data/lib/mws/api/feeds/xsd/ClothingAccessories.xsd +128 -0
  27. data/lib/mws/api/feeds/xsd/Computers.xsd +2347 -0
  28. data/lib/mws/api/feeds/xsd/EUCompliance.xsd +24 -0
  29. data/lib/mws/api/feeds/xsd/EntertainmentCollectibles.xsd +99 -0
  30. data/lib/mws/api/feeds/xsd/FBA.xsd +28 -0
  31. data/lib/mws/api/feeds/xsd/FoodAndBeverages.xsd +1000 -0
  32. data/lib/mws/api/feeds/xsd/FoodServiceAndJanSan.xsd +216 -0
  33. data/lib/mws/api/feeds/xsd/FulfillmentCenter.xsd +57 -0
  34. data/lib/mws/api/feeds/xsd/GiftCards.xsd +97 -0
  35. data/lib/mws/api/feeds/xsd/Gourmet.xsd +85 -0
  36. data/lib/mws/api/feeds/xsd/Health.xsd +335 -0
  37. data/lib/mws/api/feeds/xsd/Home.xsd +1362 -0
  38. data/lib/mws/api/feeds/xsd/HomeImprovement.xsd +1065 -0
  39. data/lib/mws/api/feeds/xsd/Industrial.xsd +315 -0
  40. data/lib/mws/api/feeds/xsd/Inventory.xsd +49 -0
  41. data/lib/mws/api/feeds/xsd/Jewelry.xsd +916 -0
  42. data/lib/mws/api/feeds/xsd/LabSupplies.xsd +178 -0
  43. data/lib/mws/api/feeds/xsd/LargeAppliances.xsd +646 -0
  44. data/lib/mws/api/feeds/xsd/Lighting.xsd +243 -0
  45. data/lib/mws/api/feeds/xsd/Listings.xsd +32 -0
  46. data/lib/mws/api/feeds/xsd/Luggage.xsd +93 -0
  47. data/lib/mws/api/feeds/xsd/MechanicalFasteners.xsd +172 -0
  48. data/lib/mws/api/feeds/xsd/Miscellaneous.xsd +157 -0
  49. data/lib/mws/api/feeds/xsd/Motorcycles.xsd +348 -0
  50. data/lib/mws/api/feeds/xsd/Music.xsd +251 -0
  51. data/lib/mws/api/feeds/xsd/MusicalInstruments.xsd +853 -0
  52. data/lib/mws/api/feeds/xsd/Office.xsd +586 -0
  53. data/lib/mws/api/feeds/xsd/OrderAcknowledgement.xsd +55 -0
  54. data/lib/mws/api/feeds/xsd/OrderAdjustment.xsd +175 -0
  55. data/lib/mws/api/feeds/xsd/OrderFulfillment.xsd +57 -0
  56. data/lib/mws/api/feeds/xsd/Override.xsd +48 -0
  57. data/lib/mws/api/feeds/xsd/PetSupplies.xsd +197 -0
  58. data/lib/mws/api/feeds/xsd/PowerTransmission.xsd +87 -0
  59. data/lib/mws/api/feeds/xsd/Price.xsd +59 -0
  60. data/lib/mws/api/feeds/xsd/ProcessingReport.xsd +87 -0
  61. data/lib/mws/api/feeds/xsd/Product.xsd +399 -0
  62. data/lib/mws/api/feeds/xsd/ProductClothing.xsd +285 -0
  63. data/lib/mws/api/feeds/xsd/ProductImage.xsd +39 -0
  64. data/lib/mws/api/feeds/xsd/RawMaterials.xsd +125 -0
  65. data/lib/mws/api/feeds/xsd/Relationship.xsd +47 -0
  66. data/lib/mws/api/feeds/xsd/SWVG.xsd +345 -0
  67. data/lib/mws/api/feeds/xsd/SettlementReport.xsd +158 -0
  68. data/lib/mws/api/feeds/xsd/Shoes.xsd +213 -0
  69. data/lib/mws/api/feeds/xsd/Sports.xsd +772 -0
  70. data/lib/mws/api/feeds/xsd/SportsMemorabilia.xsd +55 -0
  71. data/lib/mws/api/feeds/xsd/TiresAndWheels.xsd +159 -0
  72. data/lib/mws/api/feeds/xsd/Tools.xsd +82 -0
  73. data/lib/mws/api/feeds/xsd/Toys.xsd +272 -0
  74. data/lib/mws/api/feeds/xsd/ToysBaby.xsd +335 -0
  75. data/lib/mws/api/feeds/xsd/Video.xsd +406 -0
  76. data/lib/mws/api/feeds/xsd/WineAndAlcohol.xsd +181 -0
  77. data/lib/mws/api/feeds/xsd/Wireless.xsd +128 -0
  78. data/lib/mws/api/feeds/xsd/amzn-base.xsd +4350 -0
  79. data/lib/mws/api/feeds/xsd/amzn-envelope.xsd +98 -0
  80. data/lib/mws/api/feeds/xsd/amzn-header.xsd +45 -0
  81. data/lib/mws/api/fulfillment_inbound_shipment.rb +16 -0
  82. data/lib/mws/api/fulfillment_inventory.rb +14 -0
  83. data/lib/mws/api/fulfillment_outbound_shipment.rb +24 -0
  84. data/lib/mws/api/orders.rb +16 -0
  85. data/lib/mws/api/products.rb +19 -0
  86. data/lib/mws/api/recommendations.rb +14 -0
  87. data/lib/mws/api/reports.rb +17 -0
  88. data/lib/mws/api/sellers.rb +18 -0
  89. data/lib/mws/api/subscriptions.rb +15 -0
  90. data/lib/mws/connection.rb +56 -0
  91. data/lib/mws/query.rb +104 -0
  92. data/lib/mws/version.rb +4 -0
  93. data/mws_rb.gemspec +32 -0
  94. data/spec/fixtures/vcr_cassettes/feeds/submit_feed/invalid_request.yml +194 -0
  95. data/spec/fixtures/vcr_cassettes/feeds/submit_feed/text_request.yml +188 -0
  96. data/spec/fixtures/vcr_cassettes/feeds/submit_feed/xml_request.yml +224 -0
  97. data/spec/mws-rb/api/base_spec.rb +48 -0
  98. data/spec/mws-rb/api/feeds/envelope/general_spec.rb +31 -0
  99. data/spec/mws-rb/api/feeds/envelope/xml_building_spec.rb +101 -0
  100. data/spec/mws-rb/api/feeds_spec.rb +88 -0
  101. data/spec/mws-rb/api/fulfillment_inbound_shipment_spec.rb +24 -0
  102. data/spec/mws-rb/api/fulfillment_inventory_spec.rb +24 -0
  103. data/spec/mws-rb/api/fulfillment_outbound_shipment_spec.rb +24 -0
  104. data/spec/mws-rb/api/orders_spec.rb +24 -0
  105. data/spec/mws-rb/api/products_spec.rb +24 -0
  106. data/spec/mws-rb/api/recommendations_spec.rb +24 -0
  107. data/spec/mws-rb/api/reports_spec.rb +24 -0
  108. data/spec/mws-rb/api/sellers_spec.rb +28 -0
  109. data/spec/mws-rb/api/subscriptions_spec.rb +24 -0
  110. data/spec/mws-rb/connection_spec.rb +77 -0
  111. data/spec/mws-rb/mws_spec.rb +12 -0
  112. data/spec/mws-rb/query_spec.rb +150 -0
  113. data/spec/spec_helper.rb +17 -0
  114. metadata +310 -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
+
@@ -0,0 +1,16 @@
1
+ module MWS
2
+ module API
3
+ # FulfillmentInboundShipment
4
+ class FulfillmentInboundShipment < Base
5
+ ACTIONS = [:create_inbound_shipment_plan, :create_inbound_shipment, :update_inbound_shipment,
6
+ :list_inbound_shipments, :list_inbound_shipments_by_next_token, :list_inbound_shipment_items,
7
+ :list_inbound_shipment_items_by_next_token, :get_service_status]
8
+
9
+ def initialize(connection)
10
+ @uri = '/FulfillmentInboundShipment/2010-10-01'
11
+ @version = '2010-10-01'
12
+ super
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,14 @@
1
+ module MWS
2
+ module API
3
+ # FulfillmentInventory
4
+ class FulfillmentInventory < Base
5
+ ACTIONS = [:list_inventory_supply, :list_inventory_supply_by_next_token, :get_service_status]
6
+
7
+ def initialize(connection)
8
+ @uri = '/FulfillmentInventory/2010-10-01'
9
+ @version = '2010-10-01'
10
+ super
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,24 @@
1
+ module MWS
2
+ module API
3
+ # FulfilmentOutboundShipment
4
+ class FulfillmentOutboundShipment < Base
5
+ ACTIONS = [
6
+ :cancel_fulfillment_order,
7
+ :create_fulfillment_order,
8
+ :get_fulfillment_order,
9
+ :get_fulfillment_preview,
10
+ :get_package_tracking_details,
11
+ :get_service_status,
12
+ :list_all_fulfillment_orders,
13
+ :list_all_fulfillment_orders_by_next_token,
14
+ :update_fulfillment_order
15
+ ]
16
+
17
+ def initialize(connection)
18
+ @uri = '/FulfillmentOutboundShipment/2010-10-01'
19
+ @version = '2010-10-01'
20
+ super
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,16 @@
1
+ module MWS
2
+ module API
3
+ # Orders
4
+ class Orders < Base
5
+ ACTIONS = [:list_orders, :list_orders_by_next_token, :get_order, :list_order_items,
6
+ :list_order_items_by_next_token, :get_service_status]
7
+
8
+ def initialize(connection)
9
+ @uri = '/Orders/2013-09-01'
10
+ @version = '2013-09-01'
11
+ @verb = :post
12
+ super
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ module MWS
2
+ module API
3
+ # Products
4
+ class Products < Base
5
+ ACTIONS = [:list_matching_products, :get_matching_product, :get_matching_product_for_id,
6
+ :get_competitive_pricing_for_SKU, :get_competitive_pricing_for_ASIN,
7
+ :get_lowest_offer_listings_for_SKU, :get_lowest_offer_listings_for_ASIN,
8
+ :get_my_price_for_SKU, :get_my_price_for_ASIN,
9
+ :get_product_categories_for_SKU, :get_product_categories_for_ASIN,
10
+ :get_service_status]
11
+
12
+ def initialize(connection)
13
+ @uri = '/Products/2011-10-01'
14
+ @version = '2011-10-01'
15
+ super
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,14 @@
1
+ module MWS
2
+ module API
3
+ # Recommendations
4
+ class Recommendations < Base
5
+ ACTIONS = [:get_last_updated_time_for_recommendations_checks, :list_recommendations, :list_recommendations_by_next_token]
6
+
7
+ def initialize(connection)
8
+ @uri = '/Recommendations/2013-04-01'
9
+ @version = '2013-04-01'
10
+ super
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,17 @@
1
+ module MWS
2
+ module API
3
+ # Reports
4
+ class Reports < Base
5
+ ACTIONS = [:request_report, :get_report_request_list, :get_report_request_list_by_next_token,
6
+ :get_report_request_count, :cancel_report_requests, :get_report_list, :get_report_list_by_next_token,
7
+ :get_report_count, :get_report, :manage_report_schedule, :get_report_schedule_list,
8
+ :get_report_schedule_list_by_next_token, :get_report_schedule_count, :update_report_acknowledgements]
9
+
10
+ def initialize(connection)
11
+ @uri = '/'
12
+ @version = '2009-01-01'
13
+ super
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ module MWS
2
+ module API
3
+ # Sellers
4
+ class Sellers < Base
5
+ ACTIONS = [:list_marketplace_participations,
6
+ :list_marketplace_participations_by_next_token,
7
+ :get_auth_token,
8
+ :get_service_status]
9
+
10
+ def initialize(connection)
11
+ @uri = '/Sellers/2011-07-01'
12
+ @version = '2011-07-01'
13
+ @verb = :post
14
+ super
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,15 @@
1
+ module MWS
2
+ module API
3
+ # Subscriptions
4
+ class Subscriptions < Base
5
+ ACTIONS = [:register_destination, :deregister_destination, :list_registered_destinations, :send_test_notification_to_destination, :create_subscription, :get_subscription, :delete_subscription, :list_subscriptions, :update_subscription, :get_service_status]
6
+
7
+ def initialize(connection)
8
+ @uri = '/Subscriptions/2013-07-01'
9
+ @version = '2013-07-01'
10
+ @verb = :post
11
+ super
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,56 @@
1
+ module MWS
2
+ # Connection
3
+ class Connection
4
+ attr_reader :host, :aws_access_key_id, :aws_secret_access_key, :seller_id, :mws_auth_token
5
+
6
+ # rubocop:disable all
7
+ def initialize(options = {})
8
+ @host = options[:host] || 'mws.amazonservices.com'
9
+ @aws_access_key_id = options[:aws_access_key_id] || MWS.aws_access_key_id || ENV['AWS_ACCESS_KEY_ID']
10
+ @aws_secret_access_key = options[:aws_secret_access_key] || MWS.aws_secret_access_key || ENV['AWS_SECRET_ACCESS_KEY']
11
+ @mws_auth_token = options[:mws_auth_token] || ENV['MWS_AUTH_TOKEN']
12
+ @seller_id = options[:seller_id]
13
+
14
+ if @aws_access_key_id.to_s.empty? || @aws_secret_access_key.to_s.empty? || @seller_id.to_s.empty?
15
+ fail(ArgumentError, 'You must provide :aws_access_key_id, :aws_secret_access_key, :seller_id and :mws_auth_token')
16
+ end
17
+ end
18
+
19
+ # Map APIS
20
+ def feeds
21
+ @fees ||= MWS::API::Feeds.new(self)
22
+ end
23
+
24
+ def fulfillment_inbound_shipment
25
+ @fis ||= MWS::API::FulfillmentInboundShipment.new(self)
26
+ end
27
+
28
+ def fulfillment_inventory
29
+ @fi ||= MWS::API::FulfillmentInventory.new(self)
30
+ end
31
+
32
+ def fulfillment_outbound_shipment
33
+ @fos ||= MWS::API::FulfillmentOutboundShipment.new(self)
34
+ end
35
+
36
+ def orders
37
+ @orders ||= MWS::API::Orders.new(self)
38
+ end
39
+
40
+ def products
41
+ @products ||= MWS::API::Products.new(self)
42
+ end
43
+
44
+ def recommendations
45
+ @recommendations ||= MWS::API::Recommendations.new(self)
46
+ end
47
+
48
+ def reports
49
+ @reports ||= MWS::API::Reports.new(self)
50
+ end
51
+
52
+ def sellers
53
+ @sellers ||= MWS::API::Sellers.new(self)
54
+ end
55
+ end
56
+ end
data/lib/mws/query.rb ADDED
@@ -0,0 +1,104 @@
1
+ require 'addressable/uri'
2
+
3
+ # MWS
4
+ module MWS
5
+ # Query
6
+ class Query
7
+ attr_reader :verb, :uri, :host, :aws_access_key_id, :aws_secret_access_key, :mws_auth_token, :action, :seller_id,
8
+ :signature_method, :signature_version, :timestamp, :version
9
+
10
+ # rubocop:disable all
11
+ def initialize(params = {})
12
+ @verb = params[:verb] || 'GET'
13
+ @uri = params[:uri] || '/'
14
+ @host = params[:host]
15
+
16
+ @aws_access_key_id = params[:aws_access_key_id]
17
+ @aws_secret_access_key = params[:aws_secret_access_key]
18
+ @mws_auth_token = params[:mws_auth_token]
19
+ @action = params[:action].to_s.camelize.gsub(/(Sku|Asin)/i) { |_s| Regexp.last_match(1).upcase }
20
+ @seller_id = params[:seller_id]
21
+ @signature_method = params[:signature_method] || 'HmacSHA256'
22
+ @signature_version = params[:signature_version] || 2
23
+ @timestamp = params[:timestamp] || Time.now
24
+ @version = params[:version]
25
+
26
+ @params = params[:params]
27
+ end
28
+
29
+ def request_uri
30
+ 'https://' << @host << @uri << '?' << build_query(signature)
31
+ end
32
+
33
+ def canonical
34
+ canonical = [@verb.to_s.upcase, @host.downcase, @uri, build_query].join("\n")
35
+ end
36
+
37
+ def signature
38
+ digest = OpenSSL::Digest.new('sha256')
39
+ Base64.encode64(OpenSSL::HMAC.digest(digest, aws_secret_access_key, canonical)).strip
40
+ end
41
+
42
+ def build_query(signature = nil)
43
+ query = {
44
+ 'AWSAccessKeyId' => @aws_access_key_id,
45
+ 'Action' => @action,
46
+ 'SellerId' => @seller_id,
47
+ 'SignatureMethod' => @signature_method,
48
+ 'SignatureVersion' => @signature_version,
49
+ 'Timestamp' => @timestamp,
50
+ 'Version' => @version
51
+ }
52
+ query['MWSAuthToken'] = @mws_auth_token if @mws_auth_token
53
+ query['Signature'] = signature if signature
54
+
55
+ params = Helpers.camelize_keys(@params || {})
56
+ params = Helpers.make_structured_lists(params)
57
+ query.merge!(params)
58
+
59
+ # Sort hash in natural-byte order
60
+ uri = Addressable::URI.new
61
+ uri.query_values = Hash[Helpers.escape_date_time_params(query).sort]
62
+ uri.query
63
+ end
64
+
65
+ # Helpers
66
+ module Helpers
67
+ def self.escape_date_time_params(params = {})
68
+ params.map do |key, value|
69
+ case value.class.name
70
+ when 'Time', 'Date', 'DateTime'
71
+ { key => value.iso8601 }
72
+ when 'Hash'
73
+ { key => escape_date_time_params(value) }
74
+ else
75
+ { key => value }
76
+ end
77
+ end.reduce({}, :merge)
78
+ end
79
+
80
+ def self.camelize_keys(params = {})
81
+ params.map do |key, value|
82
+ case value.class.name
83
+ when 'Hash'
84
+ { key.to_s.camelize => camelize_keys(value) }
85
+ else
86
+ { key.to_s.camelize => value }
87
+ end
88
+ end.reduce({}, :merge)
89
+ end
90
+
91
+ def self.make_structured_lists(params = {})
92
+ params.map do |key, value|
93
+ if key.to_s.end_with?('list')
94
+ value[:values].each_with_index.map do |item, index|
95
+ { "#{value[:label]}.#{index + 1}" => item }
96
+ end.reduce({}, :merge)
97
+ else
98
+ { key => value }
99
+ end
100
+ end.reduce({}, :merge)
101
+ end
102
+ end
103
+ end
104
+ end