rasin 0.7.0

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 (42) hide show
  1. data/.document +3 -0
  2. data/.gitignore +6 -0
  3. data/.travis.yml +13 -0
  4. data/CHANGELOG.rdoc +49 -0
  5. data/Gemfile +4 -0
  6. data/Gemfile.lock +54 -0
  7. data/README.rdoc +166 -0
  8. data/asin.gemspec +36 -0
  9. data/lib/asin.rb +8 -0
  10. data/lib/asin/client.rb +398 -0
  11. data/lib/asin/configuration.rb +105 -0
  12. data/lib/asin/simple_cart.rb +54 -0
  13. data/lib/asin/simple_item.rb +44 -0
  14. data/lib/asin/simple_node.rb +44 -0
  15. data/lib/asin/version.rb +3 -0
  16. data/rakefile.rb +11 -0
  17. data/spec/asin.yml +4 -0
  18. data/spec/browse_node_spec.rb +17 -0
  19. data/spec/cart_spec.rb +150 -0
  20. data/spec/cassettes/asin/asin_cart_with_an_existing_cart_should_add_items_to_a_cart.yml +68 -0
  21. data/spec/cassettes/asin/asin_cart_with_an_existing_cart_should_clear_a_cart.yml +66 -0
  22. data/spec/cassettes/asin/asin_cart_with_an_existing_cart_should_get_a_cart.yml +67 -0
  23. data/spec/cassettes/asin/asin_cart_with_an_existing_cart_should_update_a_cart.yml +70 -0
  24. data/spec/cassettes/asin/browse_node_should_lookup_a_browse_node.yml +38 -0
  25. data/spec/cassettes/asin/cart_should_create_a_cart.yml +36 -0
  26. data/spec/cassettes/asin/lookup_and_search_should_have_metadata.yml +81 -0
  27. data/spec/cassettes/asin/lookup_and_search_should_lookup_a_book.yml +81 -0
  28. data/spec/cassettes/asin/lookup_and_search_should_lookup_multiple_books.yml +131 -0
  29. data/spec/cassettes/asin/lookup_and_search_should_lookup_multiple_response_groups.yml +43 -0
  30. data/spec/cassettes/asin/lookup_and_search_should_return_a_custom_item_class.yml +81 -0
  31. data/spec/cassettes/asin/lookup_and_search_should_return_a_mash_value.yml +81 -0
  32. data/spec/cassettes/asin/lookup_and_search_should_return_a_rash_value.yml +81 -0
  33. data/spec/cassettes/asin/lookup_and_search_should_return_a_raw_value.yml +81 -0
  34. data/spec/cassettes/asin/lookup_and_search_should_search_keywords_a_book_with_fulltext.yml +538 -0
  35. data/spec/cassettes/asin/lookup_and_search_should_search_keywords_and_handle_a_single_result.yml +72 -0
  36. data/spec/cassettes/asin/lookup_and_search_should_search_keywords_never_mind_music.yml +119 -0
  37. data/spec/cassettes/asin/lookup_and_search_should_search_music.yml +37 -0
  38. data/spec/cassettes/asin/lookup_and_search_should_search_never_mind_music.yml +122 -0
  39. data/spec/config_spec.rb +53 -0
  40. data/spec/search_spec.rb +101 -0
  41. data/spec/spec_helper.rb +47 -0
  42. metadata +197 -0
