Ir para conteúdo
  • Cadastre-se

dev botao

Provedor CONAM implementado no Trunk2


Edson.pol
Ver Solução Respondido por Italo Giurizzato Junior,
  • Este tópico foi criado há 3035 dias atrás.
  • Talvez seja melhor você criar um NOVO TÓPICO do que postar uma resposta aqui.

Recommended Posts

Boa noite.

Fiz diversas alterações para incluir o provedor CONAM no trunk2.

O envio de RPS, impressão e cancelamento estão funcionando.

Segue um breve resumo:

 

Cidades.INI - Alteração:

[3525300]
Nome=Jau
UF=SP
Provedor=CONAM


Novo arquivo INI:
CONAM.INI


Unit nova: 
\ACBr\Fontes\ACBrDFe\ACBrNFSe\PCNNFSe\pnfsNFSeW_CONAM.pas


Units alteradas para tratar os dados do provedor CONAM:
\ACBr\Fontes\PCNComum\pcnConversao.pas
\ACBr\Fontes\PCNComum\pcnGerador.pas
\ACBr\Fontes\PCNComum\pcnLeitor.pas
\ACBr\Fontes\PCNComum\pcnAuxiliar.pas
\ACBr\Fontes\ACBrComun\ACBrUtil.pas
\ACBr\Fontes\ACBrDFe\ACBrDFeWebService.pas
\ACBr\Fontes\ACBrDFe\ACBrDFeUtil.pas
\ACBr\Fontes\ACBrDFe\ACBrNFSe\ACBrNFSe.pas
\ACBr\Fontes\ACBrDFe\ACBrNFSe\ACBrNFSeConfiguracoes.pas
\ACBr\Fontes\ACBrDFe\ACBrNFSe\ACBrNFSeNotasFiscais.pas
\ACBr\Fontes\ACBrDFe\ACBrNFSe\ACBrNFSeWebServices.pas
\ACBr\Fontes\ACBrDFe\ACBrNFSe\PCNNFSe\pnfsEnvLoteRpsResposta.pas
\ACBr\Fontes\ACBrDFe\ACBrNFSe\PCNNFSe\pnfsConversao.pas
\ACBr\Fontes\ACBrDFe\ACBrNFSe\PCNNFSe\pnfsNFSeW.pas
\ACBr\Fontes\ACBrCapicom\ACBrCapicomACBrHTTPReqResp.pas


--------------------------------------
\ACBr\Fontes\ACBrCapicom\ACBrCapicomACBrHTTPReqResp.pas
- Incluido: function IgnoreCerticateErrors para ignorar erros de certificado em provedor que não usa certificado, como o caso do CONAM
--------------------------------------
\ACBr\Fontes\PCNComum\pclLeitor.pas
- function TLeitor.rCampo
- Alterado para suportar datas no formato dd/mm/aaa ou datas inválidas

    tcDat     : begin
                  if length(ConteudoTag)>0 then
                      if Pos('/',ConteudoTag)=1 then // Data está errada
                          result:=0
                      else if Pos('/',ConteudoTag)=3 then // Data está no formato dd/mm/aaaa
                          result := EncodeDate(StrToInt(copy(ConteudoTag, 07, 4)), StrToInt(copy(ConteudoTag, 04, 2)), StrToInt(copy(ConteudoTag, 01, 2)))
                      else // Data está no formato aaaa/mm/dd
                          result := EncodeDate(StrToInt(copy(ConteudoTag, 01, 4)), StrToInt(copy(ConteudoTag, 06, 2)), StrToInt(copy(ConteudoTag, 09, 2)))
                  else
                      result:=0;
                  end;

 

- Em anexo, units alteradas.

 

[]´s

Edson.

 

 

Units provedor CONAM.rar

Link para o comentário
Compartilhar em outros sites

Boa noite Italo.

Estou anexando o único manual que recebi do suporte (.PDF) e um arquivo xml que foi gerado por um erro no site, mas serve pra ver a estrutura.

Um ponto que percebi hoje é que enviando o RPS no Delphi, processando passo a passo com  F8, da tudo certo, o RPS é recebido, gera o protocolo, consulta o protocolo e carrega a nota para impressão.

Se executo no aplicativo, fora do Delphi, ao enviar um RPS, dá msg de arquivo aceito, "em processamento".

Como está configurado para consultar o lote após o envio, achei que fosse por causa do nr de tentativas e intervalo entre tentativas, por isto criei o método

FConsLote.Executar, para ficar igual ao TNFSeConsultarSituacaoLoteRPS.Executar, mas não sei se fiz da forma correta, porque não resolveu.

Vou continuar tentando pra ver se entendo a causa disto.

[]´s

Edson.

 

webservicenfe2.pdf

aws_nfe.aspx.xml

Link para o comentário
Compartilhar em outros sites

  • Consultores

Boa noite Edson,

Criar o executar no Consular Lote da mesma forma que o Consultar a Situação esta errado, pois gera um efeito colateral nos demais provedores.

Já fiz alguns ajustes e amanhã vou disponibilizar para que você faças novos testes.

