FocusNFe Brazilian fiscal Issuer NF-e NFC-e Java REST API Client (Open Source)
Java Connector - FocusNFe Brazilian fiscal Issuer NF-e NFC-e MD-e API
Built-based on the documentation: https://focusnfe.com.br/doc/
Supported Java Versions:
- requires Java 8 (or higher) at runtime.
Maven dependency:
<dependency>
<groupId>org.frekele.fiscal</groupId>
<artifactId>focusnfe-api-client</artifactId>
<version>1.0.4</version>
</dependency>
Gradle dependency:
compile 'org.frekele.fiscal:focusnfe-api-client:1.0.4'
Repositories:
Interfaces | Descriptions | Usage Examples |
---|---|---|
FocusNFeV2Repository | NF-e API V2 remote call | FocusNFeV2RepositoryIT |
FocusNFCeV2Repository | NFC-e API V2 remote call | FocusNFCeV2RepositoryIT |
FocusMDeV2Repository | MD-e API V2 remote call | FocusMDeV2RepositoryIT |
FocusWebHookV2Repository | WebHook API V2 remote call | FocusWebHookV2RepositoryIT |
FocusNcmV2Repository | NCM API V2 remote call | FocusNcmV2RepositoryIT |
FocusBackupV2Repository | Backups API V2 remote call | FocusBackupV2RepositoryIT |
FocusDownloadRepository | Download Files remote call | FocusDownloadRepositoryIT |
Sample Example
public class MyMainExample {
public static void main(String[] args) {
ResteasyClient client = new ResteasyClientBuilder().build();
FocusNFeAuth auth = FocusNFeAuth.newBuilder()
.withAccessToken("your-token-here")
.withEnvironment(EnvironmentFocusNFeEnum.HOMOLOGATION)
.build();
FocusNFeV2Repository nfeRepository = new FocusNFeV2RepositoryImpl(client, auth);
String reference = "your-nfe-reference";
NFeConsultarBodyResponse bodyResponse = nfeRepository.consultarNFeCompleta(reference).getBody();
NFeRetornoRequisicaoNotaFiscal requisicaoNotaFiscal = bodyResponse.getRequisicaoNotaFiscal();
NFeProtocoloNotaFiscal protocoloNotaFiscal = bodyResponse.getProtocoloNotaFiscal();
String chaveNfe = requisicaoNotaFiscal.getChaveNfe();
String numeroProtocolo = protocoloNotaFiscal.getNumeroProtocolo();
String pathXmlNFe = bodyResponse.getCaminhoXmlNotaFiscal();
String pathDanfeNFe = bodyResponse.getCaminhoDanfe();
FocusDownloadRepository downloadRepository = new FocusDownloadRepositoryImpl(client, auth);
InputStream xmlInputStream = downloadRepository.downloadXml(pathXmlNFe).getBody();
InputStream pdfInputStream = downloadRepository.downloadPdf(pathDanfeNFe).getBody();
}
}
Usage with CDI (Contexts and Dependency Injection)
public class FocusNFeProducer {
@Produces
@FocusNFe
public FocusNFeAuth producesFocusNFeAuth() {
String accessToken = System.getenv("FOCUS_NFE_ACCESS_TOKEN");
String environment = System.getenv("FOCUS_NFE_ENVIRONMENT");
return new FocusNFeAuth(accessToken, environment);
}
@Produces
@FocusNFe
public ResteasyClient producesResteasyClient() {
ResteasyClient client = new ResteasyClientBuilder()
// Example:
// Register your Custom Logging here.
//.register(CustomLoggingFilter.class)
.build();
return client;
}
public void closeResteasyClient(@Disposes @FocusNFe ResteasyClient client) {
client.close();
}
}
//Then you just need to @inject.
public class MyService {
@Inject
@FocusNFe
private FocusNFeV2Repository repository;
public void callExample() {
String reference = UUID.randomUUID().toString();
NFeEnvioRequisicaoNotaFiscal nfe = NFeEnvioRequisicaoNotaFiscal.newBuilder()
.withNaturezaOperacao("VENDA DE MERCADORIA")
.withDataEmissao(OffsetDateTime.now())
.withTipoDocumento(NFeTipoDocumentoEnum.NOTA_FISCAL_SAIDA)
........... (add more fields)
.build();
NFeAutorizarResponse response = repository.autorizar(reference, new NFeAutorizarBodyRequest(nfe));
NFeAutorizarBodyResponse body = response.getBody();
}
}
Usage without CDI
public class MyService {
public void callExample() {
//First create FocusNFeAuth
Properties prop = // read your Properties or System.env
String accessToken = prop.getProperty("accessToken");
String environment = prop.getProperty("environment"); // PRODUCTION OR HOMOLOGATION
FocusNFeAuth auth = FocusNFeAuth.newBuilder()
.withAccessToken(accessToken)
.withEnvironment(environment)
.build();
//Build one client per thread, or use CDI Injection.
ResteasyClient client = new ResteasyClientBuilder()
// Example, you can customize a connections.
// Add proxy.
//.defaultProxy("192.168.56.67", 3456)
// Change connection Pool size.
//.connectionPoolSize(3)
// Change connection TTL.
//.connectionTTL(30, TimeUnit.MINUTES)
.build();
FocusNFeV2Repository repository = new FocusNFeV2RepositoryImpl(client, auth);
repository.autorizar(reference, new NFeAutorizarBodyRequest(nfe));
//Is important to close in end, or use CDI.
client.close();
}
}
Example usage NF-e and NFC-e
POST - Autorizar NF-e (Asynchronous)
String reference = UUID.randomUUID().toString();
NFeEnvioRequisicaoNotaFiscal nfe = NFeEnvioRequisicaoNotaFiscal.newBuilder()
.withNaturezaOperacao("VENDA DE MERCADORIA")
.withDataEmissao(OffsetDateTime.now())
.withTipoDocumento(NFeTipoDocumentoEnum.NOTA_FISCAL_SAIDA)
.withFinalidadeEmissao(NFeFinalidadeEmissaoEnum.NOTA_NORMAL)
.withCnpjEmitente("your-cnpj-here")
.withNomeDestinatario("NF-E EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL")
.withCpfDestinatario("98445556550")
.withTelefoneDestinatario("5196185555")
.withLogradouroDestinatario("Av Otto Niemeyer")
.withNumeroDestinatario("600")
.withBairroDestinatario("Tristeza")
.withMunicipioDestinatario("Porto Alegre")
.withUfDestinatario(NFeUnidadeFederativaEnum.RIO_GRANDE_DO_SUL)
.withCepDestinatario("91910-001")
.withModalidadeFrete(NFeModalidadeFreteEnum.POR_CONTA_EMITENTE)
.withItems(new ArrayList<>())
.build();
NFeItem item = NFeItem.newBuilder()
.withNumeroItem("1")
.withCodigoProduto("XYZ-12345")
.withDescricao("Produto Teste 12345 XYZ")
.withCfop("5102")
.withCodigoNcm("94036000")
.withUnidadeComercial("UN")
.withQuantidadeComercial(BigDecimal.valueOf(1))
.withValorUnitarioComercial(new BigDecimal("124.35"))
.withUnidadeTributavel("UN")
.withQuantidadeTributavel(BigDecimal.valueOf(1))
.withValorUnitarioTributavel(new BigDecimal("124.35"))
.withValorBruto(new BigDecimal("124.35"))
.withIcmsSituacaoTributaria(NFeIcmsSituacaoTributariaEnum.TRIBUTADA_SIMPLES_NACIONAL_SEM_PERMISSAO_CREDITO)
.withIcmsOrigem(NFeIcmsOrigemEnum.NACIONAL)
.withPisSituacaoTributaria(NFePisCofinsSituacaoTributariaEnum.OPERACAO_ISENTA_DA_CONTRIBUICAO)
.withCofinsSituacaoTributaria(NFePisCofinsSituacaoTributariaEnum.OPERACAO_ISENTA_DA_CONTRIBUICAO)
.withIncluiNoTotal(NFeIncluiNoTotalEnum.SIM)
.build();
nfe.getItems().add(item);
NFeAutorizarBodyRequest bodyRequest = NFeAutorizarBodyRequest.newBuilder().withNfe(nfe).build();
NFeAutorizarResponse response = repository.autorizar(reference, bodyRequest);
//Get Body with Json Object Mapping.
NFeAutorizarBodyResponse responseBody = response.getBody();
//Get Body with String.
String responseBodyString = response.getBodyString();
//Get Http Header 'X-Rate-Limit-Limit'.
String responseHeaderValue = response.getRateLimitLimit();
//Get Http Header 'X-Rate-Limit-Remaining'.
String responseHeaderValue = response.getRateLimitRemaining();
//Get Http Header 'X-Rate-Limit-Reset'.
String responseHeaderValue = response.getRateLimitReset();
//Get Http Header 'X-Runtime'.
String responseHeaderValue = response.getRuntime();
//Get Http Status Response.
String responseStatus = response.getStatus();
//Get All Http Response.
Response httpResponse = response.getResponse();
POST - Autorizar NFC-e (Synchronous)
.....
NFCeAutorizarBodyRequest bodyRequest = new NFCeAutorizarBodyRequest(nfce);
NFCeAutorizarResponse response = repository.autorizarConsultarNFeCompleta(reference, bodyRequest);
POST - AutorizarConsultarNFeCompleta NFC-e (Synchronous)
.....
NFCeAutorizarBodyRequest bodyRequest = new NFCeAutorizarBodyRequest(nfce);
NFCeAutorizarResponse response = repository.autorizarConsultarNFeCompleta(reference, bodyRequest);
DELETE - Cancelar NF-e NFC-e
NFeCancelarResponse response = repository.cancelar(reference, new NFeCancelarBodyRequest("Teste de cancelamento de nota"));
//Or with Builder Pattern.
NFeCancelarBodyRequest bodyRequest = NFeCancelarBodyRequest.newBuilder()
.withJustificativa("Teste de cancelamento de nota")
.build();
NFeCancelarResponse response = repository.cancelar(reference, bodyRequest);
POST - EmitirCCe NF-e
NFeCCeBodyRequest bodyRequest = NFeCCeBodyRequest.newBuilder()
.withCorrecao("Teste de carta de correcao")
.build();
NFeCCeResponse response = repository.emitirCCe(reference, bodyRequest);
POST - EnviarEmail NF-e NFC-e
NFeEmailBodyRequest bodyRequest = NFeEmailBodyRequest.newBuilder()
.withEmails("alguem@example.org", "teste@teste.com.br")
.build();
NFeEmailResponse response = repository.enviarEmail(reference, bodyRequest);
GET - Consultar NF-e NFC-e
NFeConsultarResponse response = repository.consultar(reference);
GET - ConsultarNFeCompleta NF-e NFC-e
NFeConsultarResponse response = repository.consultarNFeCompleta(reference);
POST - Inutilizar NF-e NFC-e
NFeInutilizarBodyRequest bodyRequest = NFeInutilizarBodyRequest.newBuilder()
.withCnpj("your-cnpj-here")
.withSerie("1")
.withNumeroInicial("7")
.withNumeroFinal("9")
.withJustificativa("Teste de inutilizacao de nota")
.build();
NFeInutilizarResponse response = repository.inutilizar(bodyRequest);
Example usage MD-e
POST - Manifestar
String chaveNFe = "41180684689100015855001002510000040306642480";
MDeManifestarBodyRequest bodyRequest = MDeManifestarBodyRequest.newBuilder()
.withTipo(MDeTipoManifestacaoEnum.CONFIRMACAO)
.withJustificativa("Fornecedor entregou produtos")
.build();
MDeManifestarResponse response = repository.manifestar(chaveNFe, bodyRequest);
GET - ConsultarManifestos
String cnpjEmitente = "your-cnpj-here";
MDeConsultarManifestosResponse response = repository.consultarManifestos(cnpjEmitente);
//Or with parameter 'versao'
MDeConsultarManifestosResponse response = repository.consultarManifestos(cnpjEmitente, 40);
GET - ConsultarManifestos
String cnpjEmitente = "your-cnpj-here";
MDeConsultarManifestosResponse response = repository.consultarManifestosPendentes(cnpjEmitente);
//Or with parameter 'versao'
MDeConsultarManifestosResponse response = repository.consultarManifestosPendentes(cnpjEmitente, 40);
GET - ConsultarUltimoManifesto
String chaveNFe = "41180684689100015855001002510000040306642480";
MDeConsultarUltimoManifestoResponse response = repository.consultarUltimoManifesto(chaveNFe);
GET - ConsultarNFe
String chaveNFe = "41180684689100015855001002510000040306642480";
MDeConsultarNFeResponse response = repository.consultarNFe(chaveNFe);
GET - ConsultarNFeCompleta
String chaveNFe = "41180684689100015855001002510000040306642480";
MDeConsultarNFeResponse response = repository.consultarNFeCompleta(chaveNFe);
GET - DownloadNFe
String chaveNFe = "41180684689100015855001002510000040306642480";
MDeDownloadXmlResponse response = repository.downloadNFe(chaveNFe);
GET - DownloadCancelamento
String chaveNFe = "41180684689100015855001002510000040306642480";
MDeDownloadXmlResponse response = repository.downloadCancelamento(chaveNFe);
GET - DownloadUltimaCCe
String chaveNFe = "41180684689100015855001002510000040306642480";
MDeDownloadXmlResponse response = repository.downloadUltimaCCe(chaveNFe);
Example usage WebHooks
POST - Criar
String cnpjEmitente = "your-cnpj-here";
WebHookCriarBodyRequest bodyRequest = WebHookCriarBodyRequest.newBuilder()
.withCnpj(cnpjEmitente)
.withEvent("nfe")
.withUrl("http://minha.url/nfe")
.build();
WebHookCriarResponse response = repository.criar(bodyRequest);
String webHookId = bodyResponse.getId());
GET - Consultar
WebHookConsultarResponse response = repository.consultar(webHookId);
GET - ConsultarTodos
WebHookConsultarTodosResponse response = repository.consultarTodos();
DELETE - Excluir
WebHookExcluirResponse response = repository.excluir(webHookId);
Example usage for search NCMs
GET - Consultar
NcmConsultarResponse response = repository.consultar("94036000");
GET - ConsultarTodos
NcmQueryParam queryParam = NcmQueryParam.newBuilder().build();
NcmConsultarTodosResponse response = repository.consultarTodos(queryParam);
GET - ConsultarTodos
NcmQueryParam queryParam = NcmQueryParam.newBuilder().build();
NcmConsultarTodosResponse response = repository.consultarTodos(queryParam);
//Or with queryParams
NcmQueryParam queryParam = NcmQueryParam.newBuilder()
.withCapitulo("94")
.withPosicao("03")
.withSubposicao1("6")
.withSubposicao2("0")
.withItem1("0")
.withItem2("0")
.build();
NcmConsultarTodosResponse response = repository.consultarTodos(queryParam);
//Or with offset
NcmQueryParam queryParam = NcmQueryParam.newBuilder()
.withCodigo("9")
.withOffset("20")
.build();
NcmConsultarTodosResponse response = repository.consultarTodos(queryParam);
Example usage for search Backups
GET - Consultar
String cnpjEmitente = "your-cnpj-here";
BackupConsultaResponse response = repository.consultarTodos(cnpjEmitente);
Example usage for Download Files
GET - DownloadXml
String reference = "your-reference";
String pathXmlNFe = nfeRepository.consultar(reference).getBody().getCaminhoXmlNotaFiscal();
DownloadFileResponse response = downloadRepository.downloadXml(pathXmlNFe);
InputStream inputStream = response.getBody();
GET - DownloadPdf
String reference = "your-reference";
String pathDanfeNFe = nfeRepository.consultar(reference).getBody().getCaminhoDanfe();
DownloadFileResponse response = downloadRepository.downloadPdf(pathDanfeNFe);
InputStream inputStream = response.getBody();
GET - DownloadHtml
String reference = "your-reference";
String pathDanfeNFCe = nfeRepository.consultar(reference).getBody().getCaminhoDanfe();
DownloadFileResponse response = downloadRepository.downloadHtml(pathDanfeNFe);
InputStream inputStream = response.getBody();
GET - DownloadZip
String cnpjEmitente = "your-cnpj-here";
NFeBackup backup = backupRepository.consultarTodos(cnpjEmitente).getBody().getBackups().get(0);
DownloadFileResponse response = downloadRepository.downloadZip(backup.getDanfes());
InputStream inputStream = response.getBody();
Working with RestEasy (JAX-RS) Exceptions
try {
MDeManifestarResponse response = repository.manifestar(chaveNFe, bodyRequest);
MDeManifestarBodyResponse bodyResponse = response.getBody();
} catch (NotAuthorizedException e) {
throw new FocusNFeException("User not Authorized!", e);
} catch (ClientErrorException e) {
NFeErro nFeErro = e.getResponse().readEntity(NFeErro.class);
throw new FocusNFeException("[ " + nFeErro.getCodigo() + " ] - " + nFeErro.getMensagem(), e);
} catch (WebApplicationException e) {
int statusCode = e.getResponse().getStatus();
String bodyError = e.getResponse().readEntity(String.class);
throw new FocusNFeException(e);
}
HTTP Status Codes | Expected RestEasy (JAX-RS) throw Exceptions |
---|---|
>= 200 && < 300 | OK - Without exception. |
>= 300 && < 400 | throw new RedirectionException(response) |
400 | throw new BadRequestException(response) |
401 | throw new NotAuthorizedException(response) |
403 | throw new ForbiddenException(response) |
404 | throw new NotFoundException(response) |
405 | throw new NotAllowedException(response) |
406 | throw new NotAcceptableException(response) |
415 | throw new NotSupportedException(response) |
500 | throw new InternalServerErrorException(response) |
503 | throw new ServiceUnavailableException(response) |
>= 400 && < 500 | throw new ClientErrorException(response) |
>= 500 | throw new ServerErrorException(response) |
Others | throw new WebApplicationException(response) |
Custom Logging for Response and Request
With the filter you can intercept all requests during sending and receiving responses. Everything before the Jackson conversion (json to Object) and (Object to Json).
public class CustomLoggingFilter implements ClientResponseFilter, ClientRequestFilter {
private Logger logger = Logger.getLogger(CustomLoggingFilter.class.getName());
@Override
public void filter(ClientRequestContext requestContext) throws IOException {
this.getLogger().debug("--> Request LoggingFilter: Uri = " + requestContext.getUri());
this.getLogger().debug("--> Request LoggingFilter: Method= " + requestContext.getMethod());
// Add more logs as you want.
}
@Override
public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
this.getLogger().debug("<-- Response LoggingFilter:");
this.getLogger().debug("<-- Response LoggingFilter: Status = " + responseContext.getStatus());
// Add more logs as you want.
}
public Logger getLogger() {
return logger;
}
}
If you need to convert Json or Objects manually, do so:
Json –> JsonNode
JsonNode jsonNode = FocusNFeUtils.parseJsonToJsonNode(content);
Json –> Object
String content = "{ ..... }";
Class classType = MDeManifesto.class;
MDeManifesto manifesto = FocusNFeUtils.parseJsonTo(content, classType);
JsonNode –> String
String jsonString = FocusNFeUtils.parseJsonToString(jsonNode);
//with pretty printer
String jsonString = FocusNFeUtils.parseJsonToString(jsonNode, true);
Xml –> JsonNode
JsonNode jsonNode = FocusNFeUtils.parseXmlToJsonNode(content);
Xml –> Document
Document document = FocusNFeUtils.parseXmlToDocument(content);
Json –> Object
ObjectMapper mapper = new ObjectMapper();
String json = "{ ........ }";
MDeManifesto manifesto = mapper.readValue(json, MDeManifesto.class);
Json –> List
ObjectMapper mapper = new ObjectMapper();
String jsonArray = "[{ ........ }]";
List<MDeManifesto> manifestos = mapper.readValue(jsonArray, new TypeReference<List<MDeManifesto>>(){});
Object –> Json
ObjectMapper mapper = new ObjectMapper();
MDeManifesto manifesto = MDeManifesto.newBuilder().build();
String json = mapper.writeValueAsString(manifesto);
List –> Json
ObjectMapper mapper = new ObjectMapper();
List<MDeManifesto> manifestos = new ArrayList<>();
manifestos.add(manifesto1);
manifestos.add(manifesto2);
String jsonArray = mapper.writeValueAsString(manifestos);
InputStream –> byte[]
byte[] arrayBytes = FocusNFeUtils.parseToByteArray(inputStream);
InputStream –> ByteArrayOutputStream
ByteArrayOutputStream outputStream = FocusNFeUtils.parseToByteArrayOutputStream(inputStream);
Compile:
Compile with Maven:
mvn clean install -Dgpg.skip
Compile with integration Tests:
You need to add the environment variables to run the integration tests.
- FOCUS_NFE_ACCESS_TOKEN = //Your Access-Token
- FOCUS_NFE_CNPJ_EMITENTE = //Your CNPJ
mvn clean install -Dgpg.skip -DskipITs=false
frekele/focusnfe-api-client is licensed under the [MIT License]. The terms of the license are as follows:
MIT License
Copyright (c) 2018 @frekele<Leandro Kersting de Freitas>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.