SubmitFeed Sample Java is not working


#21

I tried to calculate the signature using the sample code and I’m getting below error. I think it’s issue with MWSAuthToken value as I’m using developer id on this, as I’m not getting any suitable answer from amazon representative. Or it’s a time difference issue as I’m creating the endpoint and then hitting it(I mean two diff services), this is how we are going to use it. Please help on this. Which can cause this issue?

<ErrorResponse xmlns=“http://mws.amazonaws.com/doc/2009-01-01/”>

<Error>

<Type>Sender</Type>

<Code>SignatureDoesNotMatch</Code>

<Message>

The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.

</Message>

</Error>

<RequestID>4763e802-ce3f-44a2-8813-01a66211c30d</RequestID>

</ErrorResponse>


#22

The token is not your Developer Id. You get the token from the seller after the seller registers your Developer Id on their account and one is given to them by Amazon.

Have you read the documentation concerning developing?


#23

Thanks for the quick reply. Is that token will be given by Amazon separately to me or it can be found on account profile? It’s been long that I’m asking the same from them but not really getting any satisfactory answer.


#24

I edited my post above …


#25

I’m sorry but may be I’m not following it properly. We have one main account and we have found MWS Developer ID, AWS Access Key ID, Client Secret and Merchant Token so far. There is no where MWSauthtoken found. I’m using Merchant Token as seller id and Developer id as MWSauthtoken(though I know it’s not correct) and using these I’m getting response through scratchpad but while using in Java code getting that signature issue.
On doc I could see - * MWSAuthToken — Represents the authorization of a specific developer of a web application by a specific Amazon seller.
But unable to figure out who is going to provide that. Because we are the seller and developers both.


#26

MWSAuthToken is for authorizing developers who have their own MWS Developer ID. This is for 3rd party users. They will develop for you but use their own credentials and in order to have access your data they need to be authorized. If you are developing your own application you don’t need this. AWSAccessKeyId is your AWS Access Key ID, Secret Key is your Client Secret and that’s all you need.


#27

Thanks for the details, I got this confirmation from Amazon recently. But I’m still facing signature mismatch issue. I have tried many combination to build the query string and I think I’m missing something and that’s why it is giving me this error.
At this moment I’m using signature version 2 but Amazon asked to use signature version 4 as I’m getting mismatch issue. But I’m trying figure out root cause of this.
Currently using signature 2 code I’m forming below string.
POST
mws.amazonservices.com
/
AWSAccessKeyId=&Action=SubmitFeed&Signature=u%2F84iwmYQK64rdDaDM8pTSFemlr2ajND%2BDLNqq%2BDNs8%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2019-07-22T21%3A03%3A39.050Z&Version=2009-01-01
and on browser I’m using
https://mws.amazonservices.com?AWSAccessKeyId=
*******&Action=SubmitFeed&Signature=u%2F84iwmYQK64rdDaDM8pTSFemlr2ajND%2BDLNqq%2BDNs8%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2019-07-22T21%3A03%3A39.050Z&Version=2009-01-01
But getting
<ErrorResponse xmlns=“http://mws.amazonaws.com/doc/2009-01-01/”>

<Error>

<Type>Sender</Type>

<Code>SignatureDoesNotMatch</Code>

<Message>

The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.

</Message>

</Error>

<RequestID>292e1dfa-9739-444d-8fb9-d4eb2d9223fb</RequestID>

</ErrorResponse>

Amazon also suggesting to get help from seller forum :slightly_smiling_face: I’m looking forward for your help as always.


#28

Pasting my code here -
package client;

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.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TimeZone;
import java.util.TreeMap;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;

public class SignatureTest {
private static final String CHARACTER_ENCODING = “UTF-8”;
final static String ALGORITHM = “HmacSHA256”;

public static void main(String[] args) throws Exception {
    
    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
    df.setTimeZone(TimeZone.getTimeZone("UTC"));
    String timeStamp = df.format(new Date());
    System.out.println("timeStamp: "+timeStamp);
    // Change this secret key to yours
    String secretKey = "*********************************";

    // Use the endpoint for your marketplace
    String serviceUrl = "https://mws.amazonservices.com/";

    // Create set of parameters needed and store in a map
    HashMap<String, String> parameters = new HashMap<String,String>();

    // Add required parameters. Change these as needed.
    
    
    parameters.put("AWSAccessKeyId", urlEncode("********************"));
    parameters.put("Action", urlEncode("SubmitFeed"));
    //parameters.put("Action", urlEncode("GetFeedSubmissionList"));
    parameters.put("ContentMD5Value", urlEncode("I3pK/R+hpYOKY1IQRviZbQ=="));
    parameters.put("FeedType", urlEncode("_POST_ORDER_FULFILLMENT_DATA_"));
    
    //parameters.put("Marketplace", urlEncode("ATVPDKIKX0DER"));
    parameters.put("Merchant", urlEncode("*********************"));
    parameters.put("PurgeAndReplace", urlEncode("false"));
    parameters.put("SignatureMethod", urlEncode(ALGORITHM));
    parameters.put("SignatureVersion", urlEncode("2"));
    //parameters.put("SubmittedFromDate",urlEncode("2013-05-01T12:00:00Z"));
    //parameters.put("Timestamp", urlEncode("2013-05-02T16:00:00Z"));
    //parameters.put("SubmittedFromDate",urlEncode(timeStamp));
    parameters.put("Timestamp", urlEncode(timeStamp));
    parameters.put("Version", urlEncode("2009-01-01"));

    // Format the parameters as they will appear in final format
    // (without the signature parameter)
    String formattedParameters = calculateStringToSignV2(parameters,
        serviceUrl);
    System.out.println("formattedParameters: "+formattedParameters);
    String signature = sign(formattedParameters, secretKey);
    System.out.println("signature: "+urlEncode(signature));
    // Add signature to the parameters and display final results
    parameters.put("Signature", urlEncode(signature));
    System.out.println("Final String: "+calculateStringToSignV2(parameters,
        serviceUrl));
}

/* If Signature Version is 2, string to sign is based on following:
*
*    1. The HTTP Request Method followed by an ASCII newline (%0A)
*
*    2. The HTTP Host header in the form of lowercase host,
*       followed by an ASCII newline.
*
*    3. The URL encoded HTTP absolute path component of the URI
*       (up to but not including the query string parameters);
*       if this is empty use a forward '/'. This parameter is followed
*       by an ASCII newline.
*
*    4. The concatenation of all query string components (names and
*       values) as UTF-8 characters which are URL encoded as per RFC
*       3986 (hex characters MUST be uppercase), sorted using
*       lexicographic byte ordering. Parameter names are separated from
*       their values by the '=' character (ASCII character 61), even if
*       the value is empty. Pairs of parameter and values are separated
*       by the '&' character (ASCII code 38).
*
*/
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/");
    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;
}

}


