Migrando da versão 2018/01 para 2019/01

Na versão 2019/01 da CTeLibrary foram feitas alterações para suportar as mudanças do MOC (Manual de Orientação do Contribuinte) versão 3.00a.

Uma das principais novidades trazidas neste MOC foi a introdução do serviço síncrono de autorização do CT-e.

Em virtude desta grande novidade, a função CTeEnviar precisou ser alterada internamente para suportar ambos os modos de envio.

O desenvolvedor precisará revisar seu código fonte para tratar adequadamente a chamada e retorno desta função.

Destacaremos aqui as mudanças necessárias.

Implementado o QRCode

A partir de 07/10/2019, passa a ser obrigatório o preenchimento da tag qrCodCTe referente ao QRCode (vide schema abaixo).

qrCodCte

Na CTeLibrary, esta tag encontra-se na estrutura tCTe.sQrcode.

Por motivos de entendimento vamos dividir esta tag em 3 partes distintas, sendo:

  • URL para acessar o CT-e, seguido do caractere “?”. As url’s podem ser consultadas no link https://dfe-portal.svrs.rs.gov.br/Cte/Servicos.
  • Chave de acesso do CT-e precedida da string “chCTe=”. A chave de acesso pode ser gerada utilizando a função CTeMontaChaveAcesso.
  • Identificação do ambiente que está sendo usado (1 – Produção; 2 – Homologação), precedido da string “&tpAmb=”.

Concatenado essas partes, teremos uma string parecida com a seguinte:
http://dfe-portal.svrs.rs.gov.br/cte/QRCode?chCTe=43181203527568020153570010002211211062211212&tpAmb=1

Sugerimos aos desenvolvedores que controlem a geração do código numérico que compõe a chave de acesso (icCT) ou, assim que gerar pela primeira vez a chave do CT-e, extraia a parte referente ao código randômico e armazene para, caso seja necessário gerar novamente a chave de acesso, seja possível informar o parâmetro {icCT}.

Caso seja necessário gerar novamente a chave e o parâmetro {icCT} não for informado, um novo icCT randômico será gerada para montar a chave e, eventualmente ocasionará divergência entre a chave informada na tag qrCodCTe e a chave utilizada no CT-e (tag cCT do nó ide).

Mudança na chamada da função CTeEnviar

Foram adicionados dois novos parâmetros que são:

  • &sRetdhProtocolo é uma variável do tipo String que precisa ser passada por referência. Se o envio foi no modo síncrono e o CT-e foi recepcionado com sucesso, este parâmetro retornará a data e hora da autorização de uso do CT-e.
  • bAssincrono é uma variável do tipo boolean e seu uso é opcional. Passando True, o envio será feito no modo assíncrono. Passando False ou não passando o parâmetro, a função fará o envio no modo síncrono e, caso a SEFAZ que receber a solicitação não suporte o modo síncrono, será reenviado em modo assíncrono. Este parâmetro é particularmente útil, se o desenvolvedor sabe que a UF na qual está trabalhando ainda não aceita o modo síncrono. Nesta situação, informar o valor False fará com que a função de envio retorne mais rapidamente o resultado, pois não fará a tentativa de envio síncrono.

O parâmetro sRetdhProcolo é obrigatório. Portanto, a primeira alteração que o desenvolvedor necessariamente precisa fazer em seu código, é acrecentar este parâmetro em todos os locais do código em que esteja chamando a função CTeEnviar. Assim, se sua linha de chamada era assim:

Move (CTeEnviar(sArq,sSgWS,&sNrRecibo,"","","","","",&sResult,False,&iCdRet)) to bOk

Precisará ser ajustada para:

Move (CTeEnviar(sArq,sSgWS,&sNrRecibo,"","","","","",&sResult,False,&iCdRet,&sRetdhProt)) to bOk

Para otimizar a execução da função CTeEnviar, você deve informar True para o novo parâmetro bAssincrono, se o WS da UF não estiver operando em modo síncrono. Se o seu sistema atende clientes de diferentes UF’s, o ideal seria você ter a informação do envio síncrono/assíncrono em um parâmetro do seu sistema (global ou por UF), e informar o valor adequado na chamada da função. No exemplo abaixo, o envio será feito de forma assíncrona, pois passamos True para o novo parâmetro:

Move (CTeEnviar(sArq,sSgWS,&sNrRecibo,"","","","","",&sResult,False,&iCdRet,&sRetdhProt,True)) to bOk

Mudança no tratamento do retorno da função CTeEnviar

A função CTeEnviar continua retornando True se o envio for bem sucedido.

Porém, o envio bem sucedido pode ser síncrono ou assícrono. Se o envio foi assíncrono, o desenvolvedor precisará indicar em seu registro que a situação é "enviado" e guardar o número do recibo para chamar posteriormente a função CTeBuscar. Se o envio foi síncrono, então precisará alterar a situação para "autorizado".

Um retorno False, indicará que o envio falhou completamente ou então foi bem sucedido, mas o retorno foi uma rejeição ou denegação. Neste caso, o desenvolvedor precisa verificar se o envio foi uma rejeição/denegação síncrona ou um erro de envio e alterar a situação do seu registro adequadamente.

Um exemplo completo do tratamento adequado do retorno pode ser visto dentro da função CTeEnviarXML do arquivo cCteDataDictionary.dd da Workspace de exemplo.