【问题标题】:Amazon API MWS SignatureDoesNotMatch亚马逊 API MWS SignatureDoesNotMatch
【发布时间】:2014-08-28 16:40:21
【问题描述】:

我一直在努力让它工作几个小时。其他问题的解决方案均无效。

我想做的是在亚马逊上获取我的订单列表。为此,我正在致电亚马逊 MWS。但是,这是我收到的错误消息:

<?xml version="1.0"?>
<ErrorResponse xmlns="https://mws.amazonservices.com/Orders/2013-09-01">
  <Error>
    <Type>Sender</Type>
    <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>03686743-15a6-4207-b0b7-316d1e4e5c8f</RequestID>
</ErrorResponse>

为了找出问题所在,我访问了亚马逊 MWS Scratchpad 并使用了相同的值,甚至时间戳(我认为您还有 15 分钟的时间),并比较了签名。他们是一样的。但是,当暂存器完美运行时,我的程序仍然出现相同的错误。

所有代码如下:

import sys, os, base64, datetime, hashlib, hmac, urllib
from time import gmtime, strftime
from requests import request
import xml.etree.ElementTree as ET

def get_timestamp():
    """Return correctly formatted timestamp"""
    return strftime("%Y-%m-%dT%H:%M:%SZ", gmtime())

def calc_signature():
    """Calculate signature to send with request"""
    sig_data = method + '\n' + domain.replace('https://', '').lower() + '\n' + URI + '\n' + request_description
    hmac_obj = hmac.new(str(SECRET_KEY), sig_data, hashlib.sha256)
    return  urllib.quote(base64.b64encode(hmac_obj.digest()), safe='-_.~')

SECRET_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
AWS_ACCESS_KEY = 'xxxxxxxxxxxxxxxxxxx'
SELLER_ID = 'xxxxxxxxxxxxxxxxxxxxxxx'
MARKETPLACE_ID = 'xxxxxxxxxxxxxxx'

Action = 'ListOrders'
SignatureMethod = 'HmacSHA256'
SignatureVersion = '2'
Timestamp = get_timestamp()
Version = '2013-09-01'
CreatedAfter = '2014-08-26T23:00:57Z' # TODO -1 day
URI = '/Orders/2013-09-01'
domain = 'https://mws.amazonservices.co.uk'
method = 'POST'

payload = {'AWSAccessKeyId': AWS_ACCESS_KEY,
           'Action': Action,
           'SellerId': SELLER_ID,
           'SignatureVersion': SignatureVersion,
           'Timestamp': Timestamp,
           'Version': Version,
           'SignatureMethod': SignatureMethod,
           'CreatedAfter': '2014-08-26T23:00:00Z',
           'MarketplaceId.Id.1': MARKETPLACE_ID
          }

request_description = '&'.join(['%s=%s' % (k, urllib.quote(payload[k], safe='-_.~').encode('utf-8')) for k in sorted(payload)])

sig = calc_signature()

url = '%s%s?%s&Signature=%s' % (domain, URI, request_description, urllib.quote(sig))
headers = {'Host': 'amazonwebservices.co.uk', 'Content-Type': 'text/xml', 'x-amazon-user-agent': 'python-requests/1.2.0 (Language=Python)'}

response = request(method, url, headers=headers)
print response.content

这是calc_signature()sig_data 的打印:

POST
mws.amazonservices.co.uk
/Orders/2013-09-01
AWSAccessKeyId=xxxxxxxxxxxxx&Action=ListOrders&CreatedAfter=2014-08-26T23%3A00%3A00Z&MarketplaceId.Id.1=xxxxxxxxxxxxx&SellerId=xxxxxxxxxxxxxxx&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2014-08-28T15%3A50%3A34Z&Version=2013-09-01

这是url的打印:

https://mws.amazonservices.co.uk/Orders/2013-09-01?AWSAccessKeyId=xxxxxxxxxxxx&Action=ListOrders&CreatedAfter=2014-08-26T23%3A00%3A00Z&MarketplaceId.Id.1=xxxxxxxxxxxx&SellerId=xxxxxxxxxxxxx&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2014-08-28T15%3A50%3A34Z&Version=2013-09-01&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

