1. <?php
  2. /**
  3.  * Controller para busca de CEP utilizando serviço dos correios
  4.  * @author Julio Vedovatto <juliovedovatto@gmail.com>
  5.  * @version 1.0
  6.  *
  7.  */
  8. class Modulo_BuscaCepController extends Mage_Core_Controller_Front_Action {
  9.    
  10.     const CORREIOS_URL = 'http://www.buscacep.correios.com.br/servicos/dnec/consultaEnderecoAction.do';
  11.     const CSS_QUERY_RESULT = '.ctrlcontent div table'; //seletor de css é bem limitado
  12.      
  13.     private $_http;
  14.    
  15.     public function indexAction() {
  16.         $request = $this->getRequest();
  17.         $output = array('success' => true);
  18.        
  19.         try {
  20.             if (strlen(preg_replace('#\D#', '', $request->getParam('cep'))) !== 8)
  21.                 throw new Exception('CEP Inválido');
  22.                
  23.             $this->_buildHttpRequest($request->getParam('cep'));
  24.            
  25.             $output['dados'] = $this->_parseResultCEP();
  26.         } catch (Exception $err) {
  27.             $output['success'] = false;
  28.             $output['error'] = $err->getMessage();
  29.             $output['stack'] = $err->getTraceAsString();
  30.         }
  31.        
  32. //      Retornar resultado, codificado em JSON  
  33.         $this->getResponse()
  34.             ->clearHeaders()
  35.             ->setHeader('Content-Type', 'application/json')
  36.             ->setBody(Mage::helper('core')->jsonEncode($output));
  37.     }
  38.    
  39. //  PRIVATE FUNCTIONS ----------------------------------------------------------------------------------------------------------  
  40.    
  41.     /**
  42.      * Construir requisicao HTTP.
  43.      * @param string $cep
  44.      */
  45.     private function _buildHttpRequest($cep) {
  46.         $this->_http = new Zend_Http_Client();
  47.         $this->_http->setUri(self::CORREIOS_URL);
  48.         $this->_http->setHeaders('User-agent', 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)');
  49.        
  50. //      NOTA: Lembrar que os Correios podem mudar os campos a qualquer momento, caso dê problema sempre verifique os campos na url http://www.buscacep.correios.com.br/    
  51.        
  52.         $this->_http->setParameterPost('relaxation', $cep);
  53.         $this->_http->setParameterPost('TipoCep', 'ALL');
  54.         $this->_http->setParameterPost('semelhante', 'N');
  55.        
  56. //      Hidden
  57.         $this->_http->setParameterPost('cfm', 1);
  58.         $this->_http->setParameterPost('Metodo', 'listaLogradouro');
  59.         $this->_http->setParameterPost('TipoConsulta', 'relaxation');
  60.         $this->_http->setParameterPost('StartRow', 1);
  61.         $this->_http->setParameterPost('EndRow', 10);
  62.     }
  63.    
  64.     /**
  65.      * Fazer a requisicao e retornar o html necessário.
  66.      * @throws Exception
  67.      * @return Zend_Dom_Query_Result
  68.      */
  69.     private function _makeRequest() {
  70.         $request = $this->_http->request('POST');
  71.            
  72.         $dom = new Zend_Dom_Query($request->getBody());
  73.        
  74.         return $dom->query(self::CSS_QUERY_RESULT);
  75.     }
  76.    
  77.     /**
  78.      * Recuperar informações do logadouro.
  79.      * @throws Exception
  80.      * @return array
  81.      */
  82.     private function _parseResultCEP() {
  83.         $results = $this->_makeRequest();
  84.            
  85.         if (count($results) === 0)
  86.             throw new Exception('Sem resultados');
  87.            
  88.         $dados = array(
  89.             'logadouro' => '',
  90.             'bairro' => '',
  91.             'localidade' => '',
  92.             'UF' => '',
  93.             'CEP' => ''
  94.         );
  95.        
  96.         $result = $results->current(); //pegar o primeiro resultado, que contém os dados
  97.        
  98.         $doc = new DOMDocument();
  99.         $doc->appendChild($doc->importNode($result, true)); //jogar o DomElement num novo DomDocument
  100.         $dom = new Zend_Dom_Query($doc->saveHTML()); //setar novo html na classe Zend_Dom_Query, somente o output do elemento acima
  101.            
  102.         if (count($result_nodes = $dom->query('td')) !== 5)
  103.             throw new Exception('Sem resultados');
  104.  
  105.         $dados['logadouro'] = $result_nodes->current()->nodeValue;
  106.        
  107.         $result_nodes->next();
  108.         $dados['bairro'] = $result_nodes->current()->nodeValue;
  109.        
  110.         $result_nodes->next();
  111.         $dados['localidade'] = $result_nodes->current()->nodeValue;
  112.        
  113.         $result_nodes->next();
  114.         $dados['UF'] = $result_nodes->current()->nodeValue;
  115.        
  116.         $result_nodes->next();
  117.         $dados['CEP'] = $result_nodes->current()->nodeValue;
  118.        
  119.         return $dados;
  120.     }
  121.    
  122. //  /PRIVATE FUNCTIONS ---------------------------------------------------------------------------------------------------------  
  123. }