Amazon Marketplace Web Service (MWS) will no longer be available after March 31, 2024. All MWS developers must migrate to Selling Partner API (SP-API) to avoid service disruptions. Refer to the Migration Hub for more information.
每个亚马逊MWS API 部分都有自己的客户端库,其中所含代码可以帮助您执行许多亚马逊MWS 常见任务。借助亚马逊MWS 客户端库,您可以节省时间,并确认所发送的请求格式正确。例如,亚马逊MWS 客户端库可以为您执行以下任务:
您可以创建自己的客户端库,为您使用亚马逊MWS 提供帮助。您应使用代码按照亚马逊MWS 所要求的格式构建请求,并为其签名,然后解析生成的 XML 响应。
您可以通过以下步骤访问亚马逊MWS:
亚马逊MWS 支持调用网络服务操作的查询请求。查询请求是简单的 HTTP 请求,使用的是 GET 或 POST 方法,并在 URL 或 HTTP 正文中分别包含查询参数。亚马逊MWS 要求使用 HTTPS,以防止第三方窃听您与亚马逊的沟通信息。
每个 HTTP 标头行必须以回车和换行符结束。查询请求必须包含 Action 参数,以代表需要执行的操作。响应是 XML 格式的文档。
要创建亚马逊MWS 查询请求,需先用查询信息构建一个查询字符串。然后为该查询字符串签名,并在提交的请求中包含该字符串。计算签名时,所有参数必须采用自然字节顺序。字符串由下列要素构成:
要创建进行签名的查询字符串,请按照以下步骤操作:
StringToSign = HTTPVerb + "\n" + ValueOfHostHeaderInLowercase + "\n" + HTTPRequestURI + "\n" + CanonicalizedQueryString <from the preceding step>
HTTPRequestURI 组件是 URI 到(但不包括)查询字符串的 HTTP 绝对路径组件。如果 HTTPRequestURI 为空,请使用正斜杠 ( / )。
以下示例为 GetFeedSubmissionResult 请求的查询字符串。请注意,排序的参数字符串中不包含空格或换行符。
POST mws.amazonservices.com / AWSAccessKeyId=AKIAFJPPO5KLY6G4XO7Q&Action=GetFeedSubmissionResult&FeedSubm issionId=4321011681&MWSAuthToken=amzn.mws.4ea38b7b-f563-7709-4bae-87aeaEXAM PLE&Marketplace=ATVPDKIKX0DER&SellerId=A3F1LGRLCQDI4D&SignatureMethod=HmacS HA256&SignatureVersion=2&Timestamp=2011-02-04T23%3A08%3A19Z&Version=2009-01 -01
该字符串即为您签名后再包含在查询请求中的字符串。“对查询请求签名”部分介绍了如何对查询请求字符串进行签名。
在请求中使用的时戳(或过期时间)必须是 dateTime 对象。时戳最好采用国际标准时间(即格林尼治时间)时区格式,例如“2009-03-03T18:12:22Z”或“2009-02-23T18:12:22.093-07:00”。请注意,如果您不在时戳内包含时区信息(“Z”代表 UTC,或者时间差值),亚马逊 MWS 会假设所用时区为 UTC。Timestamp 属性必须包含 ISO8601 格式的客户端机器时间;具有与接收机器时钟明显时间差(15 分钟)的时戳的请求将被拒绝,以防止回放式攻击。有关 XML 格式的时戳的更多信息,请参阅 http://www.w3.org/TR/xmlschema-2/#dateTime。
每个亚马逊MWS 响应的 HTTP 响应中均包括一个日期标头,可用于查看本地机器时间是否与我们的服务器时间相同,例如“Date: Tue, 24 Mar 2009 20:34:28 GMT”。您还可以在任意网络浏览器中加载亚马逊MWS 地址 https://mws.amazonservices.com/(无需提交请求),即可获得标有当前亚马逊MWS 服务器时间的响应:
<?xml version="1.0"?> <PingResponse> <Timestamp timestamp="2009-03-24T20:29:19:22Z"/> </PingResponse>
在使用时戳时,还应注意以下几点:
请求签名是验证过程的一部分,旨在识别并验证发送请求的主体。它用作您所构建的请求 URL 中 Signature 参数的值。亚马逊MWS 将验证发送者的身份,以及发送者是否已注册使用 亚马逊MWS。执行验证的方法是利用您的访问密钥编码,来查找用于创建请求签名的密钥。如果验证失败,请求将不予处理。请注意,如果您使用一个亚马逊MWS 客户端库来提交请求,则无需计算签名或时戳。
POST mws.amazonservices.com / AWSAccessKeyId=0PExampleR2&Action=SubmitFeed&FeedType=_POST_INVENTORY_AVAIL ABILITY_DATA_&MWSAuthToken=amzn.mws.4ea38b7b-f563-7709-4bae-87aeaEXAMPLE&Ma rketplace=ATExampleER&SellerId=A1ExampleE6&SignatureMethod=HmacSHA256&Signa tureVersion=2&Timestamp=2009-08-20T01%3A10%3A27.607Z&Version=2009-01-01
以下示例介绍如何使用 Java 计算签名:
import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; import java.net.URLEncoder; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.SignatureException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.TreeMap; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Base64; public class SignatureExample { private static final String CHARACTER_ENCODING = "UTF-8"; final static String ALGORITHM = "HmacSHA256"; public static void main(String[] args) throws Exception { // Change this secret key to yours String secretKey = "Your secret key"; // Use the endpoint for your marketplace String serviceUrl = "https://mws.amazonservices.com/"; // Create set of parameters needed and store in a map HashMap<String, String> parameters = new HashMap<String,String>(); // Add required parameters. Change these as needed. parameters.put("AWSAccessKeyId", urlEncode("Your Access Key Id")); parameters.put("Action", urlEncode("GetFeedSubmissionList")); parameters.put("MWSAuthToken", urlEncode("Your MWS Auth Token")); parameters.put("SellerId", urlEncode("Your Seller Id")); parameters.put("SignatureMethod", urlEncode(ALGORITHM)); parameters.put("SignatureVersion", urlEncode("2")); parameters.put("SubmittedFromDate", urlEncode("2013-05-01T12:00:00Z")); parameters.put("Timestamp", urlEncode("2013-05-02T16:00:00Z")); parameters.put("Version", urlEncode("2009-01-01")); // Format the parameters as they will appear in final format // (without the signature parameter) String formattedParameters = calculateStringToSignV2(parameters, serviceUrl); String signature = sign(formattedParameters, secretKey); // Add signature to the parameters and display final results parameters.put("Signature", urlEncode(signature)); System.out.println(calculateStringToSignV2(parameters, serviceUrl)); } /* If Signature Version is 2, string to sign is based on following: * * 1. The HTTP Request Method followed by an ASCII newline (%0A) * * 2. The HTTP Host header in the form of lowercase host, * followed by an ASCII newline. * * 3. The URL encoded HTTP absolute path component of the URI * (up to but not including the query string parameters); * if this is empty use a forward '/'. This parameter is followed * by an ASCII newline. * * 4. The concatenation of all query string components (names and * values) as UTF-8 characters which are URL encoded as per RFC * 3986 (hex characters MUST be uppercase), sorted using * lexicographic byte ordering. Parameter names are separated from * their values by the '=' character (ASCII character 61), even if * the value is empty. Pairs of parameter and values are separated * by the '&' character (ASCII code 38). * */ private static String calculateStringToSignV2( Map<String, String> parameters, String serviceUrl) throws SignatureException, URISyntaxException { // Sort the parameters alphabetically by storing // in TreeMap structure Map<String, String> sorted = new TreeMap<String, String>(); sorted.putAll(parameters); // Set endpoint value URI endpoint = new URI(serviceUrl.toLowerCase()); // Create flattened (String) representation StringBuilder data = new StringBuilder(); data.append("POST\n"); data.append(endpoint.getHost()); data.append("\n/"); data.append("\n"); Iterator<Entry<String, String>> pairs = sorted.entrySet().iterator(); while (pairs.hasNext()) { Map.Entry<String, String> pair = pairs.next(); if (pair.getValue() != null) { data.append( pair.getKey() + "=" + pair.getValue()); } else { data.append( pair.getKey() + "="); } // Delimit parameters with ampersand (&) if (pairs.hasNext()) { data.append( "&"); } } return data.toString(); } /* * Sign the text with the given secret key and convert to base64 */ private static String sign(String data, String secretKey) throws NoSuchAlgorithmException, InvalidKeyException, IllegalStateException, UnsupportedEncodingException { Mac mac = Mac.getInstance(ALGORITHM); mac.init(new SecretKeySpec(secretKey.getBytes(CHARACTER_ENCODING), ALGORITHM)); byte[] signature = mac.doFinal(data.getBytes(CHARACTER_ENCODING)); String signatureBase64 = new String(Base64.encodeBase64(signature), CHARACTER_ENCODING); return new String(signatureBase64); } private static String urlEncode(String rawValue) { String value = (rawValue == null) ? "" : rawValue; String encoded = null; try { encoded = URLEncoder.encode(value, CHARACTER_ENCODING) .replace("+", "%20") .replace("*", "%2A") .replace("%7E","~"); } catch (UnsupportedEncodingException e) { System.err.println("Unknown encoding: " + CHARACTER_ENCODING); e.printStackTrace(); } return encoded; } }
User-Agent 标头是可用于标识您的应用程序、其版本号及编程语言。亚马逊建议在提交到亚马逊MWS 的每个请求中都包括 User-Agent 标头,这样可帮助亚马逊更有效地判断和解决问题,也有助于您更好地使用亚马逊MWS。
如果您是解决方案提供商,当开发您的应用程序时,在每个请求中都包括 User-Agent 标头非常重要,这也适用于您所开发的桌面应用程序。 这样做的目的是:使亚马逊能够根据卖家使用的解决方案供应商来确定卖家身份,更有效地判断出与您的应用程序相关的问题。
亚马逊MWS 客户端库为在每个亚马逊MWS 请求中传递 User-Agent 标头提供了一种简便方法。当您初始化亚马逊MWS 客户端库时,可以添加应用程序名称或公司名称,以及版本号。其他 HTTP 库也为构建 User-Agent 标头提供了简便方法,但如果您在创建标头时遇到了任何困难,请向亚马逊MWS 寻求帮助。
要创建 User-Agent 标头,请以应用程序名称开头,然后依次是正斜杠、应用程序版本、空格、左括号、Language 名称值对,以及右括号。Language 参数是必需的属性,但您还可以添加其他属性,并以分号隔开。
以下示例展示了在最低限度上可接受的 User-Agent 标头。
AppId/AppVersionId (Language=LanguageNameAndOptionallyVersion)
如果您是第三方应用程序集成商,您可能希望采用类似下面的 User-Agent 标头:
My Desktop Seller Tool/2.0 (Language=Java/1.6.0.11; Platform=Windows/XP)
如果您是通过自己的 IT 部门进行集成的大型卖家,您可能希望采用类似下面的 User-Agent 标头,这样,亚马逊MWS 就能使用 Host 属性帮您解决问题:
MyCompanyName/build1611 (Language=Perl; Host=jane.laptop.example.com)
要指定其他属性,请使用以下格式:AttributeName=Value;,将每个名称值对用分号隔开。如果您想使用反斜杠 (\),请将它连同另一个反斜杠放在括号里 (\\)。同样,在应用程序名称中把一个正斜杠括住 (\/),在应用程序版本中包含一个左括号 (\(),在属性名称中包含一个等号 (\=),在属性值中包含一个右括号 (\)) 和分号 (\;)。
由于 User-Agent 标头要包含在每个请求中进行传送,因此建议您限制标头的长度。如果 User-Agent 标头长度超过 500 个字符,亚马逊MWS 就会拒绝该标头。
URL 包含以下各部分:
以下示例是您可以提交的完整的请求 URL,实际请求不能包含空格或换行符。
https://mws.amazonservices.com/AWSAccessKeyId=AKIAFJPPO5KLY6G4XO7Q&Action=G etFeedSubmissionResult&FeedSubmissionId=4321011681&MWSAuthToken=amzn.mws.4e a38b7b-f563-7709-4bae-87aeaEXAMPLE&Marketplace=ATVPDKIKX0DER&SellerId=A3F1L GRLCQDI4D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2011-02-0 4T23%3A08%3A19Z&Version=2009-01-0&Signature=WhateverTheSignatureWas1HTTP/1. 1Host:mws.amazonservices.comX-Amazon-User-Agent:AmazonJavascriptApp/1.0(Lan guage=Javascript)Content-Type:text/xml