I want to get the details (Price, sorting ...) of the products that I have been querying for a long time from amazon. But I was only able to generate the following answer with the following koc. The problems I encountered are as follows;
1- I am getting timestamp error.
2- I was unable to POST the message below.
Can you help me with these two issues?
Note: I am using Mulesoft (7.11.1). I can post the answer in java with https reqeuest connector.
Java Code:
package com.amazonservices.mws.products;
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.text.SimpleDateFormat;
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;
import java.util.TimeZone;
import java.util.Date;
public class signature {
private static final String CHARACTER_ENCODING = "UTF-8";
final static String ALGORITHM = "HmacSHA256";
public static void main() throws Exception {
String secretKey = "***";
String serviceUrl = "https://mws.amazonservices.com/";
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
df.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = new Date();
String timestamp = df.format(date);
HashMap<String, String> parameters = new HashMap<String,String>();
parameters.put("AWSAccessKeyId", urlEncode("***"));
parameters.put("Action", urlEncode("GetMatchingProductForId"));
parameters.put("IdList.Id.1", urlEncode("9781933988665"));
parameters.put("IdType", urlEncode("EAN"));
parameters.put("SellerId", urlEncode("***"));
parameters.put("SignatureMethod", urlEncode(ALGORITHM));
parameters.put("SignatureVersion", urlEncode("2"));
parameters.put("Timestamp", urlEncode(timestamp));
parameters.put("Version", urlEncode("2011-10-01"));
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));
}
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/Products/2011-10-01");
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(" ", " ")
.replace("*", "*")
.replace("~","~"); ;
} catch (UnsupportedEncodingException e) {
System.err.println("Unknown encoding: " CHARACTER_ENCODING);
e.printStackTrace();
}
return encoded;
}
}
Code Output:
AWSAccessKeyId=&Action=GetMatchingProductForId&SellerId=&Signature=ehjKNnTB5vhrOW3J1yWSz2T7c=&SignatureMethod=HmacSHA256&SignatureVersion=2&SubmittedFromDate=2013-05-01T12:00:00Z&Timestamp=2013-05-02T16:00:00Z&Version=2011-10-01
Thanks.
CodePudding user response:
I think you are working too hard. I suggest to use a third party Http client library that can easily do what you need, with much less code. Suggested libraries could be Apache Http client, OK Http client both are well known and well tested. I also wrote my own library that has Http client in it. Its called MgntUtils library. Much less known but very simple to use. See my answer to this question for information on where to get any of those three recommended libraries: How to check the status of POST endpoint/url in java
CodePudding user response:
Since you are apparently executing in some release of Mule 4, you could build the same URL using DataWeave builtin functions.
For example the HMACWith() function will create the signature in one step.
Unless you have hard requirements to implement this in Java, you can just use the HTTP Request operation you can just add the query parameters you build in DataWeave expressions and it will take care of encoding and all the implementation details of performing the HTTP request.