emailUtil = $util; $this->siegUtil = $siegUtil; $this->estoqueUtil = $estoqueUtil; if (!is_dir(public_path('xml_nfe'))) { mkdir(public_path('xml_nfe'), 0777, true); } if (!is_dir(public_path('xml_nfe_cancelada'))) { mkdir(public_path('xml_nfe_cancelada'), 0777, true); } if (!is_dir(public_path('xml_nfe_correcao'))) { mkdir(public_path('xml_nfe_correcao'), 0777, true); } if (!is_dir(public_path('danfe_temp'))) { mkdir(public_path('danfe_temp'), 0777, true); } if (!is_dir(public_path('danfe'))) { mkdir(public_path('danfe'), 0777, true); } } public function consultaFiscal(Request $request) { $nfe = Nfe::with('itens')->findOrFail($request->nfe_id); $empresa = $nfe->empresa; $result = app(FiscalValidator::class) ->validate($nfe, $empresa); return response()->json([ 'status' => $result['status'], 'risco' => $result['risco'], 'mensagens' => $result['mensagens'] ]); } private function getContigencia($empresa_id){ $active = Contigencia:: where('empresa_id', $empresa_id) ->where('status', 1) ->where('documento', 'NFe') ->first(); return $active != null ? 1 : 0; } public function emitir(Request $request){ $nfe = Nfe::findOrFail($request->id); $empresa = Empresa::findOrFail($nfe->empresa_id); $empresa = __objetoParaEmissao($empresa, $nfe->local_id); if($empresa->arquivo == null){ return response()->json("Certificado não encontrado para este emitente", 401); } $nfe_service = new NFeService([ "atualizacao" => date('Y-m-d h:i:s'), "tpAmb" => (int)$nfe->ambiente, "razaosocial" => $empresa->nome, "siglaUF" => $empresa->cidade->uf, "cnpj" => preg_replace('/[^0-9]/', '', $empresa->cpf_cnpj), // "schemes" => "PL_009_V4", "schemes" => "PL_010_V1.21", "versao" => "4.00", ], $empresa); $doc = $nfe_service->gerarXml($nfe); if(!isset($doc['erros_xml'])){ $xml = $doc['xml']; $chave = $doc['chave']; $xmlTemp = simplexml_load_string($xml); $itensComErro = ""; $regime = $empresa->tributacao; foreach ($xmlTemp->infNFe->det as $item) { if (isset($item->imposto->ICMS)) { $icms = (array_values((array)$item->imposto->ICMS)); if(sizeof($icms) == 0){ $itensComErro .= " Produto " . $item->prod->xProd . " não formando a TAG ICMS, confira se o CST do item corresponde a tributação, regime configurado: $regime"; } } } if($itensComErro){ return response()->json($itensComErro, 403); } if($this->validarTagsICMS($xml) != ""){ return response()->json("XML inválido: não foi encontrado o grupo ICMS/ICMSSN correspondente ao CST/CSOSN informado no " . $this->validarTagsICMS($xml), 403); } try{ $signed = $nfe_service->sign($xml); $resultado = $nfe_service->transmitir($signed, $doc['chave']); if ($resultado['erro'] == 0) { $nfe->chave = $doc['chave']; $nfe->estado = 'aprovado'; if($empresa->ambiente == 2){ $empresa->numero_ultima_nfe_homologacao = $doc['numero']; }else{ $empresa->numero_ultima_nfe_producao = $doc['numero']; } $nfe->numero = $doc['numero']; $nfe->recibo = $resultado['success']; $nfe->data_emissao = date('Y-m-d H:i:s'); $nfe->contigencia = $this->getContigencia($nfe->empresa_id); // $nfe->ambiente = $empresa->ambiente $nfe->save(); $empresa->save(); $data = [ 'recibo' => $resultado['success'], 'chave' => $nfe->chave ]; $descricaoLog = "Emitida número $nfe->numero - $nfe->chave APROVADA"; __createLog($nfe->empresa_id, 'NFe', 'transmitir', $descricaoLog); try{ $fileDir = public_path('xml_nfe/').$nfe->chave.'.xml'; $this->emailUtil->enviarXmlContador($nfe->empresa_id, $fileDir, 'NFe', $nfe->chave); }catch(\Exception $e){ } try{ $fileDir = public_path('xml_nfe/').$nfe->chave.'.xml'; $this->siegUtil->enviarXml($nfe->empresa_id, $fileDir); }catch(\Exception $e){ } return response()->json($data, 200); }else{ $error = $resultado['error']; $recibo = isset($resultado['recibo']) ? $resultado['recibo'] : null; // return response()->json($resultado, 401); $motivo = ''; if(isset($error['protNFe'])){ $motivo = $error['protNFe']['infProt']['xMotivo']; $cStat = $error['protNFe']['infProt']['cStat']; $nfe->motivo_rejeicao = substr("[$cStat] $motivo", 0, 200); } // $nfe->numero = isset($documento['numero_nfe']) ? $documento['numero_nfe'] : // Nfe::lastNumero($empresa); if($nfe->chave == ''){ $nfe->chave = $doc['chave']; } $descricaoLog = "REJEITADA $nfe->chave - $motivo"; __createLog($nfe->empresa_id, 'NFe', 'erro', $descricaoLog); if($nfe->signed_xml == null){ $nfe->signed_xml = $signed; } if($nfe->recibo == null){ $nfe->recibo = $recibo; } $nfe->estado = 'rejeitado'; $nfe->save(); if(isset($error['protNFe'])){ return response()->json("[$cStat] $motivo", 403); }else{ return response()->json($error, 403); } } }catch(\Exception $e){ $msg = $this->formatarErroNFe($e->getMessage()); return response()->json($msg, 404); } }else{ return response()->json($doc['erros_xml'], 401); } } function validarTagsICMS($xmlString) { libxml_use_internal_errors(true); $xml = simplexml_load_string($xmlString); $retorno = ""; $cont = 1; foreach ($xml->infNFe->det as $det) { $nItem = (string) $det['nItem']; $imposto = $det->imposto; $temTag = 0; $gruposICMS = [ 'ICMS00','ICMS10','ICMS20','ICMS30','ICMS40','ICMS51', 'ICMS60', 'ICMS61','ICMS70','ICMS90','ICMSST' ]; foreach ($gruposICMS as $g) { if (isset($imposto->ICMS->{$g})) { $temTag = 1; } } if (isset($imposto->ICMS->ICMSST)) { $temTag = 1; } $gruposSN = [ 'ICMSSN101','ICMSSN102','ICMSSN201','ICMSSN202','ICMSSN203', 'ICMSSN500','ICMSSN900', 'ICMS61' ]; foreach ($gruposSN as $g) { if (isset($imposto->ICMS->{$g})) { $temTag = 1; } } if($temTag == 0){ $retorno .= " item $cont."; } $cont++; } return $retorno; } private function formatarErroNFe($mensagem) { if (preg_match('/cClassTrib.*pattern.*not accepted/', $mensagem)) { return "O código de classificação tributária (cClassTrib) deve conter 6 dígitos numéricos. Verifique o campo e corrija o valor enviado (exemplo: 000002)."; } if (preg_match('/ICMSSN900.*Expected.*vICMS/', $mensagem)) { return "No regime Simples Nacional com CSOSN 900 é obrigatório informar o campo vICMS (mesmo que seja 0,00). Ajuste o XML e tente novamente."; } if (preg_match('/This element is not expected/', $mensagem)) { preg_match('/Element.*\{.*\}(.*?)\'.*Expected.*\{.*\}(.*?)\)/', $mensagem, $matches); if (isset($matches[1], $matches[2])) { return "Campo inválido no XML: {$matches[1]}. Esperado: {$matches[2]}."; } return "Erro de estrutura no XML: verifique os campos do ICMS."; } return "Erro ao validar XML. Detalhes técnicos: " . htmlspecialchars($mensagem); } public function cancelar(Request $request) { $nfe = Nfe::findOrFail($request->id); $empresa = Empresa::findOrFail($nfe->empresa_id); $empresa = __objetoParaEmissao($empresa, $nfe->local_id); if ($nfe != null) { $cnpj = preg_replace('/[^0-9]/', '', $empresa->cpf_cnpj); $nfe_service = new NFeService([ "atualizacao" => date('Y-m-d h:i:s'), "tpAmb" => (int)$nfe->ambiente, "razaosocial" => $empresa->nome, "siglaUF" => $empresa->cidade->uf, "cnpj" => preg_replace('/[^0-9]/', '', $empresa->cpf_cnpj), // "schemes" => "PL_009_V4", "schemes" => "PL_010_V1.21", "versao" => "4.00", ], $empresa); $doc = $nfe_service->cancelar($nfe, $request->motivo); if (!isset($doc['erro'])) { $nfe->estado = 'cancelado'; $nfe->save(); foreach ($nfe->itens as $i) { if ($i->produto->gerenciar_estoque) { if ($nfe->tpNF == 1) { $this->estoqueUtil->incrementaEstoque($i->produto_id, $i->quantidade, $i->variacao_id, $nfe->local_id); }else{ $this->estoqueUtil->reduzEstoque($i->produto_id, $i->quantidade, $i->variacao_id, $nfe->local_id); } } } $garantia = Garantia::where('empresa_id', $nfe->empresa_id) ->where('nfe_id', $nfe->id)->first(); if($garantia){ $garantia->delete(); } ContaPagar::where('nfe_id', $nfe->id)->delete(); ContaReceber::where('nfe_id', $nfe->id)->delete(); ProdutoUnico::where('nfe_id', $nfe->id)->delete(); $item->delete(); $nfe->fatura()->delete(); // return response()->json($doc, 200); $motivo = $doc['retEvento']['infEvento']['xMotivo']; $cStat = $doc['retEvento']['infEvento']['cStat']; if($cStat == 135){ $descricaoLog = "CANCELADA $nfe->chave"; __createLog($nfe->empresa_id, 'NFe', 'cancelar', $descricaoLog); try{ $fileDir = public_path('xml_nfe_cancelada/').$nfe->chave.'.xml'; $this->siegUtil->enviarXml($nfe->empresa_id, $fileDir); }catch(\Exception $e){ } return response()->json("[$cStat] $motivo", 200); }else{ $descricaoLog = "ERRO CANCELAR: $nfe->chave"; __createLog($nfe->empresa_id, 'NFe', 'erro', $descricaoLog); return response()->json("[$cStat] $motivo", 401); } } else { $arr = $doc['data']; $cStat = $arr['retEvento']['infEvento']['cStat']; $motivo = $arr['retEvento']['infEvento']['xMotivo']; $descricaoLog = "ERRO CANCELAR: $nfe->chave - $motivo"; __createLog($nfe->empresa_id, 'NFe', 'erro', $descricaoLog); return response()->json("[$cStat] $motivo", $doc['status']); } } else { return response()->json('Consulta não encontrada', 404); } } public function corrigir(Request $request) { $nfe = Nfe::findOrFail($request->id); $empresa = Empresa::findOrFail($nfe->empresa_id); $empresa = __objetoParaEmissao($empresa, $nfe->local_id); if ($nfe != null) { $cnpj = preg_replace('/[^0-9]/', '', $empresa->cpf_cnpj); $nfe_service = new NFeService([ "atualizacao" => date('Y-m-d h:i:s'), "tpAmb" => (int)$nfe->ambiente, "razaosocial" => $empresa->nome, "siglaUF" => $empresa->cidade->uf, "cnpj" => preg_replace('/[^0-9]/', '', $empresa->cpf_cnpj), // "schemes" => "PL_009_V4", "schemes" => "PL_010_V1.21", "versao" => "4.00", ], $empresa); $doc = $nfe_service->correcao($nfe, $request->motivo); if (!isset($doc['erro'])) { // return response()->json($doc, 200); $motivo = $doc['retEvento']['infEvento']['xMotivo']; $cStat = $doc['retEvento']['infEvento']['cStat']; if($cStat == 135){ $descricaoLog = "CORRIGIDA $nfe->chave"; __createLog($nfe->empresa_id, 'NFe', 'corrigir', $descricaoLog); try{ $fileDir = public_path('xml_nfe_correcao/').$nfe->chave.'.xml'; $this->siegUtil->enviarXml($nfe->empresa_id, $fileDir); }catch(\Exception $e){ } return response()->json("[$cStat] $motivo", 200); }else{ $descricaoLog = "ERRO CORRIGIR: $nfe->chave"; __createLog($nfe->empresa_id, 'NFe', 'erro', $descricaoLog); return response()->json("[$cStat] $motivo", 401); } } else { $descricaoLog = "ERRO CORRIGIR: $nfe->chave"; __createLog($nfe->empresa_id, 'NFe', 'erro', $descricaoLog); return response()->json($nfe['data'], $nfe['status']); } } else { return response()->json('Consulta não encontrada', 404); } } public function consultar(Request $request) { $nfe = Nfe::findOrFail($request->id); $empresa = Empresa::findOrFail($nfe->empresa_id); $empresa = __objetoParaEmissao($empresa, $nfe->local_id); if ($nfe != null) { $cnpj = preg_replace('/[^0-9]/', '', $empresa->cpf_cnpj); $nfe_service = new NFeService([ "atualizacao" => date('Y-m-d h:i:s'), "tpAmb" => (int)$nfe->ambiente, "razaosocial" => $empresa->nome, "siglaUF" => $empresa->cidade->uf, "cnpj" => preg_replace('/[^0-9]/', '', $empresa->cpf_cnpj), // "schemes" => "PL_009_V4", "schemes" => "PL_010_V1.21", "versao" => "4.00", ], $empresa); $consulta = $nfe_service->consultar($nfe); if (!isset($consulta['erro'])) { try{ $motivo = $consulta['protNFe']['infProt']['xMotivo']; $cStat = $consulta['protNFe']['infProt']['cStat']; if($cStat == 100){ return response()->json("[$cStat] $motivo", 200); }else{ return response()->json("[$cStat] $motivo", 401); } }catch(\Exception $e){ return response()->json($consulta['cStat'] . " " . $consulta['xMotivo'], 404); } }else{ return response()->json($consulta['data'], $consulta['status']); } } else { return response()->json('Consulta não encontrada', 404); } } public function inutilizar(Request $request) { $item = Inutilizacao::findOrFail($request->id); $empresa = Empresa::findOrFail($item->empresa_id); $empresa = __objetoParaEmissao($empresa, $item->local_id); if ($item != null) { $cnpj = preg_replace('/[^0-9]/', '', $empresa->cpf_cnpj); $nfe_service = new NFeService([ "atualizacao" => date('Y-m-d h:i:s'), "tpAmb" => (int)$empresa->ambiente, "razaosocial" => $empresa->nome, "siglaUF" => $empresa->cidade->uf, "cnpj" => preg_replace('/[^0-9]/', '', $empresa->cpf_cnpj), // "schemes" => "PL_009_V4", "schemes" => "PL_010_V1.21", "versao" => "4.00", ], $empresa); $consulta = $nfe_service->inutilizar($item); if (!isset($consulta['erro'])) { $cStat = $consulta['infInut']['cStat']; if($cStat == 102){ $item->estado = 'aprovado'; $item->save(); return response()->json($consulta['infInut']['xMotivo'], 200); }else{ $item->estado = 'rejeitado'; $item->save(); return response()->json($consulta['infInut']['xMotivo'], 403); } }else{ $item->estado = 'rejeitado'; $item->save(); return response()->json($consulta['data'], 403); } } else { return response()->json('Consulta não encontrada', 404); } } public function consultaStatusSefaz(Request $request){ $caixa = Caixa::where('usuario_id', $request->usuario_id)->where('status', 1)->first(); $empresa = Empresa::findOrFail($request->empresa_id); $empresa = __objetoParaEmissao($empresa, $caixa ? $caixa->local_id : null); $nfe_service = new NFeService([ "atualizacao" => date('Y-m-d h:i:s'), "tpAmb" => (int)$empresa->ambiente, "razaosocial" => $empresa->nome, "siglaUF" => $empresa->cidade->uf, "cnpj" => preg_replace('/[^0-9]/', '', $empresa->cpf_cnpj), // "schemes" => "PL_009_V4", "schemes" => "PL_010_V1.21", "versao" => "4.00", ], $empresa); $consulta = $nfe_service->consultaStatus((int)$empresa->ambiente, $empresa->cidade->uf); return response()->json($consulta, 200); } public function find(Request $request){ $item = Nfe::with('cliente')->findOrFail($request->id); return response()->json($item, 200); } public function sendMail(Request $request){ $email = $request->email; $xml = $request->xml; $danfe = $request->danfe; $id = $request->id; $nfe = Nfe::findOrFail($id); if(!$email){ return response()->json('Informe o email!', 404); } $docs = []; if($xml){ $docs[] = public_path('xml_nfe/').$nfe->chave.'.xml'; } if($danfe){ $this->gerarDanfeTemporaria($nfe); $docs[] = public_path('danfe_temp/').$nfe->chave.'.pdf'; } $emailConfig = EmailConfig::where('empresa_id', $nfe->empresa_id) ->where('status', 1) ->first(); try{ if($emailConfig != null){ $body = view('mail.nfe', compact('nfe')); $result = $this->emailUtil->enviaEmailPHPMailer($email, 'Envio de documento', $body, $emailConfig, $docs); }else{ Mail::send('mail.nfe', ['nfe' => $nfe], function($m) use ($email, $docs){ $nomeEmail = env('MAIL_FROM_NAME'); $m->from(env('MAIL_USERNAME'), $nomeEmail); $m->subject('Envio de documento'); foreach($docs as $f){ $m->attach($f); } $m->to($email); }); } //limpa diretorio danfe_temp $this->unlinkr(public_path('danfe_temp')); return response()->json("Email enviado!", 200); }catch(\Exception $e){ return response()->json($e->getMessage(), 404); } } private function gerarDanfeTemporaria($nfe){ if (!is_dir(public_path('danfe_temp'))) { mkdir(public_path('danfe_temp'), 0777, true); } $xml = file_get_contents(public_path('xml_nfe/').$nfe->chave.'.xml'); $danfe = new Danfe($xml); $pdf = $danfe->render(); file_put_contents(public_path('danfe_temp/') . $nfe->chave . '.pdf', $pdf); } private function unlinkr($dir){ $files = array_diff(scandir($dir), array('.', '..')); foreach ($files as $file) { (is_dir("$dir/$file")) ? $this->unlinkr("$dir/$file") : unlink("$dir/$file"); } return rmdir($dir); } }