Consultor SAC ACBr

Italo Giurizzato Junior
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr

Analista de Sistemas / Araraquara-SP

Araraquara - A era dos Trólebus

Link para o comentário
Compartilhar em outros sites

  • 2 semanas depois ...

Boa noite Italo.

Você conseguiu analisar as units do provedor CONAM do primeiro post ?

Atualizei o ACBr ontem e parou de funcionar o envio.

Fiz um "debug" geral, e vi que faltam algumas rotinas, porque o CONAM não usa certificado, mas usa SSL.

Vou postar aqui um resumo das units que alterei depois que fiz o update pelo svn, para que seja possível "consumir" o web-service deles.
(e para facilitar um pouco o seu trabalho com o "merge")

 

\ACBr\Fontes\ACBrDFe\ACBrDFeCapicom.pas
    - na procedure TDFeCapicom.CarregarCertificado, ignorar se provedor não utilizar certificado

\ACBr\Fontes\PCNComum\pcnLeitor.pas
    - na function TLeitor.rCampo, adicionado suporte a data e data/hora fora de padrão

\ACBr\Fontes\ACBrCapicom\ACBrHTTPReqResp.pas
    - na procedure TACBrHTTPReqResp.Execute, alteração para ignorar certificado
    - incluída a IgnoreCerticateErrors, para ignorar o erro ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED

\ACBr\Fontes\ACBrDFe\ACBrNFSe\ACBrNFSeWebServices.pas
    - procedure TNFSeWebService.InicializarServico, setar UseCertificate=False para o CONAM
        (Talvez um boa ideia seja criar mais um campo no arquivo INI, tipo UsaCertificado=False)
 

Units alteradas para Gerar/Ler XMLs no padrao CONAM:

    \ACBr\Fontes\ACBrDFe\ACBrNFSe\PCNNFSe
    pnfsConversao.pas
    pnfsNFSeG.pas
    pnfsNFSeR.pas
    pnfsConsSitLoteRpsResposta.pas
    pnfsLerListaNFSe.pas


Na impressão dos ítens da NFSe, para funcionar corretamente a quebra de linha na impressão, alterei:
\ACBr\Fontes\ACBrDFe\ACBrNFSe\DANFSE\Fortes\ACBrNFSeDANFSeRLClass.pas
    - procedure TACBrNFSeDANFSeRL.ImprimirDANFSe:
de: 
frlDANFSeRLRetrato.QuebradeLinha(TACBrNFSe(ACBrNFSe).Configuracoes.WebServices.QuebradeLinha);

para: 
frlDANFSeRLRetrato.QuebradeLinha(TACBrNFSe(ACBrNFSe).Configuracoes.Geral.ConfigGeral.QuebradeLinha);

assim a quebra de linha vem do arquivo "PROVEDOR".INI

e também o arquivo CONAM.INI, com alguns ajustes.

 

-- Anexo arquivo com as units alteradas.


[]´s
Edson Polonio.

ACBrNFSe_CONAM 01_03_2016.rar

Link para o comentário
Compartilhar em outros sites

  • Consultores

Bom dia Edson,

Vou analisar essas alterações, eu não gosto muito de fazer alterações nas Units do ACBrDFe pois podem gerar efeitos colaterais nos demais componentes.

Só altero essas Units quando tenho a certeza que nenhum problema vai ocorrer.

Consultor SAC ACBr

Italo Giurizzato Junior
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr

Analista de Sistemas / Araraquara-SP

Araraquara - A era dos Trólebus

Link para o comentário
Compartilhar em outros sites

Bom dia Italo.

Testei agora com emissão de NFe com certificado A3 e NFSe sem certificado (em produção), e deu tudo certo.

Acho que a alteração não afetará o funcionamento em outras situações. 

O principal problema era com a " ACBrHTTPReqResp.pas ", que dava erro de certificado, mesmo quando o nr de séria estava em branco. Depois que acrescentei a função "IgnoreCerticateErrors", deu tudo certo (ela só entrará em ação se ocorrer o erro: ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED)

[]´s

Edson.

Link para o comentário
Compartilhar em outros sites

Em 02/03/2016 at 10:13, Edson.pol disse:

O principal problema era com a " ACBrHTTPReqResp.pas

italo,

Existe algo oficial no ACBrNFSe para desabilitar totalmente o uso de certificados digitais?

No método TNFSeWebService.InicializarServico, verificando as linhas abaixo:

FPDFeOwner.SSL.UseCertificate := FPConfiguracoesNFSe.Geral.ConfigGeral.UseSSL;
FPDFeOwner.SSL.UseSSL := FPConfiguracoesNFSe.Geral.ConfigGeral.UseSSL;

As duas propriedades (UseCertificate e UseSSL) estão setadas como False, mas mesmo assim a exception abaixo, no método TDFeCapicom.CarregarCertificado, está dendo disparada:

raise EACBrDFeException.Create('Número de Série do Certificado Digital não especificado !');

Estou implementando para uma cidade onde a utilização de certificados não é necessária. Não estou informando nem o número de série, nem o caminho do certificado digital no exemplo existente no componente. Tentei outras formas sem alterar o código que trata dos certificados, mas sem sucesso.

 

