EFD-Reinf: What can be done to avoid certificate failure?

Asked

Viewed 577 times

1

I am working on sending information from EFD-Reinf and I am facing shipping problems.

Based on the code posted here to make the shipment, however always falls in the catch of WebException with the message below:

The SSL Connection could not be established, see Inner Exception. The remote Certificate is invalid According to the validation Procedure.

However, the certificate I am using is valid because it is not expired and the customer uses it to send information.

Below is the code used:

private string ExecuteTransmission(string filePath)
{
    X509Certificate2 digitalCertificate;
    XmlDocument xmlFile;
    XmlTextWriter xmlWriter;
    HttpWebRequest request;
    string certPath = "AQUI VAI O CAMINHO COMPLETO DO CERTIFICADO";
    string password = "SENHA DO CERTIFICADO";

    xmlFile = new XmlDocument();
    xmlFile.Load(filePath.Trim());
    xmlWriter = new XmlTextWriter(filePath, System.Text.Encoding.UTF8);
    xmlWriter.Formatting = Formatting.Indented;
    xmlFile.Save(xmlWriter);
    xmlWriter.Close();
    xmlWriter = null;

    request = (HttpWebRequest)WebRequest.Create(_urlToSend);
    request.Headers.Add("SOAPAction", _urlToSend);
    request.ContentType = "text/xml;charset=\"utf-8\"";
    request.Accept = "text/xml";
    request.Method = "POST";

    digitalCertificate = ReinfUtil.GetCertificate(certPath, password);

    DigitalcCertificateExtension.CheckValidate(digitalCertificate);

    if (digitalCertificate != null)
        request.ClientCertificates.Add(digitalCertificate);
    // if (this.TimeOutEmSegundos > 0)
    //     request.Timeout = this.TimeOutEmSegundos * 1000;
    try
    {
        using (Stream stream = request.GetRequestStream())
        {
            using (StreamWriter stmw = new StreamWriter(stream))
            {
                stmw.Write(xmlFile.InnerXml);
            }
        }
    }
    catch (Exception wex)
    {
        throw new Exception(wex.Message);
    }

    try
    {
        WebResponse webresponse = request.GetResponse();
        HttpWebResponse response = (HttpWebResponse)webresponse;
        //if(response.StatusCode == HttpStatusCode.OK)
        using (StreamReader responseReader = new StreamReader(response.GetResponseStream()))
        {
            string result = responseReader.ReadToEnd();
            return result;
        }
    }
    catch (WebException wex)
    {
        string subjacentMesssage = ReinfUtil.GetSubjacentMessage(wex);
        string msg = string.Format("{1}\r\n{0}\r\n Detalhes subjacentes: \r\n{2}",
            System.Environment.NewLine, wex.Message, subjacentMesssage);
        throw new BusinessException(msg);
        //  throw new Exception(wex.Message); 
    }
    catch
    {
        throw;
    }

}

EDITION

From what I see this message happens because the recipe address itself has an invalid certificate. I did not expect this to happen. I’ll take another look at their documentation and see if there’s anything to be done to overcome the problem if I won’t try to ignore the security exception to run the request anyway.

  • The code I based is available at :https://answall.com/questions/269338/problema-para-envio-sped-reinf-c?rq=1

2 answers

2


You have already identified part of the problem: The SERPRO certificate is not recognized as a reliable certificate. See that even accessing the service address by the browser you will be notified that the address is unsafe and will likely appear a red padlock next to the URL.

In order for the EFD-Reinf service certificate to be considered reliable, allowing it to be accessed also via code, you need to install 3 certificates made available by SERPRO, to complete the service certificate chain.

The 3 required certificates are available in the "Chain of Certificates issued on 02/06/2017", at the following address:

https://certificados.serpro.gov.br/serproacf/certificate-chain

But, below is the list with the installation order of the certificates, the direct links of each and where they should be installed:

  1. Brazilian Root Certification Authority v5 -> Should be installed in the CA repository (Certification Authorities) Root;
  2. Certification Authority SERPRO v4 -> Should be installed in the CA repository (Certification Authorities) Intermediaries;
  3. Certification Authority of SERPRO Final v5 -> Should be installed in the CA repository (Certification Authorities) Intermediaries.

I don’t know why they didn’t include those instructions in EFD-Reinf Developer’s Manual (version 1.04.00), but no eSocial Developer’s Manual (version 1.7), in the section "7.9. Digital certification", on page 115, they mention these steps, and on the eSocial FAQ page there are a few more details. I saw now that in the EFD-Reinf FAQ they also mention the need to install the SERPRO certificate chain.

