亚马逊 MWS |安息夏普 |我们计算出的请求签名与您提供的签名不匹配
Amazon MWS | RestSharp | The request signature we calculated does not match the signature you provided
我写了下面的 method
来获取 Amazon
的所有订单。我正在使用 RestSharp
库与 API
进行通信。每次我执行 request
我都会收到以下错误:
<?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>9f03f5b0-e4e4-4766-a554-00ff970b6b8c</RequestID>
</ErrorResponse>
这很奇怪,因为在 Amazon Scratchpad
(https://mws.amazonservices.de/scratchpad/index.html) 上它正在工作,我也得到相同的 signature
(当我使用在 Scratchpad 上计算的时间戳时)我的 c#
应用程序。
C#Class
public async void FetchOrders()
{
RestClient client = new RestClient("https://mws.amazonservices.de");
client.DefaultParameters.Clear();
client.ClearHandlers();
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("AWSAccessKeyId", "xxxxxxxxxx");
parameters.Add("Action", "ListOrders");
parameters.Add("CreatedAfter", "2018-01-01T11:34:00Z");
parameters.Add("MarketplaceId.Id.1", "A1PA6795UKMFR9");
parameters.Add("SellerId", "xxxxxxxxx");
parameters.Add("SignatureVersion", "2");
parameters.Add("Timestamp", DateTime.UtcNow.ToString("s") + "Z");
parameters.Add("Version", "2013-09-01");
RestRequest request = new RestRequest("Orders/2013-09-01/", Method.POST);
string signature = AmzLibrary.SignParameters(parameters, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
request.AddParameter("Signature", signature);
foreach (KeyValuePair<string, string> keyValuePair in parameters)
{
request.AddParameter(keyValuePair.Key, keyValuePair.Value);
}
IRestResponse result = await client.ExecuteTaskAsync(request);
}
public static class AmzLibrary
{
public static string GetParametersAsString(IDictionary<String, String> parameters)
{
StringBuilder data = new StringBuilder();
foreach (String key in (IEnumerable<String>)parameters.Keys)
{
String value = parameters[key];
if (value != null)
{
data.Append(key);
data.Append('=');
data.Append(UrlEncode(value, false));
data.Append('&');
}
}
String result = data.ToString();
return result.Remove(result.Length - 1);
}
public static String SignParameters(IDictionary<String, String> parameters, String key)
{
String signatureVersion = parameters["SignatureVersion"];
KeyedHashAlgorithm algorithm = new HMACSHA1();
String stringToSign = null;
if ("2".Equals(signatureVersion))
{
String signatureMethod = "HmacSHA256";
algorithm = KeyedHashAlgorithm.Create(signatureMethod.ToUpper());
parameters.Add("SignatureMethod", signatureMethod);
stringToSign = CalculateStringToSignV2(parameters);
}
else
{
throw new Exception("Invalid Signature Version specified");
}
return Sign(stringToSign, key, algorithm);
}
private static String CalculateStringToSignV2(IDictionary<String, String> parameters)
{
StringBuilder data = new StringBuilder();
IDictionary<String, String> sorted =
new SortedDictionary<String, String>(parameters, StringComparer.Ordinal);
data.Append("POST");
data.Append("\n");
Uri endpoint = new Uri("https://mws.amazonservices.de/Orders/2013-09-01");
data.Append(endpoint.Host);
if (endpoint.Port != 443 && endpoint.Port != 80)
{
data.Append(":")
.Append(endpoint.Port);
}
data.Append("\n");
String uri = endpoint.AbsolutePath;
if (uri == null || uri.Length == 0)
{
uri = "/";
}
data.Append(UrlEncode(uri, true));
data.Append("\n");
foreach (KeyValuePair<String, String> pair in sorted)
{
if (pair.Value != null)
{
data.Append(UrlEncode(pair.Key, false));
data.Append("=");
data.Append(UrlEncode(pair.Value, false));
data.Append("&");
}
}
String result = data.ToString();
return result.Remove(result.Length - 1);
}
private static String UrlEncode(String data, bool path)
{
StringBuilder encoded = new StringBuilder();
String unreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~" + (path ? "/" : "");
foreach (char symbol in System.Text.Encoding.UTF8.GetBytes(data))
{
if (unreservedChars.IndexOf(symbol) != -1)
{
encoded.Append(symbol);
}
else
{
encoded.Append("%" + String.Format("{0:X2}", (int)symbol));
}
}
return encoded.ToString();
}
private static String Sign(String data, String key, KeyedHashAlgorithm algorithm)
{
Encoding encoding = new UTF8Encoding();
algorithm.Key = encoding.GetBytes(key);
return Convert.ToBase64String(algorithm.ComputeHash(
encoding.GetBytes(data.ToCharArray())));
}
}
问题出在 Request
末尾的 "/"。删除它,一切正常。
错误
RestRequest request = new RestRequest("Orders/2013-09-01/", Method.POST);
对
RestRequest request = new RestRequest("Orders/2013-09-01", Method.POST);
我写了下面的 method
来获取 Amazon
的所有订单。我正在使用 RestSharp
库与 API
进行通信。每次我执行 request
我都会收到以下错误:
<?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>9f03f5b0-e4e4-4766-a554-00ff970b6b8c</RequestID>
</ErrorResponse>
这很奇怪,因为在 Amazon Scratchpad
(https://mws.amazonservices.de/scratchpad/index.html) 上它正在工作,我也得到相同的 signature
(当我使用在 Scratchpad 上计算的时间戳时)我的 c#
应用程序。
C#Class
public async void FetchOrders()
{
RestClient client = new RestClient("https://mws.amazonservices.de");
client.DefaultParameters.Clear();
client.ClearHandlers();
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("AWSAccessKeyId", "xxxxxxxxxx");
parameters.Add("Action", "ListOrders");
parameters.Add("CreatedAfter", "2018-01-01T11:34:00Z");
parameters.Add("MarketplaceId.Id.1", "A1PA6795UKMFR9");
parameters.Add("SellerId", "xxxxxxxxx");
parameters.Add("SignatureVersion", "2");
parameters.Add("Timestamp", DateTime.UtcNow.ToString("s") + "Z");
parameters.Add("Version", "2013-09-01");
RestRequest request = new RestRequest("Orders/2013-09-01/", Method.POST);
string signature = AmzLibrary.SignParameters(parameters, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
request.AddParameter("Signature", signature);
foreach (KeyValuePair<string, string> keyValuePair in parameters)
{
request.AddParameter(keyValuePair.Key, keyValuePair.Value);
}
IRestResponse result = await client.ExecuteTaskAsync(request);
}
public static class AmzLibrary
{
public static string GetParametersAsString(IDictionary<String, String> parameters)
{
StringBuilder data = new StringBuilder();
foreach (String key in (IEnumerable<String>)parameters.Keys)
{
String value = parameters[key];
if (value != null)
{
data.Append(key);
data.Append('=');
data.Append(UrlEncode(value, false));
data.Append('&');
}
}
String result = data.ToString();
return result.Remove(result.Length - 1);
}
public static String SignParameters(IDictionary<String, String> parameters, String key)
{
String signatureVersion = parameters["SignatureVersion"];
KeyedHashAlgorithm algorithm = new HMACSHA1();
String stringToSign = null;
if ("2".Equals(signatureVersion))
{
String signatureMethod = "HmacSHA256";
algorithm = KeyedHashAlgorithm.Create(signatureMethod.ToUpper());
parameters.Add("SignatureMethod", signatureMethod);
stringToSign = CalculateStringToSignV2(parameters);
}
else
{
throw new Exception("Invalid Signature Version specified");
}
return Sign(stringToSign, key, algorithm);
}
private static String CalculateStringToSignV2(IDictionary<String, String> parameters)
{
StringBuilder data = new StringBuilder();
IDictionary<String, String> sorted =
new SortedDictionary<String, String>(parameters, StringComparer.Ordinal);
data.Append("POST");
data.Append("\n");
Uri endpoint = new Uri("https://mws.amazonservices.de/Orders/2013-09-01");
data.Append(endpoint.Host);
if (endpoint.Port != 443 && endpoint.Port != 80)
{
data.Append(":")
.Append(endpoint.Port);
}
data.Append("\n");
String uri = endpoint.AbsolutePath;
if (uri == null || uri.Length == 0)
{
uri = "/";
}
data.Append(UrlEncode(uri, true));
data.Append("\n");
foreach (KeyValuePair<String, String> pair in sorted)
{
if (pair.Value != null)
{
data.Append(UrlEncode(pair.Key, false));
data.Append("=");
data.Append(UrlEncode(pair.Value, false));
data.Append("&");
}
}
String result = data.ToString();
return result.Remove(result.Length - 1);
}
private static String UrlEncode(String data, bool path)
{
StringBuilder encoded = new StringBuilder();
String unreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~" + (path ? "/" : "");
foreach (char symbol in System.Text.Encoding.UTF8.GetBytes(data))
{
if (unreservedChars.IndexOf(symbol) != -1)
{
encoded.Append(symbol);
}
else
{
encoded.Append("%" + String.Format("{0:X2}", (int)symbol));
}
}
return encoded.ToString();
}
private static String Sign(String data, String key, KeyedHashAlgorithm algorithm)
{
Encoding encoding = new UTF8Encoding();
algorithm.Key = encoding.GetBytes(key);
return Convert.ToBase64String(algorithm.ComputeHash(
encoding.GetBytes(data.ToCharArray())));
}
}
问题出在 Request
末尾的 "/"。删除它,一切正常。
错误
RestRequest request = new RestRequest("Orders/2013-09-01/", Method.POST);
对
RestRequest request = new RestRequest("Orders/2013-09-01", Method.POST);