亚马逊API MWS SignatureDoesNotMatch
问题描述:
我一直试图让这个工作几个小时。其他问题的解决方案都没有工作。亚马逊API MWS SignatureDoesNotMatch
我想要做的是获得我在亚马逊的订单清单。为此,我正在致电亚马逊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便签和使用相同的值,甚至时间戳(我想你有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
这里是sig_data
打印在calc_signature()
:
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是否正确。
任何帮助将大规模,大规模赞赏!
答
我知道这是迟了几个月,但尽管知道我的签名是正确的,并且发现它实际上是POST执行是问题而不是签名,但我仍然有同样的问题。如果亚马逊无法理解你的参数,它会抛出HTTP 403错误,并告诉你你的签名是错误的,即使它不是。我不能告诉你为什么是这样工作的,但尝试跳过请求库和做后续的使用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涉猎。
快乐亚马逊!
答
在calc_signature
函数中,safe
参数不允许+
和/
,它们在base64输出字符集中是允许的。因此,它对它们进行百分比编码,然后这些百分比在查询字符串中得到进一步的perecnt编码,如%25
。
我做了一些修改,所以这里的所有代码:
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
答
这似乎为我工作
foreach ($params as $key => $val) {
if(in_array($key, array('CreatedAfter', 'CreatedBefore', 'LastUpdatedAfter', 'LastUpdatedBefore'))) {
$key = str_replace("%7E", "~", rawurlencode($key));
$val = str_replace("%7E", "~", urlencode($val));
} else {
$key = str_replace("%7E", "~", rawurlencode($key));
$val = str_replace("%7E", "~", rawurlencode($val));
}
$url[] = "{$key}={$val}";
}
通知我加的是进行urlencode()方法
你是' urllib.quote'签名两次。在你的'calc_signature'里面和外面。 – 2015-02-02 12:53:03