Skip to content

Instantly share code, notes, and snippets.

@samberic
Last active December 4, 2017 21:05
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save samberic/27439e09ee336cf3dc61 to your computer and use it in GitHub Desktop.
Save samberic/27439e09ee336cf3dc61 to your computer and use it in GitHub Desktop.
Amazon Product Advertising API using Clojure
(ns yswrl.test.swirls.amazon-test
(:use clojure.test)
(:require [yswrl.test.scaffolding :refer :all]
[yswrl.swirls.amazon :as amazon])
(:use clj-http.fake)
(:use yswrl.fake.faker))
(deftest amazon-test
(testing "url Params are in order"
(let [urlToCall (amazon/search-url "javainterviewbootcamp")]
(is (.contains urlToCall (str "http://webservices.amazon.com/onca/xml?AWSAccessKeyId=your-access-key&AssociateTag=your-associate-tag&Keywords=javainterviewbootcamp&Operation=ItemSearch&ResponseGroup=Images%2CItemAttributes%2CEditorialReview&SearchIndex=Books&Service=AWSECommerceService&")) urlToCall)))
(testing "Amazon URL is correctly generated"
(let [urlToCall (amazon/createEncryptedUrl (sorted-map
:AWSAccessKeyId "your-access-key"
:AssociateTag "your-associate-tag"
:Keywords "horcrux"
:Operation "ItemSearch"
:ResponseGroup "Images,ItemAttributes"
:SearchIndex "Books"
:Service "AWSECommerceService"
:Timestamp "2015-05-14T04:26:12.000Z"
:Version "2011-08-01"
))]
(is
(.equals urlToCall
(str "http://webservices.amazon.com/onca/xml?AWSAccessKeyId=AKIAIO3J752UN7X4HUWA&AssociateTag=corejavaint0d-20&Keywords=horcrux&Operation=ItemSearch&ResponseGroup=Images%2CItemAttributes&SearchIndex=Books&Service=AWSECommerceService&Timestamp=2015-05-14T04%3A26%3A12.000Z&Version=2011-08-01&Signature=NpX9t1jcz6wR2CCLKfG%2B8Pt2RxQli9QbAZu3dHpifXc%3D")) urlToCall)))
(testing "Example 1 from http://docs.aws.amazon.com/AWSECommerceService/latest/DG/rest-signature.html"
(let [urlToCall
(ring.util.codec/form-encode (amazon/sign "1234567890"
"GET\nwebservices.amazon.com\n/onca/xml\nAWSAccessKeyId=AKIAIOSFODNN7EXAMPLE&AssociateTag=mytag-20&ItemId=0679722769&Operation=ItemLookup&ResponseGroup=Images%2CItemAttributes%2COffers%2CReviews&Service=AWSECommerceService&Timestamp=2014-08-18T12%3A00%3A00Z&Version=2013-08-01"))]
(is
(.equals urlToCall
(str "j7bZM0LXZ9eXeZruTqWm2DIvDYVUU3wxPPpp%2BiXxzQc%3D")) urlToCall)))
(testing "Real example using my key generated from http://associates-amazon.s3.amazonaws.com/scratchpad/index.html"
(let [urlToCall
(ring.util.codec/form-encode (amazon/sign amazon/amazon-key
(amazon/string-to-sign (sorted-map
:AWSAccessKeyId "your-access-key"
:AssociateTag "your-associate-tag"
:Keywords "horcrux"
:Operation "ItemSearch"
:ResponseGroup "Images,ItemAttributes"
:SearchIndex "Books"
:Service "AWSECommerceService"
:Timestamp "2015-05-14T04:26:12.000Z"
:Version "2011-08-01"
))))]
(is
(.equals urlToCall
(str "NpX9t1jcz6wR2CCLKfG%2B8Pt2RxQli9QbAZu3dHpifXc%3D")) urlToCall)))
(ns yswrl.swirls.amazon
(:use [clojure.data.zip.xml :only (attr text xml-> xml1->)])
(:require
[clj-http.client :as client]
[clj-time.core :as t]
[buddy.core.codecs :as codecs]
[buddy.core.mac.hmac :as hmac]
[clojure.zip :as zip]
[clojure.data.xml :as xml-data]))
(def amazon-key "your-key")
(def params (sorted-map
:AWSAccessKeyId "your-access-key"
:AssociateTag "your-associate-tag-20"
:ResponseGroup "Images,ItemAttributes,EditorialReview"
:Service "AWSECommerceService"
:Version "2011-08-01"
))
(defn timestamp [parameters]
(assoc parameters :Timestamp (str (t/now))))
(defn string-to-sign [pms]
(str "GET\nwebservices.amazon.com\n/onca/xml\n"
(ring.util.codec/form-encode pms)))
(defn sign [key string]
(-> (hmac/hash string key :sha256)
(codecs/bytes->base64)))
(defn createEncryptedUrl [paz]
(let [to-sign (string-to-sign paz)
encoded (clojure.string/replace to-sign "+" "%20")
signed (sign amazon-key encoded)
encodedSignature (ring.util.codec/form-encode signed)]
(str "http://webservices.amazon.com/onca/xml?" (ring.util.codec/form-encode paz) "&Signature=" encodedSignature)))
(defn search-url [bookname]
(createEncryptedUrl (assoc (timestamp params) :Keywords bookname :Operation "ItemSearch" :SearchIndex "Books"
)))
(defn handle-amazon [bookname]
(let [url (search-url bookname)
raw-data ((client/get url) :body)
result-data (xml-data/parse-str raw-data)]
(zip/xml-zip result-data)))
(defn search-books [search-term]
(if (clojure.string/blank? search-term)
{:results []}
(let [result (handle-amazon search-term)] {
:results (map (fn [r] {:url (apply str (xml-> r :DetailPageURL text))
:title (apply str (xml-> r :ItemAttributes :Title text))
:author (apply str (xml-> r :ItemAttributes :Author text))
:book-id (apply str (xml-> r :ASIN text))
:thumbnail-url (apply str (xml-> r :SmallImage :URL text))
:large-image-url (apply str (xml-> r :LargeImage :URL text))}) (xml-> result :Items :Item))
})))
(defn item-url [item-id]
(createEncryptedUrl (assoc (timestamp params) :idType "ASIN" :ItemId item-id :Operation "ItemLookup")))
(defn get-book [asin]
(let [url (item-url asin)
raw-data ((client/get url) :body)
result-data (xml-data/parse-str raw-data)
zip-data (zip/xml-zip result-data)
book (xml1-> zip-data :Items :Item)]
(println url)
{:url (apply str (xml-> book :DetailPageURL text))
:title (apply str (xml-> book :ItemAttributes :Title text))
:author (apply str (xml-> book :ItemAttributes :Author text))
:big-img-url (apply str (xml-> book :LargeImage :URL text))
:blurb (apply str (xml-> book :EditorialReviews :EditorialReview :Content text))
}
)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment