Em julho de 2012 fui convidado para desenvolver um aplicativo consumidor de um WebService para produção de Notas Fiscais de Serviço Eletrônicas (NFS-e). A questão é que, mesmo conhecendo o Delphi e seus recursos, eu ainda não tinha experiência com desenvolvimento de aplicativos para acesso de WebServices e com documentos fiscais eletrônicos. A saída foi obter o máximo de informações na internet e com outros profissionais para que o desenvolvimento não ficasse engessado.
WebService da GINFES
WebService é o nome dado a uma tecnologia que permite a integração de diferentes aplicações pela internet por meio de arquivos XML. A grande vantagem de se utilizar um WebService é a agilidade na comunicação, bem como uma padronização dos serviços disponibilizados. O objetivo é automatizar o processamento de um pacote de dados e receber a resposta de forma rápida.
Um bom exemplo de um WebService é a consulta de logradouros através do site dos Correios. Acho que você já deve ter conhecido algum sistema onde o usuário digita o CEP do cliente e todos os dados do endereço são automaticamente preenchidos. Pois então, no momento que o usuário digita o CEP, o sistema faz uma comunicação com o site dos Correios através de um WebService, informando apenas o CEP dentro de um arquivo XML.
A empresa que mantém a funcionalidade do WebService da Prefeitura de Ribeirão Preto é a GINFES, que também atua em outros municípios.
WebService no Delphi
Para consumir um WebService pelo Delphi, o primeiro passo é obter o endereço WSDL, fornecido pela própria empresa que mantém o WebService ativo. O Delphi, desde a versão 7, dispõe de uma ferramenta nativa para importação de endereços WSDL, chamado WSDL Importer:
Essa ferramenta trata de interpretar o endereço WSDL (ou arquivo WSDL, caso seja baixado para o computador), e criar uma unit com o cabeçalho das funções disponibilizadas pelo WebService, prontas para serem chamadas. O WebService da GINFES, por exemplo, fornece quatro funções: envio de RPS, consulta de lote, consulta de NFS-e e cancelamento de NFS-e. Que bom, já veio tudo pronto! Então, só preciso chamar a função e passar os parâmetros necessários! Espere aí… eu disse “parâmetros”?
Sim. As funções do WebService exigem que um arquivo XML seja obrigatoriamente passado como parâmetro, obedecendo uma estrutura pré-definida pelos desenvolvedores do WebService. Como já sabemos, um arquivo XML consiste em uma hierarquia de tags (que lembram HTML) para armazenar valores.
A GINFES disponibiliza alguns arquivos conhecidos como XML Schema (com extensão XSD) para definição de regras de validação, ou seja, o desenvolvedor deve seguir essas regras para que o WebService receba e processe o arquivo XML corretamente. Após aplicar essas regras, é possível validar a estrutura final do arquivo XML pelo site do W3C.
Exemplo de um arquivo XSD
Bom, agora nós temos o endereço do WebService e a forma como o arquivo XML deve ser criado, então já podemos utilizar as funções, certo? Ainda não.
Certificado Digital
Como se trata de uma operação fiscal, é necessário que o usuário tenha em mãos um Certificado Digital – dispositivo ou arquivo que contém informações sobre entidade emissora (como se fosse o CPF de uma Pessoa Física) – no qual se divide em dois padrões:
- A1: arquivo de computador
- A3: dispositivo portátil (cartão ou token USB)
Certificado Digital do tipo A3
Apesar da segurança em transferir o arquivo utilizando um Certificado Digital, o WebService ainda exige que o arquivo XML seja digitalmente assinado. Uma Assinatura Digital, em breves palavras, trata-se de uma garantia de que a empresa (emissora do arquivo) é autêntica e que o arquivo gerado é válido. Para ficar mais fácil de entender, pense em um contrato qualquer que exija a assinatura do contratante. Sem a assinatura o contrato não tem validade, correto? Da mesma forma, se o arquivo XML não for assinado, também não terá validade e não poderá ser processado.
DLL da FlexDocs
Eis que esse foi um dos meus grandes desafios: descobrir como assinar um arquivo pelo Delphi. Passei horas ligando para outros profissionais e tentando descobrir algo na internet, até que finalmente encontrei um site que fazia referência a uma empresa especializada em documentos eletrônicos: A FlexDocs. Após vários contatos, a empresa me disponibilizou uma DLL com uma série de funções, entre elas a geração da Assinatura Digital.
Para utilizar essa DLL no Delphi, primeiramente é preciso importá-la através do menu Component > Import Component. Ao abrir a janela de importação, deve-se selecionar opção Import a Type Library e clicar em Next. A próxima tela exibe todas as bibliotecas já registradas no Delphi. Para registrar uma nova biblioteca, clique em Add e carregue a DLL. Seguindo estes passos finalmente consegui criar uma unit com as funções da DLL para gerar a assinatura digital no arquivo.
1 2 3 4 5 |
Nome := ''; Mensagem := ''; NFSE_Util := NFSe_Util_TLB.CoUtil.Create; Retorno := NFSE_Util.PegaNomeCertificado(Nome, Mensagem); Assinatura := NFSE_Util.Assinar(XML_Envio, '', '', Nome, i, Mensagem); |
Troubleshooting
O próximo passo era começar a realizar os testes.
Como tudo na informática não funciona da primeira vez, no meu caso não foi diferente, haha. Recebi diversas mensagens acusando erros na estrutura do arquivo (o famoso código E160) e outros erros relacionados à validação dos campos, como valores de impostos, descontos e caracteres especiais na descrição do item. O tamanho do campo também é uma restrição do WebService, e foi um dos problemas que me arrancou os cabelos até descobrir que o endereço do tomador estava com dois caracteres excedidos no tamanho.
Ao realizar os testes, me deparei com mais um imprevisto: o arquivo XML era enviado ao WebService e permanecia em uma fila de espera por aproximadamente 20 segundos até que fosse processado. A solução foi programar o aplicativo para aguardar este tempo e realizar uma consulta do lote enviado. Dessa forma, o aplicativo poderia obter o número da NFS-e gerada automaticamente, ótimo! O problema é que em horários de pico este tempo é variável, dependendo da quantidade de arquivos na fila a serem processados. Quando isso ocorria, eu recebia o código E4 indicando que o RPS (arquivo) não foi processado. Portanto, tive que pensar em outra solução.
Logo, ao invés de aguardar apenas 20 segundos, decidi mover a linha de consulta do lote para dentro de um laço de repetição. Se o aplicativo recebesse o código E4, a consulta era feita novamente, caso contrário o arquivo foi processado com sucesso. Apesar de parecer simples, devo assumir que deu um trabalhão, haha.
Resultado
Infelizmente me desliguei da empresa, mas o aplicativo ainda continua sendo utilizado. Desenvolver este aplicativo foi uma grande experiência, embora eu acredite que muitos também já passaram por isso, haha. Aproveitando este artigo, gostaria de agradecer ao Elton Welsch do suporte da GINFES por atender minhas inúmeras ligações, a empresa FlexDocs pela atenção e pela disponibilização da DLL, e também a Maria Rita, Product Owner que me guiou no desenvolvimento deste aplicativo.
Bom, e no fim das contas, o resultado foi este:
Ainda está encontrando dificuldades sobre este assunto? Confiira o FAQ do WebService da GINFES aqui no blog.
Abraços e até a próxima!
Cara que experiência hein?
Abraço.
Não é querendo fazer jabá não mas tem uma empresa de Maringá-PR, a qual tive o prazer de trabalhar, que desenvolve um componente de emissão de NFS-e e já tem mais de 50 cidades homologadas.
Boa tarde. Gostaria de saber se vc ja implementou em delphi os webservices da SMARAPD. Estou com dificuldades de consumir eles.
Olá, Edvandro!
Trabalhei na SMARAPD em 2012 e desenvolvi um consumidor do WebService da GINFES de Ribeirão Preto para envio de Notas Fiscais de Serviço Eletrônicas. É sobre este WebService que você se refere?
Abraço!
boa tarde.
a SMARAPD está com webservice prórprio. Não estou conseguindo consumir ele.
Desenvolvo em Delphi 2010
Não sabia que a SMARAPD desenvolvedu um WebService próprio. Vou entrar em contato com você, ok?
Boa tarde,
estou tentando consumir o webService da empresa WebISS via delphi xe2, quando envio lote juntamente com o RPS, retorna a seguinte informação: É necessário um certificado para concluir a autenticação do cliente.
O RPS está assinado por um certificado e não estou conseguindo entender o motivo deste erro.
Olá, Carlos, tudo bem?
Infelizmente só trabalhei com o WebService da GINFES. Não tenho conhecimento das regras e estruturas da WebISS.
Mesmo assim, eu sugiro que você entre em contato com a WebISS informando o erro, solicitando um suporte. Foi assim que eu consegui desvendar vários detalhes da GINFES.
Abraço!
André, parabéns pelos seus posts.
Estou com um problema na passagem de parâmetros para consumir um WebService, gostaria de pudesse me ajudar. É o seguinte, os parâmetros mesmo sendo do mesmo tipo, não roda e informa tipos incompatíveis.
Agradeço a atenção.
METODO DO WSDL
RETORNO DO WSD
ERRO AO EXECUTAR
Olá, Claudiney, tudo bem?
Vou entrar em contato para pedir mais detalhes do erro. Abraço!
André,bom dia.
Como fazer para consumir web service com delphi 2010 com autenticação,não encontro nenhum exemplo de codificação no
delphi 2010,para o xml ficar com a forma abaixo,
1560343423
22f6cf372dhfrdeheee61bfd98f0f1
como faço para declarar as tag.
Agradeço a atenção.
Olá, Jorge, boa noite.
Normalmente, cada WebService tem um tipo de autenticação. Você provavelmente irá encontrar os procedimentos de autenticação no manual de integração ou documentação do WebService, como, por exemplo, o nome das tags, tipos de dados, tamanhos, etc.
Abraço!