Link para o comentário
Compartilhar em outros sites

Boa tarde Marcos.

Uma das alterações / sugestões que fiz para o provedor CONAM:

"\ACBr\Fontes\ACBrDFe\ACBrNFSe\ACBrNFSeWebServices.pas
    - procedure TNFSeWebService.InicializarServico, setar UseCertificate=False para o CONAM
        (Talvez um boa ideia seja criar mais um campo no arquivo INI, tipo UsaCertificado=False)"

Se puder ajudar nos testes, as alterações estão no link:
http://www.projetoacbr.com.br/forum/applications/core/interface/file/attachment.php?id=22586

 
A procedure alterada ficou assim:

procedure TNFSeWebService.InicializarServico;
begin
  { Sobrescrever apenas se necessário }
  inherited InicializarServico;

  FProvedor := FPConfiguracoesNFSe.Geral.Provedor;

  if FPConfiguracoesNFSe.Geral.ConfigGeral.VersaoSoap = '1.2' then
    FPMimeType := 'application/soap+xml'
  else
    FPMimeType := 'text/xml';

  FPDFeOwner.SSL.UseCertificate := FPConfiguracoesNFSe.Geral.ConfigGeral.UseSSL;
  FPDFeOwner.SSL.UseSSL := FPConfiguracoesNFSe.Geral.ConfigGeral.UseSSL;

  if FProvedor=proCONAM then //Provedor CONAM não requer certificado, mas usa SSL (https)
      FPDFeOwner.SSL.UseCertificate := False;

  TACBrNFSe(FPDFeOwner).SetStatus(FPStatus);
end;
 

[]´s

Edson.

Link para o comentário
Compartilhar em outros sites

Boa tarde Italo.

Atualizei agora via svn, mas percebi que você não "subiu" algumas units.

- Units alteradas para Gerar/Ler XMLs no padrao CONAM:

\ACBr\Fontes\ACBrDFe\ACBrNFSe\PCNNFSe
    pnfsConversao.pas
    pnfsNFSeG.pas
    pnfsNFSeR.pas
    pnfsConsSitLoteRpsResposta.pas
    pnfsLerListaNFSe.pas

\ACBr\Fontes\ACBrDFe\ACBrDFeCapicom.pas
    - na procedure TDFeCapicom.CarregarCertificado, ignorar se provedor não utilizar certificado

\ACBr\Fontes\PCNComum\pcnLeitor.pas
    - na function TLeitor.rCampo, adicionado suporte a data e data/hora fora de padrão

\ACBr\Fontes\ACBrCapicom\ACBrHTTPReqResp.pas
    - na procedure TACBrHTTPReqResp.Execute, alteração para ignorar certificado
    - incluída a IgnoreCerticateErrors, para ignorar o erro ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED

 

\ACBr\Fontes\ACBrDFe\ACBrNFSe\ACBrNFSeWebServices.pas
    - procedure TNFSeWebService.InicializarServico, setar UseCertificate=False para o CONAM
        (Talvez um boa ideia seja criar mais um campo no arquivo INI, tipo UsaCertificado=False)
==>> Esta vc já resolveu !


Na impressão dos ítens da NFSe, para funcionar corretamente a quebra de linha na impressão, alterei:
\ACBr\Fontes\ACBrDFe\ACBrNFSe\DANFSE\Fortes\ACBrNFSeDANFSeRLClass.pas
    - procedure TACBrNFSeDANFSeRL.ImprimirDANFSe:
de: 
frlDANFSeRLRetrato.QuebradeLinha(TACBrNFSe(ACBrNFSe).Configuracoes.WebServices.QuebradeLinha);

para: 
frlDANFSeRLRetrato.QuebradeLinha(TACBrNFSe(ACBrNFSe).Configuracoes.Geral.ConfigGeral.QuebradeLinha);

assim a quebra de linha vem do arquivo "PROVEDOR".INI

-- Pra você ficar mais tranquilo sobre as alterações, testei emitindo 20 NFSe em produção, e em seguida emiti algumas NFe´s de venda, pra garantir que a alteração na ACBrDFeCapicom / ACBrHTTPRqResp não afetem os outros documentos.

 

As units alteradas estão no post de cima:  http://www.projetoacbr.com.br/forum/applications/core/interface/file/attachment.php?id=22586

[]´s

Edson.

 

Link para o comentário
Compartilhar em outros sites

  • Consultores

Boa tarde Edson,

Eu acredito que com a inclusão da propriedade UseCertificado muita coisa será sanada para esse provedor e para outros que não utilizam o certificado digital para nada.

Eu preciso que sejam feito testes com os fontes que estão no repositório.

Consultor SAC ACBr

Italo Giurizzato Junior
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr

Analista de Sistemas / Araraquara-SP

Araraquara - A era dos Trólebus

Link para o comentário
Compartilhar em outros sites

Boa noite Italo!

Fiz um backup da minha pasta ACBr, e fiz vários testes com as units baixadas hoje:

