Skip to content

Instantly share code, notes, and snippets.

@loriopatrick
Created June 4, 2014 11:07
Show Gist options
  • Save loriopatrick/18d960f9edc23c85845f to your computer and use it in GitHub Desktop.
Save loriopatrick/18d960f9edc23c85845f to your computer and use it in GitHub Desktop.
A helper class to make requests to Amazon's product api.
import org.joda.time.DateTime;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Iterator;
import java.util.Map;
import java.util.SortedMap;
/**
* @author Patrick Lorio
*/
public class Amazon {
private static final String UTF8 = "UTF-8";
private static final String HMAC_SHA256 = "HmacSHA256";
private static final String AMNZ_URI = "/onca/xml";
private final String associateTag;
private final String accessKeyId;
private final Mac mac;
public Amazon(String associateTag, String accessKeyId, String secretKey)
throws NoSuchAlgorithmException, InvalidKeyException {
this.associateTag = associateTag;
this.accessKeyId = accessKeyId;
mac = Mac.getInstance(HMAC_SHA256);
mac.init(new SecretKeySpec(getByte(secretKey), HMAC_SHA256));
}
public String getUrl(String endpoint, SortedMap<String, String> params) {
params.put("AWSAccessKeyId", accessKeyId);
params.put("Timestamp", getTimestamp());
params.put("AssociateTag", associateTag);
String paramStr = getParams(params);
String sign = String.format("GET\n%s\n%s\n%s", endpoint, AMNZ_URI, paramStr);
String signature = DatatypeConverter.printBase64Binary(mac.doFinal(getByte(sign)));
return String.format("http://%s%s?%s&Signature=%s", endpoint, AMNZ_URI, paramStr, encodeRFC3986(signature));
}
private String getParams(SortedMap<String, String> params) {
StringBuilder sb = new StringBuilder();
Iterator<Map.Entry<String, String>> iterator = params.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, String> item = iterator.next();
sb.append(encodeRFC3986(item.getKey())).append("=").append(encodeRFC3986(item.getValue()));
if (iterator.hasNext()) {
sb.append('&');
}
}
return sb.toString();
}
private String encodeRFC3986(String str) {
try {
return URLEncoder.encode(str, UTF8)
.replace("+", "%20")
.replace("*", "%2A")
.replace("%7E", "~");
} catch (UnsupportedEncodingException ignored) {
return str;
}
}
private String getTimestamp() {
return new DateTime().toString("yyyy-MM-dd'T'HH:mm:ss'Z'");
}
private byte[] getByte(String str) {
try {
return str.getBytes(UTF8);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(UTF8 + " is not supported.", e);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment