Skip to content

Instantly share code, notes, and snippets.

@allanfreitas
Forked from luizvaz/smarapd_203.php
Created February 19, 2023 19:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save allanfreitas/2e68f9fc15ec017d8f2c41da18ccfea7 to your computer and use it in GitHub Desktop.
Save allanfreitas/2e68f9fc15ec017d8f2c41da18ccfea7 to your computer and use it in GitHub Desktop.
Assinatura e Envio de XML SMARAPD padrão ABRASF 2.03 (Vila Velha)
<?php
/**
* User: LuizVAz
* Date: 28/02/2021
* Time: 19:46
*/
namespace Provedores\webService;
use DOMDocument;
use DOMXPath;
use Exception;
use RobRichards\XMLSecLibs\XMLSecEnc;
use RobRichards\XMLSecLibs\XMLSecurityDSig;
use RobRichards\XMLSecLibs\XMLSecurityKey;
use Slim\App;
use Slim\Http\Request;
use Slim\Http\Response;
use stdClass;
class smarapd_v001 extends \Provedores\webService\webService
{
private $cnpj;
private $dir;
private $nfs_dir;
private $rps_dir;
protected $rps_id;
protected $rps_serie;
private $user;
public function __construct(Request $request, Response $response, App $app){
parent::__construct($request, $response, $app);
$ym = date('Ym');
$this->dir = $dir = getenv('BASE_PATH');
$this->user = "your_code";
$this->cnpj = "your_code";
$this->inscricaoMunicipal = "your_code";
$this->rps_dir = "$dir/$cnpj/rps/$ym/";
$this->nfs_dir = "$dir/$cnpj/nfse/$ym/";
$this->rps_id = date('Ymd') . str_pad(time() - strtotime("today"), 5, '0');
$this->rps_serie = "ws1";
}
public function consultar(stdClass $rps){
$this->rps = $rps;
return $this->consultaNFsePorRps();
}
public function consultaNFsePorRps(): stdClass
{
// Retorno
$return = new stdClass();
$return->status = 500;
$return->data = array("success" => false);
// Parametros
$rps_numero = $this->rps_id;
$rps_serie = $this->rps_serie;
$rps_tipo = "1";
$rps_cnpj = $this->cnpj;
$rps_im = $this->inscricaoMunicipal;
$envelope = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:nfse=\"http://nfse.abrasf.org.br\">
<soapenv:Header/>
<soapenv:Body>
<nfse:consultarNfsePorRps>
<xml><![CDATA[<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<ConsultarNfseRpsEnvio xmlns=\"http://www.abrasf.org.br/nfse.xsd\">
<IdentificacaoRps>
<Numero>$rps_numero</Numero>
<Serie>$rps_serie</Serie>
<Tipo>$rps_tipo</Tipo>
</IdentificacaoRps>
<Prestador>
<CpfCnpj>
<Cnpj>$rps_cnpj</Cnpj>
</CpfCnpj>
<InscricaoMunicipal>$rps_im</InscricaoMunicipal>
</Prestador>
</ConsultarNfseRpsEnvio>]]></xml>
</nfse:consultarNfsePorRps>
</soapenv:Body>
</soapenv:Envelope>";
$url = $this->end_prod;
if ($this->rps->ambienteEmissao && (strtolower($this->rps->ambienteEmissao) === "homologacao")){
$url = $this->end_homo;
}
$ret = $this->sendRequest($envelope, "", $url);
$html = $ret['html'];
$httpcode = $ret['code'];
if ($httpcode!=200){
preg_match_all('/<faultstring>(.*?)<\/faultstring>/s', html_entity_decode($html), $matches);
$response = (count($matches)&&count($matches[1])?$matches[1][0]:$html);
$return->data['errors'][] = [
"codigo" => $httpcode,
"mensagem" => $response,
"correcao" => ""
];
return $return;
}
// Extrai Retorno SOAP
preg_match_all('/<return>(.*?)<\/return>/s', html_entity_decode($html), $matches);
$response = (count($matches)&&count($matches[1])?$matches[1][0]:$html);
// Parse
$return->status = $httpcode;
$this->parseRetorno($response, $return);
return $return;
}
public function emitir(stdClass $rps){
$this->rps = $rps;
return $this->gerarNfse();
}
public function gerarNfse(): stdClass
{
//Live Mode
$live = true;
//Retorno
$return = new stdClass();
$return->status = 500;
$return->data = array("success" => false);
$rps_dir = $this->rps_dir;
//rps_id ou idExterno
$rps_id = (property_exists($this->rps, 'idExterno'))?$this->rps->idExterno:$this->rps_id;
if (!$rps_id){
$rps_id = date('Ymd') . str_pad(time() - strtotime("today"), 5, '0');
$this->rps_id = $rps_id;
} else
$this->rps_id = $rps_id;
//Garante que o diretório exista
$fname = "${rps_dir}${rps_id}.xml";
if (!file_exists("${rps_dir}")) {
mkdir("${rps_dir}", 0777, true);
}
$envelope =
"<soapenv:Envelope ".
" xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" ".
" xmlns:nfse=\"http://nfse.abrasf.org.br\">".
" <soapenv:Header/>".
" <soapenv:Body>".
" <nfse:recepcionarLoteRpsSincrono>".
" <xml><![CDATA[%DadosMsg%]]></xml>".
" </nfse:recepcionarLoteRpsSincrono>".
" </soapenv:Body>".
"</soapenv:Envelope>";
//Ambiente: 1 = Produção, 2 = Homologação
$amb = '1';
if ($this->rps->ambienteEmissao && (strtolower($this->rps->ambienteEmissao) === "homologacao")){
$amb = '2';
}
if ($live) {
//xml
$xml = $this->rpsAsXML();
/* $xml = str_ireplace('<?xml version="1.0" encoding="utf-8"?>', '', $xml); */
file_put_contents("$fname", $xml);
//$cab = htmlentities($cab, ENT_XML1 | ENT_NOQUOTES);
//$xml = htmlentities($xml, ENT_XML1 | ENT_NOQUOTES);
//$envelope = str_replace('%CabMsg%', $cab, $envelope);
$envelope = str_replace('%DadosMsg%', $xml, $envelope);
file_put_contents("${rps_dir}${rps_id}.soap", $envelope);
}
if ($live) {
//Live Mode
$url = $this->end_prod;
if ($this->rps->ambienteEmissao && (strtolower($this->rps->ambienteEmissao) === "homologacao")){
$url = $this->end_homo;
}
$ret = $this->sendRequest($envelope, "", $url);
$html = $ret["html"];
// Converte de UTF-8 para ISO-8859
//$html = utf8_decode(curl_exec($ch));
$httpcode = $ret["code"];
$return->status = $httpcode;
file_put_contents("$fname.ret", $html);
$html = utf8_decode($html); //Converter Depois de Salvo
} else {
//Test Mode
$httpcode = 200;
$return->status = $httpcode;
$html = file_get_contents("$fname.ret");
}
if ($httpcode!=200){
preg_match_all('/<faultstring>(.*?)<\/faultstring>/s', html_entity_decode($html), $matches);
$response = (count($matches)&&count($matches[1])?$matches[1][0]:$html);
$return->data['errors'][] = [
"codigo" => $httpcode,
"mensagem" => $response,
"correcao" => ""
];
return $return;
}
//Extrai
preg_match_all('/<return>(.*?)<\/return>/s', html_entity_decode($html), $matches);
$response = (count($matches)&&count($matches[1])?$matches[1][0]:$html);
$return = $this->parseRetorno($response, $return);
return $return;
}
public function parseRetorno($response, $return): stdClass
{
$dom = new DOMDocument();
$dom->preserveWhiteSpace = false;
//Verifica falha ao processar XML de RETORNO
if (@$dom->loadXML($response) === false){
//Retorno
$return->data['errors'][] = [
"codigo" => "500",
"mensagem" => "$response",
"correcao" => "Contate o suporte!"
];
return $return;
}
$xp = new DOMXPath($dom);
$xp->registerNamespace('fake', "http://nfse.abrasf.org.br");
// /retornoNfseLote/errors/erro
$nodes = $xp->query("/*/*/*[name()='MensagemRetorno']");
if ($nodes->length != 0){
if (!array_key_exists('errors', $return->data))
$return->data['errors'] = [];
for ($i = 0; $i<$nodes->length; $i++){
$msg = $nodes->item($i);
//Tags
$cod = $msg->getElementsByTagName("Codigo");
if ($cod->length>0) {
$cod = $cod->item(0);
$cod = $cod->nodeValue;
if (strlen($cod)>5) $cod = "E00"; //Texto redundante
} else
$cod = "E00";
$txt = $msg->getElementsByTagName("Mensagem");
if ($txt->length>0) {
$txt = $txt->item(0);
$txt = $txt->nodeValue;
} else
$txt = "";
$cor = $msg->getElementsByTagName("Correcao");
if ($cor->length>0) {
$cor = $cor->item(0);
$cor = $cor->nodeValue;
} else
$cor = "";
//Retorno
$return->data['errors'][] = [
"codigo" => $cod,
"mensagem" => $txt,
"correcao" => $cor
];
}
return $return;
}
// Resposta EnviarLoteRpsSincrono
$nodes = $xp->query("/*[name()='EnviarLoteRpsSincronoResposta']");
if ($nodes->length != 0){
$nfseId = "";
$msg = $nodes->item(0);
$proto = $msg->getElementsByTagName("Protocolo");
$proto = ($proto->length>0)?$proto = $proto->item(0)->nodeValue:"0";
$return->data['protocolo'] = $proto;
$lote = $msg->getElementsByTagName("NumeroLote");
$lote = ($lote->length>0)?$lote = $lote->item(0)->nodeValue:"0";
$return->data['numeroLote'] = $lote;
// Consulta por Lote não funciona
// Precisa pegar pelo RPS
$return = $this->consultaNFsePorRps();
// Pussui Erros
if (array_key_exists('errors', $return->data)){
return $return;
}
// Salva Retorno
$num = $return->data["numero"];
$nfs_dir = $this->nfs_dir;
$fname = "${nfs_dir}${num}.xml";
if (!file_exists(dirname("$fname"))) {
mkdir(dirname("$fname"), 0777, true);
}
file_put_contents($fname, $msg->ownerDocument->saveXML());
$return->data['success'] = true;
}
// Possui Nota
$nodes = $xp->query("//CompNfse");
if ($nodes->length != 0) {
$nfseId = "";
$msg = $nodes->item(0);
$id = $msg->getElementsByTagName("InfNfse");
$id = ($id->length && ($id = $id->item(0)->getAttribute("Id")))?$id:$this->rps_id;
$num = $msg->getElementsByTagName("Numero");
$num = ($num->length)?$num->item(0)->nodeValue:$this->rps_id;
$cod = $msg->getElementsByTagName("CodigoVerificacao");
$cod = ($cod->length)?$cod->item(0)->nodeValue:"N/D";
$dat = $msg->getElementsByTagName("DataEmissao");
$dat = ($dat->length)?$dat->item(0)->nodeValue:"";
$dat = str_ireplace(' ', 'T', $dat);
$return->data['nfseId'] = $id;
$return->data['numero'] = $num;
$return->data['codigoVerificacao'] = $cod;
$return->data['dataEmissao'] = $dat;
$return->data['success'] = true;
}
return $return;
}
public function rpsAsXML()
{
//DOM
$dom = new DOMDocument('1.0', 'utf-8');
$dom->formatOutput = true;
$dom->preserveWhiteSpace = true;
$dom->appendChild($enviarLoteRpsSincronoEnvio = $dom->createElement("EnviarLoteRpsSincronoEnvio"));
$enviarLoteRpsSincronoEnvio->setAttribute("xmlns", "http://www.abrasf.org.br/nfse.xsd");
// LoteRps
$enviarLoteRpsSincronoEnvio->appendChild($loteRps = $dom->createElement("LoteRps"));
$loteId = date('Ymd') . str_pad(time() - strtotime("today"), 5, '0');
$loteRps->setAttribute("versao", "2.03");
$loteRps->setAttribute("Id", "$loteId");
$loteRps->appendChild( $dom->createElement("NumeroLote", "$loteId"));
$loteRps->appendChild( $cpfCnpj = $dom->createElement("CpfCnpj"));
$cpfCnpj->appendChild( $dom->createElement("Cnpj", $this->conf->cnpj));
$loteRps->appendChild( $dom->createElement("InscricaoMunicipal", $this->conf->inscricaoMunicipal));
$loteRps->appendChild( $dom->createElement("QuantidadeRps", "1"));
// ListaRps
$loteRps->appendChild( $listaRps = $dom->createElement("ListaRps"));
//Rps
$listaRps->appendChild( $rps1 = $dom->createElement("Rps"));
//InfDeclaracaoPrestacaoServico
$rps1->appendChild( $infDec = $dom->createElement("InfDeclaracaoPrestacaoServico"));
$infDec->setAttribute("Id", "A".$this->rps_id);
//Rps
$infDec->appendChild( $rps2 = $dom->createElement("Rps"));
$rps2->setAttribute("Id", "B".$this->rps_id);
//IdentificacaoRps
$rps2->appendChild( $identificacaoRps = $dom->createElement("IdentificacaoRps"));
$identificacaoRps->appendChild($dom->createElement("Numero",$this->rps_id));
$identificacaoRps->appendChild($dom->createElement("Serie",$this->rps_serie));
$identificacaoRps->appendChild($dom->createElement("Tipo","1"));
//Formato yyyy-mm-dd
$dataEmissao = date("Y-m-d");
if ($this->rps->dataEmissao){
$dataEmissao = new \DateTime($this->rps->dataEmissao);
$dataEmissao = $dataEmissao->format('Y-m-d');
}
//DataEmissao
$rps2->appendChild($dom->createElement("DataEmissao",$dataEmissao));
//Status
$rps2->appendChild($dom->createElement("Status","1"));
//Competencia
$infDec->appendChild($dom->createElement("Competencia",$dataEmissao));
//Servico
$servico = $dom->createElement("Servico");
//Valores
$valores = $dom->createElement("Valores");
$valorTotal = 0.00;
$valor = (property_exists($this->rps->servico, 'valorServicos')?0.00+$this->rps->servico->valorServicos:0);
if (!$valor)
$valor = (property_exists($this->rps, 'valorTotal')?0.00+$this->rps->valorTotal:0);
if ($valor == 0)
throw new Exception("Informação servico->valorServicos não informada.");
$valores->appendChild(
$dom->createElement("ValorServicos", $this->formatValor($valor))
);
$valorTotal += $valor;
$valor = (property_exists($this->rps->servico, 'valorDeducoes')?0.00+$this->rps->servico->valorDeducoes:0);
if ($valor)
$valores->appendChild(
$dom->createElement("ValorDeducoes", $this->formatValor($valor))
);
$valorTotal -= $valor;
$aliquotaIss = 0;
if (property_exists($this->rps->servico, 'aliquotaIss'))
$aliquotaIss = 0.00+$this->rps->servico->aliquotaIss;
if ($aliquotaIss == 0)
if (property_exists($this->rps->servico, 'aliquota'))
$aliquotaIss = 0.00+$this->rps->servico->aliquota;
if ($aliquotaIss == 0)
throw new Exception("Informação aliquotaIss não encontrada.");
$valorIss = round($valorTotal * $aliquotaIss, 2, PHP_ROUND_HALF_EVEN);
$valores->appendChild($dom->createElement("ValorIss", $this->formatValor($valorIss*1)));
$valores->appendChild($dom->createElement("Aliquota", $this->formatValor($aliquotaIss*100)));
$servico->appendChild($valores);
//Servico
//issRetido
$issRetido = (property_exists($this->rps, 'issRetidoFonte')?$this->rps->issRetidoFonte:false);
$servico->appendChild($dom->createElement("IssRetido", $issRetido?'1':'2'));
//itemListaServicoLC116
$itemListaServico = (property_exists($this->rps, 'itemListaServicoLC116')?$this->rps->itemListaServicoLC116:false);
if (!$itemListaServico)
$itemListaServico = (property_exists($this->rps->servico, 'itemListaServico')?$this->rps->servico->itemListaServico:false);
if (!$itemListaServico)
$itemListaServico = $this->conf->itemListaServicoLC116;
$servico->appendChild($dom->createElement("ItemListaServico", $itemListaServico));
//cnae
/*
$cnae = (property_exists($this->rps, 'cnae')?$this->rps->cnae:false);
if (!$cnae)
$cnae = $this->conf->cnae;
$servico->appendChild($dom->createElement("CodigoCnae", $cnae));
*/
//codigoTributacaoMunicipio
$codigoTributacaoMunicipio = (property_exists($this->rps->servico, 'codigoTributacaoMunicipio')?$this->rps->servico->codigoTributacaoMunicipio:false);
if ($codigoTributacaoMunicipio)
$servico->appendChild($dom->createElement("CodigoTributacaoMunicipio", $codigoTributacaoMunicipio));
//descricao
$descricao = (property_exists($this->rps->servico, 'discriminacao')?$this->rps->servico->discriminacao:"");
if (!$descricao)
$descricao = (property_exists($this->rps->servico, 'descricao')?$this->rps->servico->descricao:"");
if (!$descricao)
$descricao = $this->conf->descricaoServico;
$observacao = (property_exists($this->rps->servico, 'observacao')?$this->rps->servico->observacao:"");
$descricao = ($descricao) ? "$descricao\n$observacao" : $observacao;
if ($descricao) {
// Essa limpeza será feita logo abaixo
//$descricao = str_replace(array("\r\n", "\r", "\n", "\t"), "", $descricao);
//$descricao = $this->remove_accents($descricao);
$servico->appendChild($dom->createElement("Discriminacao", $descricao));
}
//codigoMunicipio
$codigoMunicipio = (property_exists($this->rps->servico, 'codigoMunicipio')?$this->rps->servico->codigoMunicipio:0);
if (!$codigoMunicipio)
$codigoMunicipio = $this->conf->endereco->codigoIbgeCidade;
$servico->appendChild($dom->createElement("CodigoMunicipio", $codigoMunicipio));
//exigibilidadeISS
$servico->appendChild($dom->createElement("ExigibilidadeISS", "1"));
//municipioIncidencia
$municipioIncidencia = (property_exists($this->rps->servico, 'municipioPrestacaoServico')?$this->rps->servico->municipioPrestacaoServico:0);
if (!$municipioIncidencia)
$municipioIncidencia = $codigoMunicipio;
$servico->appendChild($dom->createElement("MunicipioIncidencia", $municipioIncidencia));
$infDec->appendChild($servico);
//prestador
$infDec->appendChild($prestador = $dom->createElement("Prestador"));
$cpfCnpj = $dom->createElement("CpfCnpj");
$cnpj = $dom->createElement("Cnpj", $this->conf->cnpj);
$cpfCnpj->appendChild($cnpj);
$prestador->appendChild($cpfCnpj);
$im = $dom->createElement("InscricaoMunicipal", $this->conf->inscricaoMunicipal);
$prestador->appendChild($im);
//Tomador
$infDec->appendChild($tomador = $dom->createElement("Tomador"));
$identificacaoTomador = $dom->createElement("IdentificacaoTomador");
$cpfCnpj = $dom->createElement("CpfCnpj");
$doc = null;
$temp = (property_exists($this->rps->cliente, 'cpfCnpj')?$this->rps->cliente->cpfCnpj:"");
if (strlen($temp)==14)
$doc = $dom->createElement("Cnpj", $this->rps->cliente->cpfCnpj);
elseif (strlen($temp)==11)
$doc = $dom->createElement("Cpf", $this->rps->cliente->cpfCnpj);
if ($doc){
$cpfCnpj->appendChild($doc);
$identificacaoTomador->appendChild($cpfCnpj);
}
if (property_exists($this->rps->cliente, 'inscricaoMunicipal')){
$doc = $dom->createElement('InscricaoMunicipal', $this->rps->cliente->inscricaoMunicipal);
$identificacaoTomador->appendChild($doc);
}
$tomador->appendChild($identificacaoTomador);
$temp = (property_exists($this->rps->cliente, 'nome')?$this->rps->cliente->nome:"");
if (!$temp)
$temp = (property_exists($this->rps->cliente, 'razaoSocial')?$this->rps->cliente->razaoSocial:"");
if ($temp)
$tomador->appendChild($dom->createElement("RazaoSocial", $temp));
//Endereço
$endereco = $dom->createElement("Endereco");
$temp = (property_exists($this->rps->cliente->endereco, 'logradouro')?$this->rps->cliente->endereco->logradouro:"");
if ($temp)
$endereco->appendChild($dom->createElement("Endereco", $temp));
$temp = (property_exists($this->rps->cliente->endereco, 'numero')?$this->rps->cliente->endereco->numero:"");
if ($temp)
$endereco->appendChild($dom->createElement("Numero", $temp));
$temp = (property_exists($this->rps->cliente->endereco, 'bairro')?$this->rps->cliente->endereco->bairro:"");
if ($temp)
$endereco->appendChild($dom->createElement("Bairro", $temp));
$temp = (property_exists($this->rps->cliente->endereco, 'cidade')?$this->rps->cliente->endereco->cidade:"");
if (!$temp)
$temp = (property_exists($this->rps->cliente->endereco, 'codigoMunicipio')?$this->rps->cliente->endereco->codigoMunicipio:"");
if ($temp)
$endereco->appendChild($dom->createElement("CodigoMunicipio", $temp));
$temp = (property_exists($this->rps->cliente->endereco, 'UF')?$this->rps->cliente->endereco->UF:"");
if ($temp)
$endereco->appendChild($dom->createElement("Uf", $temp));
$temp = (property_exists($this->rps->cliente->endereco, 'CEP')?$this->rps->cliente->endereco->CEP:"");
if ($temp)
$endereco->appendChild($dom->createElement("Cep", $temp));
if ($endereco->childNodes->length > 0)
$tomador->appendChild($endereco);
//Contato
$contato = $dom->createElement("Contato");
$temp = (property_exists($this->rps->cliente, 'telefone')?$this->rps->cliente->telefone:"");
if ($temp)
$contato->appendChild($dom->createElement("Telefone", $temp));
$temp = (property_exists($this->rps->cliente, 'email')?$this->rps->cliente->email:"");
if ($temp)
$contato->appendChild($dom->createElement("Email", $temp));
if ($tomador->childNodes->length > 0)
$tomador->appendChild($contato);
//RegimeEspecialTributacao
if ($this->conf->regimeEspecialTributacao)
$infDec->appendChild($dom->createElement("RegimeEspecialTributacao", $this->conf->regimeEspecialTributacao));
//OptanteSimplesNacional
$infDec->appendChild($dom->createElement("OptanteSimplesNacional", $this->conf->optanteSimplesNacional?'1':'2'));
$infDec->appendChild($dom->createElement("IncentivoFiscal", $this->conf->incentivadorCultural?'1':'2'));
//Retorna o RPS em formato XML
// limpeza do xml com a retirada dos TAB e Acentos
$decl = str_replace(array("\t"), '', $dom->saveXML());
$decl = $this->remove_accents($decl);
// Não remover a formatação depois de assinado
$decl = $this->assinaXML($decl, 'InfDeclaracaoPrestacaoServico');
$decl = str_ireplace('<?xml version="1.0" encoding="UTF-8"?>', '', $decl);
$lote = $this->assinaXML($decl, 'LoteRps');
return $lote;
}
function assinaXML($docxml, $tag){
try {
$tagid = $tag;
$crt_dir = dirname(dirname($this->rps_dir)) . '/cert';
$priKEY = "$crt_dir/pkey.pem";
$keypass = file_get_contents("$crt_dir/pass.txt");
$pubKEY = "$crt_dir/cert.pem";
// Habilita a manipulação de erros da libxml
libxml_use_internal_errors(true);
//limpar erros anteriores que possam estar em memória
libxml_clear_errors();
// carrega o documento no DOM
$xmldoc = new DOMDocument('1.0', 'UTF-8');
$xmldoc->preservWhiteSpace = true; //elimina espaços em branco
$xmldoc->formatOutput = false;
// muito importante deixar ativadas as opções para limpar os espacos em branco
// e as tags vazias
if (!$xmldoc->loadXML($docxml, LIBXML_NOBLANKS | LIBXML_NOXMLDECL | LIBXML_BIGLINES)) {
$msg = "Erro ao carregar XML, provavel erro no proprio xml!!";
$errors = libxml_get_errors();
if (!empty($errors)) {
$i = 1;
foreach ($errors as $error) {
$msg .= "\n [$i]-" . trim($error->message);
}
libxml_clear_errors();
}
throw new Exception($msg);
}
//extrair a tag com os dados a serem assinados
$xpath = new DOMXPath($xmldoc);
$xpath->registerNamespace('ns', "http://www.abrasf.org.br/nfse.xsd");
$node = $xpath->query("//ns:{$tagid}")->item(0);
if (!isset($node)) {
$msg = "A tag <$tagid> não existe no XML!!";
throw new Exception($msg);
}
// Cria novo Security object
$objDSig = new XMLSecurityDSig('');
// Usa a c14n exclusive canonicalization
$objDSig->setCanonicalMethod(XMLSecurityDSig::C14N);
// Assina usando SHA-1
$objDSig->addReference(
$node,
XMLSecurityDSig::SHA1,
[
"http://www.w3.org/2000/09/xmldsig#enveloped-signature",
"http://www.w3.org/TR/2001/REC-xml-c14n-20010315"
],
[
'id_name' => 'Id',
'overwrite' => false
]
);
// Cria nova (private) Security key
$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type'=>'private'));
$objKey->passphrase = "$keypass";
$objKey->loadKey("$priKEY", TRUE);
// Assina o XML
$objDSig->sign($objKey);
// Adiciona a public key para a signature
$objDSig->add509Cert(file_get_contents("$pubKEY"));
// Acrescenta a signature para o XML
$objDSig->appendSignature($node->parentNode);
$objDSig = null;
//grava na string o objeto DOM
$xml = $xmldoc->saveXML();
} catch (Exception $e) {
throw $e;
}
//retorna o documento assinado
return $xml;
} //fim signXML
function remove_accents($string) {
if ( !preg_match('/[\x80-\xff]/', $string) )
return $string;
$chars = array(
// Decompositions for Latin-1 Supplement
chr(195).chr(128) => 'A', chr(195).chr(129) => 'A',
chr(195).chr(130) => 'A', chr(195).chr(131) => 'A',
chr(195).chr(132) => 'A', chr(195).chr(133) => 'A',
chr(195).chr(135) => 'C', chr(195).chr(136) => 'E',
chr(195).chr(137) => 'E', chr(195).chr(138) => 'E',
chr(195).chr(139) => 'E', chr(195).chr(140) => 'I',
chr(195).chr(141) => 'I', chr(195).chr(142) => 'I',
chr(195).chr(143) => 'I', chr(195).chr(145) => 'N',
chr(195).chr(146) => 'O', chr(195).chr(147) => 'O',
chr(195).chr(148) => 'O', chr(195).chr(149) => 'O',
chr(195).chr(150) => 'O', chr(195).chr(153) => 'U',
chr(195).chr(154) => 'U', chr(195).chr(155) => 'U',
chr(195).chr(156) => 'U', chr(195).chr(157) => 'Y',
chr(195).chr(159) => 's', chr(195).chr(160) => 'a',
chr(195).chr(161) => 'a', chr(195).chr(162) => 'a',
chr(195).chr(163) => 'a', chr(195).chr(164) => 'a',
chr(195).chr(165) => 'a', chr(195).chr(167) => 'c',
chr(195).chr(168) => 'e', chr(195).chr(169) => 'e',
chr(195).chr(170) => 'e', chr(195).chr(171) => 'e',
chr(195).chr(172) => 'i', chr(195).chr(173) => 'i',
chr(195).chr(174) => 'i', chr(195).chr(175) => 'i',
chr(195).chr(177) => 'n', chr(195).chr(178) => 'o',
chr(195).chr(179) => 'o', chr(195).chr(180) => 'o',
chr(195).chr(181) => 'o', chr(195).chr(182) => 'o',
chr(195).chr(182) => 'o', chr(195).chr(185) => 'u',
chr(195).chr(186) => 'u', chr(195).chr(187) => 'u',
chr(195).chr(188) => 'u', chr(195).chr(189) => 'y',
chr(195).chr(191) => 'y',
// Decompositions for Latin Extended-A
chr(196).chr(128) => 'A', chr(196).chr(129) => 'a',
chr(196).chr(130) => 'A', chr(196).chr(131) => 'a',
chr(196).chr(132) => 'A', chr(196).chr(133) => 'a',
chr(196).chr(134) => 'C', chr(196).chr(135) => 'c',
chr(196).chr(136) => 'C', chr(196).chr(137) => 'c',
chr(196).chr(138) => 'C', chr(196).chr(139) => 'c',
chr(196).chr(140) => 'C', chr(196).chr(141) => 'c',
chr(196).chr(142) => 'D', chr(196).chr(143) => 'd',
chr(196).chr(144) => 'D', chr(196).chr(145) => 'd',
chr(196).chr(146) => 'E', chr(196).chr(147) => 'e',
chr(196).chr(148) => 'E', chr(196).chr(149) => 'e',
chr(196).chr(150) => 'E', chr(196).chr(151) => 'e',
chr(196).chr(152) => 'E', chr(196).chr(153) => 'e',
chr(196).chr(154) => 'E', chr(196).chr(155) => 'e',
chr(196).chr(156) => 'G', chr(196).chr(157) => 'g',
chr(196).chr(158) => 'G', chr(196).chr(159) => 'g',
chr(196).chr(160) => 'G', chr(196).chr(161) => 'g',
chr(196).chr(162) => 'G', chr(196).chr(163) => 'g',
chr(196).chr(164) => 'H', chr(196).chr(165) => 'h',
chr(196).chr(166) => 'H', chr(196).chr(167) => 'h',
chr(196).chr(168) => 'I', chr(196).chr(169) => 'i',
chr(196).chr(170) => 'I', chr(196).chr(171) => 'i',
chr(196).chr(172) => 'I', chr(196).chr(173) => 'i',
chr(196).chr(174) => 'I', chr(196).chr(175) => 'i',
chr(196).chr(176) => 'I', chr(196).chr(177) => 'i',
chr(196).chr(178) => 'IJ',chr(196).chr(179) => 'ij',
chr(196).chr(180) => 'J', chr(196).chr(181) => 'j',
chr(196).chr(182) => 'K', chr(196).chr(183) => 'k',
chr(196).chr(184) => 'k', chr(196).chr(185) => 'L',
chr(196).chr(186) => 'l', chr(196).chr(187) => 'L',
chr(196).chr(188) => 'l', chr(196).chr(189) => 'L',
chr(196).chr(190) => 'l', chr(196).chr(191) => 'L',
chr(197).chr(128) => 'l', chr(197).chr(129) => 'L',
chr(197).chr(130) => 'l', chr(197).chr(131) => 'N',
chr(197).chr(132) => 'n', chr(197).chr(133) => 'N',
chr(197).chr(134) => 'n', chr(197).chr(135) => 'N',
chr(197).chr(136) => 'n', chr(197).chr(137) => 'N',
chr(197).chr(138) => 'n', chr(197).chr(139) => 'N',
chr(197).chr(140) => 'O', chr(197).chr(141) => 'o',
chr(197).chr(142) => 'O', chr(197).chr(143) => 'o',
chr(197).chr(144) => 'O', chr(197).chr(145) => 'o',
chr(197).chr(146) => 'OE',chr(197).chr(147) => 'oe',
chr(197).chr(148) => 'R',chr(197).chr(149) => 'r',
chr(197).chr(150) => 'R',chr(197).chr(151) => 'r',
chr(197).chr(152) => 'R',chr(197).chr(153) => 'r',
chr(197).chr(154) => 'S',chr(197).chr(155) => 's',
chr(197).chr(156) => 'S',chr(197).chr(157) => 's',
chr(197).chr(158) => 'S',chr(197).chr(159) => 's',
chr(197).chr(160) => 'S', chr(197).chr(161) => 's',
chr(197).chr(162) => 'T', chr(197).chr(163) => 't',
chr(197).chr(164) => 'T', chr(197).chr(165) => 't',
chr(197).chr(166) => 'T', chr(197).chr(167) => 't',
chr(197).chr(168) => 'U', chr(197).chr(169) => 'u',
chr(197).chr(170) => 'U', chr(197).chr(171) => 'u',
chr(197).chr(172) => 'U', chr(197).chr(173) => 'u',
chr(197).chr(174) => 'U', chr(197).chr(175) => 'u',
chr(197).chr(176) => 'U', chr(197).chr(177) => 'u',
chr(197).chr(178) => 'U', chr(197).chr(179) => 'u',
chr(197).chr(180) => 'W', chr(197).chr(181) => 'w',
chr(197).chr(182) => 'Y', chr(197).chr(183) => 'y',
chr(197).chr(184) => 'Y', chr(197).chr(185) => 'Z',
chr(197).chr(186) => 'z', chr(197).chr(187) => 'Z',
chr(197).chr(188) => 'z', chr(197).chr(189) => 'Z',
chr(197).chr(190) => 'z', chr(197).chr(191) => 's'
);
$string = strtr($string, $chars);
return $string;
}
public function sendRequest(string $envelope, string $action, string $url): array
{
$headers = array(
"Content-type: text/xml;charset=UTF-8",
"Accept-Encoding: gzip,deflate",
"SOAPAction: \"$action\"",
"Content-length: " . strlen($envelope),
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 300);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $envelope);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_ENCODING, "identity, deflate, gzip");
//A prefeitura bloqueia os IPs externos
//$proxy = '200.255.122.174:8080';
//curl_setopt($ch, CURLOPT_PROXY, $proxy);
//curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$html = curl_exec($ch);
// Converte de UTF-8 para ISO-8859
//$html = utf8_decode(curl_exec($ch));
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return [
"html" => $html,
"code" => $httpcode
];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment