All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.github.dft.amazon.AmazonSellingPartnerSdk Maven / Gradle / Ivy
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);
}
}