在这一点上我完全没有想法。我已经三次检查我的密钥、访问密钥、卖家 ID 和市场 ID 是否正确。

任何帮助将不胜感激!

【问题讨论】:

  • 你在urllib.quote-ing 签名两次。在你的内部calc_signature 和外部。

标签: python amazon-web-services amazon-mws


【解决方案1】:

我知道这晚了几个月,但我遇到了完全相同的问题,尽管我知道我的签名是正确的,并发现问题实际上是 POST 执行而不是签名。如果亚马逊不能理解你的参数,它会抛出一个 HTTP 403 错误,并告诉你你的签名是错误的,即使它不是。我无法告诉你为什么它会这样工作,但尝试跳过请求库并在构建你的 url 之后使用 urllib.request 执行以下操作,而不是对我有用:

#using python 3.4

import urllib.request

#... your code from before...

headers = {'Host': 'mws.amazonservices.com', 'Content-Type': 'text/xml', 'x-amazon-user-agent': 'SomeApp/1.1 (Language=Python)'}
req = urllib.request.Request(method=method,url=url,headers=headers)
response = urllib.request.urlopen(req)
the_page = response.read()
print(the_page)

#As seen here: https://docs.python.org/3/howto/urllib2.html#data

如果还不行,再看看你是如何对所有内容进行编码的,也许还可以涉足 urllib.parse。

亚马逊快乐!

【讨论】:

    【解决方案2】:

    在您的 calc_signature 函数中,您的 safe 参数不允许在 base64 输出字符集中使用 +/。因此,它对它们进行百分比编码,然后这些百分比在查询字符串中进一步被编码为%25s。

    我做了一些额外的更改,所以这里是所有代码:

    import sys, os, base64, datetime, hashlib, hmac, urllib
    from time import gmtime, strftime
    from requests import request
    import xml.etree.ElementTree as ET
    
    def get_timestamp():
        """Return correctly formatted timestamp"""
        return strftime("%Y-%m-%dT%H:%M:%SZ", gmtime())
    
    def calc_signature(method, domain, URI, request_description, key):
        """Calculate signature to send with request"""
        sig_data = method + '\n' + \
            domain.lower() + '\n' + \
            URI + '\n' + \
            request_description
    
        hmac_obj = hmac.new(key, sig_data, hashlib.sha256)
        digest = hmac_obj.digest()
    
        return  urllib.quote(base64.b64encode(digest), safe='-_+=/.~')
    
    SECRET_KEY = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
    AWS_ACCESS_KEY = 'XXXXXXXXXXXXXX'
    SELLER_ID = 'XXXXXXXXXXXXX'
    MARKETPLACE_ID = 'XXXXXXXXXXXX'
    
    Action = 'ListOrders'
    SignatureMethod = 'HmacSHA256'
    SignatureVersion = '2'
    Timestamp = get_timestamp()
    Version = '2013-09-01'
    CreatedAfter = '2013-08-26T23:00:57Z' 
    URI = '/Orders/2013-09-01'
    domain = 'mws.amazonservices.com'
    proto = 'https://'
    method = 'POST'
    
    payload = {
        'AWSAccessKeyId': AWS_ACCESS_KEY,
        'Action': Action,
        'SellerId': SELLER_ID,
        'SignatureVersion': SignatureVersion,
        'Timestamp': Timestamp,
        'Version': Version,
        'SignatureMethod': SignatureMethod,
        'CreatedAfter': CreatedAfter,
        'MarketplaceId.Id.1': MARKETPLACE_ID
    }
    
    request_description = '&'.join(['%s=%s' % (k, urllib.quote(payload[k], safe='-_.~').encode('utf-8')) for k in sorted(payload)])
    
    sig = calc_signature(method, domain, URI, request_description, SECRET_KEY)
    
    url = '%s%s?%s&Signature=%s' % \
        (proto+domain, URI, request_description, urllib.quote(sig))
    
    headers = {
        'Host': domain,
        'Content-Type': 'text/xml',
        'x-amazon-user-agent': 'python-requests/1.2.0 (Language=Python)'
    }
    
    response = request(method, url, headers=headers)
    
    print response.content 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多