亞馬遜SubmitFeed接口(參考自官方API)
商品上傳(也可用于訂單跟蹤,根據FeedType來)
單獨的上傳流程(下一篇有空再寫完整的流程,包括擷取上傳結果)
有需要可檢視亞馬遜官方API文檔
public class example {
private static final String CHARACTER_ENCODING = "UTF-8"; //編碼方式
final static String ALGORITHM = "HmacSHA256"; //亞馬遜支援的哈希散列
public static void main(String[] args) throws Exception {
// 密鑰的值,注意要與AWSAccessKeyId區分開,此處是密鑰,不是keyid
String secretKey = "Your secret key";
//這有兩種生成xml模闆的方法
//1.就是直接複制xml模闆到本地磁盤
//2.用String拼接xml,并以流的形式上傳檔案
String filePath = "你的檔案位址";
//生成MD5值,本類已從官網摘抄模闆方法
String MD5 = computeContentMD5HeaderValue(new FileInputStream(filePath));
// 請求網點位址
String serviceUrl = "https://mws.amazonservices.com/";
// 建立一個存放參數的map
HashMap<String, String> parameters = new HashMap<String,String>();
// 添加設定好的參數,urlEncode是一種url位址規範方法
parameters.put("AWSAccessKeyId", urlEncode("Your Access Key Id"));
//此處的FeedType有多種,需要的可以參考官網
(http://docs.developer.amazonservices.com/zh_CN/feeds/Feeds_FeedType.html)
parameters.put("Action", urlEncode("SubmitFeed"));
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"));
//ContentMD5Value這個參數是用來判斷上傳的資料有沒有丢失缺損
parame.put("ContentMD5Value", urlEncode(md5));
//這裡存放自己擷取的即時時間戳
parameters.put("Timestamp", urlEncode("2013-05-02T16:00:00Z"));
parameters.put("Version", urlEncode("2009-01-01"));
// 生成要簽名的内容格式
String formattedParameters = calculateStringToSignV2(parameters,
serviceUrl);
//對内容進行簽名
String signature = sign(formattedParameters, secretKey);
// 添加請求簽名的參數
parameters.put("Signature", urlEncode(signature));
//對所有參數再排序一遍并以字元串輸出
String sortParam = sortParams(new StringBuilder(), parame);
//發起http請求,把請求到的資料答應出來,一般是xml格式,記得把回應流轉換成json格式
//其他的格式也可
//SubmitFeedPost(serviceUrl, sortParama);
System.out.println(SubmitFeedPost(serviceUrl, sortParama));
}
}
submitfeed發送請求(AResult可以換成别的儲存結構)
public static AResult SubmitFeedPost(String serviceUrl, String sortParama){
AResult result = new AResult();
CloseableHttpClient httpclient = HttpClients.createDefault();
//封裝成一個完整url位址,以及添加請求頭
HttpPost httpPost = new HttpPost(serviceUrl + "?" + sortParama);
httpPost.addHeader("Host", "mws.amazonservices.com");
httpPost.addHeader("Content-Type", "text/xml"); //類型參考MWS API
httpPost.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3724.8 Safari/537.36");
httpPost.addHeader("x-amazon-user-agent", "AmazonJavascriptScratchpad/1.0 (Language=Javascript)");
//注意這個FeedContent是以正文傳輸,要跟參數區分開,此處是以流的形式上傳
httpPost.setEntity(new FileEntity(new File(filePath)));
CloseableHttpResponse response = null;
try {
response = httpclient.execute(httpPost);
HttpEntity responseEntity = response.getEntity();
InputStream is = responseEntity.getContent();
AData data= parseXML(is);
result.setData(data);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
response.close();
httpclient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
生成簽名内容格式,此格式存在要求
private static String calculateStringToSignV2(
Map<String, String> parameters, String serviceUrl)
throws SignatureException, URISyntaxException {
// in TreeMap structure
String v2=null;
try{
URI endpoint = new URI(serviceUrl.toLowerCase());
StringBuilder data = new StringBuilder();
data.append("POST\n");
data.append(endpoint.getHost());
data.append("\n" + new URI(serviceUrl).getPath());
data.append("\n");
//調用該方法進行參數的排序以及格式化url位址
v2= sortParams(data, parameters);
}catch (Exception e){
e.printStackTrace();
}finally {
return v2;
}
}
對參數進行排序以及格式化(url位址有序)
public static String sortParams(StringBuilder data, Map<String, String> parameters) {
Map<String, String> sorted = new TreeMap<String, String>();
sorted.putAll(parameters);
Iterator<Map.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() + "=");
}
if (pairs.hasNext()) {
data.append("&");
}
}
return data.toString();
}
對簽名内容與密鑰一起加密轉成base64,這就是參數signature的值
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);
}
//要進行url編碼,這也是必要的,防止請求位址識别錯誤
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;
}
//轉化請求後傳回的資料,AData可以換成HashMap
private static AData parseXML(InputStream is) {
JSON xml = new XMLSerializer().readFromStream(is);
JSONObject jsonObject = JSONObject.fromObject(xml);
AData data=new AData(jsonObject.toString());
return data;
}
Content-MD5校驗和方法(MWS API),注意是流的形式
//Content-MD5校驗和
public static String computeContentMD5HeaderValue( FileInputStream fis )
throws IOException, NoSuchAlgorithmException {
DigestInputStream dis = new DigestInputStream( fis,
MessageDigest.getInstance( "MD5" ));
byte[] buffer = new byte[8192];
while( dis.read( buffer ) > 0 );
String md5Content = new String(
org.apache.commons.codec.binary.Base64.encodeBase64(
dis.getMessageDigest().digest()) );
// Effectively resets the stream to be beginning of the file
// via a FileChannel.
fis.getChannel().position( 0 );
return md5Content;
}