510 lines
14 KiB
PHP
510 lines
14 KiB
PHP
<?php
|
|
namespace App\Services;
|
|
|
|
error_reporting(E_ALL);
|
|
ini_set('display_errors', 'On');
|
|
use NFePHP\Common\Certificate;
|
|
use NFePHP\NFe\Tools;
|
|
use NFePHP\NFe\Make;
|
|
use NFePHP\NFe\Common\Standardize;
|
|
use NFePHP\NFe\Complements;
|
|
use App\Models\Nfe;
|
|
use App\Models\Empresa;
|
|
use App\Models\ConfiguracaoSuper;
|
|
|
|
class NFeServiceApi{
|
|
|
|
private $config;
|
|
private $tools;
|
|
protected $empresa_id = null;
|
|
|
|
public function __construct($config, $empresa){
|
|
|
|
$this->empresa_id = $empresa->id;
|
|
|
|
$this->config = $config;
|
|
$this->tools = new Tools(json_encode($config), Certificate::readPfx($empresa->arquivo, $empresa->senha));
|
|
$this->tools->model(55);
|
|
|
|
}
|
|
|
|
public function gerarXml(
|
|
$documento,
|
|
$destinatario,
|
|
$itens,
|
|
$frete,
|
|
$pagamento,
|
|
$fatura,
|
|
$duplicatas,
|
|
$empresa
|
|
){
|
|
|
|
$nfe = new Make();
|
|
$stdInNFe = new \stdClass();
|
|
$stdInNFe->versao = '4.00';
|
|
$stdInNFe->Id = null;
|
|
$stdInNFe->pk_nItem = '';
|
|
|
|
$infNFe = $nfe->taginfNFe($stdInNFe);
|
|
|
|
$stdIde = new \stdClass();
|
|
|
|
$stdIde->cUF = Empresa::getCodUF($empresa->cidade->uf); // codigo uf emitente
|
|
$stdIde->cNF = rand(11111, 99999);
|
|
// $stdIde->natOp = $venda->natureza->natureza;
|
|
$stdIde->natOp = $documento['natureza_operacao'];
|
|
|
|
$stdIde->mod = 55;
|
|
$stdIde->serie = $documento['numero_serie'];
|
|
$stdIde->nNF = isset($documento['numero_nfe']) ? $documento['numero_nfe'] : $empresa->lastNumeroNFe((int)$documento['ambiente']); // numero sequencial da nfe
|
|
$stdIde->dhEmi = date("Y-m-d\TH:i:sP");
|
|
$stdIde->dhSaiEnt = date("Y-m-d\TH:i:sP");
|
|
$stdIde->tpNF = 1;
|
|
$stdIde->idDest = $empresa->cidade->uf == $destinatario['uf'] ? 1 : 2;
|
|
$stdIde->cMunFG = $empresa->cidade->codigo;
|
|
$stdIde->tpImp = 1;
|
|
$stdIde->tpEmis = 1;
|
|
$stdIde->cDV = 0;
|
|
$stdIde->tpAmb = (int)$documento['ambiente'];
|
|
$stdIde->finNFe = 1;
|
|
$stdIde->indFinal = $documento['consumidor_final'];
|
|
$stdIde->indPres = 1;
|
|
$stdIde->procEmi = '0';
|
|
$stdIde->verProc = '2.0';
|
|
$tagide = $nfe->tagide($stdIde); //fim da tagide
|
|
|
|
// inicia tag do emitente
|
|
$stdEmit = new \stdClass();
|
|
$stdEmit->xNome = $empresa->nome;
|
|
$stdEmit->xFant = $empresa->nome_fantasia;
|
|
$stdEmit->CRT = $empresa->tributacao == 'Regime Normal' ? 3 : 1;
|
|
$stdEmit->IE = $empresa->ie;
|
|
|
|
$cpf_cnpj = preg_replace('/[^0-9]/', '', $empresa->cpf_cnpj);
|
|
if (strlen($cpf_cnpj) == 14) {
|
|
$stdEmit->CNPJ = $cpf_cnpj;
|
|
}else{
|
|
$stdEmit->CPF = $cpf_cnpj;
|
|
}
|
|
$emit = $nfe->tagemit($stdEmit);
|
|
|
|
$stdEnderEmit = new \stdClass();
|
|
$stdEnderEmit->xLgr = $empresa->rua;
|
|
$stdEnderEmit->nro = $empresa->numero;
|
|
$stdEnderEmit->xCpl = $empresa->complemento;
|
|
$stdEnderEmit->xBairro = $empresa->bairro;
|
|
$stdEnderEmit->cMun = $empresa->cidade->codigo;
|
|
$stdEnderEmit->xMun = $empresa->cidade->nome;
|
|
$stdEnderEmit->UF = $empresa->cidade->uf;
|
|
$stdEnderEmit->CEP = $empresa->cep;
|
|
$stdEnderEmit->cPais = '1058';
|
|
$stdEnderEmit->xPais = 'BRASIL';
|
|
$enderEmit = $nfe->tagenderEmit($stdEnderEmit); // fim tag do emitente
|
|
|
|
// inicia tag do destinatario
|
|
$stdDest = new \stdClass();
|
|
$stdDest->xNome = $destinatario['nome'];
|
|
if ($destinatario['contribuinte'] == 1) {
|
|
if ($destinatario['ie'] == 'ISENTO') {
|
|
$stdDest->indIEDest = "2";
|
|
} else {
|
|
$stdDest->indIEDest = "1";
|
|
}
|
|
} else {
|
|
$stdDest->indIEDest = "9";
|
|
}
|
|
|
|
$cpf_cnpj = preg_replace('/[^0-9]/', '', $destinatario['cpf_cnpj']);
|
|
|
|
if (strlen($cpf_cnpj) == 14) {
|
|
$stdDest->CNPJ = $cpf_cnpj;
|
|
$ie = preg_replace('/[^0-9]/', '', $destinatario['ie']);
|
|
$stdDest->IE = $ie;
|
|
} else {
|
|
$stdDest->CPF = $destinatario['cpf_cnpj'];
|
|
}
|
|
|
|
$dest = $nfe->tagdest($stdDest);
|
|
|
|
$stdEnderDest = new \stdClass();
|
|
$stdEnderDest->xLgr = $destinatario['rua'];
|
|
$stdEnderDest->nro = $destinatario['numero'];
|
|
$stdEnderDest->xCpl = $destinatario['complemento'];
|
|
$stdEnderDest->xBairro = $destinatario['bairro'];
|
|
$stdEnderDest->cMun = $destinatario['cod_municipio_ibge'];
|
|
$stdEnderDest->xMun = $destinatario['nome_municipio'];
|
|
$stdEnderDest->UF = $destinatario['uf'];
|
|
$stdEnderDest->CEP = $destinatario['cep'];
|
|
$stdEnderDest->cPais = $destinatario['cod_pais'];
|
|
$stdEnderDest->xPais = $destinatario['nome_pais'];
|
|
|
|
$enderDest = $nfe->tagenderDest($stdEnderDest);
|
|
//fim tag destinatario endereço
|
|
|
|
$somaProdutos = 0;
|
|
$somaICMS = 0;
|
|
$somaFrete = 0;
|
|
$somaIpi = 0;
|
|
$totalItens = sizeof($itens);
|
|
|
|
foreach ($itens as $itemCont => $i) {
|
|
$itemCont++;
|
|
|
|
$stdProd = new \stdClass(); // tag produto inicio
|
|
$stdProd->item = $itemCont;
|
|
$stdProd->cEAN = $i['cod_barras'];
|
|
$stdProd->cEANTrib = $i['cod_barras'];
|
|
$stdProd->cProd = $i['codigo_produto'];
|
|
$stdProd->xProd = $i['nome_produto'];
|
|
$stdProd->NCM = $i['ncm'];
|
|
$stdProd->CFOP = $i['cfop'];
|
|
$stdProd->uCom = $i['unidade'];
|
|
$stdProd->qCom = $i['quantidade'];
|
|
$stdProd->vUnCom = $this->format($i['valor_unitario']);
|
|
$stdProd->vProd = $this->format(($i['quantidade'] * $i['valor_unitario']));
|
|
$stdProd->uTrib = $i['unidade'];
|
|
$stdProd->qTrib = $i['quantidade'];
|
|
$stdProd->vUnTrib = $this->format($i['valor_unitario']);
|
|
$stdProd->indTot = $i['compoe_valor_total'];
|
|
$somaProdutos += ($i['quantidade'] * $i['valor_unitario']);
|
|
|
|
if($frete != null){
|
|
if($frete['valor'] > 0){
|
|
if($itemCont < $totalItens){
|
|
$somaFrete += $vFt =
|
|
$this->format($frete['valor']/$totalItens, 2);
|
|
$stdProd->vFrete = $this->format($vFt);
|
|
}else{
|
|
$stdProd->vFrete = $this->format(($frete['valor']-$somaFrete), 2);
|
|
}
|
|
}
|
|
}
|
|
|
|
$prod = $nfe->tagprod($stdProd); // fim tag de produtos
|
|
|
|
$stdImposto = new \stdClass();
|
|
$stdImposto->item = $itemCont;
|
|
$imposto = $nfe->tagimposto($stdImposto); // tag imposto
|
|
|
|
//frete
|
|
|
|
if ($stdEmit->CRT == 1) {
|
|
$stdICMS = new \stdClass();
|
|
|
|
$stdICMS->item = $itemCont;
|
|
$stdICMS->orig = 0;
|
|
$stdICMS->CSOSN = $i['cst_csosn'];
|
|
|
|
if(isset($i['vBCSTRet'])) $stdICMS->vBCSTRet = $i['vBCSTRet'];
|
|
if(isset($i['pST'])) $stdICMS->pST = $i['pST'];
|
|
if(isset($i['vICMSSTRet'])) $stdICMS->vICMSSTRet = $i['vICMSSTRet'];
|
|
if(isset($i['vICMSSubstituto'])) $stdICMS->vICMSSubstituto = $i['vICMSSubstituto'];
|
|
|
|
|
|
$stdICMS->pCredSN = $this->format($i['perc_icms']);
|
|
$stdICMS->vCredICMSSN = $this->format($i['perc_icms']);
|
|
$ICMS = $nfe->tagICMSSN($stdICMS);
|
|
|
|
$somaICMS = 0;
|
|
} else if ($stdEmit->CRT == 3) {
|
|
|
|
$stdICMS = new \stdClass();
|
|
$stdICMS->item = $itemCont;
|
|
$stdICMS->orig = 0;
|
|
$stdICMS->CST = $i['cst_csosn'];
|
|
$stdICMS->modBC = 0;
|
|
$stdICMS->vBC = $this->format($i['valor_unitario'] * $i['quantidade']);
|
|
$stdICMS->pICMS = $this->format($i['perc_icms']);
|
|
$stdICMS->vICMS = $stdICMS->vBC * ($stdICMS->pICMS/100);
|
|
|
|
if(isset($i['vBCSTRet'])) $stdICMS->vBCSTRet = $i['vBCSTRet'];
|
|
if(isset($i['pST'])) $stdICMS->vBCSTRet = $i['pST'];
|
|
if(isset($i['vICMSSTRet'])) $stdICMS->vBCSTRet = $i['vICMSSTRet'];
|
|
if(isset($i['vICMSSubstituto'])) $stdICMS->vBCSTRet = $i['vICMSSubstituto'];
|
|
|
|
$somaICMS += (($i['valor_unitario'] * $i['quantidade'])
|
|
* ($stdICMS->pICMS/100));
|
|
$ICMS = $nfe->tagICMS($stdICMS);
|
|
} // fim tag icms
|
|
|
|
//PIS
|
|
$stdPIS = new \stdClass();
|
|
$stdPIS->item = $itemCont;
|
|
$stdPIS->CST = $i['cst_pis'];
|
|
$stdPIS->vBC = $this->format($i['perc_pis']) > 0 ? $stdProd->vProd : 0.00;
|
|
$stdPIS->pPIS = $this->format($i['perc_pis']);
|
|
$stdPIS->vPIS = $this->format($stdProd->vProd * ($i['perc_pis'] / 100));
|
|
$PIS = $nfe->tagPIS($stdPIS);
|
|
|
|
//COFINS
|
|
$stdCOFINS = new \stdClass();
|
|
$stdCOFINS->item = $itemCont;
|
|
$stdCOFINS->CST = $i['cst_cofins'];
|
|
$stdCOFINS->vBC = $this->format($i['cst_cofins']) > 0 ? $stdProd->vProd : 0.00;
|
|
$stdCOFINS->pCOFINS = $this->format($i['perc_cofins']);
|
|
$stdCOFINS->vCOFINS = $this->format($stdProd->vProd * ($i['perc_cofins'] / 100));
|
|
$COFINS = $nfe->tagCOFINS($stdCOFINS);
|
|
|
|
|
|
$std = new \stdClass(); //IPI
|
|
$std->item = $itemCont;
|
|
$std->clEnq = null;
|
|
$std->CNPJProd = null;
|
|
$std->cSelo = null;
|
|
$std->qSelo = null;
|
|
$std->cEnq = $i['cEnq'];
|
|
$std->CST = $i['cst_ipi'];
|
|
$std->vBC = $this->format($i['perc_ipi']) > 0 ? $stdProd->vProd : 0.00;
|
|
$std->pIPI = $this->format($i['perc_ipi']);
|
|
$somaIpi += $std->vIPI = $stdProd->vProd * $this->format(($i['perc_ipi'] / 100));
|
|
$std->qUnid = null;
|
|
$std->vUnid = null;
|
|
|
|
$IPI = $nfe->tagIPI($std);
|
|
|
|
}
|
|
|
|
$stdICMSTot = new \stdClass();
|
|
$stdICMSTot->vBC = $stdEmit->CRT == 3 ? $this->format($somaProdutos) : 0.00;
|
|
$stdICMSTot->vICMS = $this->format($somaICMS);
|
|
$stdICMSTot->vICMSDeson = 0.00;
|
|
$stdICMSTot->vBCST = 0.00;
|
|
$stdICMSTot->vST = 0.00;
|
|
$stdICMSTot->vProd = 0;
|
|
$stdICMSTot->vFrete = $frete != null ? $frete['valor'] : 0;
|
|
$stdICMSTot->vSeg = 0.00;
|
|
$stdICMSTot->vDesc = 0.00;
|
|
$stdICMSTot->vII = 0.00;
|
|
$stdICMSTot->vIPI = 0.00;
|
|
$stdICMSTot->vPIS = 0.00;
|
|
$stdICMSTot->vCOFINS = 0.00;
|
|
$stdICMSTot->vOutro = 0.00;
|
|
$stdICMSTot->vNF = $this->format($fatura['total_nf'] + $fatura['desconto']);
|
|
$stdICMSTot->vTotTrib = 0.00;
|
|
$ICMSTot = $nfe->tagICMSTot($stdICMSTot);
|
|
|
|
$stdTransp = new \stdClass();
|
|
$stdTransp->modFrete = $frete != null ? $frete['modelo'] : 9;
|
|
|
|
$transp = $nfe->tagtransp($stdTransp);
|
|
|
|
if ($frete != null) {
|
|
$stdVol = new \stdClass();
|
|
$stdVol->item = 1;
|
|
$stdVol->qVol = $frete['quantidade_volumes'];
|
|
$stdVol->esp = $frete['especie'];
|
|
|
|
$stdVol->nVol = $frete['numero_volumes'];
|
|
$stdVol->pesoL = $frete['peso_liquido'];
|
|
$stdVol->pesoB = $frete['peso_bruto'];
|
|
$vol = $nfe->tagvol($stdVol);
|
|
}
|
|
|
|
$respTec = ConfiguracaoSuper::first();
|
|
if($respTec != null){
|
|
$stdResp = new \stdClass();
|
|
$stdResp->CNPJ = preg_replace('/[^0-9]/', '', $respTec->cpf_cnpj);
|
|
$stdResp->xContato = $respTec->name;
|
|
$stdResp->email = $respTec->email;
|
|
$stdResp->fone = preg_replace('/[^0-9]/', '', $respTec->telefone);
|
|
$nfe->taginfRespTec($stdResp);
|
|
}
|
|
|
|
//Fatura
|
|
$stdFat = new \stdClass();
|
|
$stdFat->nFat = $stdIde->nNF;
|
|
$stdFat->vOrig = $this->format($fatura['total_nf']);
|
|
$stdFat->vDesc = $this->format($fatura['desconto']);
|
|
$stdFat->vLiq = $this->format($fatura['total_nf'] - $fatura['desconto']);
|
|
|
|
$fatura = $nfe->tagfat($stdFat);
|
|
|
|
$contFatura = 1;
|
|
foreach ($duplicatas as $ft) {
|
|
$stdDup = new \stdClass();
|
|
$stdDup->nDup = "00" . $contFatura;
|
|
$stdDup->dVenc = substr($ft['data_vencimento'], 0, 10);
|
|
$stdDup->vDup = $this->format($ft['valor']);
|
|
|
|
$nfe->tagdup($stdDup);
|
|
$contFatura++;
|
|
}
|
|
|
|
$stdPag = new \stdClass();
|
|
$pag = $nfe->tagpag($stdPag);
|
|
|
|
$stdDetPag = new \stdClass();
|
|
$stdDetPag->tPag = $pagamento['tipo'];
|
|
$stdDetPag->vPag = $this->format($somaProdutos);
|
|
$stdDetPag->indPag = 1;
|
|
$detPag = $nfe->tagdetPag($stdDetPag);
|
|
|
|
$stdInfoAdic = new \stdClass();
|
|
$stdInfoAdic->infCpl = $documento['info_complementar'];
|
|
$infoAdic = $nfe->taginfAdic($stdInfoAdic);
|
|
|
|
try{
|
|
$nfe->montaNFe();
|
|
$arr = [
|
|
'chave' => $nfe->getChave(),
|
|
'xml' => $nfe->getXML(),
|
|
'numero' => $stdIde->nNF
|
|
];
|
|
return $arr;
|
|
}catch(\Exception $e){
|
|
return [
|
|
'erros_xml' => $nfe->getErrors()
|
|
];
|
|
}
|
|
|
|
}
|
|
|
|
public function format($number, $dec = 2)
|
|
{
|
|
return number_format((float) $number, $dec, ".", "");
|
|
}
|
|
|
|
public function sign($xml){
|
|
return $this->tools->signNFe($xml);
|
|
}
|
|
|
|
public function transmitir($signXml, $chave){
|
|
try{
|
|
$idLote = str_pad(100, 15, '0', STR_PAD_LEFT);
|
|
$resp = $this->tools->sefazEnviaLote([$signXml], $idLote);
|
|
|
|
$st = new Standardize();
|
|
$std = $st->toStd($resp);
|
|
sleep(2);
|
|
if ($std->cStat != 103) {
|
|
|
|
// return "Erro: [$std->cStat] - $std->xMotivo";
|
|
return [
|
|
'erro' => 1,
|
|
'error' => "[$std->cStat] - $std->xMotivo"
|
|
];
|
|
}
|
|
$recibo = $std->infRec->nRec;
|
|
|
|
$protocolo = $this->tools->sefazConsultaRecibo($recibo);
|
|
sleep(4);
|
|
try {
|
|
$xml = Complements::toAuthorize($signXml, $protocolo);
|
|
file_put_contents(public_path('xml_nfe/').$chave.'.xml',$xml);
|
|
return [
|
|
'erro' => 0,
|
|
'success' => $recibo
|
|
];
|
|
// $this->printDanfe($xml);
|
|
} catch (\Exception $e) {
|
|
return [
|
|
'erro' => 1,
|
|
'error' => $st->toArray($protocolo)
|
|
];
|
|
}
|
|
|
|
} catch(\Exception $e){
|
|
return [
|
|
'erro' => 1,
|
|
'error' => $e->getMessage()
|
|
];
|
|
}
|
|
}
|
|
|
|
public function consultar($nfe){
|
|
try {
|
|
|
|
$this->tools->model('55');
|
|
|
|
$chave = $nfe->chave;
|
|
$response = $this->tools->sefazConsultaChave($chave);
|
|
|
|
$stdCl = new Standardize($response);
|
|
$arr = $stdCl->toArray();
|
|
|
|
return $arr;
|
|
|
|
} catch (\Exception $e) {
|
|
return ['erro' => true, 'data' => $e->getMessage(), 'status' => 402];
|
|
}
|
|
}
|
|
|
|
public function correcao($nfe, $correcao){
|
|
try {
|
|
|
|
$chave = $nfe->chave;
|
|
$xCorrecao = $correcao;
|
|
$nSeqEvento = $nfe->sequencia_cce+1;
|
|
$response = $this->tools->sefazCCe($chave, $xCorrecao, $nSeqEvento);
|
|
sleep(2);
|
|
|
|
$stdCl = new Standardize($response);
|
|
|
|
$std = $stdCl->toStd();
|
|
|
|
$arr = $stdCl->toArray();
|
|
|
|
$json = $stdCl->toJson();
|
|
|
|
if ($std->cStat != 128) {
|
|
//TRATAR
|
|
} else {
|
|
$cStat = $std->retEvento->infEvento->cStat;
|
|
if ($cStat == '135' || $cStat == '136') {
|
|
$xml = Complements::toAuthorize($this->tools->lastRequest, $response);
|
|
file_put_contents(public_path('xml_nfe_correcao/').$chave.'.xml',$xml);
|
|
|
|
$nfe->sequencia_cce = $nfe->sequencia_cce + 1;
|
|
$nfe->save();
|
|
return $arr;
|
|
|
|
} else {
|
|
//houve alguma falha no evento
|
|
return ['erro' => true, 'data' => $arr, 'status' => 402];
|
|
}
|
|
}
|
|
} catch (\Exception $e) {
|
|
return ['erro' => true, 'data' => $e->getMessage(), 'status' => 404];
|
|
}
|
|
}
|
|
|
|
public function cancelar($nfe, $motivo){
|
|
try {
|
|
|
|
$chave = $nfe->chave;
|
|
$response = $this->tools->sefazConsultaChave($chave);
|
|
$stdCl = new Standardize($response);
|
|
$arr = $stdCl->toArray();
|
|
sleep(1);
|
|
|
|
$nProt = $arr['protNFe']['infProt']['nProt'];
|
|
|
|
$response = $this->tools->sefazCancela($chave, $motivo, $nProt);
|
|
sleep(2);
|
|
$stdCl = new Standardize($response);
|
|
$std = $stdCl->toStd();
|
|
$arr = $stdCl->toArray();
|
|
$json = $stdCl->toJson();
|
|
|
|
if ($std->cStat != 128) {
|
|
//TRATAR
|
|
} else {
|
|
$cStat = $std->retEvento->infEvento->cStat;
|
|
if ($cStat == '101' || $cStat == '135' || $cStat == '155' ) {
|
|
$xml = Complements::toAuthorize($this->tools->lastRequest, $response);
|
|
file_put_contents(public_path('xml_nfe_cancelada/').$chave.'.xml',$xml);
|
|
|
|
return $arr;
|
|
} else {
|
|
|
|
return ['erro' => true, 'data' => $arr, 'status' => 402];
|
|
}
|
|
}
|
|
} catch (\Exception $e) {
|
|
// echo $e->getMessage();
|
|
return ['erro' => true, 'data' => $e->getMessage(), 'status' => 402];
|
|
//TRATAR
|
|
}
|
|
}
|
|
|
|
} |