#29

If you are going to try and sign this manually I recommend taking a closer look at the actual library code rather than just trying to manually reverse engineer this.

com.amazonservices.mws.client.MwsUtl.calculateStringToSignV2()


#30

I will certainly check that. Maybe I’m missing something in String to Sign. I’m providing the details below if you can figure out what’s the issue.
String to sign:

POST

mws.amazonservices.com

/

AWSAccessKeyId=****************&Action=SubmitFeed&ContentMD5Value=I3pK%2FR%2BhpYOKY1IQRviZbQ%3D%3D&FeedType=POST_ORDER_FULFILLMENT_DATA&Merchant=**************&PurgeAndReplace=false&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2019-07-23T17%3A33%3A52.089Z&Version=2009-01-01

Final String with Signature:

POST

mws.amazonservices.com

/

AWSAccessKeyId=**&Action=SubmitFeed&ContentMD5Value=I3pK%2FR%2BhpYOKY1IQRviZbQ%3D%3D&FeedType=POST_ORDER_FULFILLMENT_DATA&Merchant=&PurgeAndReplace=false&Signature=%2FXb4rxeNZX5qamSFM8fInItAbeANFydGEwI1%2FwolnMg%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2019-07-23T17%3A33%3A52.089Z&Version=2009-01-01

Endpoint trying on browser:

https://mws.amazonservices.com?AWSAccessKeyId=&Action=SubmitFeed&ContentMD5Value=I3pK%2FR%2BhpYOKY1IQRviZbQ%3D%3D&FeedType=POST_ORDER_FULFILLMENT_DATA&Merchant=*****&PurgeAndReplace=false&Signature=%2FXb4rxeNZX5qamSFM8fInItAbeANFydGEwI1%2FwolnMg%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2019-07-23T17%3A33%3A52.089Z&Version=2009-01-01

Response from browser hit:

<ErrorResponse xmlns=“http://mws.amazonaws.com/doc/2009-01-01/”>

<Error>

<Type>Sender</Type>

<Code>SignatureDoesNotMatch</Code>

<Message>

The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.

</Message>

</Error>

<RequestID>cb02e821-1a9c-45bb-944c-e54f0938b8ea</RequestID>

</ErrorResponse>


#31

At the minimum use the example in the library and look at what the output of the signature is. Also use the </> button when posting after highlighting code and/or xml it makes the reply much easier to read.


#32

Amazon published a java example for sig v2 here:

https://docs.aws.amazon.com/AWSECommerceService/latest/DG/AuthJavaSampleSig2.html

Is that what you are using?

bunga bunga!


#33

I’m using example code from this link and edited where needed.

http://docs.developer.amazonservices.com/en_US/dev_guide/DG_SigningQueryRequest.html


#34

Another observation, when using scratchpad the signature I’m getting, the same signature is giving me signature mismatch error when I’m using it on browser separately which should not be, it can say signature is already used or expired. My code is generating same signature as scratchpad but no luck, still getting the same SignatureDoesNotMatch. Not getting any reply from Amazon yet on which causing this issue. So hard to debug MWS stuffs with lot of documentations here and there and hardly getting any straight forward answer.


#35

I’ve been able to use the same signature from scratchpad and reuse it in Postman to make the same call. Again there is something that you are missing from the code samples that Amazon has provided that is leading to this issue. If you were to use the Java library as is and then take a look at how it is creating the signature that should be a pretty straight forward procedure.


#36

If you are able to use the same signature(generated from scratchpad) but I’m not then do you think it’s an issue with credentials I’ve received. If you could point me what I’m missing in the code will be a great help. Would you mind to share the postman endpoint by hiding your credentials by *** or something, so that I can validate it with mine? And,
I tried to use your given utl class but I’m getting date format issue although I’m using their timestamp function only.


#37

Update - Signature generated from MwsUtl.java also giving me same mismatch error, at this point I’m totally clueless. Any help me will be appreciated!!


#38
Headers (Bulk Edit copy and paste below in postman)
Content-Type:text/xml
Host:mws.amazonservices.com
x-amazon-user-agent:AmazonJavascriptScratchpad/1.0 (Language=Javascript)

Body (Bulk Edit copy and paste below in postman after modifying AWSAccessKeyId, Merchant, Timestamp, and signature)
AWSAccessKeyId:
Action:GetReportList
Merchant:
SignatureVersion:2
Timestamp:URL decoded time stamp
Version:2009-01-01
Signature: Base64 HMAC Signature from scrathpad
SignatureMethod:HmacSHA256

#39


#40

Your body should use x-www-form-urlencoded

image