Vamos lá:

Teste utilizando o demo do ACBrNFSe.

"Gerar e Enviar Lote RPS"


Teste 1:
Erro no retorno: Error reading ws_nfe.PROCESSARPS

--> Resolvido alterando o CONAM.INI

[Recepcionar]
IncluiEncodingCab=0
IncluiEncodingDados=0
Texto1=<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
Texto2=<SOAP-ENV:Body>
Texto3=%DadosMsg%
Texto4=</SOAP-ENV:Body>
Texto5=</SOAP-ENV:Envelope>

 

Para o tópico não ficar muito extenso, vou quebrar em alguns posts...

 

Teste 2
Erro: O Sistema não pode encontrar o caminho especificado.

O erro ocorre na procedure TDFeCapicom.CarregarCertificado;

--> Resolvido alterando a procedure TDFeCapicom.CarregarCertificado; incluindo logo no início: 
begin

  // Provedor não usa certificado ? Assumir que certificado foi lido.
  if FpDFeSSL.NumeroSerie='' then
  begin
      FpCertificadoLido := True;
      exit;
  end;
  
  // Certificado já foi carregado ?
  if (FCertificado <> nil) and (FNumCertCarregado = FpDFeSSL.NumeroSerie) then
  begin
    FpCertificadoLido := True;
    exit;
  end;
 

-----------------------------------------------------------------------------

Teste 3
Erro: Mesmo setando UseCertificado=0 no arquivo INI, a tela se seleção de certificados é aberta, forçando selecionar um certificado.

Em ACBrHTTPReqResp, no trecho:

  if ((ShowCertStore) or ((FCertSerialNumber = '') and (FCertificate = nil))) then
  begin
  end;

Deve ser alterado para:

  if (FUseCertificate) then
      if ((ShowCertStore) or ((FCertSerialNumber = '') and (FCertificate = nil))) then
      begin
      end;


e no trecho:

  CertContext.Get_CertContext(HCertContext);
  pSession := InternetOpen(PChar('Borland SOAP 1.2'), AccessType, PChar(pProxy), nil, 0);

alterar para:

  if (FUseCertificate) then
      CertContext.Get_CertContext(HCertContext);
  pSession := InternetOpen(PChar('Borland SOAP 1.2'), AccessType, PChar(pProxy), nil, 0);

-----------------------------------------------------------------------------

Teste 4:
Erro Interno: 12044
Erro HTTP: 0
Access violation at address 00562e12 in module 'Demo_ACBrNFSe.exe'


--> Resolvido incluindo a
    function IgnoreCerticateErrors(oRequestHandle:HINTERNET; var aErrorMsg: ansistring): Boolean;

    e alterando o processo "HttpSendRequest"

--> As alterações estão com marcação "//< * >//"


procedure TACBrHTTPReqResp.Execute(Resp: TStream);
const
  INTERNET_OPTION_CLIENT_CERT_CONTEXT = 84;
var
  aBuffer: array[0..4096] of AnsiChar;
  BytesRead: cardinal;
  pSession: HINTERNET;
  pConnection: HINTERNET;
  pRequest: HINTERNET;
  flags: longword;

  Store: IStore;
  Certs: ICertificates;
  Cert: ICertificate2;
  Cert2: ICertificate2;
  CertContext: ICertContext;

  Ok: Boolean;
  i, AccessType, HCertContext: Integer;
  ANone, AHost, AProt, APort, APath, pProxy, Header, Msg: String;
begin

  if (FUseCertificate) then
    FUseSSL := True;

  AProt := '';
  APort := '';
  APath := '';

  ParseURL(FUrl, AProt, ANone, ANone, AHost, APort, APath, ANone);

  if (FUseCertificate) then //< * >//
      if ((ShowCertStore) or ((FCertSerialNumber = '') and (FCertificate = nil))) then
      begin
        FCertSerialNumber := OpenCertStore;
        if FCertSerialNumber <> '' then
          FCertificate := nil;
      end;

  if FCertSerialNumber <> '' then
  begin
    Store := CoStore.Create;
    Store.Open(CAPICOM_CURRENT_USER_STORE, FCertStoreName, CAPICOM_STORE_OPEN_READ_ONLY);

    Certs := Store.Certificates as ICertificates2;

    if Certs.Count > 0 then
    begin
      for i := 1 to Certs.Count do
      begin
        Cert2 := IInterface(Certs.Item) as ICertificate2;
        if Cert2.SerialNumber = FCertSerialNumber then
        begin
          Cert := Cert2;
          break;
        end;
      end;

      CertContext := Cert as ICertContext;
    end;
  end
  else
  begin
    CertContext := FCertificate as ICertContext;
  end;

  if FProxyHost <> '' then
  begin
    AccessType := INTERNET_OPEN_TYPE_PROXY;
    if (FProxyPort <> '') and (FProxyPort <> '0') then
      pProxy := FProxyHost + ':' + FProxyPort
    else
      pProxy := FProxyHost;
  end
  else
    AccessType := INTERNET_OPEN_TYPE_PRECONFIG;

  //DEBUG
  //WriteToTXT('c:\temp\httpreqresp.log', FormatDateTime('hh:nn:ss:zzz', Now)+ ' - Abrindo sessão');

  if (FUseCertificate) then
      CertContext.Get_CertContext(HCertContext);
  pSession := InternetOpen(PChar('Borland SOAP 1.2'), AccessType, PChar(pProxy), nil, 0);

  try
    if not Assigned(pSession) then
      raise EACBrHTTPReqResp.Create('Erro: Internet Open or Proxy');

    //DEBUG
    //WriteToTXT('c:\temp\httpreqresp.log', FormatDateTime('hh:nn:ss:zzz', Now)+ ' - Ajustando TimeOut: '+IntToStr(FTimeOut));

    if not InternetSetOption(pSession, INTERNET_OPTION_CONNECT_TIMEOUT, @FTimeOut, SizeOf(FTimeOut)) then
      raise EACBrHTTPReqResp.Create('Erro ao definir TimeOut de Conexão');

    if not InternetSetOption(pSession, INTERNET_OPTION_SEND_TIMEOUT, @FTimeOut, SizeOf(FTimeOut)) then
      raise EACBrHTTPReqResp.Create('Erro ao definir TimeOut de Envio');

    if not InternetSetOption(pSession, INTERNET_OPTION_DATA_SEND_TIMEOUT, @FTimeOut, SizeOf(FTimeOut)) then
      raise EACBrHTTPReqResp.Create('Erro ao definir TimeOut de Envio');

    if not InternetSetOption(pSession, INTERNET_OPTION_RECEIVE_TIMEOUT, @FTimeOut, SizeOf(FTimeOut)) then
      raise EACBrHTTPReqResp.Create('Erro ao definir TimeOut de Recebimento');

    if not InternetSetOption(pSession, INTERNET_OPTION_DATA_RECEIVE_TIMEOUT, @FTimeOut, SizeOf(FTimeOut)) then
      raise EACBrHTTPReqResp.Create('Erro ao definir TimeOut de Recebimento');

    if APort = '' then
    begin
      if (FUseSSL) then
        APort := IntToStr(INTERNET_DEFAULT_HTTPS_PORT)
      else
        APort := IntToStr(INTERNET_DEFAULT_HTTP_PORT);
    end;

    //Debug, TimeOut Test
    //AHost := 'www.google.com';
    //port := 81;

    //DEBUG
    //WriteToTXT('c:\temp\httpreqresp.log', FormatDateTime('hh:nn:ss:zzz', Now)+ ' - Abrindo Conexão: '+AHost+':'+APort);

    pConnection := InternetConnect(pSession, PChar(AHost), StrToInt(APort),
      PChar(FProxyUser), PChar(FProxyPass), INTERNET_SERVICE_HTTP, 0, 0{cardinal(Self)});
    if not Assigned(pConnection) then
      raise EACBrHTTPReqResp.Create('Erro: Internet Connect or Host');

    try
      if (FUseSSL) then
      begin
        flags := INTERNET_FLAG_KEEP_CONNECTION or INTERNET_FLAG_NO_CACHE_WRITE;
        flags := flags or INTERNET_FLAG_SECURE;

        if (FUseCertificate) then
          flags := flags or (INTERNET_FLAG_IGNORE_CERT_CN_INVALID or
            INTERNET_FLAG_IGNORE_CERT_DATE_INVALID);
      end
      else
        flags := INTERNET_SERVICE_HTTP;

      //DEBUG
      //WriteToTXT('c:\temp\httpreqresp.log', FormatDateTime('hh:nn:ss:zzz', Now)+ ' - Fazendo POST: '+APath);

      pRequest := HttpOpenRequest(pConnection, PChar('POST'),
        PChar(APath), nil, nil, nil, flags, 0);

      if not Assigned(pRequest) then
        raise EACBrHTTPReqResp.Create('Erro: Open Request');

      UpdateErrorCodes(pRequest);

      try
        if ( (APort <> IntToStr(INTERNET_DEFAULT_HTTP_PORT)) and (UpperCase(AProt) = 'HTTP') ) or
           ( (APort <> IntToStr(INTERNET_DEFAULT_HTTPS_PORT)) and (UpperCase(AProt) = 'HTTPS') ) then
          AHost := AHost +':'+ APort;

        Header := 'Host: ' + AHost + sLineBreak +
                  'Content-Type: ' + FMimeType + '; charset='+FCharsets + SLineBreak +
                  'Accept-Charset: ' + FCharsets + SLineBreak +
                  'SOAPAction: "' + FSOAPAction + '"' +SLineBreak;

        if (FUseCertificate) then
          if not InternetSetOption(pRequest, INTERNET_OPTION_CLIENT_CERT_CONTEXT,
            Pointer(HCertContext), SizeOf(CERT_CONTEXT)) then
            raise EACBrHTTPReqResp.Create('Erro: Problema ao inserir o certificado');

        if trim(FProxyUser) <> '' then
          if not InternetSetOption(pRequest, INTERNET_OPTION_PROXY_USERNAME,
            PChar(FProxyUser), Length(FProxyUser)) then
            raise EACBrHTTPReqResp.Create('Erro: Proxy User');

        if trim(FProxyPass) <> '' then
          if not InternetSetOption(pRequest, INTERNET_OPTION_PROXY_PASSWORD,
            PChar(FProxyPass), Length(FProxyPass)) then
            raise EACBrHTTPReqResp.Create('Erro: Proxy Password');

        HttpAddRequestHeaders(pRequest, PChar(Header), Length(Header),
          HTTP_ADDREQ_FLAG_ADD);

        if FEncodeDataToUTF8 then
          FData := UTF8Encode(FData);

        //DEBUG
        //WriteToTXT('c:\temp\httpreqresp.log', FormatDateTime('hh:nn:ss:zzz', Now)+ ' - Enviando Dados: '+APath);
        //WriteToTXT('c:\temp\httpreqresp.log', FData);

        //< * >// INÍCIO...
        Ok := False;
        Resp.Size := 0;

        Ok := HttpSendRequest(pRequest, nil, 0, Pointer(FData), Length(FData));
        if Ok = False then
        begin
            flags := GetLastError;
            if (flags = ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED) then
            begin
              IgnoreCerticateErrors(pRequest, Msg);
              Ok := HttpSendRequest(pRequest, nil, 0, Pointer(FData), Length(FData))
            end;
        end;

        if Ok then
        begin
          BytesRead := 0;
          //DEBUG
          //WriteToTXT('c:\temp\httpreqresp.log', FormatDateTime('hh:nn:ss:zzz', Now)+ ' - Lendo Dados');

          while InternetReadFile(pRequest, @aBuffer, SizeOf(aBuffer), BytesRead) do
          begin
            //DEBUG
            //WriteToTXT('c:\temp\httpreqresp.log', FormatDateTime('hh:nn:ss:zzz', Now)+ ' - Bytes Lido: '+IntToStr(BytesRead));

            if (BytesRead = 0) then
              Break;

            Resp.Write(aBuffer, BytesRead);
          end;

          if Resp.Size > 0 then
          begin
            Resp.Position := 0;

            //DEBUG
            //WriteToTXT('c:\temp\httpreqresp.log', FormatDateTime('hh:nn:ss:zzz', Now)+ ' - Total Lido: '+IntToStr(Resp.Size));
            //Resp.Position := 0;
            //FData := ReadStrFromStream(Resp, Resp.Size);
            //Resp.Position := 0;
            //WriteToTXT('c:\temp\httpreqresp.log', FData);

            Ok := True;
          end;
        end;
        //< * >// FINAL...

        if not OK then
        begin
          UpdateErrorCodes(pRequest);

          //DEBUG
          //WriteToTXT('c:\temp\httpreqresp.log', FormatDateTime('hh:nn:ss:zzz', Now)+
          //   ' - Erro WinNetAPI: '+IntToStr(InternalErrorCode)+' HTTP: '+IntToStr(HTTPResultCode));

          raise EACBrHTTPReqResp.Create('Erro: Requisição não enviada.' +
            sLineBreak + IntToStr(InternalErrorCode) + ' - ' + GetWinInetError(InternalErrorCode));
        end;
      finally

        InternetCloseHandle(pRequest);
      end;
    finally
      InternetCloseHandle(pConnection);
    end;
  finally
    InternetCloseHandle(pSession);
    if HCertContext<>0 then  //< * >//
        CertContext.FreeContext(HCertContext);
  end;
end;

 

 

-----------------------------------------------------------------------------      

Teste 5

Aqui já ocorrem os erros "normais" de retorno do webservice.

<Messages>
<Message>
<Id>20</Id>
<Type>0</Type>
<Description>
Data de emissão (30/12/1899) do RPS deve pertencer ao intervalo de datas informado no registro 10. (Inicial: 07/03/2016 - Final: 07/03/2016)
</Description>
<LinErr>2</LinErr>
</Message>
<Message>
<Id>20</Id>
<Type>0</Type>
<Description>Campo nome do município do tomador obrigatório.</Description>
<LinErr>2</LinErr>
</Message>
</Messages>

--> Resolvido incuindo:
     DataEmissao := Now;
     DataEmissaoRps := Now;  //<*>//

     Tomador.Endereco.xMunicipio      := 'JAU';  //<*>**


----------------------------------------------------------------------------- 

Teste 6

Erro de número do RPS inválido...

<Messages>
<Message>
<Id>10</Id>
<Type>0</Type>
<Description>
-Número do RPS incorreto. Valor informado: 800, Valor esperado: 805
</Description>
<LinErr>0</LinErr>
</Message>
</Messages>

Resolvido --> Alterando o número para 805


----------------------------------------------------------------------------- 

Teste 7 
Codigo do erro: Arquivo Aceito
Mensagem: Arquivo Aceito. Protocolo em processamento. Consulte o protocolo para conferir o processamento

A Situação [Consultar Situação do Lote] não foi disponibilizada pelo provedor CONAM.


