예제 #1
0
 /**
  * Converte para Objetos RPS
  * @param string $txt lote de RPS em TXT formatado ou path para o arquivo
  * @return array
  * @throws InvalidArgumentException
  */
 public static function toRps($txt = '')
 {
     if (empty($txt)) {
         throw new InvalidArgumentException('Algum dado deve ser passado para converter.');
     }
     $aRps = array();
     if (is_file($txt)) {
         //extrai cada linha do arquivo em um campo de matriz
         $aDados = file($txt, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES | FILE_TEXT);
     } elseif (is_array($txt)) {
         //carrega a matriz
         $aDados = $txt;
     } else {
         if (strlen($txt) > 0) {
             //carrega a matriz com as linha do arquivo
             $aDados = explode("\n", $txt);
         } else {
             return $aRps;
         }
     }
     $total = count($aDados);
     for ($x = 0; $x < $total; $x++) {
         $aDados[$x] = str_replace("\r", '', $aDados[$x]);
         $aDados[$x] = Strings::cleanString($aDados[$x]);
         $tipo = substr($aDados[$x], 0, 1);
         self::$contTipos[$tipo] += 1;
     }
     self::validTipos();
     //o numero de notas criadas será a quantidade de tipo 2 ou 3 ou 6
     self::$numRps = self::$contTipos['2'] + self::$contTipos['3'] + self::$contTipos['6'];
     for ($x = 0; $x < self::$numRps; $x++) {
         self::$aRps[] = new Rps();
     }
     self::zArray2Rps($aDados);
     self::loadRPS();
     return self::$aRps;
 }
예제 #2
0
 /**
  * Clear the string of unwanted characters
  * Will remove all duplicated spaces and if wanted
  * replace all accented characters by their originals
  * and all the special ones
  * @param string $field string to be cleaned
  */
 private function clearFieldString(&$field)
 {
     $field = trim(preg_replace('/\\s+/', ' ', $field));
     if ($this->limparString) {
         $field = Strings::cleanString($field);
     }
 }
예제 #3
0
 /**
  * zSefazEvento
  * @param string $siglaUF
  * @param string $chNFe
  * @param string $tpAmb
  * @param string $tpEvento
  * @param string $nSeqEvento
  * @param string $tagAdic
  * @return string
  * @throws Exception\RuntimeException
  * @internal function zLoadServico (Common\Base\BaseTools)
  */
 protected function zSefazEvento($siglaUF = '', $chNFe = '', $tpAmb = '2', $tpEvento = '', $nSeqEvento = '1', $tagAdic = '')
 {
     if ($tpAmb == '') {
         $tpAmb = $this->aConfig['tpAmb'];
     }
     //carrega serviço
     $servico = 'RecepcaoEvento';
     $this->zLoadServico('nfe', $servico, $siglaUF, $tpAmb);
     if ($this->urlService == '') {
         $msg = "A recepção de eventos não está disponível na SEFAZ {$siglaUF}!!!";
         throw new Exception\RuntimeException($msg);
     }
     $aRet = $this->zTpEv($tpEvento);
     $aliasEvento = $aRet['alias'];
     $descEvento = $aRet['desc'];
     $cnpj = $this->aConfig['cnpj'];
     $dhEvento = (string) str_replace(' ', 'T', date('Y-m-d H:i:sP'));
     $sSeqEvento = str_pad($nSeqEvento, 2, "0", STR_PAD_LEFT);
     $eventId = "ID" . $tpEvento . $chNFe . $sSeqEvento;
     $cOrgao = $this->urlcUF;
     if ($siglaUF == 'AN') {
         $cOrgao = '91';
     }
     $mensagem = "<evento xmlns=\"{$this->urlPortal}\" versao=\"{$this->urlVersion}\">" . "<infEvento Id=\"{$eventId}\">" . "<cOrgao>{$cOrgao}</cOrgao>" . "<tpAmb>{$tpAmb}</tpAmb>" . "<CNPJ>{$cnpj}</CNPJ>" . "<chNFe>{$chNFe}</chNFe>" . "<dhEvento>{$dhEvento}</dhEvento>" . "<tpEvento>{$tpEvento}</tpEvento>" . "<nSeqEvento>{$nSeqEvento}</nSeqEvento>" . "<verEvento>{$this->urlVersion}</verEvento>" . "<detEvento versao=\"{$this->urlVersion}\">" . "<descEvento>{$descEvento}</descEvento>" . "{$tagAdic}" . "</detEvento>" . "</infEvento>" . "</evento>";
     //assinatura dos dados
     $signedMsg = $this->oCertificate->signXML($mensagem, 'infEvento');
     $signedMsg = Strings::clearXml($signedMsg, true);
     $numLote = LotNumber::geraNumLote();
     $cons = "<envEvento xmlns=\"{$this->urlPortal}\" versao=\"{$this->urlVersion}\">" . "<idLote>{$numLote}</idLote>" . "{$signedMsg}" . "</envEvento>";
     //valida mensagem com xsd
     //no caso do evento nao tem xsd organizado, esta fragmentado
     //e por vezes incorreto por isso essa validação está desabilitada
     //if (! $this->zValidMessage($cons, 'nfe', 'envEvento', $version)) {
     //    $msg = 'Falha na validação. '.$this->error;
     //    throw new Exception\RuntimeException($msg);
     //}
     $body = "<nfeDadosMsg xmlns=\"{$this->urlNamespace}\">{$cons}</nfeDadosMsg>";
     //envia a solicitação via SOAP
     $retorno = $this->oSoap->send($this->urlService, $this->urlNamespace, $this->urlHeader, $body, $this->urlMethod);
     $lastMsg = $this->oSoap->lastMsg;
     $this->soapDebug = $this->oSoap->soapDebug;
     //salva mensagens
     $filename = "{$chNFe}-{$aliasEvento}-envEvento.xml";
     $this->zGravaFile('nfe', $tpAmb, $filename, $lastMsg);
     $filename = "{$chNFe}-{$aliasEvento}-retEnvEvento.xml";
     $this->zGravaFile('nfe', $tpAmb, $filename, $retorno);
     //tratar dados de retorno
     $this->aLastRetEvent = ReturnNFe::readReturnSefaz($servico, $retorno);
     if ($this->aLastRetEvent['cStat'] == '128') {
         if ($this->aLastRetEvent['evento'][0]['cStat'] == '135' || $this->aLastRetEvent['evento'][0]['cStat'] == '136' || $this->aLastRetEvent['evento'][0]['cStat'] == '155') {
             $pasta = 'eventos';
             //default
             if ($aliasEvento == 'CancNFe') {
                 $pasta = 'canceladas';
                 $filename = "{$chNFe}-{$aliasEvento}-procEvento.xml";
             } elseif ($aliasEvento == 'CCe') {
                 $pasta = 'cartacorrecao';
                 $filename = "{$chNFe}-{$aliasEvento}-{$nSeqEvento}-procEvento.xml";
             }
             $retorno = $this->zAddProtMsg('procEventoNFe', 'evento', $signedMsg, 'retEvento', $retorno);
             $this->zGravaFile('nfe', $tpAmb, $filename, $retorno, $pasta);
         }
     }
     return (string) $retorno;
 }
