All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.dft.amazon.AmazonSellingPartnerSdk Maven / Gradle / Ivy

There is a newer version: 2.1.9
Show newest version
package io.github.dft.amazon;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.github.dft.amazon.constantcode.ConstantCodes;
import io.github.dft.amazon.model.AmazonCredentials;
import io.github.dft.amazon.model.auth.AccessTokenResponse;
import io.github.dft.amazon.model.handler.JsonBodyHandler;
import lombok.SneakyThrows;
import org.apache.http.client.utils.URIBuilder;

import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

import static io.github.dft.amazon.constantcode.ConstantCodes.MAX_ATTEMPTS;
import static io.github.dft.amazon.constantcode.ConstantCodes.TIME_OUT_DURATION;
import static java.nio.charset.StandardCharsets.UTF_8;

public class AmazonSellingPartnerSdk {

    protected AmazonCredentials amazonCredentials;
    protected String sellingRegionEndpoint;
    protected HttpClient client;
    private ObjectMapper objectMapper;

    public AmazonSellingPartnerSdk() {
        client = HttpClient.newHttpClient();
    }

    @SneakyThrows
    public AmazonSellingPartnerSdk(AmazonCredentials amazonCredentials) {
        this.amazonCredentials = amazonCredentials;
        if (ConstantCodes.AWS_REGION_EU_WEST_1.equalsIgnoreCase(amazonCredentials.getRegion())) {
            this.sellingRegionEndpoint = "https://sellingpartnerapi-eu.amazon.com";

        } else if (ConstantCodes.AWS_REGION_US_EAST_1.equalsIgnoreCase(amazonCredentials.getRegion())) {
            this.sellingRegionEndpoint = "https://sellingpartnerapi-na.amazon.com";

        } else if (ConstantCodes.AWS_REGION_US_WEST_1.equalsIgnoreCase(amazonCredentials.getRegion())) {
            this.sellingRegionEndpoint = "https://sellingpartnerapi-fe.amazon.com";
        } else {
            this.sellingRegionEndpoint = null;
        }
        this.objectMapper = new ObjectMapper();
        client = HttpClient.newHttpClient();
    }

    @SneakyThrows
    protected void refreshAccessToken(boolean bGrantless) {
        if (amazonCredentials.getAccessToken() == null || amazonCredentials.getExpiresInTime() == null || ZonedDateTime.now(ZoneOffset.UTC).isAfter(amazonCredentials.getExpiresInTime())) {
            Map data = new HashMap<>();
            data.put(ConstantCodes.HTTP_OAUTH_PARAMETER_GRANT_TYPE, bGrantless ? ConstantCodes.GRANT_TYPE_CLIENT_CREDENTIALS : ConstantCodes.GRANT_TYPE_REFRESH_TOKEN);
            if(bGrantless) {
                data.put("scope", "sellingpartnerapi::notifications");
            } else {
                data.put(ConstantCodes.HTTP_OAUTH_PARAMETER_REFRESH_TOKEN, amazonCredentials.getRefreshToken());
            }
            data.put(ConstantCodes.HTTP_OAUTH_PARAMETER_CLIENT_ID, amazonCredentials.getClientIdentifier());
            data.put(ConstantCodes.HTTP_OAUTH_PARAMETER_CLIENT_SECRET, amazonCredentials.getClientSecret());

            HttpRequest request = HttpRequest.newBuilder(new URI(ConstantCodes.LWA_AUTHORIZATION_SERVER))
                    .header(ConstantCodes.HTTP_HEADER_CONTENT_TYPE, ConstantCodes.HTTP_HEADER_VALUE_APPLICATION_FORM_URL_ENCODED)
                    .header(ConstantCodes.HTTP_HEADER_ACCEPTS, ConstantCodes.HTTP_HEADER_VALUE_APPLICATION_JSON)
                    .POST(ofFormData(data))
                    .build();

            AccessTokenResponse accessTokenResponse = HttpClient.newHttpClient()
                    .send(request, new JsonBodyHandler<>(AccessTokenResponse.class))
                    .body();

            amazonCredentials.setAccessToken(accessTokenResponse.getAccessToken());
            amazonCredentials.setRefreshToken(accessTokenResponse.getRefreshToken());
            amazonCredentials.setExpiresInTime(ZonedDateTime.now(ZoneOffset.UTC).plusSeconds(accessTokenResponse.getExpiresIn()));
            amazonCredentials.setTokenType(accessTokenResponse.getTokenType());
        }
    }

    public HttpRequest.BodyPublisher ofFormData(Map data) {
        var builder = new StringBuilder();
        for (Map.Entry entry : data.entrySet()) {
            if (builder.length() > 0) {
                builder.append("&");
            }
            builder.append(URLEncoder.encode(entry.getKey().toString(), StandardCharsets.UTF_8));
            builder.append("=");
            builder.append(URLEncoder.encode(entry.getValue().toString(), StandardCharsets.UTF_8));
        }
        return HttpRequest.BodyPublishers.ofString(builder.toString());
    }

    @SneakyThrows
    protected String getString(Object body) {
        return objectMapper.writeValueAsString(body);
    }

    protected void addParameters(URIBuilder uriBuilder, HashMap params) {
        if (params == null || params.isEmpty()) return;
        for (String key : params.keySet()) {
            uriBuilder.addParameter(key, params.get(key));
        }
    }

    @SneakyThrows
    protected URI addParameters(URI uri, HashMap params) {
        String query = uri.getQuery();
        StringBuilder builder = new StringBuilder();

        if (query != null)
            builder.append(query);

        for (Map.Entry entry : params.entrySet()) {
            String keyValueParam = entry.getKey() + "=" + URLEncoder.encode(entry.getValue(), UTF_8);
            if (!builder.toString().isEmpty())
                builder.append("&");
            builder.append(keyValueParam);
        }
        return URI.create(uri.getScheme() + "://" + uri.getAuthority() + uri.getPath() + "?" + builder);
    }

    protected URI addParameters(String uri, HashMap params) {
        StringBuilder builder = new StringBuilder();

        for (Map.Entry entry : params.entrySet()) {
            String keyValueParam = entry.getKey() + "=" + URLEncoder.encode(entry.getValue(), UTF_8);
            if (!builder.toString().isEmpty())
                builder.append("&");
            builder.append(keyValueParam);
        }
        return URI.create(uri + "?" + builder);
    }

    @SneakyThrows
    public  T getRequestWrapped(HttpRequest request, HttpResponse.BodyHandler handler) {

        return client
                .sendAsync(request, handler)
                .thenComposeAsync(response -> tryResend(client, request, handler, response, 1))
                .get()
                .body();
    }

    @SneakyThrows
    public  CompletableFuture> tryResend(HttpClient client,
                                                            HttpRequest request,
                                                            HttpResponse.BodyHandler handler,
                                                            HttpResponse resp, int count) {

        if (resp.statusCode() == 429 && count < MAX_ATTEMPTS) {
            Thread.sleep(TIME_OUT_DURATION);
            return client.sendAsync(request, handler)
                    .thenComposeAsync(response -> tryResend(client, request, handler, response, count + 1));
        }
        return CompletableFuture.completedFuture(resp);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy