Reputation: 1
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 Anypoint Studio 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("+", "%20")
.replace("*", "%2A")
.replace("%7E","~"); ;
} catch (UnsupportedEncodingException e) {
System.err.println("Unknown encoding: " + CHARACTER_ENCODING);
e.printStackTrace();
}
return encoded;
}
}
Code Output:
AWSAccessKeyId=&Action=GetMatchingProductForId&SellerId=&Signature=ehjKNnTB5vhrOW3J1yWSz2T7c%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&SubmittedFromDate=2013-05-01T12%3A00%3A00Z&Timestamp=2013-05-02T16%3A00%3A00Z&Version=2011-10-01
Mulesoft Version: 7.11.1
Application XML Detail:
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:ee="http://www.mulesoft.org/schema/mule/ee/core"
xmlns="http://www.mulesoft.org/schema/mule/core"
xmlns:doc="http://www.mulesoft.org/schema/mule/documentation" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/ee/core http://www.mulesoft.org/schema/mule/ee/core/current/mule-ee.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd">
<flow name="awsFlow" doc:id="eeb85ef5-48cb-4c41-94ba-0e97a0765021" >
<scheduler doc:name="Scheduler" doc:id="f21548f8-1a12-4efa-adf8-27988ac587c5" >
<scheduling-strategy >
<fixed-frequency />
</scheduling-strategy>
</scheduler>
<ee:transform doc:name="Timestamp" doc:id="457efcd6-1388-49fe-88a8-f3d781d17593" >
<ee:message >
</ee:message>
<ee:variables >
<ee:set-variable variableName="requestmws" ><![CDATA[%dw 2.0
output application/json
fun getFormattedDate()=(now() >> "UTC") as String {format: "YYYY-MM-dd"} ++ "T" ++ (now() >> "UTC") as String {format: "HH:mm:ss"} ++ "Z"
---
{
myDate:"mws.amazonservices.com/Products/2011-10-01?AWSAccessKeyId=AKIAI56GX43PIHX4C7XA&Action=GetMatchingProductForId&IdList.Id.1=9781933988665&IdType=EAN&MarketplaceId=ATVPDKIKX0DER&SellerId=A28MSXET37R4N7&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2011-10-01&Timestamp=" ++ getFormattedDate() replace (':') with ('%3A')
}]]></ee:set-variable>
</ee:variables>
</ee:transform>
<ee:transform doc:name="Transform Message" doc:id="5b556411-1a0a-4d31-b536-48245baf3e0e" >
<ee:message >
</ee:message>
<ee:variables >
<ee:set-variable variableName="signature" ><![CDATA[%dw 2.0
import dw::Crypto
output application/json
---
{ "HMACWith" : Crypto::HMACWith("c4AL2hA6TQQ+vhiAti7OHQI10g7Q9bvOzVHfHOEn" as Binary, vars.requestmws.myDate as Binary, "HmacSHA256") }]]></ee:set-variable>
</ee:variables>
</ee:transform>
<ee:transform doc:name="Transform Message" doc:id="ef709e54-4f12-4db8-9088-9ccb203fda07">
<ee:message>
<ee:set-payload><![CDATA[%dw 2.0
output application/java
---
{
b : vars.requestmws.myDate ++ "&Signature=" ++ vars.signature.HMACWith
}]]></ee:set-payload>
</ee:message>
</ee:transform>
<http:request method="POST" doc:name="Request" doc:id="9301bca2-067f-48a1-badc-4dd6c03a288d" url='#["https://" ++ payload.b]'>
<http:headers ><![CDATA[#[output application/java
---
{
"User-Agent" : "Java/1.8.0_201",
"Content-Type" : "text/xml"
}]]]></http:headers>
</http:request>
<error-handler >
<on-error-continue enableNotifications="true" logException="true" doc:name="On Error Continue" doc:id="27be6630-7439-43c9-86b5-c53c6693f0c7" type="ANY">
<logger level="INFO" doc:name="Logger" doc:id="077e3a7c-902a-48bc-aa8d-6a18af941487" message="#[message]"/>
</on-error-continue>
</error-handler>
</flow>
</mule>
Thanks.
Upvotes: 0
Views: 89
Reputation: 25664
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.
Upvotes: 0