예제 #4
0
 /**
  * zClean
  * Efetua limpeza dos campos
  *
  * @param  array $aCampos
  * @return array
  */
 protected function zClean($aCampos = array())
 {
     foreach ($aCampos as $campo) {
         $campo = trim(preg_replace('/\\s+/', ' ', $campo));
         if ($this->limparString) {
             $campo = Strings::cleanString($campo);
         }
     }
     return $aCampos;
 }
예제 #5
0
 /**
  * Envia mensagem ao webservice
  * @param string $urlsevice
  * @param string $namespace
  * @param string $header
  * @param string $body
  * @param string $method
  * @return boolean|string
  */
 public function send($urlservice, $namespace, $header, $body, $method)
 {
     //monta a mensagem ao webservice
     $data = '<?xml version="1.0" encoding="utf-8"?>' . '<soap12:Envelope ';
     $data .= 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ';
     $data .= 'xmlns:xsd="http://www.w3.org/2001/XMLSchema" ';
     $data .= 'xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">';
     $data .= '<soap12:Header>' . $header . '</soap12:Header>';
     $data .= '<soap12:Body>' . $body . '</soap12:Body>';
     $data .= '</soap12:Envelope>';
     $data = Strings::clearMsg($data);
     $this->lastMsg = $data;
     //tamanho da mensagem
     $tamanho = strlen($data);
     //estabelecimento dos parametros da mensagem
     //$parametros = array(
     //    'Content-Type: application/soap+xml;charset=utf-8;action="'.$namespace."/".$method.'"',
     //    'SOAPAction: "'.$method.'"',
     //    "Content-length: $tamanho");
     $parametros = array('Content-Type: application/soap+xml;charset=utf-8', 'SOAPAction: "' . $method . '"', "Content-length: {$tamanho}");
     //solicita comunicação via cURL
     $resposta = $this->zCommCurl($urlservice, $data, $parametros);
     if (empty($resposta)) {
         $msg = "Não houve retorno do Curl.\n {$this->errorCurl}";
         throw new Exception\RuntimeException($msg);
     }
     //obtem o bloco html da resposta
     $xPos = stripos($resposta, "<");
     $blocoHtml = substr($resposta, 0, $xPos);
     if ($this->infoCurl["http_code"] != '200') {
         //se não é igual a 200 houve erro
         $msg = $blocoHtml;
         throw new Exception\RuntimeException($msg);
     }
     //obtem o tamanho da resposta
     $lenresp = strlen($resposta);
     //localiza a primeira marca de tag
     $xPos = stripos($resposta, "<");
     //se não existir não é um xml nem um html
     if ($xPos !== false) {
         $xml = substr($resposta, $xPos, $lenresp - $xPos);
     } else {
         $xml = '';
     }
     //testa para saber se é um xml mesmo ou é um html
     $result = simplexml_load_string($xml, 'SimpleXmlElement', LIBXML_NOERROR + LIBXML_ERR_FATAL + LIBXML_ERR_NONE);
     if ($result === false) {
         //não é um xml então pode limpar
         $xml = '';
     }
     if ($xml == '') {
         $msg = "Não houve retorno de um xml verifique soapDebug!!";
         throw new Exception\RuntimeException($msg);
     }
     if ($xml != '' && substr($xml, 0, 5) != '<?xml') {
         $xml = '<?xml version="1.0" encoding="utf-8"?>' . $xml;
     }
     return $xml;
 }
