Na classe NfeService crie um método chamado assinarXml, o qual deverá receber como parâmetro: o xml, a chave, a configuracao e o nfe_id e deverá:
- assinar o xml chamando o método Tools->signNFe
- após assinar deverá salvar o xml em arquivo
- salvar o log
- retornar o resultado
public static function assinarXml($xml, $chave, $configuracao, $nfe_id){
$retorno = new \stdClass();
try {
$response = $configuracao->tools->signNFe($xml);
$path ="storage/". $configuracao->pastaEmpresa."/xml/nfe/".$configuracao->pastaAmbiente."/assinadas/";
$nome_arquivo = $chave."-nfe.xml";
if (!file_exists($path)){
mkdir($path, 07777, true);
}
file_put_contents($path.$nome_arquivo, $response);
chmod($path, 07777);
NfeLogService::salvar($nfe_id, config("constantes.status.DIGITACAO"), $chave, "XML Assinado", "Xml Assinado com Sucesso");
$retorno->tem_erro = false;
$retorno->titulo = "XML assinado com sucesso";
$retorno->erro = "";
$retorno->xml = $response;
} catch (\Exception $e) {
$retorno->tem_erro = true;
$retorno->titulo = "Erro ao assinar o XML";
$retorno->erro = $e->getMessage();
NfeLogService::salvar($nfe_id, config("constantes.status.ERRO_AO_ASSINAR_XML"), $chave, "Erro ao assinar XML", $retorno->erro);
}
return $retorno;
}
Na classe NfeService crie um método chamado envarXml, o qual deverá receber como parâmetro $xml, $chave, $configuracao, $nNF, $nfe_id e deverá:
- preparar o número do lote
- enviar o lote para sefaz usando o método tools->sefazEnviaLote([$xml], $idLote)
- verificar o retorno
- salvar o log
- retornar o resultado
public static function enviarXML($xml, $chave, $configuracao, $nNF, $nfe_id){
$retorno = new \stdClass();
try {
$idLote = str_pad($nNF, 15, '0', STR_PAD_LEFT);
//envia o xml para pedir autorização ao SEFAZ
$resp = $configuracao->tools->sefazEnviaLote([$xml], $idLote);
sleep(2);
//transforma o xml de retorno em um stdClass
$st = new Standardize();
$std = $st->toStd($resp);
if ($std->cStat != 103) {
$retorno->tem_erro = true;
$retorno->titulo = "Não foi possível enviar o XML para a Sefaz";
$retorno->erro = "[$std->cStat] $std->xMotivo";
NfeLogService::salvar($nfe_id, config("constantes.status.ERRO_AO_ENVIAR_NFE"), $chave, "Erro ao Enviar XML", $retorno->erro);
return $retorno;
}
$retorno->tem_erro = false;
$retorno->titulo = "XML enviado com sucesso";
$retorno->erro = "";
$retorno->recibo = $std->infRec->nRec;
NfeLogService::salvar($nfe_id, config("constantes.status.ENVIADO"), $chave, "XML Enviado", "Xml Enviado com Sucesso");
} catch (\Exception $e) {
$retorno->tem_erro = true;
$retorno->titulo = "Erro ao enviar o lote para a Sefaz";
$retorno->erro = $e->getMessage();
NfeLogService::salvar($nfe_id, config("constantes.status.ERRO_AO_ENVIAR_NFE"), $chave, "Erro ao Enviar XML", $retorno->erro);
}
return $retorno;
}
Na classe NfeService crie um método chamado consultarPorRecibo, que deverá receber como parâmetro $xml, $chave, $recibo, $configuracao, $nfe_id e deverá:
- fazer a consulta na sefaz usando o método: tools->sefazConsultaRecibo($recibo, $configuracao->tpAmb)
- verificar o tipo de retorno
- caso o cStat de retorno seja igual a 100 modificar o arquivo assinado usando o método Complements::toAuthorize($xml, $xmlResp)
- salvar o arquivo autorizado
- salvar o protocolo na tabela nfe
- salvar o log
- retornar o resultado
public static function consultarPorRecibo($xml, $chave, $recibo, $configuracao, $nfe_id){
$retorno = new \stdClass();
try {
//consulta número de recibo
//$numeroRecibo = número do recíbo do envio do lote
$xmlResp = $configuracao->tools->sefazConsultaRecibo($recibo, $configuracao->tpAmb);
//transforma o xml de retorno em um stdClass
$st = new Standardize();
$std = $st->toStd($xmlResp);
if ($std->cStat=='103') { //lote enviado
Nfe::where("id",$nfe_id)->update(["status_id"=>config('constantes.status.EM_PROCESSAMENTO')]);
$retorno->tem_erro = true;
$retorno->titulo = "Protocolo ainda não disponível";
$retorno->erro = "O lote ainda não foi processado";
$retorno->status = config('constantes.status.EM_PROCESSAMENTO');
NfeLogService::salvar($nfe_id, config("constantes.status.EM_PROCESSAMENTO"), $chave, $retorno->titulo, $retorno->erro);
return $retorno;
}
if ($std->cStat=='105') { //lote em processamento
Nfe::where("id",$nfe_id)->update(["status_id"=>config('constantes.status.EM_PROCESSAMENTO')]);
$retorno->tem_erro = true;
$retorno->titulo = "Protocolo sendo processado";
$retorno->erro = "Lote em processamento, tente, mais tarde";
$retorno->status = config('constantes.status.EM_PROCESSAMENTO');
NfeLogService::salvar($nfe_id, config("constantes.status.EM_PROCESSAMENTO"), $chave, $retorno->titulo, $retorno->erro);
return $retorno;
}
if ($std->cStat=='104') { //lote processado (tudo ok)
if ($std->protNFe->infProt->cStat=='100') { //Autorizado o uso da NF-e
$protocolo = $std->protNFe->infProt->nProt;
$xml_autorizado = Complements::toAuthorize($xml, $xmlResp);
$path = "storage/". $configuracao->pastaEmpresa."/xml/nfe/". $configuracao->pastaAmbiente."/autorizadas/";
$nome_arquivo = $chave."-nfe.xml";
if (!file_exists($path)){
mkdir($path, 07777, true);
}
file_put_contents($path.$nome_arquivo, $xml_autorizado);
chmod($path, 07777);
Nfe::where("id",$nfe_id)->update([ "protocolo"=>$protocolo, "status_id"=>config('constantes.status.AUTORIZADO')]);
$retorno->tem_erro = false;
$retorno->titulo = "XML autorizado com sucesso";
$retorno->erro = "";
$retorno->recibo = $recibo;
$retorno->chave = $chave;
$retorno->status = config('constantes.status.AUTORIZADO');
$retorno->protocolo = $protocolo;
$retorno->xml = $xmlResp;
NfeLogService::salvar($nfe_id, config("constantes.status.AUTORIZADO"), $chave, "XML Autorizado", "Xml Autorizado com Sucesso");
} elseif (in_array($std->protNFe->infProt->cStat,["110", "301", "302"])) { //DENEGADAS
Nfe::where("id",$nfe_id)->update([ "status_id"=>config('constantes.status.DENEGADA')]);
$path = "storage/". $configuracao->pastaEmpresa."/xml/nfe/". $configuracao->pastaAmbiente."/denegadas/";
$nome_arquivo = $chave."-nfe.xml";
if (!file_exists($path)){
mkdir($path, 07777, true);
}
// Nota::Create(["cnpj" =>$configuracao->cnpj,"chave"=>$chave,"recibo"=>$recibo]);
$retorno->tem_erro = true;
$retorno->titulo = "Nota Denegada";
$retorno->erro = $std->protNFe->infProt->cStat . ":". $std->protNFe->infProt->xMotivo ;
$retorno->protocolo = $std->protNFe->infProt->nProt;
$retorno->xml = $xmlResp;
$retorno->status = config('constantes.status.DENEGADA');
$retorno->cstat = $std->protNFe->infProt->cStat;
NfeLogService::salvar($nfe_id, config("constantes.status.DENEGADO"), $chave, $retorno->titulo, $retorno->erro);
return $retorno;
} else { //não autorizada (rejeição)
Nfe::where("id",$nfe_id)->update([ "status_id"=>config('constantes.status.REJEITADO')]);
$retorno->tem_erro = true;
$retorno->titulo = "Nota Rejeitada";
$retorno->erro = $std->protNFe->infProt->cStat . ":". $std->protNFe->infProt->xMotivo ;
$retorno->cstat = $std->protNFe->infProt->cStat;
$retorno->status = config('constantes.status.REJEITADO');
NfeLogService::salvar($nfe_id, config("constantes.status.REJEITADO"), $chave, $retorno->titulo, $retorno->erro);
return $retorno;
}
} else { //outros erros possíveis
Nfe::where("id",$nfe_id)->update([ "status_id"=>config('constantes.status.REJEITADO')]);
$retorno->tem_erro = true;
$retorno->titulo = "Nota Rejeitada";
$retorno->erro = $std->cStat . ":". $std->xMotivo ;
$retorno->cstat = $std->cStat;
$retorno->status = config('constantes.status.REJEITADO');
NfeLogService::salvar($nfe_id, config("constantes.status.REJEITADO"), $chave, $retorno->titulo, $retorno->erro);
return $retorno;
}
} catch (\Exception $e) {
Nfe::where("id",$nfe_id)->update([ "status_id"=>config('constantes.status.REJEITADO')]);
$retorno->tem_erro = true;
$retorno->titulo = "Erro ao consultar a nota na Sefaz";
$retorno->erro = $e->getMessage();
$retorno->status = config('constantes.status.REJEITADO');
NfeLogService::salvar($nfe_id, config("constantes.status.REJEITADO"), $chave, $retorno->titulo, $retorno->erro);
return $retorno;
}
return $retorno;
}
Segue o código completo de como deverá ser chamado no NfeController
public function transmitirPelaNfe($nfe_id){
$notafiscal = NotaFiscalService::prepararNfe($nfe_id);
ValidaDadosNfeService::valida($notafiscal);
$nfe = NfeService::gerarNfe($notafiscal);
$configuracao = ConfiguracaoService::getConfiguracaoNfe($notafiscal->emitente->cnpj,$notafiscal->emitente->xNome, $notafiscal->emitente->UF, $notafiscal->ide->tpAmb );
$xml = NfeService::gerarXml($nfe, $configuracao, $nfe_id);
if(!$xml->tem_erro){
$xml_assinado = NfeService::assinarXml($xml->xml, $xml->chave, $configuracao, $nfe_id );
if(!$xml_assinado->tem_erro){
$envio = NfeService::enviarXml($xml_assinado->xml,$xml->chave, $configuracao, $notafiscal->ide->nNF, $nfe_id);
if(!$envio->tem_erro){
$i=0;
do{
sleep(3);
$i++;
$protocolo = NfeService::consultarPorRecibo($xml_assinado->xml, $xml->chave, $envio->recibo, $configuracao, $nfe_id);
}while($protocolo->status==config('constantes.status.EM_PROCESSAMENTO') && $i<3);
return $protocolo;
}else{
return $envio;
}
}else{
return $xml_assinado;
}
}else{
return $xml;
}
}