Some sources:

Taking advantage, in your code you are using the same variable for both the service address and the SOAPAction, but, you must use different values in these two cases.

For the service URL you must use:

In the Production environment (official):
https://reinf.receita.fazenda.gov.br/WsREINF/RecepcaoLoteReinf.svc

In the Restricted Production Environment (test):
https://preprodefdreinf.receita.fazenda.gov.br/WsREINF/RecepcaoLoteReinf.svc

Already in the SOAPAction you must use this value (you can see it set in WSDL of the service):
"http://sped.fazenda.gov.br/RecepcaoLoteReinf/ReceberLoteEventos"

And, a hint, it’s much easier add a reference to the service of EFD-Reinf in the project, using Visual Studio, through the WSDL of the service, and use the generated class, which inherits System.ServiceModel.ClientBase, so that the . NET does all the work of SOAP communication for you, instead of you having to do everything by hand, using HttpWebRequest.

If you want, here’s an example of how to do it the way I said:

And here’s an example of the way you’re doing, using HttpWebRequest, only for eSocial:

By the way, here at Sopt there are several other questions and answers about and , if you need other answers.

  • Thank you very much for your detailed response. I will execute the instructions and post here if it worked. As for the mapping of the service I was already thinking about doing, I just didn’t because I had the code apparently ready here. Hug!

0

Pedro Gaspar, your directions were determined to unlock my development. Again, thank you!

I’m actually developing on a project that works with dotnet core where the development stations are in linux with vscode. To make this happen I had to find the output for some things like, for example, the tool to map services on dotnet core is svcutil, however I could not run the reinf service on it, I lifted a vm windows, I installed the visual studio and managed to do the mapping, then I continued working on linux and vs code. Below is the initial version of the dotnet core method.

    {
        // Carrega o certificado digital a partir de um arquivo PFX, informando a senha.
        X509Certificate2 x509Cert = new X509Certificate2(certPath, certPassword);
        // Carrega o XML de lote a partir de um arquivo.
        // Mas os XMLs dos eventos devem ser assinados digitalmente antes de inseridos no XML de lote.
        // Para isso é possível usar a função SignXmlDoc() disponível na resposta abaixo:
        // /a/277476/
        XDocument eventsBlockXDoc = XDocument.Load(filePath);

        var address = new EndpointAddress(environmentUrl);
        // BasicHttpsBinding está disponível somente a partir do .NET Framework 4.5.
        // Se estiver usando uma versão anterior, use a linha comentada abaixo.
        //var binding = new BasicHttpBinding(BasicHttpsSecurityMode.Transport);
        var binding = new BasicHttpsBinding();

        // Informa que será usado um certificado digital para acessar o serviço.
        binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;

        // Veja essa pergunta para mais detalhes:
        // /q/318351/
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;

        // Cria o objeto cliente (do tipo System.ServiceModel.ClientBase) para acesso ao WebService.
        var wsClient = new RecepcaoLoteReinfClient(binding, address);
        // Passa o certificado digital para o objeto do tipo System.ServiceModel.ClientBase.
        wsClient.ClientCredentials.ClientCertificate.Certificate = x509Cert;

        // Veja: https://stackoverflow.com/a/49303859/
        await wsClient.OpenAsync();           


        // Chama o WebService de fato, passando o XML do lote.
        // O método espera um objeto do tipo XElement, e retorna outro objeto XElement.

        var feedbackXElement = await wsClient.ReceberLoteEventosAsync(eventsBlockXDoc.Root);

        await wsClient.CloseAsync();


    }
  • I’m glad you were able to solve the @user1927055 problem! But, you may not be familiar with the operation here. It serves to solve individual questions and problems, but its main purpose is to serve as a repository of solutions for all developers, with a practical system of questions and answers. So for your specific question of error, The SSL connection could not be established that was occurring, which answer actually solved the problem, my or your?

  • Please mark as an answer to anyone who has solved this particular problem, to be well documented for people who come looking for this solution in the future! And, if your answer is not really an answer to the original problem, you can edit the question and put that message at the end of it, complementing the question. You can for example indicate a header Editing, or Complement, or Solution, or anything of the kind, indicating that something was added after the solution of the problem.

  • I don’t know if you noticed but I had already edited your question adding as EDITION the text you had posted as an answer, because it was not in fact an answer, but rather a complement to the question. I also added to the question the link you had posted as a comment.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.