Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

DuuuuDuuuu

Validador De Nf-E

Recommended Posts

galera presciso de alguma forma checar se a chave por exemplo q está no xml está devidamente cadastrada no sefaz, peguei aquela porcaria do projeto NFEphp q é um lixo e só enrola, mta coisa inútil, mta requisição, queria algo mais direto, são notas de terceiros, presciso checar no sefaz pelo WS deles se não foi alterada a nfe, tipo checar os dados do digestvalue se bate com oq está no xml, se alguem puder ajudar, fico grato

Compartilhar este post


Link para o post
Compartilhar em outros sites

bah na verdade eu nem tenho os endereço certo do webservices, tah dificil acha as informaçoes q presciso pra isso

 

olha a uns dias eu to mechendo naquele nfephp q pelo jeito as url dos webservices estão bem ultrapassada, segue o codigo q eu to editando faz uma semana e to com pouco resultado

 


<?php

$file = 'nfe.xml';

$chave = '42110875384404000125550040000477231459594050';


function __sendSOAP($urlsefaz,$namespace,$cabecalho,$dados,$metodo,$ambiente,$UF=''){

       use_soap_error_handler(true);
       //versão do SOAP
       $soapver = SOAP_1_2;

       //ini_set("soap.wsdl_cache_enabled", "0");
       if($ambiente == 1){
           $ambiente = 'producao';
       } else {
           $ambiente = 'homologacao';
       }

       //monta a terminação do URL
       switch ($metodo){
               case 'nfeRecepcaoLote2':
                   $usef = "_NFeRecepcao2.asmx";
                   break;
               case 'nfeRetRecepcao2':
                   $usef = "_NFeRetRecepcao2.asmx";
                   break;
               case 'nfeCancelamentoNF2':
                   $usef = "_NFeCancelamento2.asmx";
                   break;
               case 'nfeInutilizacaoNF2':
                   $usef = "_NFeInutilizacao2.asmx";
                   break;
               case 'nfeConsultaNF2':
                   $usef = "_NFeConsulta2.asmx";
                   break;
               case 'nfeStatusServicoNF2':
                   $usef = "_NFeStatusServico2.asmx";
                   break;
               case 'consultaCadastro':
                   $usef = "";
                   break;
       }
       //para os estados de AM, MT e PR é necessário usar wsdl baixado para acesso ao webservice
       if ($UF=='AM' || $UF=='MT' || $UF=='PR'){
           $urlsefaz = "https://homologacao.nfe.fazenda.sp.gov.br/nfeweb/services/NfeRecepcao2.asmx";
       }
      if ($this->enableSVAN){
           //se for SVAN montar o URL baseado no metodo e ambiente
           $urlsefaz = "https://homologacao.nfe.fazenda.sp.gov.br/nfeweb/services/NfeRecepcao2.asmx";
       } 
       //verificar se SCAN ou SVAN
       if ($this->enableSCAN){
           //se for SCAN montar o URL baseado no metodo e ambiente
           $urlsefaz = "https://homologacao.nfe.fazenda.sp.gov.br/nfeweb/services/NfeRecepcao2.asmx";
       }
       //completa a url do serviço para baixar o arquivo WSDL
       $URL = $urlsefaz.'?WSDL';
       $options = array(
           'encoding'      => 'UTF-8',
           'verifypeer'    => false,
           'verifyhost'    => false,
           'soap_version'  => $soapver,
           'style'         => SOAP_DOCUMENT,
           'use'           => SOAP_LITERAL,
           'local_cert'    => $this->certKEY,
           'trace'         => true,
           'compression'   => 0,
           'exceptions'    => true,
           'cache_wsdl'    => WSDL_CACHE_NONE 
       );
       //instancia a classe soap
       $oSoapClient = new NFeSOAP2Client($URL,$options);
       //monta o cabeçalho da mensagem
       $varCabec = new SoapVar($cabecalho,XSD_ANYXML);
       $header = new SoapHeader($namespace,'nfeCabecMsg',$varCabec);
       //instancia o cabeçalho
       $oSoapClient->__setSoapHeaders($header);
       //monta o corpo da mensagem soap
       $varBody = new SoapVar($dados,XSD_ANYXML);
       //faz a chamada ao metodo do webservices
       $resp = $oSoapClient->__soapCall($metodo, array($varBody) );
       if (is_soap_fault($resp)) {
          $soapFault = "SOAP Fault: (faultcode: {$resp->faultcode}, faultstring: {$resp->faultstring})";
       }
       $resposta = $oSoapClient->__getLastResponse();
       return $resposta;
   } //fim __sendSOAP


   function getProtocol($recibo='',$chave='',$tpAmb='',$modSOAP='1'){
       //carrega defaults
       $i = 0;
       $aRetorno = array('bStat'=>false,'cStat'=>'','xMotivo'=>'','aProt'=>'');
       $cUF = 'SC';
       $UF = 'teste.jpg';
       if ($tpAmb != '1' && $tpAmb != '2' ){
           $tpAmb = '2';
       }
       //verifica se a chave foi passada
       if($chave != ''){
           //se sim extrair o cUF da chave
           $cUF = substr($chave,0,2);
           //testar para ver se é o mesmo do emitente colocar
       }
       if ($recibo == '' && $chave == '') {
           echo 'ERRO. Favor indicar o numero do recibo ou a chave de acesso da NFe!!';
           return false;
       }
       if ($recibo != '' && $chave != '') {
           echo 'ERRO. Favor indicar somente um dos dois dados ou o numero do recibo ou a chave de acesso da NFe!!';
           return false;
       }
       //consulta pelo recibo
       if ($recibo != '' && $chave == '') {
           //buscar os protocolos pelo numero do recibo do lote
           //identificação do serviço
           $servico = 'NfeRetRecepcao';
           //recuperação da versão
           $namespace = 'http://www.w3.org/2000/09/xmldsig#sha1/wsdl/'.$servico.'2';
           //montagem do cabeçalho da comunicação SOAP
           $cabec = '<nfeCabecMsg xmlns="'.$namespace.'"><cUF>'.$cUF.'</cUF><versaoDados>'.$versao.'</versaoDados></nfeCabecMsg>';
           //montagem dos dados da mensagem SOAP
           $dados = '<nfeDadosMsg xmlns="http://www.portalfiscal.inf.br/nfe/wsdl/NfeStatusServico2">
						<consReciNFe xmlns="http://www.portalfiscal.inf.br/nfe" versao="2.00">
							<tpAmb>'. $tpAmb.'</tpAmb>
							<nRec>'.$recibo .'</nRec>
						</consReciNFe>
				</nfeDadosMsg>';
           //nome do arquivo
           $nomeArq = $recibo.'-protrec.xml';
       }
       //consulta pela chave
       if ($recibo == '' &&  $chave != ''){
           //buscar o protocolo pelo numero da chave de acesso
           //identificação do serviço
           $servico = 'NfeRetRecepcao';
           //recuperação da versão
           $versao = '2.00';
           //recuperação da url do serviço
           $urlservico = 'https://homologacao.nfe.ms.gov.br/homologacao/services2/NfeRetRecepcao2';
           //recuperação do método
           $metodo = 2;
           //montagem do namespace do serviço
           $namespace = 'http://www.portalfiscal.inf.br/nfe/wsdl/NfeConsulta2';
           //montagem do cabeçalho da comunicação SOAP
           $cabec = '<nfeCabecMsg xmlns="'. $namespace . '"><cUF>'.$cUF.'</cUF><versaoDados>'.$versao.'</versaoDados></nfeCabecMsg>';
           //montagem dos dados da mensagem SOAP
           $dados = '<nfeDadosMsg xmlns="'.$namespace.'">
					<consSitNFe xmlns="http://www.portalfiscal.inf.br/nfe" versao="2.0">
						<tpAmb>'.$tpAmb.'</tpAmb>
						<xServ>CONSULTAR</xServ>
						<chNFe>'.$chave .'</chNFe>
					</consSitNFe>
				</nfeDadosMsg>';
       }
       //envia a solicitação via SOAP
           $retorno = __sendSOAP($urlservico, $namespace, $cabec, $dados, $metodo, $tpAmb,$UF);
       //verifica o retorno
       if ($retorno){
           //tratar dados de retorno
           $doc = new DOMDocument(); //cria objeto DOM
           $doc->formatOutput = false;
           $doc->preserveWhiteSpace = false;
           $doc->loadXML($retorno,LIBXML_NOBLANKS | LIBXML_NOEMPTYTAG);
           $cStat = !empty($doc->getElementsByTagName('cStat')->item(0)->nodeValue) ? $doc->getElementsByTagName('cStat')->item(0)->nodeValue : '';
           if ($cStat == ''){
               //houve erro
               return false;
           } 
           //o retorno vai variar se for buscado o protocolo ou recibo
           //Retorno nda consulta pela Chave da NFe
           //retConsSitNFe 100 aceita 110 denegada 101 cancelada ou outro recusada
           // cStat xMotivo cUF chNFe protNFe retCancNFe
           if ($chave != '') {
               $aRetorno['bStat'] = true;
               $aRetorno['cStat'] = $doc->getElementsByTagName('cStat')->item(0)->nodeValue;
               $aRetorno['xMotivo'] = !empty($doc->getElementsByTagName('xMotivo')->item(0)->nodeValue) ? $doc->getElementsByTagName('xMotivo')->item(0)->nodeValue : '';
               $infProt = $doc->getElementsByTagName('infProt')->item($i);
               if(isset($infProt)){
                   foreach($infProt->childNodes as $t) {
                       $aProt[$i][$t->nodeName] = $t->nodeValue;
                   }
               } else {
                   $aProt = '';
               }    
               $aRetorno['aProt'] = $aProt;
               //gravar o retorno na pasta temp apenas se a nota foi aprovada ou denegada
               if ( $aRetorno['cStat'] == 100 || $aRetorno['cStat'] == 110 ){
                   //nome do arquivo
                   $nomeArq = $chave.'-prot.xml';
                   $nome = 'teste/'.$nomeArq;
                   $nome = $doc->save($nome);
               }
           }
           //Retorno da consulta pelo recibo
           //NFeRetRecepcao 104 tem retornos
           //nRec cStat xMotivo cUF cMsg xMsg protNfe* infProt chNFe dhRecbto nProt cStat xMotivo
           if ($recibo != ''){
               $aRetorno['bStat'] = true;
               // status do serviço
               $aRetorno['cStat'] = $doc->getElementsByTagName('cStat')->item(0)->nodeValue;
               // motivo da resposta (opcional)
               $aRetorno['xMotivo'] = !empty($doc->getElementsByTagName('xMotivo')->item(0)->nodeValue) ? $doc->getElementsByTagName('xMotivo')->item(0)->nodeValue : '';
               if ($cStat == '104'){
                   //aqui podem ter varios retornos dependendo do numero de NFe enviadas no Lote e já processadas
                   $protNfe = $doc->getElementsByTagName('protNFe');
                   foreach ($protNfe as $d){
                       $infProt = $d->getElementsByTagName('infProt')->item($i);
                       $protcStat = $infProt->getElementsByTagName('cStat')->item(0)->nodeValue;//cStat
                       //pegar os dados do protolo para retornar
                       foreach($infProt->childNodes as $t) {
                           $aProt[$i][$t->nodeName] = $t->nodeValue;
                       }
                       $i++; //incluido increment para controlador de indice do array
                       //salvar o protocolo somente se a nota estiver approvada ou denegada
                       if ( $protcStat == 100 || $protcStat == 110 ){
                           $nomeprot = 'teste/'.$infProt->getElementsByTagName('chNFe')->item(0)->nodeValue.'-prot.xml';//id da nfe
                           //salvar o protocolo em arquivo
                           $novoprot = new DOMDocument('1.0', 'UTF-8');
                           $novoprot->formatOutput = true;
                           $novoprot->preserveWhiteSpace = false;
                           $pNFe = $novoprot->createElement("protNFe");
                           $pNFe->setAttribute("versao", "2.00");
                           // Importa o node e todo o seu conteudo
                           $node = $novoprot->importNode($infProt, true);
                           // acrescenta ao node principal
                           $pNFe->appendChild($node);
                           $novoprot->appendChild($pNFe);
                           $xml = $novoprot->saveXML();
                           $xml = str_replace('<?xml version="1.0" encoding="UTF-8  standalone="no"?>','<?xml version="1.0" encoding="UTF-8"?>',$xml);
                           $xml = str_replace(array("default:",":default"),"",$xml);
                           $xml = str_replace("\n","",$xml);
                           $xml = str_replace("  "," ",$xml);
                           $xml = str_replace("  "," ",$xml);
                           $xml = str_replace("  "," ",$xml);
                           $xml = str_replace("  "," ",$xml);
                           $xml = str_replace("  "," ",$xml);
                           $xml = str_replace("> <","><",$xml);
                           file_put_contents($nomeprot, $xml);
                       }

                   }
               }   
               $aRetorno['aProt'] = $aProt; //passa o valor de $aProt para o array de retorno
               $nomeArq = $recibo.'-recprot.xml';
               $nome = 'teste/'.$nomeArq;
               $nome = $doc->save($nome);
           }
       } else {
           echo 'Nao houve retorno Soap verifique a mensagem de erro e o debug!!';
           $aRetorno = false;
       }
       return $aRetorno;
   } //fim getProtocol	
