I'm new to the community and I'm developing a C # application for EFD-REINF. I had a problem signing in, and I got a lot of help from Pedro in this link .
I'm still not able to send the XML from the R-1000 event to the remote production server, as I'm having problems with my signature: "Bad Reference Element." in the "signedXml.ComputeSignature ()" line . Has anyone else ever had this problem?
Basically, I created my EnvioREINF class by calling individual methods for each of the information to be sent: R-1000, R-2010, R-2020 ... (I believe there may be a simpler way to do this, however as I do not have much experience with Web Service I implemented it this way) as follows: //R-1000
public bool EnvioEventoevtInfoContribuinte(Empresa objEmpresa, DateTime periodoApuracao)
{
try
{
EventosREINF auxiliar = new EventosREINF();
_reinf.evtInfoContri = auxiliar.EnviarEvtInfoContri(objEmpresa, periodoApuracao);
ReinfEvtInfoContri evtInfoContri = _reinf.evtInfoContri;
//serializa o evento informações do Contribuinte
string xmlEventoInclusao = XMLConverte.SerializaObjeto<ReinfEvtInfoContri>(evtInfoContri);
//Exibe a lista de certificados para o usuário selecionar
X509Certificate2 oX509Cert = BuscarCertificadoEmpresa();
//Adiciona a assinatura digital ao evento
XmlDocument xmlDoc = new XmlDocument();
Assinar(xmlDoc, oX509Cert, xmlEventoInclusao);
//XmlDocument xmlReinf = Assinar(xmlEventoInclusao, oX509Cert);
//Inicializa o vetor de eventos do lote a ser enviado
REINF.Model.v1_04.TArquivoeReinf[] xmlsEvento = new REINF.Model.v1_04.TArquivoeReinf[1];
//Adicionar Arquivo XML ao array de Eventos do Lote
REINF.Model.v1_04.TArquivoeReinf arquivoR_1000 = new REINF.Model.v1_04.TArquivoeReinf
{
id = objEmpresa.ToString(),
Any = xmlDoc.DocumentElement
};
xmlsEvento[0] = arquivoR_1000;
//Adiciona o xml do evento de informações do Contribuinte ao xml do evento de envio
XmlDocument xmlDocEventoEnvio = AdicionarLoteAoEventoEnvio(xmlsEvento, objEmpresa);
//Envia arquivo xml para o web service e obtém o xml de retorno
XmlElement xmlRetorno = EnviarXML(xmlDocEventoEnvio, oX509Cert);
}
catch
{
throw;
}
return true;
}
//R-2010
public bool EnvioEventoevtServTom(List<NotaFiscal> objNotasFiscais, Empresa objEmpresa, DateTime periodoApuracao)
{
try
{
ReinfEvtServTom reinfEvtServTom = new ReinfEvtServTom();
EventosREINF auxiliar = new EventosREINF();
_reinf.evtServTom = auxiliar.EnviarevtServTom(objNotasFiscais, objEmpresa, periodoApuracao);
//Exibe a lista de certificados para o usuário selecionar
X509Certificate2 oX509Cert = BuscarCertificadoEmpresa();
//Inicializa o vetor de eventos do lote a ser enviado
REINF.Model.v1_04.TArquivoeReinf[] xmlsEvento = ComunicacaoREINF(objNotasFiscais, oX509Cert).ToArray();
//Adicionar Arquivo XML ao array de Eventos do Lote
REINF.Model.v1_04.TArquivoeReinf arquivoR_2010 = new REINF.Model.v1_04.TArquivoeReinf
{
id = objEmpresa.ToString(),
};
xmlsEvento[0] = arquivoR_2010;
//Adiciona o xml do evento de informações do Contribuinte ao xml do evento de envio
XmlDocument xmlR2010 = AdicionarLoteAoEventoEnvio(xmlsEvento, objEmpresa);
//Envia arquivo xml para o web service e obtém o xml de retorno
XmlElement xmlRetorno = EnviarXML(xmlR2010, oX509Cert);
//Converte o xml de retorno para a classe retorno de envio
ReinfRetornoLoteEventos reinfRetornoLoteEventos = XMLConverte.DeserializaObjeto<ReinfRetornoLoteEventos>(xmlRetorno.OuterXml);
}
catch
{
throw;
}
return true;
}
//R-2020
public bool EnvioEventoevtServPrest(List<NotaFiscal> objNotasFiscais, Empresa objEmpresa, DateTime periodoApuracao)
{
try
{
ReinfEvtServPrest reinfEvtServPrest = new ReinfEvtServPrest();
EventosREINF auxiliar = new EventosREINF();
_reinf.evtServPrest = auxiliar.EnviarevtServPrest(objNotasFiscais, objEmpresa, periodoApuracao);
//Exibe a lista de certificados para o usuário selecionar
X509Certificate2 oX509Cert = BuscarCertificadoEmpresa();
//Inicializa o vetor de eventos do lote a ser enviado
REINF.Model.v1_04.TArquivoeReinf[] xmlsEvento = ComunicacaoREINF(objNotasFiscais, oX509Cert).ToArray();
//Adicionar Arquivo XML ao array de Eventos do Lote
REINF.Model.v1_04.TArquivoeReinf arquivoR_2020 = new REINF.Model.v1_04.TArquivoeReinf
{
id = objEmpresa.ToString(),
};
xmlsEvento[0] = arquivoR_2020;
//Adiciona o xml do evento de informações do Contribuinte ao xml do evento de envio
XmlDocument xmlR2100 = AdicionarLoteAoEventoEnvio(xmlsEvento, objEmpresa);
//Envia arquivo xml para o web service e obtém o xml de retorno
XmlElement xmlRetorno = EnviarXML(xmlR2100, oX509Cert);
//Converte o xml de retorno para a classe retorno de envio
ReinfRetornoLoteEventos reinfRetornoLoteEventos = XMLConverte.DeserializaObjeto<ReinfRetornoLoteEventos>(xmlRetorno.OuterXml);
}
catch
{
throw;
}
return true;
}
private List<TArquivoeReinf> ComunicacaoREINF(List<NotaFiscal> objNotasFiscais, X509Certificate2 oX509Cert)
{
List<TArquivoeReinf> loteEnvio = new List<TArquivoeReinf>();
foreach (NotaFiscal notaFiscal in objNotasFiscais)
{
ReinfLoteEventos reinfLoteEventos = new ReinfLoteEventos();
string xmlEventoInfoContribuinte = XMLConverte.SerializaObjeto<ReinfLoteEventos>(reinfLoteEventos);
var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlEventoInfoContribuinte);
TArquivoeReinf ObjArqXmlFilho = new TArquivoeReinf
{
id = notaFiscal.TipoDocumento.Id.ToString(),
Any = xmlDoc.DocumentElement
};
loteEnvio.Add(ObjArqXmlFilho);
}
return loteEnvio;
}
public ReinfRetornoLoteEventos RetornoLoteEventos(ReinfRetornoLoteEventos retornoLoteEventosInicial, string xmlRetorno)
{
try
{
ReinfRetornoLoteEventos reinfRetornoLoteEventos = new ReinfRetornoLoteEventos();
reinfRetornoLoteEventos = XMLConverte.DeserializaObjeto<ReinfRetornoLoteEventos>(xmlRetorno);
ReinfRetornoLoteEventosRetornoEventos reinfRetornoLoteEventosRetornoEventos = new ReinfRetornoLoteEventosRetornoEventos
{
evento = reinfRetornoLoteEventos.retornoEventos.evento
};
REINF.Model.ConsultaEvento_ProducaoRestrita.ConsultaInformacoesConsolidadasRequest consultaInformacoesConsolidadasRequest = new ConsultaEvento_ProducaoRestrita.ConsultaInformacoesConsolidadasRequest
{
Body = new ConsultaEvento_ProducaoRestrita.ConsultaInformacoesConsolidadasRequestBody()
};
//consultaInformacoesConsolidadasRequest.Body.numeroInscricaoContribuinte = "";
//consultaInformacoesConsolidadasRequest.Body.numeroProtocoloFechamento = "";
//consultaInformacoesConsolidadasRequest.Body.tipoInscricaoContribuinte = "";
REINF.Model.ConsultaEvento_ProducaoRestrita.ConsultasReinfClient consultasReinfClient = new ConsultaEvento_ProducaoRestrita.ConsultasReinfClient();
}
catch
{
throw;
}
return retornoLoteEventosInicial;
}
private XmlDocument AdicionarLoteAoEventoEnvio(TArquivoeReinf[] xmlsEvento, Empresa objEmpresa)
{
//Leiaute Mensagem Entrada
ReinfLoteEventos reinfLoteEventos = new ReinfLoteEventos
{
evento = new TArquivoeReinf[1]
};
reinfLoteEventos.evento = xmlsEvento;
//Serializa objeto evento de envio
string xmlEventoEnvio = XMLConverte.SerializaObjeto<ReinfLoteEventos>(reinfLoteEventos);
//Converte xml do evento envio para XMLDocumente que será transmitido para o web service
XmlDocument xmlDocEventoEnvio = XMLConverte.ConverterXMLParaXMLDocument(xmlEventoEnvio);
return xmlDocEventoEnvio;
}
private static string UTF8ByteArrayToString(byte[] characters)
{
UTF8Encoding encoding = new UTF8Encoding();
string constructedString = encoding.GetString(characters);
return (constructedString);
}
public void Assinar(XmlDocument xmlDoc, X509Certificate2 X509Cert, string xmlEventoInclusao)
{
// Cria o objeto SignedXml baseado no XmlDocument passado.
SignedXml signedXml = new SignedXml(xmlDoc);
signedXml.SigningKey = X509Cert.PrivateKey;
signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
// Checa se foi informado um URI para a referência, se foi acrescenta o "#" no começo.
xmlEventoInclusao = String.IsNullOrEmpty(xmlEventoInclusao) ? "" : $"#{xmlEventoInclusao}";
Reference reference = new Reference(xmlEventoInclusao);
reference.Id = _reinf.evtInfoContri.id;
reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
reference.AddTransform(new XmlDsigC14NTransform());
reference.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256";
signedXml.AddReference(reference);
// Carrega o certificado em um objeto KeyInfoX509Data e o adiciona ao objeto KeyInfo.
KeyInfo KeyInfo = new KeyInfo();
KeyInfo.AddClause(new KeyInfoX509Data(X509Cert));
signedXml.KeyInfo = KeyInfo;
// Calcula a assinatura.
signedXml.ComputeSignature();
// Obtém a representação XML da assinatura e a armazena em um objeto XmlElement.
XmlElement xmlDigitalSignature = signedXml.GetXml();
// Acrescenta o elemento ao documento XML.
xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));
// Se o primeiro nó do documento for o nó de declaração XML
// '<?xml version="1.0" encoding="utf-8"?>', remove ele.
if (xmlDoc.FirstChild is XmlDeclaration)
xmlDoc.RemoveChild(xmlDoc.FirstChild);
}
private X509Certificate2 BuscarCertificadoEmpresa()
{
X509Certificate2 cert = null;
ServicePointManager.ServerCertificateValidationCallback += ValidateRemoteCertificate;
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
X509Certificate2Collection certcollection = (X509Certificate2Collection)store.Certificates;
// pick a certificate from the store
cert = X509Certificate2UI.SelectFromCollection(certcollection,
"Autenticação do Certificado",
"Informe um certificao válido", X509SelectionFlag.SingleSelection)[0];
store.Close();
return cert;
}
private XmlElement EnviarXML(XmlDocument xmlDocEventoEnvio, X509Certificate2 oX509Cert)
{
XmlElement xmlResult = null;
var urlServicoEnvio = @"https://preprodefdreinf.receita.fazenda.gov.br/wsreinf/RecepcaoLoteReinf.svc";
var address = new EndpointAddress(urlServicoEnvio);
var binding = new BasicHttpsBinding();
// Informa que será usado um certificado digital para acessar o serviço.
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
// Cria o objeto cliente (do tipo System.ServiceModel.ClientBase) para acesso ao WebService.
var recepcaoLoteReinfClient = new RecepcaoLoteReinfClient(binding, address);
// Passa o certificado digital para o objeto do tipo System.ServiceModel.ClientBase.
recepcaoLoteReinfClient.ClientCredentials.ClientCertificate.Certificate = oX509Cert;
// Chama o WebService de fato, passando o XML do lote.
recepcaoLoteReinfClient.Open();
// O método espera um objeto do tipo XElement, e retorna outro objeto XElement.
//xmlResult = recepcaoLoteReinfClient.ReceberLoteEventos(xmlDoc.DocumentElement);
var retornoEnvioXElement = recepcaoLoteReinfClient.ReceberLoteEventos((XElement.Parse(xmlDocEventoEnvio.OuterXml)));
recepcaoLoteReinfClient.Close();
return xmlResult;
}
private bool ValidateRemoteCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
// If the certificate is a valid, signed certificate, return true.
if (sslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
{
return true;
}
Console.WriteLine("X509Certificate [{0}] Policy Error: '{1}'",
certificate.Subject,
sslPolicyErrors.ToString());
return false;
}
EDITION
The XML that is being generated is hidden by hiding the personal information:
<?xml version="1.0" encoding="utf-8"?>
<Reinf xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.reinf.esocial.gov.br/schemas/envioLoteEventos/v1_04_00">
<evtInfoContri id="ID1000000000000002018121815063800001" xmlns="http://www.w3.org/2000/09/xmldsig#">
<ideEvento>
<tpAmb>2</tpAmb>
<procEmi>1</procEmi>
<verProc>1.0.0.0</verProc>
</ideEvento>
<ideContri>
<tpInsc>1</tpInsc>
<nrInsc>00000000000000</nrInsc>
</ideContri>
<infoContri>
<inclusao>
<idePeriodo>
<iniValid>2018-12</iniValid>
</idePeriodo>
<infoCadastro>
<classTrib>1</classTrib>
<indEscrituracao>0</indEscrituracao>
<indDesoneracao>0</indDesoneracao>
<indAcordoIsenMulta>0</indAcordoIsenMulta>
<contato>
<nmCtt>Nome Contato</nmCtt>
<cpfCtt>00000000000</cpfCtt>
<foneFixo>0000000000</foneFixo>
</contato>
<softHouse>
<cnpjSoftHouse>00000000000000</cnpjSoftHouse>
<nmRazao>Empresa</nmRazao>
<nmCont>Contato</nmCont>
</softHouse>
</infoCadastro>
</inclusao>
</infoContri>
</evtInfoContri>
</Reinf>