diff --git a/README.md b/README.md index 0ea83d4b..fb75c0eb 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Add this dependency to your project's POM: com.wallee wallee-java-sdk - 6.2.0 + 7.0.0 compile ``` @@ -33,7 +33,7 @@ Add this dependency to your project's POM: Add this dependency to your project's build file: ```groovy -compile "com.wallee:wallee-java-sdk:6.2.0" +compile "com.wallee:wallee-java-sdk:7.0.0" ``` ### Others @@ -46,7 +46,7 @@ mvn clean package Then manually install the following JARs: -* `target/wallee-java-sdk-6.2.0.jar` +* `target/wallee-java-sdk-7.0.0.jar` * `target/lib/*.jar` ## Usage @@ -155,6 +155,43 @@ public class TransactionPaymentPageExample { } ``` +Consider using the following overloaded ApiClient constructor and following code snippet to gain access to a resource behind a **proxy** server with a Basic Authentication scheme +```java + // Create an instance of the ApiClient with the user's unique credentials and proxy information. + ApiClient apiClient = new ApiClient(userId, secret, String proxyHostname, int proxyPort); + + Authenticator authenticator = new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + // Check if the authentication request is for a proxy + if (getRequestorType() == RequestorType.PROXY) { + // Check if the authentication scheme is Basic + if ("Basic".equalsIgnoreCase(getRequestingScheme())) { + // Return the PasswordAuthentication instance with the proxy credentials + return new PasswordAuthentication(proxyUsername, proxyPassword.toCharArray()); + } + } + + return null; + } + }; + + // Set the default Authenticator that will be used by the networking code when a proxy or an HTTP server asks for authentication. + // Authenticator.setDefault will set the java.net.Authenticator that processes all authentication requests. + Authenticator.setDefault(authenticator); +``` +### Disable Basic authentication for HTTPS tunneling + +>In some environments, certain authentication schemes may be undesirable when proxying HTTPS. Accordingly, the Basic authentication scheme has been deactivated, by default, in the Oracle +>Java Runtime, by adding Basic to the jdk.http.auth.tunneling.disabledSchemes networking property. Now, proxies requiring Basic authentication when setting up a tunnel for HTTPS +>will no longer succeed by default. If required, this authentication scheme can be reactivated by removing Basic from the jdk.http.auth.tunneling.disabledSchemes networking +>property, or by setting a system property of the same name to "" ( empty ) on the command line. + +```java + System.setProperty("jdk.http.auth.tunneling.disabledSchemes", ""); + System.setProperty("jdk.http.auth.proxying.disabledSchemes", ""); +``` + ## Recommendation It is recommended to create an instance of `ApiClient` per thread in a multithreaded environment to avoid any potential issues. diff --git a/build.gradle b/build.gradle index 8561272f..190c8b7f 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'idea' apply plugin: 'eclipse' group = 'com.wallee' -version = '6.2.0' +version = '7.0.0' buildscript { repositories { @@ -105,7 +105,7 @@ ext { dependencies { compile "io.swagger:swagger-annotations:$swagger_annotations_version" - compile "com.google.api-client:google-api-client:${google_api_client_version}" { + compile ("com.google.api-client:google-api-client:$google_api_client_version") { exclude group: 'commons-codec', module: 'commons-codec' } compile "com.google.guava:guava:$guava_version" diff --git a/build.sbt b/build.sbt index a5e042cb..12f7e89d 100644 --- a/build.sbt +++ b/build.sbt @@ -2,7 +2,7 @@ lazy val root = (project in file(".")). settings( organization := "com.wallee", name := "wallee-java-sdk", - version := "6.2.0", + version := "7.0.0", scalaVersion := "2.11.4", scalacOptions ++= Seq("-feature"), javacOptions in compile ++= Seq("-Xlint:deprecation"), diff --git a/pom.xml b/pom.xml index 3d5f3ef5..a81d185b 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ wallee-java-sdk jar wallee-java-sdk - 6.2.0 + 7.0.0 https://www.wallee.com The SDK for simplifying the integration with wallee API. @@ -53,8 +53,8 @@ - (,3.9) - Invalid Maven version. It should, at least, be 2.0 + [3.2,3.8] + Invalid Maven version. It should be between 3.2 and 3.8 inclusive. diff --git a/src/main/java/com/wallee/sdk/ApiClient.java b/src/main/java/com/wallee/sdk/ApiClient.java index d4106f13..9741a5ce 100644 --- a/src/main/java/com/wallee/sdk/ApiClient.java +++ b/src/main/java/com/wallee/sdk/ApiClient.java @@ -1,35 +1,51 @@ package com.wallee.sdk; import com.wallee.sdk.service.*; + +import java.net.InetSocketAddress; +import java.net.Proxy; import java.util.HashMap; import java.util.Map; + import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.google.api.client.http.AbstractHttpContent; -import com.google.api.client.http.HttpRequest; import com.google.api.client.http.HttpRequestFactory; -import com.google.api.client.http.HttpRequestInitializer; import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.client.json.Json; -import com.google.api.client.http.HttpHeaders; import java.io.IOException; import java.io.OutputStream; +/** +* The ApiClient class is responsible for setting up and maintaining the state and configuration +* necessary to interact with a remote API service. +*/ public class ApiClient { + + private static final String DEFAULT_BASE_PATH = "https://app-wallee.com:443/api"; + + // Configuration fields private int readTimeOut = 25; - private final String basePath; - private final HttpRequestFactory httpRequestFactory; - private final ObjectMapper objectMapper; - private final long userId; - private final String applicationKey; - private final Map defaultHeaders; + private String basePath; + private HttpRequestFactory httpRequestFactory; + private ObjectMapper objectMapper; + private long userId; + private String applicationKey; + private Map defaultHeaders = new HashMap<>(); - // A reasonable default object mapper. Client can pass in a chosen ObjectMapper anyway, this is just for reasonable defaults. + // Proxy settings + private String proxyHostname; + private int proxyPort; + + /** + * Creates a default ObjectMapper for JSON serialization/deserialization. + * This mapper will ignore unknown properties and set proper date formats among other configurations. + */ private static ObjectMapper createDefaultObjectMapper() { ObjectMapper objectMapper = new ObjectMapper() .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) @@ -40,60 +56,121 @@ private static ObjectMapper createDefaultObjectMapper() { return objectMapper; } - - /** - * Constructor for ApiClient - * - * @param userId - * @param applicationKey - */ - public ApiClient(long userId, String applicationKey) { - this(userId, applicationKey, "https://app-wallee.com:443/api"); - } - /** - * Constructor for ApiClient - * - * @param userId - * @param applicationKey - */ - public ApiClient(long userId, String applicationKey, String basePath) { + * Validates the primary inputs required for establishing a connection with the API. + * + * @param userId The user ID that will be authenticated. + * @param applicationKey The application key corresponding to the user's account, used for authentication. + * @param basePath The base URL for the API against which all the requests would be made. + * @throws IllegalArgumentException if any argument does not meet the criteria. + */ + private void validateInputs(long userId, String applicationKey, String basePath) { if (applicationKey == null || applicationKey.trim().isEmpty()) { - throw new IllegalArgumentException("The application key cannot be empty or null."); + throw new IllegalArgumentException("Application key cannot be null or empty."); } if (userId < 1) { - throw new IllegalArgumentException("The user id is invalid."); + throw new IllegalArgumentException("User ID must be positive."); } if (basePath == null || basePath.trim().isEmpty()) { - throw new IllegalArgumentException("The base path cannot be empty."); - } - - this.basePath = basePath; + throw new IllegalArgumentException("Base path cannot be null or empty."); + } + } + + /** + * Initializes common properties for the API client. + */ + private void initializeBaseProperties(long userId, String applicationKey, String basePath) { + validateInputs(userId, applicationKey, basePath); + this.basePath = basePath; this.userId = userId; this.applicationKey = applicationKey; - this.defaultHeaders = new HashMap<>(); - this.httpRequestFactory = this.createRequestFactory(); this.objectMapper = createDefaultObjectMapper(); } - public HttpRequestFactory getHttpRequestFactory() { - return httpRequestFactory; + /** + * Sets up the proxy properties for the API client. + */ + private void initializeProxyProperties(String proxyHostname, int proxyPort) { + this.proxyHostname = proxyHostname; + this.proxyPort = proxyPort; } - public HttpRequestFactory createRequestFactory() { + /** + * Constructs an ApiClient with the default base path. + */ + public ApiClient(long userId, String applicationKey) { + this(userId, applicationKey, DEFAULT_BASE_PATH); + } + + /** + * Constructs an ApiClient with a custom base path. + */ + public ApiClient(long userId, String applicationKey, String basePath) { + initializeBaseProperties(userId, applicationKey, basePath); + this.httpRequestFactory = createRequestFactory(); + } + + /** + * Constructor for ApiClient specifying user credentials, proxy details, and base path. + * + * @param userId user identifier for authentication. + * @param applicationKey unique application key for user authentication. + * @param basePath the base URL for API requests. + * @param proxyHostname the hostname of the proxy server. + * @param proxyPort the port of the proxy server. + */ + public ApiClient(long userId, String applicationKey, String basePath, String proxyHostname, int proxyPort) { + initializeBaseProperties(userId, applicationKey, basePath); + initializeProxyProperties(proxyHostname, proxyPort); + this.httpRequestFactory = createRequestFactory(); + } + + /** + * Constructor for ApiClient specifying user credentials with the default base path and proxy details. + * + * @param userId user identifier for authentication. + * @param applicationKey unique application key for user authentication. + * @param proxyHostname the hostname of the proxy server. + * @param proxyPort the port of the proxy server. + */ + public ApiClient(long userId, String applicationKey, String proxyHostname, int proxyPort) { + this(userId, applicationKey, DEFAULT_BASE_PATH, proxyHostname, proxyPort); + } + + /** + * Creates an HttpRequestFactory configured for making HTTP requests. The method initializes a transport builder + * and potentially sets a proxy for it. + * + * @return HttpRequestFactory This factory is configured with the built transport and the interceptor. + * It is ready for making HTTP requests, handling the details of connection + * and protocol, allowing for high configurability and ease of modifications. + */ + private HttpRequestFactory createRequestFactory() { final RequestInterceptor interceptor = new RequestInterceptor(this.userId, this.applicationKey, this.defaultHeaders); - NetHttpTransport transport = new NetHttpTransport(); - return transport.createRequestFactory(new HttpRequestInitializer() { - public void initialize(HttpRequest request) { - request.setInterceptor(interceptor); - } - }); + NetHttpTransport.Builder builder = new NetHttpTransport.Builder(); + + if (proxyHostname != null && !proxyHostname.isEmpty()) { + Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHostname, proxyPort)); + builder.setProxy(proxy); + } + + NetHttpTransport transport = builder.build(); + + return transport.createRequestFactory(request -> request.setInterceptor(interceptor)); } + /** + * Allows the addition of default headers that will be sent with each request. + */ public void addDefaultHeader (String key, String value) { this.defaultHeaders.put(key, value); } + // Standard getters and setters + public HttpRequestFactory getHttpRequestFactory() { + return httpRequestFactory; + } + public String getBasePath() { return basePath; } diff --git a/src/main/java/com/wallee/sdk/DefaultHeaders.java b/src/main/java/com/wallee/sdk/DefaultHeaders.java index 7ad1c05e..a9ea1b05 100644 --- a/src/main/java/com/wallee/sdk/DefaultHeaders.java +++ b/src/main/java/com/wallee/sdk/DefaultHeaders.java @@ -34,7 +34,7 @@ public void intercept(HttpRequest request) throws IOException { private HttpHeaders getDefaultHeaders() { HttpHeaders headers = new HttpHeaders(); - headers.put("x-meta-sdk-version", "6.2.0"); + headers.put("x-meta-sdk-version", "7.0.0"); headers.put("x-meta-sdk-language", "java"); headers.put("x-meta-sdk-provider", "wallee"); headers.put("x-meta-sdk-language-version", System.getProperty("java.version")); diff --git a/src/main/java/com/wallee/sdk/model/RestCountry.java b/src/main/java/com/wallee/sdk/model/RestCountry.java index b3cebb69..f3ac257a 100644 --- a/src/main/java/com/wallee/sdk/model/RestCountry.java +++ b/src/main/java/com/wallee/sdk/model/RestCountry.java @@ -39,16 +39,16 @@ public class RestCountry { - @JsonProperty("ISOCode2Letter") - protected String isOCode2Letter = null; + @JsonProperty("addressFormat") + protected RestAddressFormat addressFormat = null; - @JsonProperty("ISOCode3Letter") - protected String isOCode3Letter = null; + @JsonProperty("isoCode2") + protected String isoCode2 = null; - @JsonProperty("addressFormat") - protected RestAddressFormat addressFormat = null; + @JsonProperty("isoCode3") + protected String isoCode3 = null; @JsonProperty("name") @@ -65,32 +65,32 @@ public class RestCountry { /** - * The country's two-letter code (ISO 3166-1 alpha-2 format). - * @return isOCode2Letter + * Specifies the country's way of formatting addresses. + * @return addressFormat **/ - @ApiModelProperty(value = "The country's two-letter code (ISO 3166-1 alpha-2 format).") - public String getIsOCode2Letter() { - return isOCode2Letter; + @ApiModelProperty(value = "Specifies the country's way of formatting addresses.") + public RestAddressFormat getAddressFormat() { + return addressFormat; } /** - * The country's three-letter code (ISO 3166-1 alpha-3 format). - * @return isOCode3Letter + * The country's two-letter code (ISO 3166-1 alpha-2 format). + * @return isoCode2 **/ - @ApiModelProperty(value = "The country's three-letter code (ISO 3166-1 alpha-3 format).") - public String getIsOCode3Letter() { - return isOCode3Letter; + @ApiModelProperty(value = "The country's two-letter code (ISO 3166-1 alpha-2 format).") + public String getIsoCode2() { + return isoCode2; } /** - * Specifies the country's way of formatting addresses. - * @return addressFormat + * The country's three-letter code (ISO 3166-1 alpha-3 format). + * @return isoCode3 **/ - @ApiModelProperty(value = "Specifies the country's way of formatting addresses.") - public RestAddressFormat getAddressFormat() { - return addressFormat; + @ApiModelProperty(value = "The country's three-letter code (ISO 3166-1 alpha-3 format).") + public String getIsoCode3() { + return isoCode3; } @@ -134,9 +134,9 @@ public boolean equals(java.lang.Object o) { return false; } RestCountry restCountry = (RestCountry) o; - return Objects.equals(this.isOCode2Letter, restCountry.isOCode2Letter) && - Objects.equals(this.isOCode3Letter, restCountry.isOCode3Letter) && - Objects.equals(this.addressFormat, restCountry.addressFormat) && + return Objects.equals(this.addressFormat, restCountry.addressFormat) && + Objects.equals(this.isoCode2, restCountry.isoCode2) && + Objects.equals(this.isoCode3, restCountry.isoCode3) && Objects.equals(this.name, restCountry.name) && Objects.equals(this.numericCode, restCountry.numericCode) && Objects.equals(this.stateCodes, restCountry.stateCodes); @@ -144,7 +144,7 @@ public boolean equals(java.lang.Object o) { @Override public int hashCode() { - return Objects.hash(isOCode2Letter, isOCode3Letter, addressFormat, name, numericCode, stateCodes); + return Objects.hash(addressFormat, isoCode2, isoCode3, name, numericCode, stateCodes); } @@ -153,9 +153,9 @@ public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class RestCountry {\n"); - sb.append(" isOCode2Letter: ").append(toIndentedString(isOCode2Letter)).append("\n"); - sb.append(" isOCode3Letter: ").append(toIndentedString(isOCode3Letter)).append("\n"); sb.append(" addressFormat: ").append(toIndentedString(addressFormat)).append("\n"); + sb.append(" isoCode2: ").append(toIndentedString(isoCode2)).append("\n"); + sb.append(" isoCode3: ").append(toIndentedString(isoCode3)).append("\n"); sb.append(" name: ").append(toIndentedString(name)).append("\n"); sb.append(" numericCode: ").append(toIndentedString(numericCode)).append("\n"); sb.append(" stateCodes: ").append(toIndentedString(stateCodes)).append("\n"); diff --git a/src/main/java/com/wallee/sdk/service/TokenService.java b/src/main/java/com/wallee/sdk/service/TokenService.java index d31b6947..68c7433f 100644 --- a/src/main/java/com/wallee/sdk/service/TokenService.java +++ b/src/main/java/com/wallee/sdk/service/TokenService.java @@ -448,6 +448,132 @@ public HttpResponse createForHttpResponse(Long spaceId, TokenCreate entity, Map< HttpRequest httpRequest = apiClient.getHttpRequestFactory().buildRequest(HttpMethods.POST, genericUrl, content); + int readTimeOut = apiClient.getReadTimeOut() * 1000; + httpRequest.setReadTimeout(readTimeOut); + return httpRequest.execute(); + } + + /** + * Create Token + + * This operation creates a token for the given transaction. + *