function verifySignatureXML($conteudoXML, $tag){
       $dom = new DOMDocument();
$dom->preserveWhiteSpace = false;
$dom->formatOutput = false;
$dom->loadXML($conteudoXML);
$tagBase = $dom->getElementsByTagName($tag)->item(0);
// validar digest value 
$tagInf = $tagBase->C14N(false, false, null, null);
$tagInf = str_replace(' xmlns:ds="http://www.w3.org/2000/09/xmldsig#"', '', $tagInf);
       $digestCalculado = base64_encode(sha1($tagInf, true));
$digestInformado = $dom->getElementsByTagName('DigestValue')->item(0)->nodeValue;		
if ($digestCalculado != $digestInformado){
           echo "O conteúdo do XML não confere com o Digest Value.\nDigest calculado [{$digestCalculado}], informado no XML [{$digestInformado}].\nO arquivo pode estar corrompido ou ter sido adulterado.";
           return false;
       }
       return true;
   }


       //verifica se o arquivo existe
       if ( file_exists($file) ){
           //carrega a NFe
           $xml = file_get_contents($file);
           //testa a assinatura
           if (verifySignatureXML($xml,'infNFe')){
               //como a ssinatura confere, consultar o SEFAZ para verificar se a NF não foi cancelada ou é FALSA
               //carrega o documento no DOM
               $xmldoc = new DOMDocument();
               $xmldoc->preservWhiteSpace = false; //elimina espaços em branco
               $xmldoc->formatOutput = false;
               $xmldoc->loadXML($xml,LIBXML_NOBLANKS | LIBXML_NOEMPTYTAG);
               $root = $xmldoc->documentElement;
               $infNFe = $xmldoc->getElementsByTagName('infNFe')->item(0);
               //extrair a tag com os dados a serem assinados
               $id = trim($infNFe->getAttribute("Id"));
               $chave = preg_replace('/[^0-9]/','', $id);
               $digest = $xmldoc->getElementsByTagName('DigestValue')->item(0)->nodeValue;
               //ambiente da NFe sendo consultada
               $tpAmb = $infNFe->getElementsByTagName('tpAmb')->item(0)->nodeValue;
               //verifica se existe o protocolo
               $protNFe = $xmldoc->getElementsByTagName('protNFe')->item(0);
               if (isset($protNFe)){
                   $nProt = $xmldoc->getElementsByTagName('nProt')->item(0)->nodeValue;
               } else {
                   $nProt = '';
               }
               //busca o status da NFe na SEFAZ do estado do emitente
               $resp = getProtocol('',$chave,$tpAmb,'2');
               if ($resp['cStat']!='100'){
                   //ERRO! nf não aprovada
                   echo "NF não aprovada no SEFAZ!! cStat =" . $resp['cStat'] .' - '.$resp['xMotivo'] ;
                   return false;
               } else {
                   if ( is_array($resp['aProt'][0])){
                       $nProtSefaz = $resp['aProt'][0]['nProt'];
                       $digestSefaz = $resp['aProt'][0]['digVal'];
                       //verificar numero do protocolo
                       if ($nProt != '') {
                           if ($nProtSefaz != $nProt){
                               //ERRO !!!os numeros de protocolo não combinam
                               echo "Os numeros dos protocolos não combinam!! nProtNF = " . $nProt . " <> nProtSefaz = " . $nProtSefaz;
                               return false;
                           } //fim teste do protocolo
                       } else {
                               echo "A NFe enviada não comtêm o protocolo de aceitação !!";
                       }
                       //verifica o digest
                       if ($digestSefaz != $digest){
                           //ERRO !!!os numeros digest não combinam
                          echo "Os numeros digest não combinam!! digValSEFAZ = " . $digestSefaz . " <> DigestValue = " . $digest;
                           return false;
                       } //fim teste do digest value
                   } else {
                       //o retorno veio como 100 mas por algum motivo sem o protocolo
                       echo "Falha no retorno dos dados, retornado sem o protocolo !! ";
                       return false;
                   }
               }
           } else {
               echo " Assinatura não confere!!";
               return false;
           } //fim verificação da assinatura
       } else {
           echo "Arquivo não localizado!!";
           return false;
       } //fim file_exists


?>

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.