@@ -0,0 +1,105 @@
1
+ require "yaml"
2
+ require 'logger'
3
+
4
+ module ASIN
5
+ class Configuration
6
+ class << self
7
+
8
+ attr_accessor :secret, :key, :host, :logger
9
+ attr_accessor :item_type, :cart_type, :node_type
10
+ attr_accessor :version, :associate_tag
11
+
12
+ # Rails initializer configuration.
13
+ #
14
+ # Expects at least +secret+ and +key+ for the API call:
15
+ #
16
+ # ASIN::Configuration.configure do |config|
17
+ # config.secret = 'your-secret'
18
+ # config.key = 'your-key'
19
+ # end
20
+ #
21
+ # With the latest version of the Product Advertising API you need to include your associate_tag[https://affiliate-program.amazon.com/gp/advertising/api/detail/api-changes.html].
22
+ #
23
+ # You may pass options as a hash as well:
24
+ #
25
+ # ASIN::Configuration.configure :secret => 'your-secret', :key => 'your-key'
26
+ #
27
+ # Or configure everything using YAML:
28
+ #
29
+ # ASIN::Configuration.configure :yaml => 'config/asin.yml'
30
+ #
31
+ # ASIN::Configuration.configure :yaml => 'config/asin.yml' do |config, yml|
32
+ # config.key = yml[Rails.env]['aws_access_key']
33
+ # end
34
+ #
35
+ # ==== Options:
36
+ #
37
+ # [secret] the API secret key (required)
38
+ # [key] the API access key (required)
39
+ # [associate_tag] your Amazon associate tag. Default is blank (required in latest API version)
40
+ # [host] the host, which defaults to 'webservices.amazon.com'
41
+ # [logger] a different logger than logging to STDERR (nil for no logging)
42
+ # [version] a custom version of the API calls. Default is 2010-11-01
43
+ # [item_type] a different class for SimpleItem, use :mash / :rash for Hashie::Mash / Hashie::Rash or :raw for a plain hash
44
+ # [cart_type] a different class for SimpleCart, use :mash / :rash for Hashie::Mash / Hashie::Rash or :raw for a plain hash
45
+ # [node_type] a different class for SimpleNode, use :mash / :rash for Hashie::Mash / Hashie::Rash or :raw for a plain hash
46
+ #
47
+ def configure(options={})
48
+ init_config
49
+ if yml_path = options[:yaml] || options[:yml]
50
+ yml = File.open(yml_path) { |file| YAML.load(file) }
51
+ if block_given?
52
+ yield self, yml
53
+ else
54
+ yml.each do |key, value|
55
+ send(:"#{key}=", value)
56
+ end
57
+ end
58
+ elsif block_given?
59
+ yield self
60
+ else
61
+ options.each do |key, value|
62
+ send(:"#{key}=", value)
63
+ end
64
+ end
65
+ self
66
+ end
67
+
68
+ # Checks if given credentials are valid and raises an error if not.
69
+ #
70
+ def validate_credentials!
71
+ raise "you have to configure ASIN: 'configure :secret => 'your-secret', :key => 'your-key'" if blank?(:secret) || blank?(:key)
72
+ [:host, :item_type, :cart_type, :node_type, :version, :associate_tag].each { |item| raise "nil is not a valid value for #{item}" unless self.send item }
73
+ end
74
+
75
+ # Resets configuration to defaults
76
+ #
77
+ def reset
78
+ init_config(true)
79
+ end
80
+
81
+ # Check if a key is set
82
+ #
83
+ def blank?(key)
84
+ val = self.send :key
85
+ val.nil? || val.empty?
86
+ end
87
+
88
+ private()
89
+
90
+ def init_config(force=false)
91
+ return if @init && !force
92
+ @init = true
93
+ @secret = ''
94
+ @key = ''
95
+ @host = 'webservices.amazon.com'
96
+ @logger = Logger.new(STDERR)
97
+ @item_type = SimpleItem
98
+ @cart_type = SimpleCart
99
+ @node_type = SimpleNode
100
+ @version = '2010-11-01'
101
+ @associate_tag = ''
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,54 @@
1
+ require 'hashie'
2
+
3
+ module ASIN
4
+
5
+ # = SimpleCart
6
+ #
7
+ # The +SimpleCart+ class is a wrapper for the Amazon XML-REST-Response.
8
+ #
9
+ # A Hashie::Mash is used for the internal data representation and can be accessed over the +raw+ attribute.
10
+ #
11
+ class SimpleCart
12
+
13
+ attr_reader :raw
14
+
15
+ def initialize(hash)
16
+ @raw = Hashie::Mash.new(hash)
17
+ end
18
+
19
+ def cart_id
20
+ @raw.CartId
21
+ end
22
+
23
+ def hmac
24
+ @raw.HMAC
25
+ end
26
+
27
+ def url
28
+ @raw.PurchaseURL
29
+ end
30
+
31
+ def price
32
+ @raw.SubTotal.FormattedPrice
33
+ end
34
+
35
+ def items
36
+ return [] unless @raw.CartItems
37
+ @raw.CartItems.CartItem.is_a?(Array) ? @raw.CartItems.CartItem : [@raw.CartItems.CartItem]
38
+ end
39
+
40
+ def saved_items
41
+ return [] unless @raw.SavedForLaterItems
42
+ @raw.SavedForLaterItems.SavedForLaterItem.is_a?(Array) ? @raw.SavedForLaterItems.SavedForLaterItem : [@raw.SavedForLaterItems.SavedForLaterItem]
43
+ end
44
+
45
+ def valid?
46
+ @raw.Request.IsValid == 'True'
47
+ end
48
+
49
+ def empty?
50
+ @raw.CartItems.nil?
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,44 @@
1
+ require 'hashie'
2
+
3
+ module ASIN
4
+
5
+ # =SimpleItem
6
+ #
7
+ # The +SimpleItem+ class is a wrapper for the Amazon XML-REST-Response.
8
+ #
9
+ # A Hashie::Mash is used for the internal data representation and can be accessed over the +raw+ attribute.
10
+ #
11
+ class SimpleItem
12
+
13
+ attr_reader :raw
14
+
15
+ def initialize(hash)
16
+ @raw = Hashie::Mash.new(hash)
17
+ end
18
+
19
+ def asin
20
+ @raw.ASIN
21
+ end
22
+
23
+ def title
24
+ @raw.ItemAttributes!.Title
25
+ end
26
+
27
+ def amount
28
+ @raw.ItemAttributes!.ListPrice!.Amount.to_i
29
+ end
30
+
31
+ def details_url
32
+ @raw.DetailPageURL
33
+ end
34
+
35
+ def review
36
+ @raw.EditorialReviews!.EditorialReview!.Content
37
+ end
38
+
39
+ def image_url
40
+ @raw.LargeImage!.URL
41
+ end
42
+ end
43
+
44
+ end
@@ -0,0 +1,44 @@
1
+ require 'hashie'
2
+
3
+ module ASIN
4
+
5
+ # =SimpleNode
6
+ #
7
+ # The +SimpleNode+ class is a wrapper for the Amazon XML-REST-Response.
8
+ #
9
+ # A Hashie::Mash is used for the internal data representation and can be accessed over the +raw+ attribute.
10
+ #
11
+ class SimpleNode
12
+
13
+ attr_reader :raw
14
+
15
+ def initialize(hash)
16
+ @raw = Hashie::Mash.new(hash)
17
+ end
18
+
19
+ def name
20
+ @raw.Name
21
+ end
22
+
23
+ def node_id
24
+ @raw.BrowseNodeId
25
+ end
26
+
27
+ def children
28
+ return [] unless @raw.Children
29
+ @raw.Children.BrowseNode.is_a?(Array) ? @raw.Children.BrowseNode : [@raw.Children.BrowseNode]
30
+ end
31
+
32
+ def ancestors
33
+ return [] unless @raw.Ancestors
34
+ @raw.Ancestors.BrowseNode.is_a?(Array) ? @raw.Ancestors.BrowseNode : [@raw.Ancestors.BrowseNode]
35
+ end
36
+
37
+ def top_item_set
38
+ return [] unless @raw.TopItemSet
39
+ @raw.TopItemSet.TopItem.is_a?(Array) ? @raw.TopItemSet.TopItem : [@raw.TopItemSet.TopItem]
40
+ end
41
+
42
+ end
43
+
44
+ end
@@ -0,0 +1,3 @@
1
+ module ASIN
2
+ VERSION = "0.7.0"
3
+ end
@@ -0,0 +1,11 @@
1
+ require "bundler"
2
+ require "rspec/core/rake_task"
3
+
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ RSpec::Core::RakeTask.new do |t|
7
+ t.rspec_opts = ["--format Fuubar", "--color"]
8
+ t.pattern = 'spec/**/*_spec.rb'
9
+ end
10
+
11
+ task :default=>:spec
@@ -0,0 +1,4 @@
1
+ secret: 'secret_yml'
2
+ key: 'key_yml'
3
+ host: 'host_yml'
4
+ logger: 'logger_yml'
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ module ASIN
4
+ describe ASIN do
5
+ context "browse_node" do
6
+ before do
7
+ @helper.configure :secret => @secret, :key => @key
8
+ end
9
+
10
+ it "should lookup a browse_node", :vcr do
11
+ item = @helper.browse_node(ANY_BROWSE_NODE_ID)
12
+ item.node_id.should eql(ANY_BROWSE_NODE_ID)
13
+ item.name.should eql('Comedy')
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,150 @@
1
+ require 'spec_helper'
2
+
3
+ module ASIN
4
+ describe ASIN do
5
+ before do
6
+ @helper.configure :secret => @secret, :key => @key
7
+ end
8
+
9
+ context "cart" do
10
+
11
+ it "should create a cart", :vcr do
12
+ cart = @helper.create_cart({:asin => ANY_ASIN, :quantity => 1}, {:asin => ANY_OTHER_ASIN, :quantity => 2})
13
+ cart.valid?.should be(true)
14
+ cart.empty?.should be(false)
15
+ end
16
+
17
+ it "should handle item paramters" do
18
+ params = @helper.send(:create_item_params, [{:asin => 'any_asin', :quantity => 1}, {:cart_item_id => 'any_cart_item_id', :quantity => 2}, {:offer_listing_id => 'any_offer_listing_id', :quantity => 3},{:cart_item_id => 'any_cart_item_id', :action => :SaveForLater}])
19
+ params.should eql({"Item.0.ASIN"=>"any_asin", "Item.0.Quantity"=>"1", "Item.1.CartItemId"=>"any_cart_item_id", "Item.1.Quantity"=>"2", "Item.2.OfferListingId"=>"any_offer_listing_id", "Item.2.Quantity"=>"3", "Item.3.CartItemId"=>"any_cart_item_id", "Item.3.Action"=>"SaveForLater"})
20
+ end
21
+
22
+ context "with an existing cart" do
23
+
24
+ it "should clear a cart", :vcr do
25
+ @cart = @helper.create_cart({:asin => ANY_ASIN, :quantity => 1})
26
+ cart = @helper.clear_cart(@cart)
27
+ cart.valid?.should be(true)
28
+ cart.empty?.should be(true)
29
+ end
30
+
31
+ it "should get a cart", :vcr do
32
+ @cart = @helper.create_cart({:asin => ANY_ASIN, :quantity => 1})
33
+ cart = @helper.get_cart(@cart.cart_id, @cart.hmac)
34
+ cart.valid?.should be(true)
35
+ cart.empty?.should be(false)
36
+ end
37
+
38
+ it "should add items to a cart", :vcr do
39
+ @cart = @helper.create_cart({:asin => ANY_ASIN, :quantity => 1})
40
+ cart = @helper.add_items(@cart, {:asin => ANY_OTHER_ASIN, :quantity => 2})
41
+ cart.valid?.should be(true)
42
+ cart.empty?.should be(false)
43
+ cart.items.should have(2).things
44
+ end
45
+
46
+ it "should update a cart", :vcr do
47
+ @cart = @helper.create_cart({:asin => ANY_ASIN, :quantity => 1})
48
+ item_id = @cart.items.first.CartItemId
49
+ cart = @helper.update_items(@cart, {:cart_item_id => item_id, :action => 'SaveForLater'}, {:cart_item_id => item_id, :quantity => 7})
50
+ cart.saved_items.should have(1).things
51
+ cart.valid?.should be(true)
52
+ end
53
+
54
+ end
55
+
56
+ context SimpleCart do
57
+
58
+ before do
59
+ @helper.configure :secret => @secret, :key => @key
60
+ @two_items = {"Request"=>
61
+ {"IsValid"=>"True",
62
+ "CartAddRequest"=>
63
+ {"CartId"=>"186-8702292-9782208",
64
+ "HMAC"=>"Ck5MXUE+OQiC/Jh8u6NhBf5FbV8=",
65
+ "Items"=>{"Item"=>{"ASIN"=>"1430216263", "Quantity"=>"2"}}}},
66
+ "CartId"=>"186-8702292-9782208",
67
+ "HMAC"=>"Ck5MXUE+OQiC/Jh8u6NhBf5FbV8=",
68
+ "URLEncodedHMAC"=>"Ck5MXUE%2BOQiC%2FJh8u6NhBf5FbV8%3D",
69
+ "PurchaseURL"=>
70
+ "https://www.amazon.com/gp/cart/aws-merge.html?cart-id=186-8702292-9782208%26associate-id=ws%26hmac=Ck5MXUE%2BOQiC/Jh8u6NhBf5FbV8=%26SubscriptionId=AKIAJFA5X7RTOKFNPVZQ%26MergeCart=False",
71
+ "SubTotal"=>
72
+ {"Amount"=>"6595", "CurrencyCode"=>"USD", "FormattedPrice"=>"$65.95"},
73
+ "CartItems"=>
74
+ {"SubTotal"=>
75
+ {"Amount"=>"6595", "CurrencyCode"=>"USD", "FormattedPrice"=>"$65.95"},
76
+ "CartItem"=>
77
+ [{"CartItemId"=>"U3CFEHHIPJNW3L",
78
+ "ASIN"=>"1430216263",
79
+ "MerchantId"=>"ATVPDKIKX0DER",
80
+ "SellerId"=>"A2R2RITDJNW1Q6",
81
+ "SellerNickname"=>"Amazon.com",
82
+ "Quantity"=>"2",
83
+ "Title"=>"Beginning iPhone Development: Exploring the iPhone SDK",
84
+ "ProductGroup"=>"Book",
85
+ "Price"=>
86
+ {"Amount"=>"1978", "CurrencyCode"=>"USD", "FormattedPrice"=>"$19.78"},
87
+ "ItemTotal"=>
88
+ {"Amount"=>"3956", "CurrencyCode"=>"USD", "FormattedPrice"=>"$39.56"}},
89
+ {"CartItemId"=>"U3G241HVLLB8N6",
90
+ "ASIN"=>"1430218150",
91
+ "MerchantId"=>"ATVPDKIKX0DER",
92
+ "SellerId"=>"A2R2RITDJNW1Q6",
93
+ "SellerNickname"=>"Amazon.com",
94
+ "Quantity"=>"1",
95
+ "Title"=>"Learn Objective-C on the Mac (Learn Series)",
96
+ "ProductGroup"=>"Book",
97
+ "Price"=>
98
+ {"Amount"=>"2639", "CurrencyCode"=>"USD", "FormattedPrice"=>"$26.39"},
99
+ "ItemTotal"=>
100
+ {"Amount"=>"2639",
101
+ "CurrencyCode"=>"USD",
102
+ "FormattedPrice"=>"$26.39"}}]}}
103
+ @one_item = {"Request"=>
104
+ {"IsValid"=>"True",
105
+ "CartCreateRequest"=>
106
+ {"Items"=>{"Item"=>{"ASIN"=>"1430218150", "Quantity"=>"1"}}}},
107
+ "CartId"=>"176-9182855-2326919",
108
+ "HMAC"=>"KgeVCA0YJTbuN/7Ibakrk/KnHWA=",
109
+ "URLEncodedHMAC"=>"KgeVCA0YJTbuN%2F7Ibakrk%2FKnHWA%3D",
110
+ "PurchaseURL"=>
111
+ "https://www.amazon.com/gp/cart/aws-merge.html?cart-id=176-9182855-2326919%26associate-id=ws%26hmac=KgeVCA0YJTbuN/7Ibakrk/KnHWA=%26SubscriptionId=AKIAJFA5X7RTOKFNPVZQ%26MergeCart=False",
112
+ "SubTotal"=>
113
+ {"Amount"=>"2639", "CurrencyCode"=>"USD", "FormattedPrice"=>"$26.39"},
114
+ "CartItems"=>
115
+ {"SubTotal"=>
116
+ {"Amount"=>"2639", "CurrencyCode"=>"USD", "FormattedPrice"=>"$26.39"},
117
+ "CartItem"=>
118
+ {"CartItemId"=>"U3G241HVLLB8N6",
119
+ "ASIN"=>"1430218150",
120
+ "MerchantId"=>"ATVPDKIKX0DER",
121
+ "SellerId"=>"A2R2RITDJNW1Q6",
122
+ "SellerNickname"=>"Amazon.com",
123
+ "Quantity"=>"1",
124
+ "Title"=>"Learn Objective-C on the Mac (Learn Series)",
125
+ "ProductGroup"=>"Book",
126
+ "Price"=>
127
+ {"Amount"=>"2639", "CurrencyCode"=>"USD", "FormattedPrice"=>"$26.39"},
128
+ "ItemTotal"=>
129
+ {"Amount"=>"2639", "CurrencyCode"=>"USD", "FormattedPrice"=>"$26.39"}}}}
130
+ end
131
+
132
+ it "should handle response data" do
133
+ cart = SimpleCart.new(@two_items)
134
+ cart.valid?.should be(true)
135
+ cart.cart_id.should eql('186-8702292-9782208')
136
+ cart.hmac.should eql('Ck5MXUE+OQiC/Jh8u6NhBf5FbV8=')
137
+ cart.url.should eql('https://www.amazon.com/gp/cart/aws-merge.html?cart-id=186-8702292-9782208%26associate-id=ws%26hmac=Ck5MXUE%2BOQiC/Jh8u6NhBf5FbV8=%26SubscriptionId=AKIAJFA5X7RTOKFNPVZQ%26MergeCart=False')
138
+ cart.price.should eql('$65.95')
139
+ cart.items.first.CartItemId eql('U3G241HVLLB8N6')
140
+ end
141
+
142
+ it "should handle one item" do
143
+ cart = SimpleCart.new(@two_items)
144
+ cart.items.first.CartItemId eql('U3G241HVLLB8N6')
145
+ end
146
+
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,68 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :get
5
+ uri: http://webservices.amazon.com:80/onca/xml?AWSAccessKeyId=AKIAJFA5X7RTOKFNPVZQ&AssociateTag=&Item.0.ASIN=1430218150&Item.0.Quantity=1&Operation=CartCreate&Service=AWSECommerceService&Signature=5sWyeKMk9jtVYoITVfJMjolGlzvDJ0fIk7rP4il81Lo=&Timestamp=2011-11-17T12:26:34Z&Version=2010-11-01
6
+ body:
7
+ headers:
8
+ response: !ruby/struct:VCR::Response
9
+ status: !ruby/struct:VCR::ResponseStatus
10
+ code: 200
11
+ message: OK
12
+ headers:
13
+ date:
14
+ - Thu, 17 Nov 2011 12:26:34 GMT
15
+ server:
16
+ - Server
17
+ content-type:
18
+ - text/xml;charset=UTF-8
19
+ vary:
20
+ - Accept-Encoding,User-Agent
21
+ nncoection:
22
+ - close
23
+ transfer-encoding:
24
+ - chunked
25
+ body: <?xml version="1.0" encoding="UTF-8"?><CartCreateResponse xmlns="http://webservices.amazon.com/AWSECommerceService/2010-11-01"><OperationRequest><HTTPHeaders><Header
26
+ Name="UserAgent" Value="Jakarta Commons-HttpClient/3.0.1"></Header></HTTPHeaders><RequestId>014QB123K7ASW4SE6QEM</RequestId><Arguments><Argument
27
+ Name="AssociateTag"></Argument><Argument Name="Service" Value="AWSECommerceService"></Argument><Argument
28
+ Name="Item.0.Quantity" Value="1"></Argument><Argument Name="Signature" Value="5sWyeKMk9jtVYoITVfJMjolGlzvDJ0fIk7rP4il81Lo="></Argument><Argument
29
+ Name="Item.0.ASIN" Value="1430218150"></Argument><Argument Name="Operation"
30
+ Value="CartCreate"></Argument><Argument Name="AWSAccessKeyId" Value="AKIAJFA5X7RTOKFNPVZQ"></Argument><Argument
31
+ Name="Timestamp" Value="2011-11-17T12:26:34Z"></Argument><Argument Name="Version"
32
+ Value="2010-11-01"></Argument></Arguments><RequestProcessingTime>0.162961006164551</RequestProcessingTime></OperationRequest><Cart><Request><IsValid>True</IsValid><CartCreateRequest><Items><Item><ASIN>1430218150</ASIN><Quantity>1</Quantity></Item></Items></CartCreateRequest></Request><CartId>183-2540013-3419242</CartId><HMAC>QqoPIkmIkhVQ4/giDmvD0ouD1vo=</HMAC><URLEncodedHMAC>QqoPIkmIkhVQ4%2FgiDmvD0ouD1vo%3D</URLEncodedHMAC><PurchaseURL>https://www.amazon.com/gp/cart/aws-merge.html?cart-id=183-2540013-3419242%26associate-id=ws%26hmac=QqoPIkmIkhVQ4/giDmvD0ouD1vo=%26SubscriptionId=AKIAJFA5X7RTOKFNPVZQ%26MergeCart=False</PurchaseURL><SubTotal><Amount>2171</Amount><CurrencyCode>USD</CurrencyCode><FormattedPrice>$21.71</FormattedPrice></SubTotal><CartItems><SubTotal><Amount>2171</Amount><CurrencyCode>USD</CurrencyCode><FormattedPrice>$21.71</FormattedPrice></SubTotal><CartItem><CartItemId>U3G241HVLLB8N6</CartItemId><ASIN>1430218150</ASIN><MerchantId>ATVPDKIKX0DER</MerchantId><SellerId>A2R2RITDJNW1Q6</SellerId><SellerNickname>Amazon.com</SellerNickname><Quantity>1</Quantity><Title>Learn
33
+ Objective-C on the Mac (Learn Series)</Title><ProductGroup>Book</ProductGroup><Price><Amount>2171</Amount><CurrencyCode>USD</CurrencyCode><FormattedPrice>$21.71</FormattedPrice></Price><ItemTotal><Amount>2171</Amount><CurrencyCode>USD</CurrencyCode><FormattedPrice>$21.71</FormattedPrice></ItemTotal></CartItem></CartItems></Cart></CartCreateResponse>
34
+ http_version: '1.1'
35
+ - !ruby/struct:VCR::HTTPInteraction
36
+ request: !ruby/struct:VCR::Request
37
+ method: :get
38
+ uri: http://webservices.amazon.com:80/onca/xml?AWSAccessKeyId=AKIAJFA5X7RTOKFNPVZQ&AssociateTag=&CartId=183-2540013-3419242&HMAC=QqoPIkmIkhVQ4/giDmvD0ouD1vo=&Item.0.ASIN=1430216263&Item.0.Quantity=2&Operation=CartAdd&Service=AWSECommerceService&Signature=FR0UOB+2MqOE9YuJ/CVBCTw9ONTLDa5Q78ISyT0TATw=&Timestamp=2011-11-17T12:26:34Z&Version=2010-11-01
39
+ body:
40
+ headers:
41
+ response: !ruby/struct:VCR::Response
42
+ status: !ruby/struct:VCR::ResponseStatus
43
+ code: 200
44
+ message: OK
45
+ headers:
46
+ date:
47
+ - Thu, 17 Nov 2011 12:26:34 GMT
48
+ server:
49
+ - Server
50
+ content-type:
51
+ - text/xml;charset=UTF-8
52
+ vary:
53
+ - Accept-Encoding,User-Agent
54
+ nncoection:
55
+ - close
56
+ transfer-encoding:
57
+ - chunked
58
+ body: ! '<?xml version="1.0" encoding="UTF-8"?><CartAddResponse xmlns="http://webservices.amazon.com/AWSECommerceService/2010-11-01"><OperationRequest><HTTPHeaders><Header
59
+ Name="UserAgent" Value="Jakarta Commons-HttpClient/3.0.1"></Header></HTTPHeaders><RequestId>0JBNK5NQF7NJE0TSNSM1</RequestId><Arguments><Argument
60
+ Name="AssociateTag"></Argument><Argument Name="Service" Value="AWSECommerceService"></Argument><Argument
61
+ Name="Item.0.Quantity" Value="2"></Argument><Argument Name="Signature" Value="FR0UOB+2MqOE9YuJ/CVBCTw9ONTLDa5Q78ISyT0TATw="></Argument><Argument
62
+ Name="Item.0.ASIN" Value="1430216263"></Argument><Argument Name="HMAC" Value="QqoPIkmIkhVQ4/giDmvD0ouD1vo="></Argument><Argument
63
+ Name="Operation" Value="CartAdd"></Argument><Argument Name="CartId" Value="183-2540013-3419242"></Argument><Argument
64
+ Name="AWSAccessKeyId" Value="AKIAJFA5X7RTOKFNPVZQ"></Argument><Argument Name="Timestamp"
65
+ Value="2011-11-17T12:26:34Z"></Argument><Argument Name="Version" Value="2010-11-01"></Argument></Arguments><RequestProcessingTime>0.119147062301636</RequestProcessingTime></OperationRequest><Cart><Request><IsValid>True</IsValid><CartAddRequest><CartId>183-2540013-3419242</CartId><HMAC>QqoPIkmIkhVQ4/giDmvD0ouD1vo=</HMAC><Items><Item><ASIN>1430216263</ASIN><Quantity>2</Quantity></Item></Items></CartAddRequest></Request><CartId>183-2540013-3419242</CartId><HMAC>QqoPIkmIkhVQ4/giDmvD0ouD1vo=</HMAC><URLEncodedHMAC>QqoPIkmIkhVQ4%2FgiDmvD0ouD1vo%3D</URLEncodedHMAC><PurchaseURL>https://www.amazon.com/gp/cart/aws-merge.html?cart-id=183-2540013-3419242%26associate-id=ws%26hmac=QqoPIkmIkhVQ4/giDmvD0ouD1vo=%26SubscriptionId=AKIAJFA5X7RTOKFNPVZQ%26MergeCart=False</PurchaseURL><SubTotal><Amount>7449</Amount><CurrencyCode>USD</CurrencyCode><FormattedPrice>$74.49</FormattedPrice></SubTotal><CartItems><SubTotal><Amount>7449</Amount><CurrencyCode>USD</CurrencyCode><FormattedPrice>$74.49</FormattedPrice></SubTotal><CartItem><CartItemId>U3CFEHHIPJNW3L</CartItemId><ASIN>1430216263</ASIN><MerchantId>ATVPDKIKX0DER</MerchantId><SellerId>A2R2RITDJNW1Q6</SellerId><SellerNickname>Amazon.com</SellerNickname><Quantity>2</Quantity><Title>Beginning
66
+ iPhone Development: Exploring the iPhone SDK</Title><ProductGroup>Book</ProductGroup><Price><Amount>2639</Amount><CurrencyCode>USD</CurrencyCode><FormattedPrice>$26.39</FormattedPrice></Price><ItemTotal><Amount>5278</Amount><CurrencyCode>USD</CurrencyCode><FormattedPrice>$52.78</FormattedPrice></ItemTotal></CartItem><CartItem><CartItemId>U3G241HVLLB8N6</CartItemId><ASIN>1430218150</ASIN><MerchantId>ATVPDKIKX0DER</MerchantId><SellerId>A2R2RITDJNW1Q6</SellerId><SellerNickname>Amazon.com</SellerNickname><Quantity>1</Quantity><Title>Learn
67
+ Objective-C on the Mac (Learn Series)</Title><ProductGroup>Book</ProductGroup><Price><Amount>2171</Amount><CurrencyCode>USD</CurrencyCode><FormattedPrice>$21.71</FormattedPrice></Price><ItemTotal><Amount>2171</Amount><CurrencyCode>USD</CurrencyCode><FormattedPrice>$21.71</FormattedPrice></ItemTotal></CartItem></CartItems></Cart></CartAddResponse>'
68
+ http_version: '1.1'