예제 #6
0
 /**
  * Carga tributária total estimada
  * Dados normalmente obtidos no IBPT
  * @param float $valor
  * @param float $percentual
  * @param string $fonte
  */
 public function cargaTributaria($valor, $percentual, $fonte)
 {
     $this->valorCargaTributariaRPS = number_format($valor, 2, '.', '');
     $this->percentualCargaTributariaRPS = number_format($percentual, 4, '.', '');
     $this->fonteCargaTributariaRPS = substr(Strings::cleanString($fonte), 0, 10);
 }
예제 #7
0
 public function cancelamento($motivo)
 {
     $this->motCancelamento = Strings::cleanString($motivo);
 }
예제 #8
0
 /**
  * addCancelamento
  * Adiciona a tga de cancelamento a uma CTe já autorizada
  * NOTA: não é requisito da SEFAZ, mas auxilia na identificação das CTe que foram canceladas
  * @param string $pathCTefile
  * @param string $pathCancfile
  * @param bool $saveFile
  * @return string
  * @throws Exception\RuntimeException
  */
 public function addCancelamento($pathCTefile = '', $pathCancfile = '', $saveFile = false)
 {
     $procXML = '';
     //carrega a CTe
     $docCTe = new Dom();
     if (file_exists($pathCTefile)) {
         //carrega o XML pelo caminho do arquivo informado
         $docCTe->loadXMLFile($pathCTefile);
     } else {
         //carrega o XML pelo conteúdo
         $docCTe->loadXMLString($pathCTefile);
     }
     $nodeCTe = $docCTe->getNode('CTe', 0);
     if ($nodeCTe == '') {
         $msg = "O arquivo indicado como CTe não é um xml de CTe!";
         throw new Exception\RuntimeException($msg);
     }
     $proCTe = $docCTe->getNode('protCTe');
     if ($proCTe == '') {
         $msg = "A CTe não está protocolada ainda!!";
         throw new Exception\RuntimeException($msg);
     }
     $chaveCTe = $proCTe->getElementsByTagName('chCTe')->item(0)->nodeValue;
     //$nProtCTe = $proCTe->getElementsByTagName('nProt')->item(0)->nodeValue;
     $tpAmb = $docCTe->getNodeValue('tpAmb');
     $anomes = date('Ym', DateTime::convertSefazTimeToTimestamp($docCTe->getNodeValue('dhEmi')));
     //carrega o cancelamento
     //pode ser um evento ou resultado de uma consulta com multiplos eventos
     $doccanc = new Dom();
     if (file_exists($pathCancfile)) {
         //carrega o XML pelo caminho do arquivo informado
         $doccanc->loadXMLFile($pathCancfile);
     } else {
         //carrega o XML pelo conteúdo
         $doccanc->loadXMLString($pathCancfile);
     }
     $retEvento = $doccanc->getElementsByTagName('retEventoCTe')->item(0);
     $eventos = $retEvento->getElementsByTagName('infEvento');
     foreach ($eventos as $evento) {
         //evento
         $cStat = $evento->getElementsByTagName('cStat')->item(0)->nodeValue;
         $tpAmb = $evento->getElementsByTagName('tpAmb')->item(0)->nodeValue;
         $chaveEvento = $evento->getElementsByTagName('chCTe')->item(0)->nodeValue;
         $tpEvento = $evento->getElementsByTagName('tpEvento')->item(0)->nodeValue;
         //$nProtEvento = $evento->getElementsByTagName('nProt')->item(0)->nodeValue;
         //verifica se conferem os dados
         //cStat = 135 ==> evento homologado
         //cStat = 136 ==> vinculação do evento à respectiva NF-e prejudicada
         //cStat = 155 ==> Cancelamento homologado fora de prazo
         //tpEvento = 110111 ==> Cancelamento
         //chave do evento == chave da CTe
         //protocolo do evneto ==  protocolo da CTe
         if (($cStat == '135' || $cStat == '136' || $cStat == '155') && $tpEvento == '110111' && $chaveEvento == $chaveCTe) {
             $proCTe->getElementsByTagName('cStat')->item(0)->nodeValue = '101';
             $proCTe->getElementsByTagName('xMotivo')->item(0)->nodeValue = 'Cancelamento de CT-e homologado';
             $procXML = $docCTe->saveXML();
             //remove as informações indesejadas
             $procXML = Strings::clearProt($procXML);
             if ($saveFile) {
                 $filename = "{$chaveCTe}-protCTe.xml";
                 $this->zGravaFile('cte', $tpAmb, $filename, $procXML, 'canceladas', $anomes);
             }
             break;
         }
     }
     return (string) $procXML;
 }
