Levecke

CorreiosMethod.php

Sep 21st, 2023 (edited)
223
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 38.93 KB | Source Code | 0 0
  1. <?php
  2. /**
  3. COMO INSTALAR: https://magentoblog.com.br/nova-apis-dos-correios-e-pedro-teixeira/
  4.  
  5.  * This source file is subject to the MIT License.
  6.  * It is also available through http://opensource.org/licenses/MIT
  7.  *
  8.  * @category  PedroTeixeira
  9.  * @package   PedroTeixeira_Correios
  10.  * @author    Pedro Teixeira <[email protected]>
  11.  * @copyright 2015 Pedro Teixeira (http://pedroteixeira.io)
  12.  * @license   http://opensource.org/licenses/MIT MIT
  13.  * @link      https://github.com/pedro-teixeira/correios
  14.  */
  15. class PedroTeixeira_Correios_Model_Carrier_CorreiosMethod
  16.     extends Mage_Shipping_Model_Carrier_Abstract
  17.     implements Mage_Shipping_Model_Carrier_Interface
  18. {
  19.     /**
  20.      * _code property
  21.      *
  22.      * @var string
  23.      */
  24.     protected $_code = 'pedroteixeira_correios';
  25.     protected $_isFixed = true;
  26.  
  27.     /**
  28.      * _result property
  29.      *
  30.      * @var Mage_Shipping_Model_Rate_Result|Mage_Shipping_Model_Tracking_Result
  31.      */
  32.     protected $_result = null;
  33.  
  34.     /**
  35.      * ZIP code vars
  36.      */
  37.     protected $_fromZip = null;
  38.     protected $_toZip = null;
  39.  
  40.     /**
  41.      * Value and Weight
  42.      */
  43.     protected $_packageValue = null;
  44.     protected $_packageWeight = null;
  45.     protected $_volumeWeight = null;
  46.     protected $_freeMethodWeight = null;
  47.     protected $_midSize = null;
  48.     protected $_splitUp = 0;
  49.     protected $_postingDays = 0;
  50.  
  51.     /**
  52.      * Post methods
  53.      */
  54.     protected $_postMethods = null;
  55.     protected $_postMethodsFixed = null;
  56.     protected $_postMethodsExplode = null;
  57.  
  58.     /**
  59.      * Free method request
  60.      */
  61.     protected $_freeMethodRequest = false;
  62.     protected $_freeMethodRequestResult = null;
  63.  
  64.     /**
  65.      * Collect Rates
  66.      *
  67.      * @param Mage_Shipping_Model_Rate_Request $request Mage request
  68.      *
  69.      * @return bool|Mage_Shipping_Model_Rate_Result|Mage_Shipping_Model_Tracking_Result
  70.      */
  71.     public function collectRates(Mage_Shipping_Model_Rate_Request $request)
  72.     {
  73.         // Do initial check
  74.         if ($this->_inicialCheck($request) === false) {
  75.             return false;
  76.         }
  77.  
  78.         // Check package value
  79.         if ($this->_packageValue < $this->getConfigData('min_order_value')
  80.             || $this->_packageValue > $this->getConfigData('max_order_value')
  81.         ) {
  82.             $this->_throwError('valueerror', 'Value limits', __LINE__);
  83.             return $this->_result;
  84.         }
  85.  
  86.         // Check ZIP Code
  87.         if (!preg_match('/^([0-9]{8})$/', $this->_toZip)) {
  88.             $this->_throwError('zipcodeerror', 'Invalid Zip Code', __LINE__);
  89.             return $this->_result;
  90.         }
  91.  
  92.         if ($this->_packageWeight == 0) {
  93.             $this->_packageWeight = $this->_getNominalWeight($request);
  94.         }
  95.  
  96.         if ($this->getConfigData('weight_type') == PedroTeixeira_Correios_Model_Source_WeightType::WEIGHT_GR) {
  97.             $this->_packageWeight = number_format($this->_packageWeight / 1000, 2, '.', '');
  98.         }
  99.  
  100.         // Check weight zero
  101.         if ($this->_packageWeight <= 0) {
  102.             $this->_throwError('weightzeroerror', 'Weight zero', __LINE__);
  103.             return $this->_result;
  104.         }
  105.  
  106.         $this->_postMethods        = $this->getConfigData('postmethods');
  107.         $this->_postMethodsFixed   = $this->_postMethods;
  108.         $this->_postMethodsExplode = explode(',', $this->getConfigData('postmethods'));
  109.  
  110.         // Generate Volume Weight
  111.         if ($this->_generateVolumeWeight($request) === false || $this->_removeInvalidServices() === false) {
  112.             $this->_throwError('dimensionerror', 'Dimension error', __LINE__);
  113.             return $this->_result;
  114.         }
  115.  
  116.         $this->_filterMethodByItemRestriction($request);
  117.  
  118.         if (empty($this->_postMethods)) {
  119.             return false;
  120.         }
  121.         //Show Quotes
  122.         $this->_getQuotes();
  123.  
  124.         // Use descont codes
  125.         $this->_updateFreeMethodQuote($request);
  126.  
  127.         return $this->_result;
  128.     }
  129.  
  130.     /**
  131.      * Retrieve all visible items from request
  132.      *
  133.      * @param Mage_Shipping_Model_Rate_Request $request Mage request
  134.      *
  135.      * @return array
  136.      */
  137.     protected function _getRequestItems($request)
  138.     {
  139.  
  140.         $allItems = $request->getAllItems();
  141.         $items = array();
  142.  
  143.         foreach ($allItems as $item) {
  144.             if (!$item->getParentItemId()) {
  145.                 $items[] = $item;
  146.             }
  147.         }
  148.  
  149.         $items = $this->_loadBundleChildren($items);
  150.  
  151.         return $items;
  152.     }
  153.  
  154.     /**
  155.     * Gets Nominal Weight
  156.     *
  157.     * @param Mage_Shipping_Model_Rate_Request $request Mage request
  158.     *
  159.     * @return number
  160.     */
  161.     protected function _getNominalWeight($request)
  162.     {
  163.         $weight = 0;
  164.         $items = $this->_getRequestItems($request);
  165.  
  166.         foreach ($items as $item) {
  167.             $product = Mage::getModel('catalog/product')->load($item->getProductId());
  168.             $weight += $product->getWeight();
  169.         }
  170.  
  171.         return $weight;
  172.     }
  173.  
  174.     /**
  175.      * Get shipping quote
  176.      *
  177.      * @return Mage_Shipping_Model_Rate_Result|Mage_Shipping_Model_Tracking_Result
  178.      */
  179.     protected function _getQuotes()
  180.     {
  181.         $softErrors     = explode(',', $this->getConfigData('soft_errors'));
  182.         $correiosReturn = $this->_getCorreiosReturn();
  183.  
  184.         if ($correiosReturn !== false) {
  185.             $errorList = array();
  186.             $correiosReturn = $this->_addPostMethods($correiosReturn);
  187.  
  188.             foreach ($correiosReturn as $servicos) {
  189.                 $errorId = (string) $servicos->Erro;
  190.                 $errorList[$errorId] = $servicos->MsgErro;
  191.  
  192.                 if ($errorId != '0' && !in_array($errorId, $softErrors)) {
  193.                     continue;
  194.                 }
  195.  
  196.                 $servicos->Valor = $this->_getFormatPrice((string) $servicos->Valor);
  197.                 $this->_appendShippingReturn($servicos);
  198.             }
  199.             $this->_appendShippingErrors($errorList);
  200.         } else {
  201.             return $this->_result;
  202.         }
  203.  
  204.         if ($this->_freeMethodRequest === true) {
  205.             return $this->_freeMethodRequestResult;
  206.         } else {
  207.             return $this->_result;
  208.         }
  209.     }
  210.  
  211.     /**
  212.      * Make initial checks and iniciate module variables
  213.      *
  214.      * @param Mage_Shipping_Model_Rate_Request $request Mage request
  215.      *
  216.      * @return bool
  217.      */
  218.     protected function _inicialCheck(Mage_Shipping_Model_Rate_Request $request)
  219.     {
  220.  
  221.         if (!$this->getConfigFlag('active')) {
  222.             // Disabled
  223.             Mage::log('pedroteixeira_correios: Disabled');
  224.             return false;
  225.         }
  226.  
  227.         $origCountry = Mage::getStoreConfig('shipping/origin/country_id', $this->getStore());
  228.         $destCountry = $request->getDestCountryId();
  229.         if ($origCountry != 'BR' || $destCountry != 'BR') {
  230.             // Out of delivery area
  231.             Mage::log('pedroteixeira_correios: Out of delivery area');
  232.             return false;
  233.         }
  234.  
  235.         $this->_fromZip = Mage::getStoreConfig('shipping/origin/postcode', $this->getStore());
  236.         $this->_toZip   = $request->getDestPostcode();
  237.  
  238.         // Fix ZIP code
  239.         $this->_fromZip = str_replace(array('-', '.'), '', trim($this->_fromZip));
  240.         $this->_toZip   = str_replace(array('-', '.'), '', trim($this->_toZip));
  241.  
  242.         if (!preg_match('/^([0-9]{8})$/', $this->_fromZip)) {
  243.             Mage::log('pedroteixeira_correios: From ZIP Code Error');
  244.             return false;
  245.         }
  246.  
  247.         if (!trim($this->_toZip)) {
  248.             return false;
  249.         }
  250.  
  251.         $uniqueCityZip = $this->getConfigData('unique_city_zip');
  252.         if ($uniqueCityZip && !strcmp ($this->_fromZip, $this->_toZip)) {
  253.             return false;
  254.         }
  255.  
  256.         $this->_result       = Mage::getModel('shipping/rate_result');
  257.         $this->_packageValue = $request->getBaseCurrency()->convert(
  258.             $request->getPackageValue(),
  259.             $request->getPackageCurrency()
  260.         );
  261.  
  262.         $this->_packageWeight    = number_format($request->getPackageWeight(), 2, '.', '');
  263.         $this->_freeMethodWeight = number_format($request->getFreeMethodWeight(), 2, '.', '');
  264.     }
  265.  
  266.     /**
  267.      * Get Correios return
  268.      *
  269.      * @return bool|SimpleXMLElement[]
  270.      *
  271.      * @throws Exception
  272.      */
  273.     protected function _getCorreiosReturn()
  274.     {
  275.         include_once "correiosapi.php";
  276.  
  277.         $idCorreios = "Id_de_entrada_no_portal cws.correios.com.br";
  278.         $codAcesso = "cod_acesso_gerado_no_portal PEGA COM TEU GERENTE CORREIOS";
  279.         $cartao = "numero_cartao_postagem";
  280.  
  281.         $access_code = base64_encode($idCorreios . ":" . $codAcesso);
  282.         $tokenA = getToken($access_code, $cartao);
  283.         if (false === $tokenA) {
  284.         Mage::log("correiosapi: Erro: nao conseguiu pegar token!");
  285.         return false;
  286.         }
  287.  
  288.         $token = $tokenA[1];
  289.         $expiraEm = $tokenA[0];
  290.  
  291.         // vamos ver quantos servicos temos para buscar
  292.         $metods = explode(",", $this->_postMethods);
  293.         //Mage::log("metods=" . $this->_postMethods);
  294.         $xml_total="<Servicos>";
  295.         foreach($metods as $metod) {
  296.         $ret_xml = correiosapi($token, $metod, $this->_fromZip, $this->_toZip, $this->_packageWeight * 1000, 1, $this->_midSize, $this->_midSize, $this->_midSize, "", 0);
  297.         $xml_total .= $ret_xml;
  298.         }
  299.         $xml_total .= "</Servicos>";
  300.         $xml = new SimpleXMLElement($xml_total);
  301.         //Mage::log("xml=" . print_r($xml,true));
  302.         //Mage::log("xml_total=" . print_r($xml_total,true));
  303.  
  304.         return $xml->cServico;
  305.         //aqui seria a continuacao do metodo, mas nao vai passar, tem um return antes
  306.        
  307.         $filename      = $this->getConfigData('url_ws_correios');
  308.  
  309.         try {
  310.             $client = new Zend_Http_Client($filename);
  311.             $client->setConfig(
  312.                 array(
  313.                     'timeout' => $this->getConfigData('ws_timeout'),
  314.                     'adapter' => Mage::getModel('pedroteixeira_correios/http_client_adapter_socket')
  315.                 )
  316.             );
  317.  
  318.             $client->setParameterGet('StrRetorno', 'xml');
  319.             $client->setParameterGet('nCdServico', $this->_postMethods);
  320.             $client->setParameterGet('nVlPeso', $this->_packageWeight);
  321.             $client->setParameterGet('sCepOrigem', $this->_fromZip);
  322.             $client->setParameterGet('sCepDestino', $this->_toZip);
  323.             $client->setParameterGet('nCdFormato', 1);
  324.             $client->setParameterGet('nVlComprimento', $this->_midSize);
  325.             $client->setParameterGet('nVlAltura', $this->_midSize);
  326.             $client->setParameterGet('nVlLargura', $this->_midSize);
  327.  
  328.             if ($this->getConfigData('mao_propria')) {
  329.                 $client->setParameterGet('sCdMaoPropria', 'S');
  330.             } else {
  331.                 $client->setParameterGet('sCdMaoPropria', 'N');
  332.             }
  333.  
  334.             if ($this->getConfigData('aviso_recebimento')) {
  335.                 $client->setParameterGet('sCdAvisoRecebimento', 'S');
  336.             } else {
  337.                 $client->setParameterGet('sCdAvisoRecebimento', 'N');
  338.             }
  339.  
  340.             if ($this->getConfigData('valor_declarado')
  341.                 || in_array($this->getConfigData('acobrar_code'), $this->_postMethodsExplode)
  342.             ) {
  343.                 $client->setParameterGet('nVlValorDeclarado', number_format($this->_packageValue, 2, ',', ''));
  344.             } else {
  345.                 $client->setParameterGet('nVlValorDeclarado', 0);
  346.             }
  347.  
  348.             $nCdEmpresa = $this->getConfigData('cod_admin');
  349.             $sDsSenha = $this->getConfigData('senha_admin');
  350.             if (!empty($nCdEmpresa) && !empty($sDsSenha)) {
  351.                 $client->setParameterGet('nCdEmpresa', $nCdEmpresa);
  352.                 $client->setParameterGet('sDsSenha', $sDsSenha);
  353.             }
  354.  
  355.             $content = $client->request()->getBody();
  356.  
  357.             if ($content == '') {
  358.                 throw new Exception('No XML returned [' . __LINE__ . ']');
  359.             }
  360.  
  361.             libxml_use_internal_errors(true);
  362.             $sxe = simplexml_load_string($content);
  363.             if (!$sxe) {
  364.                 throw new Exception('Bad XML [' . __LINE__ . ']');
  365.             }
  366.  
  367.             $xml = new SimpleXMLElement($content);
  368.  
  369.             if (count($xml->cServico) <= 0) {
  370.                 throw new Exception('No tag cServico in Correios XML [' . __LINE__ . ']');
  371.             }
  372.  
  373.             return $xml->cServico;
  374.         } catch (Exception $e) {
  375.             $this->_throwError('urlerror', 'URL Error - ' . $e->getMessage(), __LINE__);
  376.             return false;
  377.         }
  378.     }
  379.    
  380.     /**
  381.      * Apend shipping value to return
  382.      *
  383.      * @param SimpleXMLElement $servico Service Data
  384.      *
  385.      * @return void
  386.      */
  387.     protected function _appendShippingReturn(SimpleXMLElement $servico)
  388.     {
  389.         $correiosDelivery = (int) $servico->PrazoEntrega;
  390.         $shippingMethod   = (string) $servico->Codigo;
  391.         $shippingPrice    = (float) $servico->Valor;
  392.         if ($shippingPrice <= 0) {
  393.             return;
  394.         }
  395.  
  396.         $errorMsg = $this->_getSoftErrorMsg((string) $servico->Erro);
  397.         $method = Mage::getModel('shipping/rate_result_method');
  398.         $method->setCarrier($this->_code);
  399.         $method->setCarrierTitle($this->getConfigData('title') . $this->_getSplitUpMsg() . $errorMsg);
  400.         $method->setMethod($shippingMethod);
  401.  
  402.         $shippingCost  = $shippingPrice;
  403.         $shippingPrice = $shippingPrice + $this->getConfigData('handling_fee');
  404.  
  405.         $shippingData = Mage::helper('pedroteixeira_correios')->getShippingLabel($shippingMethod);
  406.         $shippingData = Mage::helper('pedroteixeira_correios')->__($shippingData);
  407.  
  408.         if ($shippingMethod == $this->getConfigData('acobrar_code')) {
  409.             $shippingData = $shippingData . ' ( R$' . number_format($shippingPrice, 2, ',', '.') . ' )';
  410.             $shippingPrice   = 0;
  411.         }
  412.  
  413.         if ($this->getConfigFlag('prazo_entrega')) {
  414.             if ($correiosDelivery > 0) {
  415.                 $method->setMethodTitle(
  416.                     sprintf(
  417.                         $this->getConfigData('msgprazo'),
  418.                         $shippingData,
  419.                         (int) ($correiosDelivery + $this->getConfigData('add_prazo') + $this->_postingDays)
  420.                     )
  421.                 );
  422.             }
  423.         } else {
  424.             $method->setMethodTitle($shippingData);
  425.         }
  426.  
  427.         $method->setPrice($shippingPrice);
  428.         $method->setCost($shippingCost);
  429.  
  430.         if ($this->_freeMethodRequest === true) {
  431.             $this->_freeMethodRequestResult->append($method);
  432.         } else {
  433.             $this->_result->append($method);
  434.         }
  435.     }
  436.  
  437.     /**
  438.      * Throw error
  439.      *
  440.      * @param string     $message Message placeholder
  441.      * @param string     $log     Message
  442.      * @param string|int $line    Line of log
  443.      * @param string     $custom  Custom variables for placeholder
  444.      *
  445.      * @return void
  446.      */
  447.     protected function _throwError($message, $log = null, $line = 'NO LINE', $custom = null)
  448.     {
  449.         $this->_result = null;
  450.         $this->_result = Mage::getModel('shipping/rate_result');
  451.  
  452.         $error = Mage::getModel('shipping/rate_result_error');
  453.         $error->setCarrier($this->_code);
  454.         $error->setCarrierTitle($this->getConfigData('title'));
  455.  
  456.         if (is_null($custom) || $this->getConfigData($message) == '') {
  457.             Mage::log($this->_code . ' [' . $line . ']: ' . $log);
  458.             $error->setErrorMessage($this->getConfigData($message));
  459.         } else {
  460.             Mage::log($this->_code . ' [' . $line . ']: ' . $log);
  461.             $error->setErrorMessage(sprintf($this->getConfigData($message), $custom));
  462.         }
  463.  
  464.         $this->_result->append($error);
  465.     }
  466.  
  467.     /**
  468.      * Retrieves a simple product
  469.      *
  470.      * @param Mage_Catalog_Model_Product $product Catalog Product
  471.      *
  472.      * @return Mage_Catalog_Model_Product
  473.      */
  474.     protected function _getSimpleProduct($product)
  475.     {
  476.         $type = $product->getTypeInstance(true);
  477.         if ($type->getProduct($product)->hasCustomOptions()
  478.             && ($simpleProductOption = $type->getProduct($product)->getCustomOption('simple_product'))
  479.         ) {
  480.             $simpleProduct = $simpleProductOption->getProduct($product);
  481.             if ($simpleProduct) {
  482.                 return $this->_getSimpleProduct($simpleProduct);
  483.             }
  484.         }
  485.         return $type->getProduct($product);
  486.     }
  487.  
  488.     /**
  489.      * Generate Volume weight
  490.      *
  491.      * @param Mage_Shipping_Model_Rate_Request $request Mage request
  492.      *
  493.      * @return bool
  494.      */
  495.     protected function _generateVolumeWeight($request)
  496.     {
  497.         $pesoCubicoTotal = 0;
  498.  
  499.         $items = $this->_getRequestItems($request);
  500.  
  501.         foreach ($items as $item) {
  502.             $_product = $this->_getSimpleProduct($item->getProduct());
  503.  
  504.             if ($_product->getData('volume_altura') == '' || (int) $_product->getData('volume_altura') == 0) {
  505.                 $itemAltura = $this->getConfigData('altura_padrao');
  506.             } else {
  507.                 $itemAltura = $_product->getData('volume_altura');
  508.             }
  509.  
  510.             if ($_product->getData('volume_largura') == '' || (int) $_product->getData('volume_largura') == 0) {
  511.                 $itemLargura = $this->getConfigData('largura_padrao');
  512.             } else {
  513.                 $itemLargura = $_product->getData('volume_largura');
  514.             }
  515.  
  516.             if ($_product->getData('volume_comprimento') == '' || (int) $_product->getData('volume_comprimento') == 0) {
  517.                 $itemComprimento = $this->getConfigData('comprimento_padrao');
  518.             } else {
  519.                 $itemComprimento = $_product->getData('volume_comprimento');
  520.             }
  521.  
  522.             if ($this->getConfigFlag('check_dimensions')) {
  523.                 foreach ($this->_postMethodsExplode as $key => $method) {
  524.                     $sizeMax = max($itemAltura, $itemLargura, $itemComprimento);
  525.                     $sumMax  = ($itemAltura + $itemLargura + $itemComprimento);
  526.                     $isValid = ($sizeMax <= $this->getConfigData("validate/serv_{$method}/max/size"));
  527.                     $isValid &= ($sumMax <= $this->getConfigData("validate/serv_{$method}/max/sum"));
  528.  
  529.                     if (!$isValid) {
  530.                         unset($this->_postMethodsExplode[$key]);
  531.                     }
  532.                 }
  533.  
  534.                 if (count($this->_postMethodsExplode) == 0) {
  535.                     return false;
  536.                 }
  537.  
  538.                 $this->_postMethods      = implode(',', $this->_postMethodsExplode);
  539.                 $this->_postMethodsFixed = $this->_postMethods;
  540.             }
  541.  
  542.             $itemAltura = $this->_getFitHeight($item);
  543.             $pesoCubicoTotal += (($itemAltura * $itemLargura * $itemComprimento) *
  544.                     $item->getTotalQty()) / $this->getConfigData('coeficiente_volume');
  545.  
  546.             $this->_postingDays = max($this->_postingDays, (int) $_product->getData('posting_days'));
  547.         }
  548.  
  549.         $this->_volumeWeight = number_format($pesoCubicoTotal, 2, '.', '');
  550.  
  551.         return true;
  552.     }
  553.  
  554.     /**
  555.      * Generate free shipping for a product
  556.      *
  557.      * @param string $freeMethod Free method
  558.      *
  559.      * @return void
  560.      */
  561.     protected function _setFreeMethodRequest($freeMethod)
  562.     {
  563.         $this->_freeMethodRequest       = true;
  564.         $this->_freeMethodRequestResult = Mage::getModel('shipping/rate_result');
  565.  
  566.         $this->_postMethods        = $freeMethod;
  567.         $this->_postMethodsExplode = array($freeMethod);
  568.  
  569.         if ($this->getConfigData('weight_type') == PedroTeixeira_Correios_Model_Source_WeightType::WEIGHT_GR) {
  570.             $this->_freeMethodWeight = number_format($this->_freeMethodWeight / 1000, 2, '.', '');
  571.         }
  572.  
  573.         $this->_packageWeight = $this->_freeMethodWeight;
  574.         $this->_pacWeight     = $this->_freeMethodWeight;
  575.     }
  576.  
  577.     /**
  578.      * Check if current carrier offer support to tracking
  579.      *
  580.      * @return bool true
  581.      */
  582.     public function isTrackingAvailable()
  583.     {
  584.         return true;
  585.     }
  586.  
  587.     /**
  588.      * Get Tracking Info
  589.      *
  590.      * @param mixed $tracking Tracking
  591.      *
  592.      * @return mixed
  593.      */
  594.     public function getTrackingInfo($tracking)
  595.     {
  596.         $result = $this->getTracking($tracking);
  597.         if ($result instanceof Mage_Shipping_Model_Tracking_Result) {
  598.             if ($trackings = $result->getAllTrackings()) {
  599.                 return $trackings[0];
  600.             }
  601.         } elseif (is_string($result) && !empty($result)) {
  602.             return $result;
  603.         }
  604.  
  605.         return false;
  606.     }
  607.  
  608.     /**
  609.      * Get Tracking
  610.      *
  611.      * @param array $trackings Trackings
  612.      *
  613.      * @return Mage_Shipping_Model_Tracking_Result
  614.      */
  615.     public function getTracking($trackings)
  616.     {
  617.         $this->_result = Mage::getModel('shipping/tracking_result');
  618.         foreach ((array) $trackings as $code) {
  619.             $this->_getTracking($code);
  620.         }
  621.  
  622.         return $this->_result;
  623.     }
  624.  
  625.     /**
  626.      * Loads the parameters and calls the webservice using SOAP
  627.      *
  628.      * @param string $code Code
  629.      *
  630.      * @return bool|array
  631.      *
  632.      * @throws Exception
  633.      */
  634.     protected function _getTrackingRequest($code)
  635.     {
  636.         $response = false;
  637.         $params = array(
  638.             'usuario'   => $this->getConfigData('sro_username'),
  639.             'senha'     => $this->getConfigData('sro_password'),
  640.             'tipo'      => $this->getConfigData('sro_type'),
  641.             'resultado' => 'T',
  642.             'lingua'    => $this->getConfigData('sro_language'),
  643.             'objetos'   => $code,
  644.         );
  645.  
  646.         try {
  647.             $client = new SoapClient(
  648.                 $this->getConfigData('url_sro_correios'), Mage::helper('pedroteixeira_correios')->getStreamContext()
  649.             );
  650.             $response = $client->buscaEventos($params);
  651.             if (empty($response)) {
  652.                 throw new Exception("Empty response");
  653.             }
  654.         } catch (Exception $e) {
  655.             Mage::log("Soap Error: {$e->getMessage()}");
  656.         }
  657.         return $response;
  658.     }
  659.  
  660.     /**
  661.      * Loads tracking progress details
  662.      *
  663.      * @param SimpleXMLElement $evento      XML Element Node
  664.      * @param bool             $isDelivered Delivery Flag
  665.      *
  666.      * @return array
  667.      */
  668.     protected function _getTrackingProgressDetails($evento, $isDelivered = false)
  669.     {
  670.         $date = new Zend_Date($evento->data, 'dd/MM/YYYY', new Zend_Locale('pt_BR'));
  671.         $track = array(
  672.             'deliverydate'  => $date->toString('YYYY-MM-dd'),
  673.             'deliverytime'  => $evento->hora . ':00',
  674.             'status'        => $evento->descricao,
  675.         );
  676.         if (!$isDelivered) {
  677.             $msg = array($evento->descricao);
  678.             if (isset($evento->destino) && isset($evento->destino->local)) {
  679.                 $msg = array("{$evento->descricao} para {$evento->destino->local}");
  680.             }
  681.             $track['activity'] = implode(' | ', $msg);
  682.             $track['deliverylocation'] = "{$evento->local} - {$evento->cidade}/{$evento->uf}";
  683.         }
  684.         return $track;
  685.     }
  686.  
  687.     /**
  688.      * Loads progress data using the WSDL response
  689.      *
  690.      * @param string $request Request response
  691.      *
  692.      * @return array
  693.      */
  694.     protected function _getTrackingProgress($request)
  695.     {
  696.         $track = array();
  697.         $progress = array();
  698.         $eventTypes = explode(',', $this->getConfigData("sro_event_type_last"));
  699.  
  700.         if (count($request->return->objeto->evento) == 1) {
  701.             $progress[] = $this->_getTrackingProgressDetails($request->return->objeto->evento);
  702.         } else {
  703.             foreach ($request->return->objeto->evento as $evento) {
  704.                 $progress[] = $this->_getTrackingProgressDetails($evento);
  705.                 $isDelivered = ((int) $evento->status < 2 && in_array($evento->tipo, $eventTypes));
  706.                 if ($isDelivered) {
  707.                     $track = $this->_getTrackingProgressDetails($evento, $isDelivered);
  708.                 }
  709.             }
  710.         }
  711.  
  712.         $progress[] = $track;
  713.         return $progress;
  714.     }
  715.  
  716.     /**
  717.      * Protected Get Tracking, opens the request to Correios
  718.      *
  719.      * @param string $code Code
  720.      *
  721.      * @return bool
  722.      */
  723.     protected function _getTracking($code)
  724.     {
  725.         $error = Mage::getModel('shipping/tracking_result_error');
  726.         $error->setTracking($code);
  727.         $error->setCarrier($this->_code);
  728.         $error->setCarrierTitle($this->getConfigData('title'));
  729.         $error->setErrorMessage($this->getConfigData('urlerror'));
  730.        
  731.         $request = $this->_getTrackingRequest($code);
  732.         if (!isset($request->return)) {
  733.             $this->_result->append($error);
  734.             return false;
  735.         }
  736.  
  737.         $progress = $this->_getTrackingProgress($request);
  738.         if (!empty($progress)) {
  739.             $track = array_pop($progress);
  740.             $track['progressdetail'] = $progress;
  741.  
  742.             $tracking = Mage::getModel('shipping/tracking_result_status');
  743.             $tracking->setTracking($code);
  744.             $tracking->setCarrier($this->_code);
  745.             $tracking->setCarrierTitle($this->getConfigData('title'));
  746.             $tracking->addData($track);
  747.  
  748.             $this->_result->append($tracking);
  749.             return true;
  750.         } else {
  751.             $this->_result->append($error);
  752.             return false;
  753.         }
  754.     }
  755.  
  756.     /**
  757.      * Returns the allowed carrier methods
  758.      *
  759.      * @return array
  760.      */
  761.     public function getAllowedMethods()
  762.     {
  763.         $output = array($this->_code => $this->getConfigData('title'));
  764.         $serviceObject = Mage::getSingleton('pedroteixeira_correios/postmethod');
  765.         foreach ($serviceObject->getCollection() as $service) {
  766.             $output[ $service->getMethodCode() ] = "{$service->getMethodCode()} - {$service->getMethodTitle()}";
  767.         }
  768.         return $output;
  769.     }
  770.  
  771.     /**
  772.      * Define ZIP Code as required
  773.      *
  774.      * @param string $countryId Country ID
  775.      *
  776.      * @return bool
  777.      */
  778.     public function isZipCodeRequired($countryId = null)
  779.     {
  780.         return true;
  781.     }
  782.  
  783.     /**
  784.      * Retrieve an average size.
  785.      * For optimization purposes all tree box sizes are converted in one medium dimension.
  786.      * Result cant exceed the minimum transportation limits.
  787.      *
  788.      * @return PedroTeixeira_Correios_Model_Carrier_CorreiosMethod
  789.      */
  790.     protected function _loadMidSize()
  791.     {
  792.         $volumeFactor   = $this->getConfigData('coeficiente_volume');
  793.         $volumeTotal    = $this->_volumeWeight * $volumeFactor;
  794.         $pow            = round(pow((int) $volumeTotal, (1 / 3)));
  795.         $min            = $this->getConfigData('midsize_min');
  796.         $this->_midSize = max($pow, $min);
  797.         return $this;
  798.     }
  799.  
  800.     /**
  801.      * Validate post methods removing invalid services from quotation.
  802.      *
  803.      * @return boolean|PedroTeixeira_Correios_Model_Carrier_CorreiosMethod
  804.      */
  805.     protected function _removeInvalidServices()
  806.     {
  807.         $tmpMethods = $this->_postMethodsExplode;
  808.         $tmpMethods = $this->_filterMethodByConfigRestriction($tmpMethods);
  809.         $isDivisible = (count($tmpMethods) == 0);
  810.  
  811.         if ($isDivisible) {
  812.             return $this->_splitPack();
  813.         }
  814.  
  815.         $this->_postMethodsExplode = $tmpMethods;
  816.         $this->_postMethods        = implode(',', $this->_postMethodsExplode);
  817.         $this->_postMethodsFixed   = $this->_postMethods;
  818.         return $this;
  819.     }
  820.  
  821.     /**
  822.      * Include an additional method to quote content before showing.
  823.      * When requested the new method is added in xml content as specified in config.xml like below:
  824.      *
  825.      *     <add_method_0>
  826.      *         <code>10065</code>
  827.      *         <price>2.45</price>
  828.      *         <days>5</days>
  829.      *         <from>
  830.      *             <zip>00000000</zip>
  831.      *             <weight>0.0</weight>
  832.      *             <size>0</size>
  833.      *         </from>
  834.      *         <to>
  835.      *             <zip>99999999</zip>
  836.      *             <weight>0.1</weight>
  837.      *             <size>150</size>
  838.      *         </to>
  839.      *     </add_method_0>
  840.      *
  841.      * @param SimpleXMLElement $cServico XML Node
  842.      *
  843.      * @see http://www.correios.com.br/para-voce/consultas-e-solicitacoes/precos-e-prazos/servicos-nacionais_pasta/carta
  844.      *
  845.      * @return SimpleXMLElement
  846.      */
  847.     protected function _addPostMethods($cServico)
  848.     {
  849.         $addMethods = $this->getConfigData("add_postmethods");
  850.         if (empty($addMethods) || !is_array($addMethods)) {
  851.             return $cServico;
  852.         }
  853.         foreach ($addMethods as $configData) {
  854.             $isValid = true;
  855.             $isValid &= $this->_packageWeight >= $configData['from']['weight'];
  856.             $isValid &= $this->_packageWeight <= $configData['to']['weight'];
  857.             $isValid &= $this->_midSize >= $configData['from']['size'];
  858.             $isValid &= $this->_midSize <= $configData['to']['size'];
  859.             $isValid &= $this->_toZip >= $configData['from']['zip'];
  860.             $isValid &= $this->_toZip <= $configData['to']['zip'];
  861.  
  862.             if ($isValid) {
  863.                 $price   = $configData['price'];
  864.                 $days    = $configData['days'];
  865.                 $method  = $configData['code'];
  866.                 foreach ($cServico as $servico) {
  867.                     if ($servico->Codigo == $method) {
  868.                         if (!empty($price)) {
  869.                             $servico->Valor = number_format($price, 2, ',', '');
  870.                         }
  871.                         if (!empty($days)) {
  872.                             $servico->PrazoEntrega = $days;
  873.                         }
  874.                         $servico->EntregaDomiciliar = 'S';
  875.                         $servico->EntregaSabado     = 'S';
  876.                         $servico->Erro              = '0';
  877.                         $servico->MsgErro           = '<![CDATA[]]>';
  878.                     }
  879.                 }
  880.             }
  881.         }
  882.  
  883.         return $cServico;
  884.     }
  885.  
  886.     /**
  887.      * This keeps only postmethods available for all items in cart.
  888.      * In other words you can set post methods by products.
  889.      * Methods not available for all items in cart are removed.
  890.      * Require attribute creation called postmethods.
  891.      * Example:
  892.      *  code:     postmethods
  893.      *  type:     multiselect
  894.      *  label:    [free]
  895.      *  value 1:  41068
  896.      *  value 2:  40096
  897.      *  ...
  898.      *  value 99: 81019
  899.      *
  900.      * @param Mage_Shipping_Model_Rate_Request $request Mage request
  901.      *
  902.      * @return PedroTeixeira_Correios_Model_Carrier_CorreiosMethod
  903.      */
  904.     protected function _filterMethodByItemRestriction($request)
  905.     {
  906.         if ($this->getConfigFlag('filter_by_item')) {
  907.             $items = $this->_getRequestItems($request);
  908.             $intersection = $this->_postMethodsExplode;
  909.             foreach ($items as $item) {
  910.                 $product         = $this->_getSimpleProduct($item->getProduct());
  911.                 $prodPostMethods = explode(
  912.                     ',', $product->getResource()->getAttributeRawValue(
  913.                         $product->getId(), 'postmethods', $request->getStoreId()
  914.                     )
  915.                 );
  916.                 $intersection    = array_intersect($prodPostMethods, $intersection);
  917.             }
  918.  
  919.             $this->_postMethodsExplode = $intersection;
  920.             $this->_postMethods        = implode(',', $intersection);
  921.             $this->_postMethodsFixed   = $this->_postMethods;
  922.         }
  923.  
  924.         return $this;
  925.     }
  926.  
  927.     /**
  928.      * Added a fit size for items in large quantities.
  929.      * Means you can join items like two or more glasses, pots and vases.
  930.      * The calc is applied only for height side.
  931.      * Required attribute fit_size. Example:
  932.      *
  933.      *         code: fit_size
  934.      *         type: varchar
  935.      *
  936.      * After you can set a fit size for all products and improve your sells
  937.      *
  938.      * @param Mage_Eav_Model_Entity_Abstract $item Order Item
  939.      *
  940.      * @return number
  941.      */
  942.     protected function _getFitHeight($item)
  943.     {
  944.         $product = $this->_getSimpleProduct($item->getProduct());
  945.         $height  = $product->getData('volume_altura');
  946.         $height  = ($height > 0) ? $height : (int) $this->getConfigData('altura_padrao');
  947.         $fitSize = (float) $product->getData('fit_size');
  948.  
  949.         if ($item->getQty() > 1 && is_numeric($fitSize) && $fitSize > 0) {
  950.             $totalSize = $height + ($fitSize * ($item->getQty() - 1));
  951.             $height    = $totalSize / $item->getQty();
  952.         }
  953.  
  954.         return $height;
  955.     }
  956.  
  957.     /**
  958.      * Splits the package in two parts.
  959.      * If the package is already splited, each piece will be splited in two equal parts.
  960.      *
  961.      * @return boolean|PedroTeixeira_Correios_Model_Carrier_CorreiosMethod
  962.      */
  963.     protected function _splitPack()
  964.     {
  965.         $isSplitEnabled = $this->getConfigFlag('split_pack');
  966.         $isMethodAvailable = (count($this->_postMethodsExplode) > 0);
  967.         if ($isSplitEnabled && $isMethodAvailable) {
  968.             $this->_splitUp++;
  969.             $this->_volumeWeight /= 2;
  970.             $this->_packageWeight /= 2;
  971.             $this->_packageValue /= 2;
  972.             return $this->_removeInvalidServices();
  973.         }
  974.         return false;
  975.     }
  976.  
  977.     /**
  978.      * Receive a list of methods, and validate one-by-one using the config settings.
  979.      * Returns a list of valid methods or empty.
  980.      *
  981.      * @param array $postmethods Services List
  982.      *
  983.      * @return array
  984.      */
  985.     protected function _filterMethodByConfigRestriction($postmethods)
  986.     {
  987.         $validMethods = array();
  988.         $this->_loadMidSize();
  989.         foreach ($postmethods as $key => $method) {
  990.             $isOverSize = ($this->_midSize > $this->getConfigData("validate/serv_{$method}/max/size"));
  991.             $isOverSize |= ($this->_midSize * 3 > $this->getConfigData("validate/serv_{$method}/max/sum"));
  992.             $isOverWeight = ($this->_packageWeight > $this->getConfigData("validate/serv_{$method}/max/weight"));
  993.             $isOverCubic = ($this->_volumeWeight > $this->getConfigData("validate/serv_{$method}/max/volume_weight"));
  994.             $isZipAllowed = $this->_validateZipRestriction($method);
  995.  
  996.             if (!$isOverSize && !$isOverWeight && !$isOverCubic && $isZipAllowed) {
  997.                 $validMethods[] = $method;
  998.             }
  999.         }
  1000.         return $validMethods;
  1001.     }
  1002.  
  1003.     /**
  1004.      * Loads the zip range list.
  1005.      * Returns TRUE only if zip target is included in the range.
  1006.      *
  1007.      * @param array $method Current Post Method
  1008.      *
  1009.      * @return boolean
  1010.      */
  1011.     protected function _validateZipRestriction($method)
  1012.     {
  1013.         $zipConfig = $this->getConfigData("validate/serv_{$method}/zips");
  1014.         foreach ($zipConfig as $data) {
  1015.             $zipRange = explode(',', $data);
  1016.             $isBetweenRange = true;
  1017.             $isBetweenRange &= ($this->_toZip >= $zipRange[0]);
  1018.             $isBetweenRange &= ($this->_toZip <= $zipRange[1]);
  1019.             if ($isBetweenRange) {
  1020.                 return true;
  1021.             }
  1022.         }
  1023.         return false;
  1024.     }
  1025.  
  1026.     /**
  1027.      * Some special errors must be sent to users.
  1028.      * If not applicable, the default error will be sent.
  1029.      *
  1030.      * @param array $errorList Error List
  1031.      *
  1032.      * @return boolean
  1033.      */
  1034.     protected function _appendShippingErrors($errorList)
  1035.     {
  1036.         $output = false;
  1037.         $successCode = '0';
  1038.         $hasValidQuote = array_key_exists($successCode, $errorList);
  1039.         if (!$hasValidQuote) {
  1040.             $displayErrorList = explode(',', $this->getConfigData('hard_errors'));
  1041.             if ($this->getConfigFlag('show_soft_errors')) {
  1042.                 $softErrorList = explode(',', $this->getConfigData('soft_errors'));
  1043.                 $displayErrorList = array_merge($displayErrorList, $softErrorList);
  1044.             }
  1045.             foreach ($errorList as $errorCode => $errorMsg) {
  1046.                 $isDisplayError = in_array($errorCode, $displayErrorList);
  1047.                 if ($isDisplayError) {
  1048.                     $error = Mage::getModel('shipping/rate_result_error');
  1049.                     $error->setCarrier($this->_code);
  1050.                     $error->setErrorMessage($errorMsg);
  1051.                     $this->_result->append($error);
  1052.                     $output = true;
  1053.                 }
  1054.             }
  1055.             if (!$output) {
  1056.                 $logMsg = implode(',', $errorList);
  1057.                 Mage::log("{$this->_code}: Warning! There is no valid quotes, and no one error was throwed: {$logMsg}");
  1058.             }
  1059.         }
  1060.         return $output;
  1061.     }
  1062.  
  1063.     /**
  1064.      * Returns a short message showing the number of the packs that will be needed.
  1065.      *
  1066.      * @return string
  1067.      */
  1068.     protected function _getSplitUpMsg()
  1069.     {
  1070.         $msg = "";
  1071.         if ($this->_splitUp > 0) {
  1072.             $qty = pow(2, $this->_splitUp);
  1073.             $msg.= " / {$qty} volumes";
  1074.         }
  1075.         return $msg;
  1076.     }
  1077.  
  1078.     /**
  1079.      * Returns a short warning message.
  1080.      *
  1081.      * @param string $error Error Id
  1082.      *
  1083.      * @return string
  1084.      */
  1085.     protected function _getSoftErrorMsg($error)
  1086.     {
  1087.         $msg = "";
  1088.         if ($this->getConfigFlag('show_soft_errors')) {
  1089.             $softErrorList = explode(',', $this->getConfigData('soft_errors'));
  1090.             $isSoftError = in_array($error, $softErrorList);
  1091.             if ($isSoftError) {
  1092.                 $msg.= " / Área de Risco";
  1093.             }
  1094.         }
  1095.         return $msg;
  1096.     }
  1097.  
  1098.     /**
  1099.      * Returns the price as float, and fixed by pack division.
  1100.      *
  1101.      * @param string $price Price String
  1102.      *
  1103.      * @return float
  1104.      */
  1105.     protected function _getFormatPrice($price)
  1106.     {
  1107.         $stringPrice = str_replace('.', '', $price);
  1108.         $stringPrice = str_replace(',', '.', $stringPrice);
  1109.         $shippingPrice = floatval($stringPrice);
  1110.         $shippingPrice *= pow(2, $this->_splitUp);
  1111.         return $shippingPrice;
  1112.     }
  1113.  
  1114.     /**
  1115.      * Filter visible and bundle children products.
  1116.      *
  1117.      * @param array $items Product Items
  1118.      *
  1119.      * @return array
  1120.      */
  1121.     protected function _loadBundleChildren($items)
  1122.     {
  1123.         $visibleAndBundleChildren = array();
  1124.         /* @var $item Mage_Sales_Model_Quote_Item */
  1125.         foreach ($items as $item) {
  1126.             $product = $item->getProduct();
  1127.             $isBundle = ($product->getTypeId() == Mage_Catalog_Model_Product_Type::TYPE_BUNDLE);
  1128.             if ($isBundle) {
  1129.                 /* @var $child Mage_Sales_Model_Quote_Item */
  1130.                 foreach ($item->getChildren() as $child) {
  1131.                     $visibleAndBundleChildren[] = $child;
  1132.                 }
  1133.             } else {
  1134.                 $visibleAndBundleChildren[] = $item;
  1135.             }
  1136.         }
  1137.         return $visibleAndBundleChildren;
  1138.     }
  1139. }
  1140.  
Add Comment
Please, Sign In to add comment