From 551c6be905dd9c58f6d5eba94692f3d5fec74f5d Mon Sep 17 00:00:00 2001 From: Thiago dos Santos Date: Fri, 26 Dec 2025 12:09:28 -0300 Subject: [PATCH 1/2] Upgrade to comply with OAuth2.0 --- pom.xml | 10 +-- .../userede/erede/AccessTokenResponse.java | 41 +++++++++++ .../br/com/userede/erede/Environment.java | 4 +- .../java/br/com/userede/erede/HttpUtils.java | 36 +++++++++ .../com/userede/erede/OAuthEnvironment.java | 28 +++++++ .../java/br/com/userede/erede/OAuthStore.java | 46 ++++++++++++ src/main/java/br/com/userede/erede/Store.java | 33 ++++----- src/main/java/br/com/userede/erede/eRede.java | 9 ++- .../service/AbstractTransactionService.java | 73 ++++++------------- .../userede/erede/service/OAuthService.java | 65 +++++++++++++++++ .../java/br/com/userede/erede/eRedeTest.java | 24 ++++-- 11 files changed, 287 insertions(+), 82 deletions(-) create mode 100644 src/main/java/br/com/userede/erede/AccessTokenResponse.java create mode 100644 src/main/java/br/com/userede/erede/HttpUtils.java create mode 100644 src/main/java/br/com/userede/erede/OAuthEnvironment.java create mode 100644 src/main/java/br/com/userede/erede/OAuthStore.java create mode 100644 src/main/java/br/com/userede/erede/service/OAuthService.java diff --git a/pom.xml b/pom.xml index 153d4e6..2a96968 100644 --- a/pom.xml +++ b/pom.xml @@ -5,15 +5,15 @@ br.com.userede.erede erede - 1.2.1 + 1.3.0 org.apache.maven.plugins maven-compiler-plugin - 11 - 11 + 15 + 15 @@ -37,12 +37,12 @@ org.apache.httpcomponents httpclient - 4.5.13 + 4.5.14 com.google.code.gson gson - 2.9.0 + 2.12.1 diff --git a/src/main/java/br/com/userede/erede/AccessTokenResponse.java b/src/main/java/br/com/userede/erede/AccessTokenResponse.java new file mode 100644 index 0000000..a3489d8 --- /dev/null +++ b/src/main/java/br/com/userede/erede/AccessTokenResponse.java @@ -0,0 +1,41 @@ +package br.com.userede.erede; + +public class AccessTokenResponse { + + private String access_token; + private String token_type; + private Long expires_in; + private String scope; + + public String getAccessToken() { + return access_token; + } + + public String getTokenType() { + return token_type; + } + + public Long getExpiresIn() { + return expires_in; + } + + public String getScope() { + return scope; + } + + public void setAccessToken(String access_token) { + this.access_token = access_token; + } + + public void setTokenType(String token_type) { + this.token_type = token_type; + } + + public void setExpiresIn(Long expires_in) { + this.expires_in = expires_in; + } + + public void setScope(String scope) { + this.scope = scope; + } +} diff --git a/src/main/java/br/com/userede/erede/Environment.java b/src/main/java/br/com/userede/erede/Environment.java index 25f1f14..ae193a9 100755 --- a/src/main/java/br/com/userede/erede/Environment.java +++ b/src/main/java/br/com/userede/erede/Environment.java @@ -5,8 +5,8 @@ public class Environment { private static final String PRODUCTION = "https://api.userede.com.br/erede"; - private static final String SANDBOX = "https://api.userede.com.br/desenvolvedores"; - private static final String VERSION = "v1"; + private static final String SANDBOX = "https://sandbox-erede.useredecloud.com.br"; + private static final String VERSION = "v2"; @SerializedName("ip") private String ip; diff --git a/src/main/java/br/com/userede/erede/HttpUtils.java b/src/main/java/br/com/userede/erede/HttpUtils.java new file mode 100644 index 0000000..25c92c4 --- /dev/null +++ b/src/main/java/br/com/userede/erede/HttpUtils.java @@ -0,0 +1,36 @@ +package br.com.userede.erede; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.zip.GZIPInputStream; + +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; + +public class HttpUtils { + + public static String parseResponse(HttpResponse response) throws IOException { + HttpEntity responseEntity = response.getEntity(); + InputStream responseEntityContent = responseEntity.getContent(); + + Header contentEncoding = response.getFirstHeader("Content-Encoding"); + + if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) { + responseEntityContent = new GZIPInputStream(responseEntityContent); + } + + BufferedReader responseReader = new BufferedReader( + new InputStreamReader(responseEntityContent)); + StringBuilder responseBuilder = new StringBuilder(); + String line; + + while ((line = responseReader.readLine()) != null) { + responseBuilder.append(line); + } + + return responseBuilder.toString(); + } +} diff --git a/src/main/java/br/com/userede/erede/OAuthEnvironment.java b/src/main/java/br/com/userede/erede/OAuthEnvironment.java new file mode 100644 index 0000000..92615da --- /dev/null +++ b/src/main/java/br/com/userede/erede/OAuthEnvironment.java @@ -0,0 +1,28 @@ +package br.com.userede.erede; + +import com.google.gson.annotations.SerializedName; + +public class OAuthEnvironment { + + private static final String PRODUCTION = "https://api.userede.com.br/redelabs/oauth2/token"; + private static final String SANDBOX = "https://rl7-sandbox-api.useredecloud.com.br/oauth2/token"; + + @SerializedName("endpoint") + private String endpoint; + + public OAuthEnvironment(String endpoint) { + this.endpoint = endpoint; + } + + public static OAuthEnvironment production() { + return new OAuthEnvironment(OAuthEnvironment.PRODUCTION); + } + + public static OAuthEnvironment sandbox() { + return new OAuthEnvironment(OAuthEnvironment.SANDBOX); + } + + public String getEndpoint() { + return endpoint; + } +} diff --git a/src/main/java/br/com/userede/erede/OAuthStore.java b/src/main/java/br/com/userede/erede/OAuthStore.java new file mode 100644 index 0000000..98b4bea --- /dev/null +++ b/src/main/java/br/com/userede/erede/OAuthStore.java @@ -0,0 +1,46 @@ +package br.com.userede.erede; + +public class OAuthStore { + + private OAuthEnvironment environment; + private String clientId; // OLD PV + private String clientSecret; // OLD CHAVE INTEGRACAO + + + public OAuthStore(String clientId, String clientSecret, OAuthEnvironment environment) { + this.clientId = clientId; + this.clientSecret = clientSecret; + this.environment = environment; + } + + public OAuthStore(String filiation, String token) { + this(filiation, token, OAuthEnvironment.production()); + } + + public OAuthEnvironment getEnvironment() { + return environment; + } + + public OAuthStore setEnvironment(OAuthEnvironment environment) { + this.environment = environment; + return this; + } + + /**Old PV**/ + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + /**Old CHAVE INTEGRACAO**/ + public String getClientSecret() { + return clientSecret; + } + + public void setClientSecret(String clientSecret) { + this.clientSecret = clientSecret; + } +} diff --git a/src/main/java/br/com/userede/erede/Store.java b/src/main/java/br/com/userede/erede/Store.java index 2e92ed1..3577b8b 100755 --- a/src/main/java/br/com/userede/erede/Store.java +++ b/src/main/java/br/com/userede/erede/Store.java @@ -3,17 +3,17 @@ public class Store { private Environment environment; - private String filiation; - private String token; + private String filiation; // clientId + private String accessToken; // temporary access_token - public Store(String filiation, String token, Environment environment) { - this.environment = environment; - this.filiation = filiation; - this.token = token; + public Store(String filiation, String accessToken, Environment environment) { + this.filiation = filiation; + this.accessToken = accessToken; + this.environment = environment; } - public Store(String filiation, String token) { - this(filiation, token, Environment.production()); + public Store(String filiation, String accessToken) { + this(filiation, accessToken, Environment.production()); } public Environment getEnvironment() { @@ -33,13 +33,12 @@ public Store setFiliation(String filiation) { this.filiation = filiation; return this; } - - public String getToken() { - return token; - } - - public Store setToken(String token) { - this.token = token; - return this; - } + + public String getAccessToken() { + return accessToken; + } + + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } } diff --git a/src/main/java/br/com/userede/erede/eRede.java b/src/main/java/br/com/userede/erede/eRede.java index b5d08c0..949f8d4 100755 --- a/src/main/java/br/com/userede/erede/eRede.java +++ b/src/main/java/br/com/userede/erede/eRede.java @@ -4,12 +4,13 @@ import br.com.userede.erede.service.CaptureTransactionService; import br.com.userede.erede.service.CreateTransactionService; import br.com.userede.erede.service.GetTransactionService; +import br.com.userede.erede.service.OAuthService; import java.util.logging.Logger; public class eRede { - public static final String VERSION = "1.2.0"; + public static final String VERSION = "1.3.0"; public static final String ARTIFACT_ID = "br.com.userede.erede"; public static final String USER_AGENT = "eRede/" + eRede.VERSION + " (Java; %s)"; @@ -28,6 +29,12 @@ public eRede(Store store, Logger logger) { public TransactionResponse authorize(Transaction transaction) { return create(transaction); } + + /**Returns a new access_token*/ + public String generateAccessToken(OAuthStore oAuthStore) { + OAuthService oAuthService = new OAuthService(); + return oAuthService.generateAccessToken(oAuthStore); + } public TransactionResponse create(Transaction transaction) { CreateTransactionService createTransactionService = new CreateTransactionService(store, diff --git a/src/main/java/br/com/userede/erede/service/AbstractTransactionService.java b/src/main/java/br/com/userede/erede/service/AbstractTransactionService.java index b18cad8..552cf94 100755 --- a/src/main/java/br/com/userede/erede/service/AbstractTransactionService.java +++ b/src/main/java/br/com/userede/erede/service/AbstractTransactionService.java @@ -1,14 +1,10 @@ package br.com.userede.erede.service; -import br.com.userede.erede.Store; -import br.com.userede.erede.Transaction; -import br.com.userede.erede.TransactionResponse; -import br.com.userede.erede.eRede; -import br.com.userede.erede.service.error.RedeError; -import br.com.userede.erede.service.error.RedeException; -import com.google.gson.Gson; -import org.apache.http.Header; -import org.apache.http.HttpEntity; +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.logging.Level; +import java.util.logging.Logger; + import org.apache.http.HttpHeaders; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpUriRequest; @@ -16,16 +12,15 @@ import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; -import java.util.Base64; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.zip.GZIPInputStream; +import com.google.gson.Gson; + +import br.com.userede.erede.HttpUtils; +import br.com.userede.erede.Store; +import br.com.userede.erede.Transaction; +import br.com.userede.erede.TransactionResponse; +import br.com.userede.erede.eRede; +import br.com.userede.erede.service.error.RedeError; +import br.com.userede.erede.service.error.RedeException; abstract class AbstractTransactionService { @@ -44,18 +39,14 @@ abstract class AbstractTransactionService { URIBuilder getUri() throws URISyntaxException { return new URIBuilder(store.getEnvironment().getEndpoint("transactions")); - } + } TransactionResponse sendRequest(HttpUriRequest request) { - String credentials = Base64.getEncoder() - .encodeToString(String.format("%s:%s", store.getFiliation(), store.getToken()).getBytes( - StandardCharsets.US_ASCII)); - - request - .addHeader(HttpHeaders.USER_AGENT, String.format(eRede.USER_AGENT, store.getFiliation())); + + request.addHeader(HttpHeaders.USER_AGENT, String.format(eRede.USER_AGENT, store.getFiliation())); request.addHeader(HttpHeaders.ACCEPT, "application/json"); request.addHeader(HttpHeaders.CONTENT_TYPE, "application/json"); - request.addHeader(HttpHeaders.AUTHORIZATION, "Basic " + credentials); + request.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + store.getAccessToken()); request.addHeader("Transaction-Response", "brand-return-opened"); @@ -66,15 +57,15 @@ TransactionResponse sendRequest(HttpUriRequest request) { HttpResponse httpResponse = closeableHttpClient.execute(request); int status = httpResponse.getStatusLine().getStatusCode(); - String response = parseResponse(httpResponse); + String response = HttpUtils.parseResponse(httpResponse); TransactionResponse transactionResponse = new Gson() .fromJson(response, TransactionResponse.class); - + if (status < 200 || status >= 400) { RedeError redeError = new RedeError(transactionResponse.getReturnCode(), transactionResponse.getReturnMessage()); - throw new RedeException(httpResponse.getStatusLine().toString(), redeError, + throw new RedeException(response, redeError, transactionResponse); } @@ -87,25 +78,5 @@ TransactionResponse sendRequest(HttpUriRequest request) { return null; } - private String parseResponse(HttpResponse response) throws IOException { - HttpEntity responseEntity = response.getEntity(); - InputStream responseEntityContent = responseEntity.getContent(); - - Header contentEncoding = response.getFirstHeader("Content-Encoding"); - - if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) { - responseEntityContent = new GZIPInputStream(responseEntityContent); - } - - BufferedReader responseReader = new BufferedReader( - new InputStreamReader(responseEntityContent)); - StringBuilder responseBuilder = new StringBuilder(); - String line; - - while ((line = responseReader.readLine()) != null) { - responseBuilder.append(line); - } - - return responseBuilder.toString(); - } + } diff --git a/src/main/java/br/com/userede/erede/service/OAuthService.java b/src/main/java/br/com/userede/erede/service/OAuthService.java new file mode 100644 index 0000000..eb4d840 --- /dev/null +++ b/src/main/java/br/com/userede/erede/service/OAuthService.java @@ -0,0 +1,65 @@ +package br.com.userede.erede.service; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Base64; + +import org.apache.http.HttpHeaders; +import org.apache.http.HttpResponse; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.message.BasicNameValuePair; + +import com.google.gson.Gson; + +import br.com.userede.erede.AccessTokenResponse; +import br.com.userede.erede.HttpUtils; +import br.com.userede.erede.OAuthStore; +import br.com.userede.erede.eRede; + +public class OAuthService { + + public String generateAccessToken(OAuthStore store) { + + // Base64(clientId:clientSecret) + String clientId = store.getClientId(); + String clientSecret = store.getClientSecret(); + String basic = Base64.getEncoder().encodeToString((clientId + ":" + clientSecret).getBytes(StandardCharsets.UTF_8)); + + String tokenUrl = store.getEnvironment().getEndpoint(); + + HttpPost post = new HttpPost(tokenUrl); + + post.addHeader(HttpHeaders.USER_AGENT, String.format(eRede.USER_AGENT, store.getClientId())); + post.addHeader(HttpHeaders.ACCEPT, "application/json"); + post.addHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded"); + post.addHeader(HttpHeaders.AUTHORIZATION, "Basic " + basic); + + // grant_type=client_credentials + post.setEntity(new UrlEncodedFormEntity(Arrays.asList(new BasicNameValuePair("grant_type", "client_credentials")), StandardCharsets.UTF_8)); + + try (CloseableHttpClient client = HttpClientBuilder.create().build()) { + HttpResponse httpResponse = client.execute(post); + int status = httpResponse.getStatusLine().getStatusCode(); + + String response = HttpUtils.parseResponse(httpResponse); + + if (status < 200 || status >= 400) { + throw new RuntimeException("Erro ao gerar access token. Status=" + status + " Body=" + response); + } + + AccessTokenResponse tokenResponse = new Gson().fromJson(response, AccessTokenResponse.class); + + if (tokenResponse == null || tokenResponse.getAccessToken() == null || tokenResponse.getAccessToken().isBlank()) { + throw new RuntimeException("Resposta inválida ao gerar access token: " + response); + } + + return tokenResponse.getAccessToken(); + } catch (IOException e) { + throw new RuntimeException("Falha ao gerar access token", e); + } + } +} diff --git a/src/test/java/br/com/userede/erede/eRedeTest.java b/src/test/java/br/com/userede/erede/eRedeTest.java index 5930113..2b82049 100755 --- a/src/test/java/br/com/userede/erede/eRedeTest.java +++ b/src/test/java/br/com/userede/erede/eRedeTest.java @@ -1,19 +1,25 @@ package br.com.userede.erede; -import junit.framework.TestCase; - import java.util.Date; -@SuppressWarnings("NewClassNamingConvention") +import br.com.userede.erede.service.OAuthService; +import junit.framework.TestCase; + public class eRedeTest extends TestCase { private Store store; + private OAuthStore oAuthStore; private int sequence; public void setUp() { - // Configuração da loja - store = new Store("36046288", "3cf40bfefad642d788c4a2721c0a0b11", Environment.sandbox()); - + + // novo: obtendo access token + OAuthService oAuthService = new OAuthService(); + oAuthStore = new OAuthStore("36046288", "3cf40bfefad642d788c4a2721c0a0b11", OAuthEnvironment.sandbox()); + String accessToken = oAuthService.generateAccessToken(oAuthStore); + + // Configuração da loja + store = new Store("36046288", accessToken, Environment.sandbox()); sequence = 0; } @@ -202,4 +208,10 @@ public void testShouldCreateADebitcardTransactionWithAuthentication() { transactionResponse.getThreeDSecure().getUrl() ); } + + public void testShouldGenerateAccessToken() { + OAuthService oAuthService = new OAuthService(); + String accessToken = oAuthService.generateAccessToken(oAuthStore); + assertNotNull(accessToken); + } } From 9e75f63bf683ee49f19d0bc333acd420827ed524 Mon Sep 17 00:00:00 2001 From: Thiago dos Santos Date: Fri, 26 Dec 2025 14:50:29 -0300 Subject: [PATCH 2/2] Separate responsibility of authentication with OAuthRede --- .../java/br/com/userede/erede/OAuthRede.java | 17 +++++++++++++++++ .../java/br/com/userede/erede/OAuthStore.java | 5 +++-- src/main/java/br/com/userede/erede/eRede.java | 13 +++---------- .../com/userede/erede/service/OAuthService.java | 8 +++++++- .../java/br/com/userede/erede/eRedeTest.java | 11 ++++++----- 5 files changed, 36 insertions(+), 18 deletions(-) create mode 100644 src/main/java/br/com/userede/erede/OAuthRede.java diff --git a/src/main/java/br/com/userede/erede/OAuthRede.java b/src/main/java/br/com/userede/erede/OAuthRede.java new file mode 100644 index 0000000..3515086 --- /dev/null +++ b/src/main/java/br/com/userede/erede/OAuthRede.java @@ -0,0 +1,17 @@ +package br.com.userede.erede; + +import br.com.userede.erede.service.OAuthService; + +public class OAuthRede { + + private OAuthService oAuthService; + + public OAuthRede(OAuthStore oAuthStore) { + this.oAuthService = new OAuthService(oAuthStore); + } + + /**Returns a new access_token*/ + public String generateAccessToken() { + return oAuthService.generateAccessToken(); + } +} diff --git a/src/main/java/br/com/userede/erede/OAuthStore.java b/src/main/java/br/com/userede/erede/OAuthStore.java index 98b4bea..1bc4601 100644 --- a/src/main/java/br/com/userede/erede/OAuthStore.java +++ b/src/main/java/br/com/userede/erede/OAuthStore.java @@ -13,8 +13,9 @@ public OAuthStore(String clientId, String clientSecret, OAuthEnvironment environ this.environment = environment; } - public OAuthStore(String filiation, String token) { - this(filiation, token, OAuthEnvironment.production()); + /**Constructs production OAuthStore*/ + public OAuthStore(String clientId, String clientSecret) { + this(clientId, clientSecret, OAuthEnvironment.production()); } public OAuthEnvironment getEnvironment() { diff --git a/src/main/java/br/com/userede/erede/eRede.java b/src/main/java/br/com/userede/erede/eRede.java index 949f8d4..2e2a8ac 100755 --- a/src/main/java/br/com/userede/erede/eRede.java +++ b/src/main/java/br/com/userede/erede/eRede.java @@ -1,12 +1,11 @@ package br.com.userede.erede; +import java.util.logging.Logger; + import br.com.userede.erede.service.CancelTransactionService; import br.com.userede.erede.service.CaptureTransactionService; import br.com.userede.erede.service.CreateTransactionService; import br.com.userede.erede.service.GetTransactionService; -import br.com.userede.erede.service.OAuthService; - -import java.util.logging.Logger; public class eRede { @@ -28,13 +27,7 @@ public eRede(Store store, Logger logger) { public TransactionResponse authorize(Transaction transaction) { return create(transaction); - } - - /**Returns a new access_token*/ - public String generateAccessToken(OAuthStore oAuthStore) { - OAuthService oAuthService = new OAuthService(); - return oAuthService.generateAccessToken(oAuthStore); - } + } public TransactionResponse create(Transaction transaction) { CreateTransactionService createTransactionService = new CreateTransactionService(store, diff --git a/src/main/java/br/com/userede/erede/service/OAuthService.java b/src/main/java/br/com/userede/erede/service/OAuthService.java index eb4d840..595250a 100644 --- a/src/main/java/br/com/userede/erede/service/OAuthService.java +++ b/src/main/java/br/com/userede/erede/service/OAuthService.java @@ -22,7 +22,13 @@ public class OAuthService { - public String generateAccessToken(OAuthStore store) { + private OAuthStore store; + + public OAuthService(OAuthStore store) { + this.store = store; + } + + public String generateAccessToken() { // Base64(clientId:clientSecret) String clientId = store.getClientId(); diff --git a/src/test/java/br/com/userede/erede/eRedeTest.java b/src/test/java/br/com/userede/erede/eRedeTest.java index 2b82049..6dfd67e 100755 --- a/src/test/java/br/com/userede/erede/eRedeTest.java +++ b/src/test/java/br/com/userede/erede/eRedeTest.java @@ -2,7 +2,6 @@ import java.util.Date; -import br.com.userede.erede.service.OAuthService; import junit.framework.TestCase; public class eRedeTest extends TestCase { @@ -14,9 +13,11 @@ public class eRedeTest extends TestCase { public void setUp() { // novo: obtendo access token - OAuthService oAuthService = new OAuthService(); oAuthStore = new OAuthStore("36046288", "3cf40bfefad642d788c4a2721c0a0b11", OAuthEnvironment.sandbox()); - String accessToken = oAuthService.generateAccessToken(oAuthStore); + + OAuthRede oAuthRede = new OAuthRede(oAuthStore); + + String accessToken = oAuthRede.generateAccessToken(); // Configuração da loja store = new Store("36046288", accessToken, Environment.sandbox()); @@ -210,8 +211,8 @@ public void testShouldCreateADebitcardTransactionWithAuthentication() { } public void testShouldGenerateAccessToken() { - OAuthService oAuthService = new OAuthService(); - String accessToken = oAuthService.generateAccessToken(oAuthStore); + OAuthRede oAuthRede = new OAuthRede(oAuthStore); + String accessToken = oAuthRede.generateAccessToken(); assertNotNull(accessToken); } }