Skip to content

Instantly share code, notes, and snippets.

@LeonanCarvalho
Created September 5, 2017 11:58
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 LeonanCarvalho/2871c96f522ca56dd3aa37f0f139f97a to your computer and use it in GitHub Desktop.
Save LeonanCarvalho/2871c96f522ca56dd3aa37f0f139f97a to your computer and use it in GitHub Desktop.
SOAP Client
<?php
namespace Application\WebServices;
/**
*
* @author LeonanCarvalho <j.leonancarvalho@gmail.com>
*/
abstract class AbstractSoapClient {
protected $_url = "";
protected $_options = array("cache_wsdl" => 0, "trace" => 1, "exception" => 0);
private $_SoapClient;
public function __construct($wsdl_cache = "0", $socket_timeout = "5000") {
ini_set("soap.wsdl_cache_enabled", $wsdl_cache);
ini_set("default_socket_timeout", $socket_timeout);
try {
$this->_SoapClient = new \SoapClient($this->_url, $this->_options);
} catch (\Exception $e) {
throw new \Exception("Não foi possível estabelecer uma conexão com o servidor remoto.", 500, $e);
}
}
protected function methodCall($methodName, array $arguments, array $options = null, $input_headers = null, array &$output_headers = null) {
$result = $this->_SoapClient->__soapCall($methodName, $arguments);
$response = json_decode($this->XML2JSON(trim($result)));
if (is_object($response)) {
$response->__serviceURI__ = $this->_url;
$response->__serviceMethod__ = $methodName;
}
return $response;
}
public function getFunctions() {
return $this->_SoapClient->__getFunctions();
}
public function getLastRequest() {
return $this->_SoapClient->__getLastRequest();
}
public function getLastRequestHeaders() {
return $this->_SoapClient->__getLastRequestHeaders();
}
public function getLastResponse() {
return $this->_SoapClient->__getLastResponse();
}
public function getLastResponseHeaders() {
return $this->_SoapClient->__getLastResponseHeaders();
}
public function getTypes() {
return $this->_SoapClient->__getTypes();
}
public function setCookies() {
return $this->_SoapClient->__setCookie();
}
public function setLocation() {
return $this->_SoapClient->__setLocation();
}
public function setHeaders($soapheaders) {
return $this->_SoapClient->__setSoapHeaders($soapheaders);
}
public function getCookies() {
return $this->_SoapClient->__getCookies();
}
public static function normalizeSimpleXML($obj, &$result) {
$data = $obj;
if (is_object($data)) {
$data = get_object_vars($data);
}
if (is_array($data)) {
foreach ($data as $key => $value) {
$res = null;
self::normalizeSimpleXML($value, $res);
if (($key == '@attributes') && ($key)) {
$result = $res;
} else {
$result[$key] = $res;
}
}
} else {
$result = $data;
}
}
//http://stackoverflow.com/questions/2261530/fix-malformed-xml-in-php-before-processing-using-domdocument-functions
public function cleanXml($xml) {
$xmlOut = '';
$inTag = false;
$xmlLen = strlen($xml);
for ($i = 0; $i < $xmlLen; ++$i) {
$char = $xml[$i];
// $nextChar = $xml[$i+1];
switch ($char) {
case '<':
if (!$inTag) {
// Seek forward for the next tag boundry
for ($j = $i + 1; $j < $xmlLen; ++$j) {
$nextChar = $xml[$j];
switch ($nextChar) {
case '<': // Means a < in text
$char = htmlentities($char);
break 2;
case '>': // Means we are in a tag
$inTag = true;
break 2;
}
}
} else {
$char = htmlentities($char);
}
break;
case '>':
if (!$inTag) { // No need to seek ahead here
$char = htmlentities($char);
} else {
$inTag = false;
}
break;
default:
if (!$inTag) {
$char = htmlentities($char);
}
break;
}
$xmlOut .= $char;
}
return trim($xmlOut);
}
public function XML2JSON($xml) {
// $xml_clean = trim(preg_replace('#&(?=[a-z_0-9]+=)#', '&amp;', $xml));
// $xml_clean = trim(preg_replace('/&[^; ]{0,6}.?/e', "((substr('\\0',-1) == ';') ? '\\0' : '&amp;'.substr('\\0',1))", $xml));
$xml_clean = $this->cleanXml($xml);
self::normalizeSimpleXML(simplexml_load_string($xml_clean), $result);
return json_encode($result);
}
}
<?php
namespace Application\WebServices\Clients\EmpresaXPTO;
use Application\WebServices\AbstractSoapClient;
use \Exception as SysException; //Classe customizada de execeção, implemente a sua como quiser.
use Application\WebServices\WebServiceException;
/**
* Description of ModernizacaoPublica
*
* @author LeonanCarvalho <j.leonancarvalho@gmail.com>
*/
class Tributos extends AbstractSoapClient {
protected $_url;
/**
* O WebService tem sempre 2 parâmetros de entrada, uma senha fixa para somente aceitar chamadas desta senha e o arquivo XML
* P1: Senha fixa: ********
* P2: Arquivo XML, seguem vários exemplo de envio:
* @var type
*/
private $_defaultArgs = array("P1" => "******", "P2" => null);
private $_defaultMethod = "ProSincXmlReceber";
//Mapa de Serviços
const ERRO = "ERRO"; //DEFAULT É RESERVADO
const CADASTRO = "CADASTRO";
const CONSULTA = "CONSULTA";
const CONSULTA_LOTE = "CONSULTA_LOTE";
const CONSULTA_EXTRATO = "CONSULTA_EXTRATO";
public function __construct($url, $soapMethod = "ProSincXmlReceber", $soapArgs = array("P1" => "*****", "P2" => null)) {
$this->_url = $url;
$this->_defaultArgs = $soapArgs;
$this->_defaultMethod = $soapMethod;
parent::__construct();
}
/**
* Facilita o envio de xml, pois a operação se repete para todos os métodos.
* @param string $xml
* @return type
*/
private function sendXml($xml) {
$arguments = array_merge($this->_defaultArgs, array('P2' => $xml));
$response = $this->methodCall($this->_defaultMethod, $arguments);
return $this->getResponse($response);
}
/**
* Trata A resposta do webservice
*
* @param type $response
* @return type
* @throws WebServiceException
*/
private function getResponse($response){
if ($response == null || !is_object($response)) {
throw new WebServiceException("Erro inesperado.");
}
if(isset($response->lote)){ //Se o retorno for um lote
if(is_array($response->lote)){ //Se o lote retornar mais de um será um array,ok
return $response->lote;
}elseif(is_object($response->lote)){ //Se retornar apenas um será um objeto,
//transformo em array para ter o mesmo retorno.
return array($response->lote);
}
}
if(isset($response->taxa)){ //Se o retorno for um extrato de taxas
if(is_array($response->taxa)){ //Se o lote retornar mais de um será um array,ok
return $response->taxa;
}elseif(is_object($response->taxa)){ //Se retornar apenas um registro será um objeto,
//transformo em array para ter o mesmo retorno.
return array($response->taxa);
}
}
if (!isset($response->servico)) {
throw new WebServiceException("Serviço não localizado.");
}
if ($response->servico == self::ERRO) {
$msgError = "";
switch (utf8_decode($response->tipo)) {
case "CPF ou CNPJ não localizado":
$msgError = "Não foi possível localizar o processo para o documento informado.";
break;
case "Processo arquivado":
$msgError = "Este processo está arquivado.";
break;
case "Assunto não localizado":
$msgError = "Não existe o cadastro deste tipo de processo no sistema de protocolo.";
break;
default:
$msgError = utf8_decode($response->tipo);
break;
}
throw new WebServiceException($msgError);
}
return $response;
}
/**
* Monta o objeto XML padrão que será usado como P2 no defaultArgs.
* @param type $serviceName
* @return \SimpleXMLElement
*/
private function getDefaultXML($serviceName, $encoding= "UTF-8") {
$xml = new \SimpleXMLElement('<?xml version="1.0" encoding="'.$encoding.'" ?><xml/>');
$xml->addChild('servico', $serviceName);
return $xml;
}
/**
* Insere os dados de pessoa globais para a tag <pessoais></pessoais>
* @param type $tipoPessoa
* @param type $doc
* @param type $pessoais
* @throws SysException
*/
private function setPessoaXml($tipoPessoa, $doc, &$pessoais) {
$doc_s = preg_replace("/[^0-9]/", "", trim($doc)); //Deixando apenas numeros
$pessoais->addChild("tipo", strtoupper(trim($tipoPessoa)));
if ($tipoPessoa == "F") {
$cpf = str_pad($doc_s, 11, '0', STR_PAD_LEFT);
$pessoais->addChild("cpf", $cpf);
$pessoais->addChild("cnpj", "");
} else if ($tipoPessoa == "J") {
$cnpj = str_pad($doc_s, 14, '0', STR_PAD_LEFT);
$pessoais->addChild("cnpj", $cnpj);
$pessoais->addChild("cpf", "");
} else {
throw new WebServiceException("Tipo de pessoa inválido.");
}
}
/**
* Envia os dados para cadastramento da taxa (tag <servico>CADASTRO</servico>)
* Se a PF ou PJ não existir, é cadastrada, se existir, reconhece atráves do CPF/CNPJ
* Ex:
* <?xml version="1.0" encoding="ISO-8859-1" ?>
* <xml>
* <servico>CADASTRO</servico>
* <pessoais>
* <nome>CADASTRO DE PESSOA FÍSICA</nome>
* <tipo>F</tipo>
* <cpf>00100200304</cpf>
* <cnpj></cnpj>
* </pessoais>
* <processo>
* <numero>21650</numero>
* <ano>2015</ano>
* </processo>
* <taxa>
* <receita>6</receita>
* <atividade>10546</atividade>
* <observacao>TESTE DE OBSERVAÇÃO 1
* TESTE DE OBSERVAÇÃO 3</observacao>
* </taxa>
* </xml>
*
* @param type $nome da pessoa
* @param type $doc cpf ou cnpj
* @param type $numero Número do processo
* @param type $ano Ano do processo
* @param type $receita da taxa
* @param type $atividade da taxa
* @param type $tipoPessoa
* @throws SysException
*/
public function cadastro($nome, $doc, $numero, $ano, $receita, $atividade, $obs = "", $tipoPessoa = "F") {
$xml = $this->getDefaultXML(self::CADASTRO);
$pessoais = $xml->addChild("pessoais");
$pessoais->addChild("nome", trim($nome));
// $pessoais->addChild("nome", utf8_decode(trim($nome)));
// $pessoais->addChild("nome", iconv('UTF-8', 'ISO-8859-1', trim($nome)));
$this->setPessoaXml($tipoPessoa, $doc, $pessoais);
$processo = $xml->addChild("processo");
$processo->addChild("numero", $numero);
$processo->addChild("ano", $ano);
$taxa = $xml->addChild("taxa");
$taxa->addChild("receita", $receita);
$taxa->addChild("atividade", $atividade);
$taxa->addChild("observacao", trim($obs));
// $taxa->addChild("observacao", utf8_decode(trim($obs)));
return $this->sendXml($xml->asXML());
}
/**
* Envia os dados para consulta de processo (tag <servico>CONSULTA</servico>)
*
* XML De envio:
* <?xml version="1.0" encoding="ISO-8859-1" ?>
* <xml>
* <servico>CONSULTA</servico>
* <pessoais>
* <tipo>F</tipo>
* <cpf>00100200304</cpf>
* <cnpj></cnpj>
* </pessoais>
* <dam>2150917</dam>
* </xml>
*
* @param type $dam
* @param type $ano
* @param type $doc
* @param type $tipoPessoa
*/
public function consulta($dam, $doc, $tipoPessoa = "F") {
$xml = $this->getDefaultXML(self::CONSULTA);
$pessoais = $xml->addChild("pessoais");
$this->setPessoaXml($tipoPessoa, $doc, $pessoais);
$xml->addChild("dam", trim($dam));
return $this->sendXml($xml->asXML());
}
public function consulta_lote($lote){
$xml = $this->getDefaultXML(self::CONSULTA_LOTE);
foreach ($lote as $sequencia => $lote){
$xml_lote = $xml->addChild("lote");
$xml_lote->addChild("sequencia", $sequencia+1);
$pessoais = $xml_lote->addChild("pessoais");
$this->setPessoaXml($lote->tipoPessoa, $lote->doc, $pessoais);
$xml_lote->addChild("dam", trim($lote->dam));
}
return $this->sendXml($xml->asXML());
}
public function extrato($processo, $doc, $tipoPessoa = "F"){
$xml = $this->getDefaultXML(self::CONSULTA_EXTRATO);
$pessoais = $xml->addChild("pessoais");
$this->setPessoaXml($tipoPessoa, $doc, $pessoais);
$xml->addChild("processo", trim($processo));
return $this->sendXml($xml->asXML());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment