亚马逊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;
}