예제 #9
0
 /**
  * zSefazEvento
  *
  * @param    string $siglaUF
  * @param    string $chave
  * @param    string $cOrgao
  * @param    string $tpAmb
  * @param    string $tpEvento
  * @param    string $nSeqEvento
  * @param    string $tagAdic
  * @return   string
  * @throws   Exception\RuntimeException
  * @internal function zLoadServico (Common\Base\BaseTools)
  */
 protected function zSefazEvento($siglaUF = '', $chave = '', $cOrgao = '', $tpAmb = '2', $tpEvento = '', $nSeqEvento = '1', $tagAdic = '')
 {
     if ($tpAmb == '') {
         $tpAmb = $this->aConfig['tpAmb'];
     }
     //carrega serviço
     $servico = 'MDFeRecepcaoEvento';
     $this->zLoadServico('mdfe', $servico, $siglaUF, $tpAmb);
     if ($this->urlService == '') {
         $msg = "A recepção de eventos não está disponível na SEFAZ {$siglaUF}!!!";
         throw new Exception\RuntimeException($msg);
     }
     $aRet = $this->zTpEv($tpEvento);
     $aliasEvento = $aRet['alias'];
     $cnpj = $this->aConfig['cnpj'];
     $dhEvento = (string) str_replace(' ', 'T', date('Y-m-d H:i:s'));
     $sSeqEvento = str_pad($nSeqEvento, 2, "0", STR_PAD_LEFT);
     $eventId = "ID" . $tpEvento . $chave . $sSeqEvento;
     if ($cOrgao == '') {
         $cOrgao = $this->urlcUF;
     }
     $mensagem = "<eventoMDFe xmlns=\"{$this->urlPortal}\" versao=\"{$this->urlVersion}\">" . "<infEvento Id=\"{$eventId}\">" . "<cOrgao>{$cOrgao}</cOrgao>" . "<tpAmb>{$tpAmb}</tpAmb>" . "<CNPJ>{$cnpj}</CNPJ>" . "<chMDFe>{$chave}</chMDFe>" . "<dhEvento>{$dhEvento}</dhEvento>" . "<tpEvento>{$tpEvento}</tpEvento>" . "<nSeqEvento>{$nSeqEvento}</nSeqEvento>" . "<detEvento versaoEvento=\"{$this->urlVersion}\">" . "{$tagAdic}" . "</detEvento>" . "</infEvento>" . "</eventoMDFe>";
     //assinatura dos dados
     $signedMsg = $this->oCertificate->signXML($mensagem, 'infEvento');
     $cons = Strings::clearXml($signedMsg, true);
     //valida mensagem com xsd
     //no caso do evento nao tem xsd organizado, esta fragmentado
     //e por vezes incorreto por isso essa validação está desabilitada
     //if (! $this->zValidMessage($cons, 'mdfe', 'eventoMDFe', $version)) {
     //    $msg = 'Falha na validação. '.$this->error;
     //    throw new Exception\RuntimeException($msg);
     //}
     $body = "<mdfeDadosMsg xmlns=\"{$this->urlNamespace}\">{$cons}</mdfeDadosMsg>";
     //envia a solicitação via SOAP
     $retorno = $this->oSoap->send($this->urlService, $this->urlNamespace, $this->urlHeader, $body, $this->urlMethod);
     $lastMsg = $this->oSoap->lastMsg;
     $this->soapDebug = $this->oSoap->soapDebug;
     //salva mensagens
     $filename = "{$chave}-{$aliasEvento}-eventoMDFe.xml";
     $this->zGravaFile('mdfe', $tpAmb, $filename, $lastMsg);
     $filename = "{$chave}-{$aliasEvento}-retEventoMDFe.xml";
     $this->zGravaFile('mdfe', $tpAmb, $filename, $retorno);
     //tratar dados de retorno
     $this->aLastRetEvent = Response::readReturnSefaz($servico, $retorno);
     return (string) $retorno;
 }