Mahesh Gosemath
Mahesh Gosemath

Reputation: 426

Retrieving amazon order history programmatically using Java

I want to log into my amazon account and retrieve purchase history programmatically in java.

I did a lot of research and came across screen scraping. Is this the only way or does amazon provide apis for logging in and retrieving purchase history?

Also researched about AWS but its too confusing. There are lot of APIs and I'm not able to figure out which one to use.

Upvotes: 17

Views: 14192

Answers (3)

Timi Ajiboye
Timi Ajiboye

Reputation: 146

Amazon doesn't have a first party API but you can use Gandalf's SDK to programmatically pull Amazon order history (from the beginning of the previous year)

Caveats/Disclosure

  • Gandalf isn't in any way affiliated with Amazon
  • As of today, you'll need an iOS device to use it.
  • I am the founder of Gandalf.

Since the docs don't contain Java specific instructions, despite the service being language agnostic. Here's how you might do it with Java.

First you construct the Gandalf URL and embed it in your application such that when you click on it, it triggers the Gandalf App Clip that will ask you to sign in to Amazon.

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

public static String createGandalfConnectURL(String redirectUrl, String publicKey) {
    try {
        String encodedServices = URLEncoder.encode("{\"amazon\":true}", "UTF-8");
        String encodedRedirectUrl = URLEncoder.encode(redirectUrl, "UTF-8");
        String encodedPublicKey = URLEncoder.encode(publicKey, "UTF-8");

        return "https://appclip.apple.com/id?p=network.gandalf.connect.Clip" +
                "&services=" + encodedServices +
                "&redirectUrl=" + encodedRedirectUrl +
                "&publicKey=" + encodedPublicKey;
    } catch (UnsupportedEncodingException e) {
        // Handle the exception according to your needs
        e.printStackTrace();
        return null;
    }
}

// Example invocation
String url = createGandalfConnectURL("https://your.redirect.url", "your-public-key");

System.out.println(url);

Once the authentication process is complete, the App Clip will navigate to the redirect URL specified above with a dataKey query parameter.

Next steps:

  1. Receive the dataKey: Extract the dataKey from the query parameter sent to your server's redirect endpoint after the user has linked their account.

  2. Prepare the GraphQL query: Craft a GraphQL query that will be used to request the desired data from the Sauron API.

  3. Sign the request: Generate a digital signature of your request body. You would hash the body of your request using SHA-256 and then sign the hash with ECDSA using your private key.

  4. Execute the query: Send the GraphQL query to the Sauron API using an HTTP client, including the signature in the header to authenticate the request.

Here's a simplified Java code snippet that demonstrates these steps:

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import org.apache.http.HttpHeaders;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

public class SauronApiRequest {

    private static final String GRAPHQL_ENDPOINT = "https://sauron.gandalf.network/public/graphql";
    private static final String PRIVATE_KEY_BASE64 = "YOUR_PRIVATE_KEY_BASE64"; // replace with your actual private key in base64 format

    public static void main(String[] args) throws Exception {
        String dataKey = "dataKeyReceivedFromRedirect"; // Replace with actual dataKey received

        // Prepare your GraphQL query
        String query = "{\"query\":\"{ getActivity(dataKey: \\\"" + dataKey + "\\\", source: Amazon, limit: 10, page: 1) { ... } }\"}";

        // Generate signature
        String signature = generateSignature(query);

        // Execute GraphQL request
        String response = executeGraphQLRequest(query, signature);
        System.out.println(response);
    }

    private static String generateSignature(String payload) throws Exception {
        // Decode the base64 private key
        byte[] privateKeyBytes = Base64.getDecoder().decode(PRIVATE_KEY_BASE64);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("EC");
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

        // Create a SHA256withECDSA signature
        Signature ecdsaSign = Signature.getInstance("SHA256withECDSA");
        ecdsaSign.initSign(privateKey);
        ecdsaSign.update(payload.getBytes("UTF-8"));
        byte[] signature = ecdsaSign.sign();

        // Encode signature in base64 to attach to the header
        return Base64.getEncoder().encodeToString(signature);
    }

    private static String executeGraphQLRequest(String query, String signature) throws Exception {
        try (CloseableHttpClient client = HttpClients.createDefault()) {
            HttpPost httpPost = new HttpPost(GRAPHQL_ENDPOINT);

            // Set the GraphQL query as the request body
            StringEntity entity = new StringEntity(query);
            httpPost.setEntity(entity);
            
            // Add the required headers
            httpPost.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
            httpPost.setHeader("X-Gandalf-Signature", signature);

            // Execute the request
            return EntityUtils.toString(client.execute(httpPost).getEntity());
        }
    }
}

Make sure to:

  • Replace "YOUR_PRIVATE_KEY_BASE64" with the actual base64 encoded string of your private key.
  • Replace "dataKeyReceivedFromRedirect" with the actual dataKey you receive from the redirect URI.
  • The GraphQL query should be modified to include the actual fields you want to retrieve.

Upvotes: 0

Elisha Kramer
Elisha Kramer

Reputation: 86

I had the same problem, and didn't find a public Amazon API for retrieving purchase history.

So, I built a Chrome Extension to solve it. The repo is open-source and available here.

I also built a Udemy Course which essentially reviews the codebase: https://www.udemy.com/course/build-a-full-stack-chrome-extension-with-nodejs-and-mongdb

Here's the Chrome Extension: Amazon Scraper King

I also built a web app which enables you to take your Amazon History and create a Social Shopping Profile.

Upvotes: -2

EFeit
EFeit

Reputation: 2142

Doesn't look like Amazon provides an API to specifically do what you need, however I came across this thread. You may have already seen it.

Upvotes: 6

Related Questions