... Agora preciso "debugar" com calma... mas a pilha acabou. 
Amanhã de manhã eu continuo...

 

 

 

Anexando o CONAM.INI

e ACBrHTTPReqResp.pas

 

CONAM.INI

ACBrHTTPReqResp.pas

Editado por Edson.pol
Link para o comentário
Compartilhar em outros sites

  • Consultores

Bom dia Edson,

Lhe peço para que não post fragmentos longos de código ou de conteúdo de arquivos, o melhor é anexa-los.

Consultor SAC ACBr

Italo Giurizzato Junior
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr

Analista de Sistemas / Araraquara-SP

Araraquara - A era dos Trólebus

Link para o comentário
Compartilhar em outros sites

  • Fundadores

Não seria mais simples ajustar os Flags antes da abertura ?

por favor tente com a Unit em anexo

ACBrHTTPReqResp.pas

Consultor SAC ACBr

Daniel Simões de Almeida
O melhor TEF, é com o Projeto ACBr - Clique e Conheça
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Link para o comentário
Compartilhar em outros sites

Boa tarde Daniel.

De quais Flags está falando ?

Testei com a unit que você anexou, mas dá o erro da figura em anexo.

"É necessário um certificado para concluir a autenticação do cliente".

O erro é disparado porque a linha 

      if HttpSendRequest(pRequest, nil, 0, Pointer(FData), Length(FData)) then

resulta em False.

 

Na unit que postei, o primeiro HttpSendRequest também retorna False (por causa da "falta" do certificado), mas o IgnoreCertificateErros corrige o problema e chama novamente o HttpSendRequest, desta vez sem erro.

        Ok := HttpSendRequest(pRequest, nil, 0, Pointer(FData), Length(FData));
        if Ok = False then
        begin
            flags := GetLastError;
            if (flags = ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED) then
            begin
              IgnoreCerticateErrors(pRequest, Msg);
              Ok := HttpSendRequest(pRequest, nil, 0, Pointer(FData), Length(FData))
            end;
        end;

Já testei esta unit na emissão tanto de NFSe quanto de NFe, e não houve nenhum problema.

 

[]´s

Edson.

ErroNFSe.png

ACBrHTTPReqResp.pas

Link para o comentário
Compartilhar em outros sites

  • Fundadores

Por favor analise o código da Unit que anexei...

Porque precisamos tentar a conexão, se sabemos que ela dará erro ??

Minha implementação procura ajustar as mesmas configurações (flags) que vc está implementando na segunda tentativa... Porém antes da 1a tentativa...

A implementação da sua sugestão é sua ou você achou na Internet ? Se for a segunda opção, qual a origem ?

Consultor SAC ACBr

Daniel Simões de Almeida
O melhor TEF, é com o Projeto ACBr - Clique e Conheça
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Link para o comentário
Compartilhar em outros sites

Em 07/03/2016 at 14:40, assis_marcos disse:

Existe algo oficial no ACBrNFSe para desabilitar totalmente o uso de certificados digitais?

Pessoal,

Utilizei a unit ACBrHTTPReqResp.pas fornecida pelo Daniel e funcionou sem problemas, consegui emitir uma nota fiscal em um provedor que não exige certificado.

Tive que fazer apenas um alteração na unit  ACBrDFeCapicom.pas, no método TDFeCapicom.CarregarCertificado, incluindo o trecho abaixo:

if EstaVazio(FpDFeSSL.NumeroSerie) then
begin
   FpCertificadoLido := True;
   Exit;
end;

 

Retirei este código das alterações que o Edson postou. Sem este tratamento, a exceção raise EACBrDFeException.Create('Número de Série do Certificado Digital não especificado !')

Este é o melhor ponto para fazer esta verificação ou deve se feito em outro local?

A verificação correta é esta mesmo?

Link para o comentário
Compartilhar em outros sites

Boa tarde.

Marcos: Pra qual cidade você está testando ? o provedor é CONAM ? Homologação ou Produção ?

Daniel: Dentre as diversas alternativas que testei, essa que estou usando encontrei no "stack overflow"

http://stackoverflow.com/questions/9861309/wininet-ssl-client-authenticate-oddness

Pelo que percebi no seu código, os flags são setados antes do HttpSendRequest, e não sei porque, não fazem efeito.

Na outra forma, verificando se o erro do HttpSendRequest é "ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED" e refazendo o "InternetSetOption" após o erro, dá tudo certo.

[]´s

Edson.

Link para o comentário
Compartilhar em outros sites

16 horas atrás, assis_marcos disse:

Tive que fazer apenas um alteração na unit  ACBrDFeCapicom.pas, no método TDFeCapicom.CarregarCertificado, incluindo o trecho abaixo:

if EstaVazio(FpDFeSSL.NumeroSerie) then
begin
   FpCertificadoLido := True;
   Exit;
end;

Daniel/Italo,

O trecho de código acima será efetivado no repositório ou vocês pensam em algo diferente?

Link para o comentário
Compartilhar em outros sites

  • Fundadores

Enviei para o SVN modificações que devem corrigir o problema...

