Request signature does not match signature provided for Amazon AWS using Python
Question: So I'm attempting to collect reviews from Amazon using their API.
Unfortunately though it seems that I might be doing something wrong at some
point in my program. It's sending back a response that many others were
apparently getting. Believe me, I've gone through and looked and everyone
elses questions and nothing has worked. Please help me.

Here's the code:

    
    
    __author__ = 'dperkins'
    
    import requests
    import amazonproduct
    import time
    import datetime
    import hmac
    import hashlib
    import base64
    import urllib
    import ssl
    from bs4 import BeautifulSoup
    
    # Configuration for the AWS credentials
    config = {
        'access_key': 'XXXXXXXXXXXXXXXXXXXX',
        'secret_key': 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
        'associate_tag': 'dperkgithu-20',
        'locale': 'us'
    }
    api = amazonproduct.API(cfg=config)
    
    productASIN = ''
    productTitle = ''
    
    # Product look up for the official iPhone 5s White 16gb Unlocked
    for product in api.item_search('Electronics', Keywords='iPhone'):
        if product .ASIN == 'B00F3J4E5U':
            productTitle = product.ItemAttributes.Title
            productASIN = product.ASIN
    
    # Product Title with ASIN and a formatted underline
    print productTitle + ': ' + productASIN
    
    underline = ''
    for int in range(len(productTitle + ': ' + productASIN)):
        underline += '-'
    print underline
    
    # URL First portion of the request for reviews
    signatureTime = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
    signatureTime = urllib.quote_plus(signatureTime)    # Must url encode the timestamp
    url = "http://webservices.amazon.com/onca/xml?Service=AWSECommerceService&Operation=ItemLookup&ResponseGroup=Reviews&IdType=ASIN&ItemId=%s&AssociateTag=%s&AWSAccessKeyId=%s&Timestamp=%s" % (productASIN, api.associate_tag, api.access_key, signatureTime)
    
    # # HMAC with SHA256 hash algorithm
    # dig = hmac.new(api.secret_key, msg=url, digestmod=hashlib.sha256).digest()
    # signature = base64.b64encode(dig).decode()      # py3k-mode
    
    #url = 'http://webservices.amazon.com/onca/xml?Service=AWSECommerceService&Operation=ItemLookup&ResponseGroup=Reviews&IdType=ASIN&ItemId=%s&AssociateTag=%s&AWSAccessKeyId=%s&Timestamp=%s&Signature=%s' % (productASIN, api.associate_tag, api.access_key, signatureTime, signature)
    
    #Split and byte order the request (poorly but should always be the same)
    parameters = [1, 2, 3, 4, 5, 6, 7]
    for line in url.split('&'):
        if (line.startswith('AssociateTag')):
            parameters[0] = line
        elif (line.startswith('AWSAccessKeyId')):
            parameters[1] = line
        elif (line.startswith('IdType')):
            parameters[2] = line
        elif (line.startswith('ItemId')):
            parameters[3] = line
        elif (line.startswith('Operation')):
            parameters[4] = line
        elif (line.startswith('ResponseGroup')):
            parameters[5] = line
        elif (line.startswith('Timestamp')):
            parameters[6] = line
    rejoined = ''
    i = 1
    for line in parameters:
        if i < len(parameters):
            rejoined += line + '&'
        else:
            rejoined += line
        i += 1
    print 'Rejoined: ' + rejoined
    
    # Prepend the request beginning
    prepend = 'GET\nwebservices.amazon.com\n/onca/xml\n' + rejoined
    print 'Prepend: ' + prepend
    
    # HMAC with SHA256 hash algorithm
    dig = hmac.new(api.access_key, msg=prepend, digestmod=hashlib.sha256).digest()
    signature = base64.b64encode(dig).decode()      # py3k-mode
    print 'Signature: ' + signature
    encodedSignature = urllib.quote_plus(signature)     # encode the signature
    print 'Encoded Signature: ' + encodedSignature
    finalRequest = 'http://webservices.amazon.com/onca/xml?' + rejoined + '&Signature=' + encodedSignature
    
    # Final request to send
    print 'URL: ' + finalRequest
    
    # Use BeautifulSoup to create the html
    r = requests.get(finalRequest)
    soup = BeautifulSoup(r.content)
    print soup.prettify()
    

Here's the response:

    
    
    Apple iPhone 5s, Gold 16GB (Unlocked): B00F3J4E5U
    -------------------------------------------------
    Rejoined: AssociateTag=dperkgithu-20&AWSAccessKeyId=XXXXXXXXXXXXXXXXXXXX&IdType=ASIN&ItemId=B00F3J4E5U&Operation=ItemLookup&ResponseGroup=Reviews&Timestamp=2014-10-01T19%3A36%3A41Z
    Prepend: GET
    webservices.amazon.com
    /onca/xml
    AssociateTag=dperkgithu-20&AWSAccessKeyId=XXXXXXXXXXXXXXXXXXXX&IdType=ASIN&ItemId=B00F3J4E5U&Operation=ItemLookup&ResponseGroup=Reviews&Timestamp=2014-10-01T19%3A36%3A41Z
    Signature: YAeIaDuigxbTX7AoZzRreZzn//RbIucCiwsG9VqMayQ=
    Encoded Signature: YAeIaDuigxbTX7AoZzRreZzn%2F%2FRbIucCiwsG9VqMayQ%3D
    URL: http://webservices.amazon.com/onca/xml?AssociateTag=dperkgithu-20&AWSAccessKeyId=XXXXXXXXXXXXXXXXXXXX&IdType=ASIN&ItemId=B00F3J4E5U&Operation=ItemLookup&ResponseGroup=Reviews&Timestamp=2014-10-01T19%3A36%3A41Z&Signature=YAeIaDuigxbTX7AoZzRreZzn%2F%2FRbIucCiwsG9VqMayQ%3D
    <html>
     <body>
      <itemlookuperrorresponse xmlns="http://ecs.amazonaws.com/doc/2005-10-05/">
       <error>
        <code>
         SignatureDoesNotMatch
        </code>
        <message>
         The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.
        </message>
       </error>
       <requestid>
        c159b688-9b08-4cc9-94fe-35245aa69cc9
       </requestid>
      </itemlookuperrorresponse>
     </body>
    </html>
    


Answer: You already have a successful request to the Amazon Product Advertising API.
If you want to have a peek at the returned XML, use the product object.

As for you reviews, they are no longer available as plain text via the API.
You would need to scrape HTML from Amazon.com directly.

