Skip to content

Commit 6d0dcb4

Browse files
Merge pull request #333 from rodrigocananea/master
Adicionado consulta CFF de tributações classTrib
2 parents c277430 + b2a66c8 commit 6d0dcb4

File tree

6 files changed

+506
-0
lines changed

6 files changed

+506
-0
lines changed
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
package br.com.swconsultoria.nfe;
2+
3+
import br.com.swconsultoria.certificado.Certificado;
4+
import br.com.swconsultoria.certificado.CertificadoService;
5+
import br.com.swconsultoria.certificado.exception.CertificadoException;
6+
import br.com.swconsultoria.nfe.dom.ConfiguracoesNfe;
7+
import br.com.swconsultoria.nfe.exception.NfeException;
8+
import br.com.swconsultoria.nfe.util.ConfiguracoesUtil;
9+
import br.com.swconsultoria.nfe.util.WebServiceUtil;
10+
import br.com.swconsultoria.nfe.dto.CstDTO;
11+
import com.fasterxml.jackson.core.type.TypeReference;
12+
import com.fasterxml.jackson.databind.ObjectMapper;
13+
import org.apache.commons.httpclient.HttpClient;
14+
import org.apache.commons.httpclient.methods.GetMethod;
15+
16+
import javax.net.ssl.SSLSocketFactory;
17+
import javax.net.ssl.SSLContext;
18+
import javax.net.ssl.HttpsURLConnection;
19+
import java.io.BufferedInputStream;
20+
import java.io.ByteArrayOutputStream;
21+
import java.io.IOException;
22+
import java.io.InputStream;
23+
import java.net.URL;
24+
import java.nio.charset.StandardCharsets;
25+
import java.util.List;
26+
27+
/**
28+
* Serviço para consulta de classTrib (CFF).
29+
*
30+
* Nesta versão: o método getClassTrib(ConfiguracoesNfe) aceita somente a ConfiguracoesNfe.
31+
* Internamente tenta, na ordem:
32+
* 1) obter um HttpClient via CertificadoService.getHttpsClient(...) e usá-lo (reaproveita StubUtil/CertificadoService);
33+
* 2) tentar obter SSLSocketFactory/SSLContext via reflexão em CertificadoService (se disponível);
34+
* 3) tentar obter SSLSocketFactory/SSLContext do próprio objeto Certificado (se disponível);
35+
* 4) se nada for possível, lançar IllegalStateException explicando o que chamar.
36+
*
37+
* Objetivo: o usuário só precisa passar a ConfiguracoesNfe (como em outras APIs da lib).
38+
*/
39+
public class ConsultaTributacao {
40+
41+
private static final ObjectMapper MAPPER = new ObjectMapper();
42+
43+
/**
44+
* Conveniência: o usuário passa apenas ConfiguracoesNfe.
45+
* Tenta primeiro criar e usar o HttpClient via CertificadoService (mais robusto e consistente com StubUtil),
46+
* fazendo fallback para SSLSocketFactory quando necessário.
47+
*/
48+
public static List<CstDTO> getClassTrib(ConfiguracoesNfe config) throws NfeException, IOException {
49+
// inicializa configurações e certificado (lança NfeException se algo inválido)
50+
ConfiguracoesUtil.iniciaConfiguracoes(config);
51+
52+
String url = WebServiceUtil.getCustomUrl(config, "CFF", "classTrib");
53+
Certificado certificado = config.getCertificado();
54+
55+
// 1) Tentar criar HttpClient via CertificadoService (recomendado — igual ao StubUtil)
56+
if (certificado != null) {
57+
try {
58+
HttpClient httpClient;
59+
InputStream cacertStream = config.getCacert();
60+
if (cacertStream != null) {
61+
// usa overload que aceita InputStream (se disponível na Java_Certificado)
62+
httpClient = CertificadoService.getHttpsClient(certificado, url, cacertStream);
63+
} else {
64+
httpClient = CertificadoService.getHttpsClient(certificado, url);
65+
}
66+
if (httpClient != null) {
67+
return getClassTrib(config, httpClient);
68+
}
69+
} catch (CertificadoException ce) {
70+
// falha ao montar HttpClient — tentaremos fallback abaixo
71+
} catch (Throwable t) {
72+
// caso CertificadoService não tenha a assinatura esperada ou outra falha, tentar fallback
73+
}
74+
}
75+
76+
// 2) Tentar obter SSLSocketFactory via CertificadoService (reflexão) ou via Certificado
77+
SSLSocketFactory sslFactory = tryResolveSslSocketFactory(config);
78+
if (sslFactory != null) {
79+
return getClassTrib(config, sslFactory);
80+
}
81+
82+
// 3) Não foi possível resolver automaticamente: instruir usuário a passar HttpClient ou habilitar multithreading
83+
throw new IllegalStateException("Não foi possível resolver mecanismo SSL automaticamente. " +
84+
"Passe um HttpClient criado por CertificadoService.getHttpsClient(certificado,url) e chame getClassTrib(config, httpClient), " +
85+
"ou habilite modo multithreading no certificado se preferir que a biblioteca gere o HttpClient automaticamente.");
86+
}
87+
88+
/**
89+
* Implementação usando Apache HttpClient (reaproveita CertificadoService/StubUtil).
90+
*/
91+
public static List<CstDTO> getClassTrib(ConfiguracoesNfe config, HttpClient httpClient) throws IOException, NfeException {
92+
String url = WebServiceUtil.getCustomUrl(config, "CFF", "classTrib");
93+
94+
GetMethod get = new GetMethod(url);
95+
get.addRequestHeader("Accept", "application/json");
96+
try {
97+
int status = httpClient.executeMethod(get);
98+
if (status != 200) {
99+
InputStream err = get.getResponseBodyAsStream();
100+
String body = toString(err);
101+
throw new IOException("HTTP " + status + " -> " + body);
102+
}
103+
try (InputStream responseStream = new BufferedInputStream(get.getResponseBodyAsStream())) {
104+
return MAPPER.readValue(responseStream, new TypeReference<List<CstDTO>>() {
105+
});
106+
}
107+
} finally {
108+
get.releaseConnection();
109+
}
110+
}
111+
112+
/**
113+
* Implementação usando SSLSocketFactory (fallback).
114+
*/
115+
public static List<CstDTO> getClassTrib(ConfiguracoesNfe config, SSLSocketFactory sslFactory) throws IOException, NfeException {
116+
String url = WebServiceUtil.getCustomUrl(config, "CFF", "classTrib");
117+
118+
HttpsURLConnection conn = null;
119+
InputStream is = null;
120+
try {
121+
URL u = new URL(url);
122+
conn = (HttpsURLConnection) u.openConnection();
123+
conn.setSSLSocketFactory(sslFactory);
124+
conn.setRequestMethod("GET");
125+
conn.setRequestProperty("Accept", "application/json");
126+
conn.setConnectTimeout(15000);
127+
conn.setReadTimeout(30000);
128+
conn.setDoInput(true);
129+
130+
int code = conn.getResponseCode();
131+
if (code != 200) {
132+
InputStream err = conn.getErrorStream();
133+
String body = toString(err);
134+
throw new IOException("HTTP " + code + " -> " + body);
135+
}
136+
137+
is = new BufferedInputStream(conn.getInputStream());
138+
return MAPPER.readValue(is, new TypeReference<List<CstDTO>>() {});
139+
} finally {
140+
if (is != null) {
141+
try { is.close(); } catch (IOException ignored) {}
142+
}
143+
if (conn != null) {
144+
conn.disconnect();
145+
}
146+
}
147+
}
148+
149+
/**
150+
* Tenta resolver SSLSocketFactory via reflexão a partir da infra de certificado existente.
151+
* Primeira tentativa: métodos estáticos em CertificadoService (getSSLSocketFactory/getSslContext).
152+
* Segunda tentativa: métodos públicos no próprio objeto Certificado.
153+
*/
154+
private static SSLSocketFactory tryResolveSslSocketFactory(ConfiguracoesNfe config) {
155+
// 1) tenta métodos estáticos em CertificadoService
156+
try {
157+
Class<?> svc = Class.forName("br.com.swconsultoria.certificado.CertificadoService");
158+
try {
159+
java.lang.reflect.Method m = svc.getMethod("getSSLSocketFactory", Class.forName("br.com.swconsultoria.certificado.Certificado"));
160+
Object res = m.invoke(null, config.getCertificado());
161+
if (res instanceof SSLSocketFactory) {
162+
return (SSLSocketFactory) res;
163+
}
164+
} catch (NoSuchMethodException ignored) {}
165+
try {
166+
java.lang.reflect.Method m2 = svc.getMethod("getSslContext", Class.forName("br.com.swconsultoria.certificado.Certificado"));
167+
Object res2 = m2.invoke(null, config.getCertificado());
168+
if (res2 instanceof SSLContext) {
169+
return ((SSLContext) res2).getSocketFactory();
170+
}
171+
} catch (NoSuchMethodException ignored) {}
172+
} catch (Throwable ignored) {}
173+
174+
// 2) tenta métodos no próprio objeto Certificado (getSSLSocketFactory / getSslContext / getSocketFactory)
175+
Object cert = config.getCertificado();
176+
if (cert != null) {
177+
try {
178+
java.lang.reflect.Method m = cert.getClass().getMethod("getSSLSocketFactory");
179+
Object res = m.invoke(cert);
180+
if (res instanceof SSLSocketFactory) {
181+
return (SSLSocketFactory) res;
182+
}
183+
} catch (Throwable ignored) {}
184+
try {
185+
java.lang.reflect.Method m2 = cert.getClass().getMethod("getSslContext");
186+
Object res2 = m2.invoke(cert);
187+
if (res2 instanceof SSLContext) {
188+
return ((SSLContext) res2).getSocketFactory();
189+
}
190+
} catch (Throwable ignored) {}
191+
try {
192+
java.lang.reflect.Method m3 = cert.getClass().getMethod("getSocketFactory");
193+
Object res3 = m3.invoke(cert);
194+
if (res3 instanceof SSLSocketFactory) {
195+
return (SSLSocketFactory) res3;
196+
}
197+
} catch (Throwable ignored) {}
198+
}
199+
200+
return null;
201+
}
202+
203+
private static String toString(InputStream is) throws IOException {
204+
if (is == null) {
205+
return "";
206+
}
207+
// leitura compatível com Java 8
208+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
209+
byte[] buffer = new byte[4096];
210+
int read;
211+
while ((read = is.read(buffer)) != -1) {
212+
baos.write(buffer, 0, read);
213+
}
214+
return new String(baos.toByteArray(), StandardCharsets.UTF_8);
215+
}
216+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package br.com.swconsultoria.nfe.dto;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import lombok.Getter;
5+
import lombok.NoArgsConstructor;
6+
import lombok.Setter;
7+
8+
import java.math.BigDecimal;
9+
10+
@Getter
11+
@Setter
12+
@NoArgsConstructor
13+
public class ClassificacaoTributariaDTO {
14+
15+
@JsonProperty("cClassTrib")
16+
private String cClassTrib;
17+
18+
@JsonProperty("DescricaoClassTrib")
19+
private String descricaoClassTrib;
20+
21+
@JsonProperty("pRedIBS")
22+
private BigDecimal pRedIBS;
23+
24+
@JsonProperty("pRedCBS")
25+
private BigDecimal pRedCBS;
26+
27+
@JsonProperty("IndRedutorBC")
28+
private Boolean indRedutorBC;
29+
30+
@JsonProperty("IndTribRegular")
31+
private Boolean indTribRegular;
32+
33+
@JsonProperty("IndCredPresOper")
34+
private Boolean indCredPresOper;
35+
36+
@JsonProperty("IndEstornoCred")
37+
private Boolean indEstornoCred;
38+
39+
@JsonProperty("TipoAliquota")
40+
private String tipoAliquota;
41+
42+
@JsonProperty("IndNFe")
43+
private Boolean indNFe;
44+
45+
@JsonProperty("IndNFCe")
46+
private Boolean indNFCe;
47+
48+
@JsonProperty("IndCTe")
49+
private Boolean indCTe;
50+
51+
@JsonProperty("IndCTeOS")
52+
private Boolean indCTeOS;
53+
54+
@JsonProperty("IndBPe")
55+
private Boolean indBPe;
56+
57+
@JsonProperty("IndNF3e")
58+
private Boolean indNF3e;
59+
60+
@JsonProperty("IndNFCom")
61+
private Boolean indNFCom;
62+
63+
@JsonProperty("IndNFSE")
64+
private Boolean indNFSE;
65+
66+
@JsonProperty("IndBPeTM")
67+
private Boolean indBPeTM;
68+
69+
@JsonProperty("IndBPeTA")
70+
private Boolean indBPeTA;
71+
72+
@JsonProperty("IndNFAg")
73+
private Boolean indNFAg;
74+
75+
@JsonProperty("IndNFSVIA")
76+
private Boolean indNFSVIA;
77+
78+
@JsonProperty("IndNFABI")
79+
private Boolean indNFABI;
80+
81+
@JsonProperty("IndNFGas")
82+
private Boolean indNFGas;
83+
84+
@JsonProperty("IndDERE")
85+
private Boolean indDERE;
86+
87+
@JsonProperty("Anexo")
88+
private Integer anexo;
89+
90+
@JsonProperty("Link")
91+
private String link;
92+
93+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package br.com.swconsultoria.nfe.dto;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import lombok.Getter;
5+
import lombok.NoArgsConstructor;
6+
import lombok.Setter;
7+
8+
import java.util.List;
9+
10+
@Getter
11+
@Setter
12+
@NoArgsConstructor
13+
public class CstDTO {
14+
15+
@JsonProperty("CST")
16+
private String cst;
17+
18+
@JsonProperty("DescricaoCST")
19+
private String descricaoCST;
20+
21+
@JsonProperty("IndIBSCBS")
22+
private Boolean indIBSCBS;
23+
24+
@JsonProperty("IndRedBC")
25+
private Boolean indRedBC;
26+
27+
@JsonProperty("IndRedAliq")
28+
private Boolean indRedAliq;
29+
30+
@JsonProperty("IndTransfCred")
31+
private Boolean indTransfCred;
32+
33+
@JsonProperty("IndDif")
34+
private Boolean indDif;
35+
36+
@JsonProperty("IndAjusteCompet")
37+
private Boolean indAjusteCompet;
38+
39+
@JsonProperty("IndIBSCBSMono")
40+
private Boolean indIBSCBSMono;
41+
42+
@JsonProperty("IndCredPresIBSZFM")
43+
private Boolean indCredPresIBSZFM;
44+
45+
@JsonProperty("classificacoesTributarias")
46+
private List<ClassificacaoTributariaDTO> classificacoesTributarias;
47+
}

0 commit comments

Comments
 (0)