-- ACBrDFeSSL, ACBrDFeCapicom, ACBrDFeOpenSSL, ACBrHTTPReqResp --
[*] Ajustes para o correto funcionamento, quando a propriedade
    DFeSSL.UseCertificate = False          (por: DSA)

-- ACBrDFeCapicom --
[-] Correção no ajuste do Proxy, quando informando valores vazios   (por: DSA)

-- ACBrDFeOpenSSL --
[-] Correção de encoding nas mensagens de Erro de "VerificarAssinatura"  (por: DSA) 

Fiz um teste bem simples, usando uma consulta em um WebService do Correios.

procedure TForm1.Button7Click(Sender: TObject);
var
  Acao: String;
begin
  Acao := '<?xml version="1.0" encoding="UTF-8" standalone="no"?>'+
     '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" '+
     'xmlns:cli="http://cliente.bean.master.sigep.bsb.correios.com.br/"> '+
     ' <soapenv:Header/>'+
     ' <soapenv:Body>' +
     ' <cli:consultaCEP>' +
     ' <cep>18270-170</cep>' +
     ' </cli:consultaCEP>' +
     ' </soapenv:Body>' +
     ' </soapenv:Envelope>';

  ACBrNFe1.SSL.UseCertificate := False;
  ACBrNFe1.SSL.UseSSL := False;
  WBResposta.Text := ACBrNFe1.SSL.Enviar(Acao, 'https://apps.correios.com.br/SigepMasterJPA/AtendeClienteService/AtendeCliente?wsdl', '');
end;    

 

Consultor SAC ACBr

Daniel Simões de Almeida
O melhor TEF, é com o Projeto ACBr - Clique e Conheça
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Link para o comentário
Compartilhar em outros sites

  • 2 semanas depois ...

Olá Amigos,

Estou enviando os Arquivos Conan.ini e cidades.ini atualizados, pois o provedor conam recebe suas requisições de acordo com a cidade emitente conforme destaquei abaixo.

Também inclui no arquivo cidades.ini a cidade de Poá-SP e ajustei a cidade de Pirassununga que são atendidas pelo provedor conam.

[3525300]
Nome=Jau
UF=SP
Provedor=CONAM
NomeURL_H=sp.jahu
NomeURL_P=sp.jahu

 

[URL_P]
RecepcaoLoteRPS=https://nfe.etransparencia.com.br/%NomeURL_P%/webservice/aws_nfe.aspx?wsdl

[URL_H]
RecepcaoLoteRPS=https://nfehomologacao.etransparencia.com.br/%NomeURL_H%/webservice/aws_nfe.aspx?wsdl
 

Abraços,

Cidades.ini

CONAM.ini

André Medeiros

Link para o comentário
Compartilhar em outros sites

Olá Amigos

Estou enviando abaixo alguns ajustes que foram necessários para que fosse possível o consumo do WS Conam

1) Completei um pouco mais a classe TNFSews_CONAM, pode não ser a versão final, mas procurei ser o mais fiel ao manual do provedor.
2) Adicionei na classe TNFSe a propriedade DataOptanteSimplesNacional, pois se o emitente é é optante pelo simples está informação é obrigatória.
3) Deixei o método Gera_DadosMsgEnviarLote da classe TNFSeG um pouco mais limpo, deixando a responsabilidade maior para classe TNFSews_CONAM
4) Estou usando Lazarus 1.4.4 com FPC 2.6.4 em Linux CentOS 6 - 32 bits, foi necessário iniciar o projeto de demonstração da NFSe com a seguinte formatação
DefaultFormatSettings.DateSeparator := '/';
DefaultFormatSettings.DecimalSeparator:=',';

Não sei se isto é necessário em outros ambientes, por isso deixei a cargo do programador usar ou não a configuração em seu projeto. O Fato é que o provedor Conam, exige que a formatação das datas sejam dd/mm/yyyy e os numero sejam 0,00
5) Ainda no projeto de demonstração adicionei os seguinte items
DataEmissaoRps:=Now;
DataOptanteSimplesNacional:=Now-500; //se o emitente for optante pelo simples 
ValoresNfse.Aliquota:= 2;

Com estes ajustes já estamos recebendo o arquivo de retorno conforme anexo, porém percebi que ainda não temos o tratamento deste retorno.

Estarei focado nestes dias para finalizar este projeto e irei postando meus avanços.

Espero ter contribuído com estes ajustes,

Abraços 

pnfsNFSe.pas

pnfsNFSeW_CONAM.pas

pnfsNFSeG.pas

Frm_Demo_ACBrNFSe.pas

CB403127453BAB240988-rec.xml

André Medeiros

Link para o comentário
Compartilhar em outros sites

  • Este tópico foi criado há 3035 dias atrás.
  • Talvez seja melhor você criar um NOVO TÓPICO do que postar uma resposta aqui.

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar Agora
×
×
  • Criar Novo...

Informação Importante

Colocamos cookies em seu dispositivo para ajudar a tornar este site melhor. Você pode ajustar suas configurações de cookies, caso contrário, assumiremos que você está bem para continuar.

The popup will be closed in 10 segundos...