Rapaz....
"Eu quero te ajudar! Mas agora você tem que me ajudar a te ajudar. ..."
Brincadeira...
Quando eu estava desenvolvendo a nota fiscal no ano passado, encontrei o seguinte metodo na internet:
public function assinaPHPNF($nfe, $tagid='infCanc',$taginicio='cancNFe', $outDir=''){
//carrega as chaves do certifciado p12
$key = file_get_contents($this->pathCert);
$resp = openssl_pkcs12_read ($key,$x509certdata,$this->passKey);
$rPrivkey = openssl_pkey_get_private($x509certdata['pkey']);
$rPubkey = openssl_pkey_get_public($x509certdata['cert']);
$certX509= '';
$data = '';
$arCert = explode("\n", $x509certdata['cert']);
foreach ($arCert AS $curData) {
if (strncmp($curData, '-----BEGIN CERTIFICATE', 22) != 0 && strncmp($curData, '-----END CERTIFICATE', 20) != 0 ) {
$data .= trim($curData);
}
}
// certificado que sera incluso no xml
$certX509 = $data;
// limpeza do xml com a retirada dos CR e LF
$order = array("\r\n", "\n", "\r");
$replace = '';
$nfe = str_replace($order, $replace, $nfe);
// carrega o documento no DOM
$xmldoc = new DOMDocument();
$xmldoc->preservWhiteSpace = FALSE; //elimina espaços em branco
$xmldoc->formatOutput = FALSE;
// muito importante deixar ativadas as opçoes para limpar os espacos em branco
// e as tags vazias
$xmldoc->loadXML("$nfe",LIBXML_NOBLANKS | LIBXML_NOEMPTYTAG);
//extrair a tag com os dados a serem assinados
$infNFe = $xmldoc->getElementsByTagName($tagid)->item(0);
$id = trim($infNFe->getAttribute("Id"));
$outname = $this->getPastaArquivoXML().'assinado/'.$id.'.xml';
//extrai os dados da tag para uma string
$dados = $infNFe->C14N(FALSE,FALSE,NULL,NULL);
//calcular o hash dos dados
$hashValue = hash('sha1',$dados,TRUE);
//converte o valor para base64 para serem colocados no xml
$digValue = base64_encode($hashValue);
//monta a tag da assinatura digital
$templsign = '<Signature xmlns="'.$this->URLdsig.'"><SignedInfo><CanonicalizationMethod Algorithm="
http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /><SignatureMethod Algorithm="
http://www.w3.org/2000/09/xmldsig#rsa-sha1" /><Reference URI="#'.$id.'"><Transforms><Transform Algorithm="
http://www.w3.org/2000/09/xmldsig#enveloped-signature" /><Transform Algorithm="
http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /></Transforms><DigestMethod Algorithm="
http://www.w3.org/2000/09/xmldsig#sha1" /><DigestValue>'.$digValue.'</DigestValue></Reference></SignedInfo><SignatureValue></SignatureValue><KeyInfo><X509Data><X509Certificate>'.$certX509.'</X509Certificate></X509Data></KeyInfo></Signature>';
//salva o xml normalizado
$nfe = $xmldoc->saveXML();
//remove a tag de fechamento final da NFe </NFe>
$nfe = str_replace("</$taginicio>","",$nfe);
//acrescenta o template da assinatura
$nfe = $nfe . $templsign."</$taginicio>";
// limpa algumas variaveis da memoria
unset($xmldoc);
unset($dados);
unset($hashValue);
unset($digValue);
unset($id);
unset($infNFe);
unset($order);
unset($replace);
unset($templsign);
unset($data);
//carrega novamente o DOM com a NFe
$xmldoc = new DOMDocument();
$xmldoc->preservWhiteSpace = FALSE; //elimina espaços em branco
$xmldoc->formatOutput = FALSE;
$xmldoc->loadXML($nfe,LIBXML_NOBLANKS | LIBXML_NOEMPTYTAG);
//obtem a tag com as informaçoes da assinatura
// esta informaçoes e que serao assinadas
$SignedInfo = $xmldoc->getElementsByTagName('SignedInfo')->item(0);
// extrai os dados a serem assinados para uma string
$dados = $SignedInfo->C14N(FALSE,FALSE,NULL,NULL);
$signature = '';
//executa a assinatura digital usando o resource da chave privada
$resp = openssl_sign($dados,$signature,$rPrivkey);
//codifica assinatura para o padrao base64
$signatureValue = base64_encode($signature);
$SignValue = $xmldoc->getElementsByTagName('SignatureValue')->item(0);
$SignValue->nodeValue = $signatureValue;
$nfe = $xmldoc->saveXML();
//se for passado parametro de destino salvar o xml como arquvo
$ret = $xmldoc->save($outname);
return $nfe;
}
Isso resolveu meus problemas com assinatura.
Mais hoje estou com o problema do SOAP para resolver, se puder me ajudar, fico agradecido.
Evantoni Fuchs