200 - This status code indicates that a client request was successfully received, understood, and accepted. + *

442 - This status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error. + *

542 - This status code indicates that the server encountered an unexpected condition that prevented it from fulfilling the client request. + * @param spaceId + * @param transactionId The id of the transaction for which we want to create the token. + * @return Token + * @throws IOException if an error occurs while attempting to invoke the API + * For more information visit this link. + * @see Create Token Documentation + + **/ + public Token createToken(Long spaceId, Long transactionId) throws IOException { + HttpResponse response = createTokenForHttpResponse(spaceId, transactionId); + String returnType = "Token"; + if(returnType.equals("String")){ + return (Token) (Object) response.parseAsString(); + } + TypeReference typeRef = new TypeReference() {}; + if (isNoBodyResponse(response)) { + throw new WalleeSdkException(ErrorCode.ENTITY_NOT_FOUND, "Entity was not found for: " + typeRef.getType().getTypeName()); + } + return (Token)apiClient.getObjectMapper().readValue(response.getContent(), typeRef); + } + + /** + * Create Token + + * This operation creates a token for the given transaction. + *

200 - This status code indicates that a client request was successfully received, understood, and accepted. + *

442 - This status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error. + *

542 - This status code indicates that the server encountered an unexpected condition that prevented it from fulfilling the client request. + * @param spaceId + * @param transactionId The id of the transaction for which we want to create the token. + * @param params Map of query params. A collection will be interpreted as passing in multiple instances of the same query param. + * @return Token + * @throws IOException if an error occurs while attempting to invoke the API + * For more information visit this link. + * @see Create Token Documentation + + **/ + public Token createToken(Long spaceId, Long transactionId, Map params) throws IOException { + HttpResponse response = createTokenForHttpResponse(spaceId, transactionId, params); + String returnType = "Token"; + if(returnType.equals("String")){ + return (Token) (Object) response.parseAsString(); + } + TypeReference typeRef = new TypeReference() {}; + if (isNoBodyResponse(response)) { + throw new WalleeSdkException(ErrorCode.ENTITY_NOT_FOUND, "Entity was not found for: " + typeRef.getType().getTypeName()); + } + return (Token)apiClient.getObjectMapper().readValue(response.getContent(), typeRef); + } + + public HttpResponse createTokenForHttpResponse(Long spaceId, Long transactionId) throws IOException { + // verify the required parameter 'spaceId' is set + if (spaceId == null) { + throw new IllegalArgumentException("Missing the required parameter 'spaceId' when calling createToken"); + } + // verify the required parameter 'transactionId' is set + if (transactionId == null) { + throw new IllegalArgumentException("Missing the required parameter 'transactionId' when calling createToken"); + } + URIBuilder uriBuilder = URIBuilderUtil.create(apiClient.getBasePath() + "/token/create-token"); + if (spaceId != null) { + String key = "spaceId"; + Object value = spaceId; + uriBuilder = URIBuilderUtil.applyQueryParam(uriBuilder, key, value); + } + if (transactionId != null) { + String key = "transactionId"; + Object value = transactionId; + uriBuilder = URIBuilderUtil.applyQueryParam(uriBuilder, key, value); + } + + GenericUrl genericUrl = new GenericUrl(URIBuilderUtil.build(uriBuilder)); + + HttpContent content = apiClient.new JacksonJsonHttpContent(null); + HttpRequest httpRequest = apiClient.getHttpRequestFactory().buildRequest(HttpMethods.POST, genericUrl, content); + + + int readTimeOut = apiClient.getReadTimeOut() * 1000; + httpRequest.setReadTimeout(readTimeOut); + return httpRequest.execute(); + } + + public HttpResponse createTokenForHttpResponse(Long spaceId, Long transactionId, Map params) throws IOException { + // verify the required parameter 'spaceId' is set + if (spaceId == null) { + throw new IllegalArgumentException("Missing the required parameter 'spaceId' when calling createToken"); + } + // verify the required parameter 'transactionId' is set + if (transactionId == null) { + throw new IllegalArgumentException("Missing the required parameter 'transactionId' when calling createToken"); + } + URIBuilder uriBuilder = URIBuilderUtil.create(apiClient.getBasePath() + "/token/create-token"); + + // Copy the params argument if present, to allow passing in immutable maps + Map allParams = params == null ? new HashMap() : new HashMap(params); + // Add the required query param 'spaceId' to the map of query params + allParams.put("spaceId", spaceId); + // Add the required query param 'transactionId' to the map of query params + allParams.put("transactionId", transactionId); + + for (Map.Entry entryMap: allParams.entrySet()) { + String key = entryMap.getKey(); + Object value = entryMap.getValue(); + if (key != null && value != null) { + uriBuilder = URIBuilderUtil.applyQueryParam(uriBuilder, key, value); + } + } + + GenericUrl genericUrl = new GenericUrl(URIBuilderUtil.build(uriBuilder)); + + HttpContent content = apiClient.new JacksonJsonHttpContent(null); + HttpRequest httpRequest = apiClient.getHttpRequestFactory().buildRequest(HttpMethods.POST, genericUrl, content); + + int readTimeOut = apiClient.getReadTimeOut() * 1000; httpRequest.setReadTimeout(readTimeOut); return httpRequest.execute();