Webservice Consulta de Frete JAMEF

Quem já precisou integrar a consulta de frete da transportadora JAMEF se deparou com o problema de não retornar o prazo de entrega. Eis a solução. Ao criar esse conexão também montei o código para trazer o prazo de entrega.

Um detalhe importante é quanto ao tempo de processamento, o servidor da JAMEF demora para responder e isso pode tornar a consulta mais lenta que encontrado em outros webservices.

consultajamef.php

<?php
class JamefConsultaFrete
{
	/* ATRIBUTOS */
	private $wsdlSchema    = 'http://';
	private $wsdlSock      = 'http://';
	private $wsdlHost      = 'www.jamef.com.br';
	private $wsdlQuery     = '/internet/e-comerce/calculafrete.asp?';
	private $trackQuery    = '/internet/e-comerce/calculafrete_xml.asp?';
	private $wsdlPort      = 80;
	private $function      = '';
	private $soapAction    = '';
	private $error         = false;

	//Login
	private $username      = ‘[CNPJ DA EMPRESA]’;
	private $_services     = array(
				'R' => array('name'  => 'Transportadora Jamef', 'title' => 'Encomenda Rodoviario',  'code' => '54'), 	//Rodoviario								'A' => array('name'  => 'Transportadora Jamef', 'title' => 'Encomenda Aereo',		'code' => '55'), 	//Aereo									);
	//Config.
	private $zipcodeSRC    = ‘[CEP_ORIGEM]’;
	private $zipcodeDST    = ‘[CEP_DESTINO]’;
	private $ufDST         = ‘[UF_DESTINO]’;
	private $cityDST       = ‘[CIDADE_DESTINO]’;
	private $width         = 0.00;			//Largura
	private $length        = 0.00;			//Comprimento
	private $height	       = 0.00;			//Altura
	private $diameter      = 0.00;			//Diametro
	private $weight        = 0.00;			//Peso
	private $price         = 0.00;			//Valor Declarado
	//Serviços
	private $ndocSRC       = array(			//Documento do Destinatário
			174 => array('name' => 'AJU', 'title' => '(Filial Aracajú)',     'uf' => 'SE'),
			122 => array('name' => 'BAR', 'title' => '(Filial Barueri)',     'uf' => 'SP'),
			111 => array('name' => 'BAU', 'title' => '(Filial Bauru)',     'uf' => 'SP'),
			1   => array('name' => 'BHZ', 'title' => '(Filial Belo Horizonte)',     'uf' => 'MG'),
			13  => array('name' => 'BNU', 'title' => '(Filial Blumenau)',     'uf' => 'SC'),
			163 => array('name' => 'BSB', 'title' => '(Filial Brasilia)',     'uf' => 'DF'),
			160 => array('name' => 'CCM', 'title' => '(Filial Criciuma)',     'uf' => 'SC'),
			12  => array('name' => 'CPQ', 'title' => '(Filial Campinas)',     'uf' => 'SP'),
			5   => array('name' => 'CXJ', 'title' => '(Filial Caxias do Sul)',     'uf' => 'RS'),
			10  => array('name' => 'CWB', 'title' => '(Filial Curitiba)',     'uf' => 'PR'),
			192 => array('name' => 'FES', 'title' => '(Filial Feira de Santana)',     'uf' => 'BA'),
			11  => array('name' => 'FLN', 'title' => '(Filial Florianópolis)',     'uf' => 'SC'),
			177 => array('name' => 'FOR', 'title' => '(Filial Fortaleza)',     'uf' => 'CE'),
			148 => array('name' => 'GYN', 'title' => '(Filial Goiânia)',     'uf' => 'GO'),
			193 => array('name' => 'ITJ', 'title' => '(Filial Itajaí)',     'uf' => 'SC'),
			4   => array('name' => 'JAS', 'title' => '(Filial Jaraguá do Sul)',     'uf' => 'SC'),
			9   => array('name' => 'JOI', 'title' => '(Filial Joinville)',     'uf' => 'SC'),
			8   => array('name' => 'LDB', 'title' => '(Filial Londrina)',     'uf' => 'PR'),
			149 => array('name' => 'MAO', 'title' => '(Filial Manaus)',     'uf' => 'AM'),
			183 => array('name' => 'MCZ', 'title' => '(Filial Maceió)',     'uf' => 'AL'),
			14  => array('name' => 'POA', 'title' => '(Filial Porto Alegre)',     'uf' => 'RS'),
			159 => array('name' => 'PSA', 'title' => '(Filial Pouso Alegre)',     'uf' => 'RS'),
			121 => array('name' => 'RAO', 'title' => '(Filial Ribeirão Preto)',     'uf' => 'SP'),
			171 => array('name' => 'REC', 'title' => '(Filial Recife)',     'uf' => 'PE'),
			3   => array('name' => 'RIO', 'title' => '(Filial Rio de Janeiro)',     'uf' => 'RJ'),
			2   => array('name' => 'SAO', 'title' => '(Filial São Paulo)',     'uf' => 'SP'),
			125 => array('name' => 'SJK', 'title' => '(Filial São José dos Campos',     'uf' => 'SP'),
			124 => array('name' => 'SJP', 'title' => '(Filial São José do Rio Preto)',     'uf' => 'SP'),
			168 => array('name' => 'SSA', 'title' => '(Filial Salvador)',     'uf' => 'BA'),
			109 => array('name' => 'UDI', 'title' => '(Filial Uberlândia)',     'uf' => 'MG'),
			7   => array('name' => 'VIX', 'title' => '(Filial Vitória)',     'uf' => 'ES')	
								  );
	private $company       = [CODIGO_FILIAL_JAMEF];		//Empresa
	private $volume	       = 1;				//Quantidade de Volume	
	//Adicionais
	private $cost 	       = 0.00;				//AdValore
	private $timeProcedure = 1;				//Tempo Minimo
	private $weightAdd     = 0.00;				//Kg adicional

	//Dados
	private $_data         = array();			//Registro - retorno da Jamef

	/* CONSTRUTOR */
	public function __construct($username, $src_zipcode, $dst_zipcode, $dst_city, $dst_uf, $company)
	{
		//Limpa os vetores de dados.
		$this->reset();

		$this->setUsername($username);
		$this->setCompany($company);

		$this->setZipcodeSRC($src_zipcode);
		$this->setZipcodeDST($dst_zipcode);
		$this->setCityDST($dst_city);
		$this->setUFDST($dst_uf);

	}

	public function setObject($width=0.00, $length=0.00, $height=0.00, $diameter=0.00, $weight=0.00, $price=0.00,$volume=1)
	{
		$this->setWidth($width);
		$this->setLength($length);
		$this->setHeight($height);
		$this->setDiameter($diameter);
		$this->setWeight($weight);
		$this->setPrice($price);
		$this->setVolume($volume);

		return $this;
	}	

	/* METODOS */
	private function getUsername()
	{
		return $this->username;
	}
	private function getPassword()
	{
		return $this->password;
	}

	private function getCompany()
	{
		return $this->company;
	}
	private function setCompany($org_id)
	{
		if ($org_id > 0) $this->company = $org_id;
	}
	private function getWsdlSchema()
	{
		return $this->wsdlSchema;
	}
	private function getWsdlSock()
	{
		return $this->wsdlSock;
	}
	private function getWsdlHost()
	{
		return $this->wsdlHost;
	}
	private function getWsdlPort()
	{
		return $this->wsdlPort;
	}
	private function getWsdlQuery()
	{
		return $this->wsdlQuery;
	}
	private function getFunction()
	{
		return $this->function;
	}
	private function getSoapAction()
	{
		return $this->soapAction;
	}
	private function getWsdl()
	{
		return $this->getWsdlSchema().$this->getWsdlHost().$this->getWsdlQuery();
	}

	private function getTracking()
	{
		return $this->getWsdlSchema().$this->getWsdlHost().$this->trackQuery;
	}

	private function checkConnect()
	{
		$fp = @fsockopen($this->getWsdlHost(), $this->getWsdlPort(), $errno, $errstr, 3);	
		if (is_resource($fp))
		{
			@fclose($fp);
			return true;			
		}
		return false;		
	}

	private function setZipcodeSRC($zipcode)
	{
		$zipcode = str_replace(array('(', ')', '-', '.', ' '), '', $zipcode);

		if (is_numeric($zipcode) & strlen($zipcode) == 8)
		{
			$this->zipcodeSRC = $zipcode;
			return true;
		}		
		return false;
	}
	private function getZipcodeSRC()
	{
		return $this->zipcodeSRC;
	}

	private function setZipcodeDST($zipcode)
	{
		$zipcode = str_replace(array('(', ')', '-', '.', ' '), '', $zipcode);

		if (is_numeric($zipcode) & strlen($zipcode) == 8)
		{
			$this->zipcodeDST = $zipcode;
			return true;
		}		
		return false;
	}	
	private function getZipcodeDST()
	{
		return $this->zipcodeDST;
	}

	private function setUFDST($uf)
	{
		if (strlen($uf) == 2)
		{
			$this->ufDST = $uf;
			return true;
		}		
		return false;
	}	
	private function getUFDST()
	{
		return $this->ufDST;
	}

	private function setCityDST($city)
	{
		$this->cityDST = $city;
	}	
	private function getCityDST()
	{
		return $this->city;
	}

	private function setWeight($weight)
	{
		$weight = doubleval($weight);
		if (is_double($weight))
		{
			$this->weight = $weight;		
			return true;
		}
		return false;
	}
	private function getWeight()
	{
		return ($this->weight + $this->getWeightAdd()) * 1;	//peso deve ser informado em Kilograma.
	}
	private function getWeightAdd()
	{
		return $this->weightAdd;
	}

	private function setDiameter($diameter)
	{
		$diameter = doubleval($diameter);
		if (is_double($diameter))
		{
			$this->diameter = $diameter/100;		
			return true;
		}
		return false;
	}
	private function getDiameter()
	{
		return $this->diameter;
	}

	private function setWidth($width)
	{
		$width = doubleval($width);
		if (is_double($width))
		{
			$this->width = $width/100;		
			return true;
		}
		return false;
	}
	private function getWidth()
	{
		return $this->width;
	}

	private function setLength($length)
	{
		$length = doubleval($length);
		if (is_double($length))
		{
			$this->length = $length/100;
			return true;
		}
		return false;
	}
	public function getLength()
	{
		return $this->length;
	}

	private function setHeight($height)
	{
		$height = doubleval($height);
		if (is_double($height))
		{
			$this->height = $height/100;
			return true;
		}
		return false;
	}
	private function getHeight()
	{
		return $this->height;
	}

	private function setPrice($price)
	{
		$price = doubleval($price);
		if (is_double($price))
		{
			$this->price = $price;
			return true;
		}
		return false;
	}
	private function getPrice()
	{
		return $this->price;
	}

	private function getCost()
	{
		return $this->cost;
	}

	private function getTimeProcedure()
	{
		return $this->timeProcedure;
	}

	private function reset()
	{
		$this->width     = 0.00;		//Largura
		$this->length    = 0.00;		//Comprimento
		$this->height	 = 0.00;		//Altura
		$this->diameter  = 0.00;		//Diametro
		$this->weight    = 0.00;		//Peso
		$this->price     = 0.00;		//Valor Declarado
	}

	private function getServicesId($code)
	{
		$_services = $this->_services;
		$name      = $_services[$code]['code'];	
		return $name; //JAMEF		
	}

	private function getNDocSRC()
	{
		return $this->ndocSRC[$this->getCompany()];
	}

	private function getVolume()
	{
		return $this->volume;
	}
	private function setVolume($volume)
	{
		if ($volume <= 0) $volume = 1;		 		$this->volume = $volume;
	}

	private function getServicesName($code)
	{
		$_services = $this->_services;
		$name      = $_services[$code]['name'];		
		return $name;
	}

	private function getServicesTitle($code)
	{
		$_services = $this->_services;
		$name      = $_services[$code]['title'];		
		return $name;
	}

	private function getConnect()
	{
		$wsdl   = $this->getWsdl();
		$client = new soap_client($wsdl, true); // true = sem namespace
		//$client = new nusoap_client($wsdl, 'wsdl'); // true = sem namespace
		$client->soap_defencoding = 'UTF-8'; 

		return $client;
	}

	private function curl_post($url, $fields)
	{
		//open connection
		$ch = curl_init();

		//set the url, number of POST vars, POST data
		curl_setopt($ch,CURLOPT_URL, $url);
		curl_setopt($ch,CURLOPT_POST, count($fields));
		curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);

		//execute post
		$result = curl_exec($ch);

		//close connection
		curl_close($ch);

		return $result;
	}

	public function getDeliveryDB($city, $uf)
	{
		$time = 7;
		if ($city != '' & $uf != '')
		{
			$l_date = date('d/m/Y');
			$url    = 'http://www.jamef.com.br/jamef/previsao_entrega.do';
			$data   = '?x=x&calcula=x&txtUf_orig=PR&txtMum_orig=LONDRINA&txtDataEmbarque='.$l_date.'&txtUf_dest='.$uf.'&txtMum_dest='.$city.'&=&';
			$result = $this->curl_post($url, $data);
			$result = str_replace("'", '"', str_replace(array("{'array':[", "]}"), "", trim($result)));
			$result = json_decode($result, true);
			if ($result != null)
			{
				if ($result['dataEntrega'] != '') $time   = Main::diffDate($result['dataEmbarque'], $result['dataEntrega']);					
			}
		}		
		return $time;
	}

	private function callFunction($format='CalcularFrete', $_param=array())
	{
		switch($format)
		{
			case 'CalcularFrete':
				$xml     = $this->convert($_param, 'CalcularFreteResult4’);
				$url     = $this->getTracking().$xml;	
				//echo $url; //exit();
				ini_set('allow_url_fopen', 1);		
				$_result = @file_get_contents($url);	
				if(!is_string($_result)) $error = true;
			break;
		}

		$this->error = $error;

		return $_result;
	}

	private function setParam($_param)
	{
		$xml     = $this->convert($_param, 'CalcularFreteResult2’);
	}

	private function toDecimal($value)
	{
		return number_format($value, 2, '.', '');
	}

	private function toNumber($value)
	{
		return number_format($value, 2, ',', '.');
	}

	private function toNumber2($value, $dec=2)
	{
		return number_format($value, $dec, ',', '');
	}

	private function convertDecimal($value)
	{
		$l_value = str_replace(".", "", $value);
		$l_value = str_replace(",", ".", $l_value);
		$l_value = $this->toDecimal(doubleval($l_value));

		return $l_value;
	}

	private function check()
	{
		$l_weight = $this->getWeight();
		if ($l_weight > 0)
		{
			$l_block  = $this->checkConnect();			
			return $l_block;
		}
		return false;
	}

	private function __get_days_up($code, $days)
	{
		$l_time = 0;
		switch($code)
		{
			default: 
				$l_time = 1;
				if (intval($days) >= 10)    $l_time = 3;
				elseif (intval($days) >= 5) $l_time = 2;
			break;
		}

		return $l_time;		
	}

	private function addCost($code, $price)
	{
		$l_cost  = $price;
		$l_price = $this->getPrice();		
		$v_cost  = $this->getCost();
		switch($code)
		{
			default: $l_cost = ($v_cost * $l_price) + $price; break;
		}		
		return doubleval($l_cost);
	}

	private function getDeliveryTime($time)
	{
		//Regra Padrao
		if ($time < 1) return 3;		 		return $time; 	} 	 	private function getUF() 	{ 		$_array = $this->getNDocSRC();
		return $_array['uf'];
	}

	private function convert($_param, $format='XML')
	{
		$xml     = '';
		$v_param = $_param[0];		
		if (is_array($v_param))
		{
			$i      = 0;
			$f      = sizeof($v_param);
			$v_keys = array_keys($v_param);

			switch($format)
			{
				case 'CalcularFreteResultXML’:

					$xml    = '        <'.$this->getFunction().' xmlns="http://schemas.xmlsoap.org/soap/encoding/">';
					while($i<$f)
					{
						$key   = $v_keys[$i];
						$value = $v_param[$key];

						$xml .= '		<'.$key.'>'.$value.'';
						$i++;
					}
					$xml .= 'getFunction().'>';
				break;

				case 'CalcularFreteResult’:
					while($i<$f)
					{
						$key   = $v_keys[$i];
						$value = $v_param[$key];

						$xml[] = $key.'='.$value;
						$i++;
					}

					$xml = implode(",", $xml);	
				break;

				case 'CalcularFreteResult2’:
					while($i<$f)
					{
						$key   = $v_keys[$i];
						$value = $v_param[$key];

						$xml[] = $value;
						$i++;
					}

					$xml = implode(",", $xml);	
				break;

				case 'CalcularFreteResult4’:
					while($i<$f) 					{ 						$key   = $v_keys[$i]; 						$value = $v_param[$key]; 									 						$xml[] = $key.'='.$value; 						$i++; 					} 					 					$xml = implode("&", $xml);	 				break; 			} 		} 		 		return $xml; 	} 	 	public function getData() 	{ 		$error   = false; 		$check   = $this->check();
		if ($check)
		{
			//echo $this->getWidth();
			//echo ($this->getVolume()*$this->getWidth()*$this->getHeight()*$this->getLength()); exit();
			$_param  = array (
							array (
								'P_CIC_NEGC'	      => $this->getUsername(),
								'P_COG_REGN'	      => $this->getCompany(),
								'P_CEP'		      => $this->getZipcodeDST(),
								'P_PESO_KG'    	      => $this->toNumber2($this->getWeight()),
								'P_VLR_CARG'          => $this->toNumber2($this->getPrice()),
								'P_UF'                => $this->getUF(),
								'P_CUBG'              => $this->toNumber2(($this->getWidth()*$this->getHeight()*$this->getLength()), 4)
								)
							);

			//echo '
'; print_r($_param); echo '

‘;//exit();
$_result = $this->callFunction(‘CalcularFrete, $_param);
$error = $this->error;
$_data = array();
if (!$error)
{
$data = ($_result);
$xml = new xml2array();
$_array = $xml->parse($data);
//echo ‘

';	print_r($_array);	exit();
				$_array = $_array[0]['children'][0]['children'];
				if ($_array[0]['tagData'] == '1')
				{
					$_data    = array(
								0 => 
									array(
										'Codigo'		 		=> $this->getServicesId($_array[3]['tagData']),
										'Valor' 		 		=> $_array[2]['tagData'],
										'PrazoEntrega'   		=> $this->getDeliveryDB($this->getCityDST(), $this->getUFDST()),
										'Erro' 			        => 0,
										'MsgErro'		        => '',
										'ValorMaoPropria'       => 0,
										'ValorAvisoRecebimento' => 0,
										'ValorValorDeclarado'	=> 0.00,
										'EntregaDomiciliar' 	=> 'N',
										'Seguro'			 	=> 'N',
										'EntregaSabado' 		=> 'N'
										)
									);
				}
			}

			$this->_data = $_data;			
		}
		return $this;
	}

	public function procedure()
	{
		$_data        = $this->_data;		
		$l_count      = sizeof($_data);

		if ($l_count > 0)		
		{
			$x                 = 0;	//Inicio
			while($x < $l_count) 			{ 				$l_value = $this->convertDecimal($_data[$x]['Valor']);
				$l_time1 = intval($_data[$x]['PrazoEntrega']);
				$l_code  = $_data[$x]['Codigo'];
				if ($l_code != '' & $l_value > 0.00 & $l_time1 > 0)	//Codigo com erro -1 -2 -99
				{
					$l_time = $this->getDeliveryTime($l_time1);
					$l_value= $this->convertDecimal($_data[$x]['Valor'])*0.9;

					$_data[$x]['Nome']      			 = $this->getServicesName($l_code);
					$_data[$x]['Descricao'] 			 = $this->getServicesTitle($l_code);
					$_data[$x]['ValorReal'] 			 = $l_value;
					$_data[$x]['Valor']    				 = $this->convertDecimal($this->toNumber($this->addCost($l_code, $_data[$x]['ValorReal'])));
					$_data[$x]['ValorTotal'] 			 = $this->toDecimal($_data[$x]['Valor'] + $_data[$x]['ValorMaoPropria'] + $_data[$x]['ValorAvisoRecebimento'] + $_data[$x]['ValorValorDeclarado']);
					$_data[$x]['PrazoEntregaReal'] 		 = $l_time1;
					$_data[$x]['PrazoEntrega'] 			 = ($l_time + $this->getTimeProcedure() + $this->__get_days_up($l_code, $l_time));

				}
				else unset($_data[$x]);

				$x++;
			}
		}
		else return -1;		
		return $_data;
	}
}
?>

resultado.php

<?php

$CNPJ = '';		// CNPJ da empresa
$CEP_ORIGEM = '';	// CEP da empresa
$CEP_DESTINO = '';	// CEP do destinatario
$CIDADE = '';	        // CIDADE do destinario
$UF = '';		// UF do destinario
$FILIAL_JAMEF = '';	// FILIAL da Jamef que irá fazer a coleta

$jamef = new JamefConsultaFrete($CNPJ, $CEP_ORIGEM, $CEP_DESTINO, $CIDADE, $UF, $FILIAL_JAMEF);
$jamef->setObject($largura, $comprimento, $altura, $diametro, $peso, $valor_declarado_da_nota, $qtde_volume);
$resultado = $jamef->getData()->procedure();

echo '<pre>';
print_r($resultado);
echo '</pre>';
?>

Frete! O pesadelo de todo gestor de e-commerce

Texto revisado

Recebo e leio constantemente as opiniões de clientes informando de que as lojas são ótimas, as experiências são agradáveis, fácil navegação para encontrar tudo o que precisa, bons produtos, facilidades na escolha do pagamento, etc e etc. Nos gestores ficamos felizes, parece um “conto de fadas”, a loja ser reconhecida pelos seus esforços e conquistar a satisfação de seus clientes é uma experiência gratificante. Porém, como todo super-homem, temos ponto fraco, a criptonita, o conhecido FRETE.

O custo de transportar uma mercadoria até o cliente é uma das discussões mais antigas entre os lojistas e seus e-consumidores. Antes, para adquirir um produto, o cliente deveria se deslocar até a empresa X, procurar o produto desejado, andar até a empresa Y, Z e fazer cotações dos produtos para finalmente concluir sua compra. Saíam felizes depois da décima quinta loja visitada, pois acreditava ter feito um bom negócio e estavam leva-no para casa o item tão desejado.

As coisas mudaram! A violência e os riscos de sair de casa aumentaram, o tempo se tornou curto e cada vez mais escasso na agenda das pessoas. O cliente quando ia buscar a mercadoria na loja, com certeza tinha-se um custo (só passava despercebido): seja o combustível, passe de transporte, taxi, o estacionamento e muitas outras despesas.

EmbalagemEntretanto, a tecnologia disponibilizou uma nova forma de comprar, a VIRTUAL. Essa nova forma de adquirir produtos – que utiliza a internet como ambiente de compra e venda – oferece a comodidade de receber as nossas compras em casa, no trabalho ou qualquer outro lugar que desejar colocar para entrega, ao invés de termos que andar por N lojas; efetuar compras com agilidade e gastar pouco tempo na tomada de decisão, além da liberdade de horário para comprar – o melhor dos mundos! E agora eu me pergunto: quem paga por toda essa comodidade de receber o produto em casa?
Sabemos que os custos operacionais de um e-commerce exige menos que uma loja física tradicional (que acredito ser mais indicada para produtos especializados, tema para outra discussão).  Porém, não podemos desprezar ou ignorar a conta de transporte para os produtos até o cliente.

Quando as lojas virtuais surgiram, era comum o frete ser calculado dentro de um percentual do valor total do pedido ou da nota fiscal. Esse mesmo cálculo era feito pelos transportadores, e assim, os sites cobravam de seus clientes esse valor, tornando junto a negociação a todos.

Por exemplo: se um produto era vendido por R$100,00 o frete 10% do valor da compra, seria R$10,00 o valor cobrado.

No passado dos e-commerces, para melhorarem suas participações dentro dos canais existentes e aumentarem seus adeptos da compra virtual (consequentemente melhorar seus faturamento), o frete foi banalizado, como forma de investimento, utilizado como marketing e isso agradou a todos (e como!), ajudando a contribuir para o crescimento desse canal de vendas.

Sabemos que essa realidade de cálculo de frete mudou, e muito. O Brasil é um dos maiores países em extensão territorial e sua malha viária é precária. Faltam investimentos para pavimentação, manutenção de veículos, além dos altos custos operacionais e de impostos (ex. protocolo 21/2011). Tudo isso, torna o valor do frete para um produto pequeno, cobrado pelo transportador, extremamente caro. Às vezes, dependendo da localidade, próximo ao valor de venda do produto.

Como a prática de baixos valores para o fretes tornaram-se comuns e acostumou mal os novos e-consumidores, e é dever dos gestores de e-commerces renovarem constantemente suas estratégias para gerenciar essas despesas. As estratégias podem ser, desde tabelas de valores de frete por região à incorporação de parte do valor do frete no preço de venda dos produtos.

“Trabalhe com inteligência ou vai perder dinheiro, e ele, é FINITO”.

A realidade é que essa despesa é cara e, se não for tomado o devido cuidado, tornar-se um “custo fixo” alto. Ter uma estratégia de frete balanceada é uma obrigatoriedade em e-commerce. Saber dosar uma boa política que custeia parte do valor cobrado do frete ao cliente pode ter resultados positivos para o crescimento da loja, além de conseguir boas opiniões e motivar novos clientes. Pense nisso e dedique um pouco do seu tempo nessa etapa do seu e-commerce. Pode estar ai um caminho a percorrer para ter melhores resultados!

Sugestões sempre bem vindas. Abraço é até a próxima.

Nova consulta de Fretes do WebServices do Correios

Licença Creative Commons
FreightCorreios de Thiago Zampieri é licenciado sob uma Licença Creative Commons Attribution


UPDATE: O Correios ama os desenvolvedores… Recebi um e-mail informado que eles alterarão as URL de acesso para MELHORAR e FACILITAR a conexão… Bom vamos as alterações então neh..

A unica coisa que deve ser alterado é a parte de atributos blz? Segue abaixo:

/* ATRIBUTOS */
//private $wsdlSchema    = 'https://';
private $wsdlSchema    = 'http://';
//private $wsdlSock      = 'ssl://';
private $wsdlSock      = 'http://';
//private $wsdlHost      = 'shopping.correios.com.br';
private $wsdlHost      = 'ws.correios.com.br';
//private $wsdlQuery     = '/wbm/shopping/script/CalcPrecoPrazo.asmx?wsdl';
private $wsdlQuery     = '/calculador/CalcPrecoPrazo.asmx?wsdl';
//private $wsdlPort      = 443;
private $wsdlPort      = 80;
private $function      = 'CalcPrecoPrazo';
private $soapAction    = 'http://tempuri.org/';

Bom mais uma vez estou aqui para mostrar a implementação da consulta de frete dos correios, que entrará em vigor apartir do dia 30/07/2010 ( o suporte a forma antiga acabou 30 dias antes .aff).

Estava eu na minha mesa de trabalho quando verifico meus e-mail e la estava uma mensagem assim

“Mais uma integração espero que essa seja mais facil! rss”

Bom vi o conteudo do material e comecei a codificação. Após alguns detalhes e ligações ao suporte dessa grande empresa (rss) consegui fazer tudo funcionar.

Antes de postar o codigo fonte quero fazer algumas resalvas sobre esse novo metodo:

– É necessário agora informar as dimensões da embalagem dos itens ( o que é muito ruim ), ou seja, Altura x Largura x Comprimento.

– Quem já implementou a regra anterior sabe que antigamente você não repassava nenhum serviço dos correios, nessa versão é necessário informá-los (o que eu achei muito bacana, evitando retirar serviços que não uso na minha empresa)

– Outro detalhe é que a versão nova utiliza outro usuário e senha (putz até descobri isso foi complicado porque na empresa em que trabalho temos varios cartões de identificação)

Bom vamos ao código, e galera por favor quem utiizar o código favor manter os créditos.

Abraço e qualquer coisa me avisem. (Todas as classes estão funcionando em ambientes produtivos).

Abaixo o código:

<?php
/**
* Class......: FreightCorreios
* Author.....: Thiago Zampieri
* E-mail.....:
* Site.......: thiagozampieri.wordpress.com
* Post date..: 20.06.2010
* Description: Conexão com o webservices do correios para calcular o frete e prazo de entrega
* @access public
*/
class FreightCorreios
{
/* ATRIBUTOS */
private $wsdlSchema    = 'https://';
private $wsdlSock      = 'ssl://';
private $wsdlHost      = 'shopping.correios.com.br';
private $wsdlQuery     = '/wbm/shopping/script/CalcPrecoPrazo.asmx?wsdl';
private $wsdlPort      = 443;
private $function      = 'CalcPrecoPrazo';
private $soapAction    = 'http://tempuri.org/';

//Login
private $username      = 'USER_8_CHARS';
private $password      = 'PASS_8_CHARS';

//Services
/*
* Os codigos abaixos são alguns dos codigos disponíveis para consulta, porém o código 41106 é um código que permite ser consultado sem
* login e senha já que é um serviço liberado pelo correio. Caso deseje saber mais sobre os código entre no site do correios
* www.correios.com.br
* Parametros:
* name  = Nome do serviço
* title = Descrição do serviço
* cost  = AdValore individual
*
* PS: o valor assim será somado com o adValore Geral.
*
* Ad Valore é utilizando muito pelas empresas para evitar erros nos calculos e também custiar os seguros de transporte,
* ou seja, não é incorreto.
*/
private $_services     = array(
'40444' => array('name' => 'SEDEX', 	'title' => 'Sedex Convencional',			'cost' => 0.00), 	//SEDEX com contrato
'81019' => array('name' => 'e-SEDEX', 	'title' => 'Contrato especial e-commerce',	'cost' => 0.00), 	//e-SEDEX com contrato
'41068' => array('name' => 'PAC', 		'title' => 'PAC - Diferenciado',			'cost' => 0.00),	//PAC com contrato
'41025' => array('name' => 'CORREIOS', 	'title' => 'Encomenda Normal',				'cost' => 0.00),	//Encomenda Normal
'41106' => array('name' => 'PAC', 		'title' => 'PAC - Comum',					'cost' => 0.00),	//PAC sem contrato
);
//Config.
private $zipcodeSRC    = '86025040';	//LONDRINA - PR
private $zipcodeDST    = '12345000';	//SAO PAULO - SP
//TIPO DA EMBALAGEM:
private $format        = 1;				//1 - Formato caixa/pacote 2 - Formato rolo/prisma
private $width         = 0.00;			//Largura
private $length        = 0.00;			//Comprimento
private $height	       = 0.00;			//Altura
private $diameter      = 0.00;			//Diametro
private $weight        = 0.00;			//Peso
private $price         = 0.00;			//Valor Declarado
//ServiÁos
private $maoPropria    = 'N';			//ServiÁo M„o PrÛpria
private $receipt       = 'N';			//Aviso de Recebimento
//Adicionais
private $cost 		   = 0.00;			//AdValore (Caso deseja adicionar um valor no retorno dos valores (Geral))
private $timeProcedure = 0;				//Valor Minimo (Numeros de dias para aumentar com o retorno dos correios (Geral))
private $weightAdd     = 0.000;			//Kg (Peso adicional)

//Dados
private $_data         = array();		//Registro - retorno do Correio

/* CONSTRUTOR */
public function __construct($src_zipcode, $dst_zipcode, $width=0.00, $length=0.00, $height=0.00, $diameter=0.00, $weight=0.00, $price=0.00)
{
//Limpa os vetores de dados.
$this->reset();

$this->setZipcodeSRC($src_zipcode);
$this->setZipcodeDST($dst_zipcode);

$this->setWidth($width);
$this->setLength($length);
$this->setHeight($height);
$this->setDiameter($diameter);
$this->setWeight($weight);
$this->setPrice($price);
}

/* METODOS */
private function getUsername()
{
return $this->username;
}
private function getPassword()
{
return $this->password;
}

private function getWsdlSchema()
{
return $this->wsdlSchema;
}
private function getWsdlSock()
{
return $this->wsdlSock;
}
private function getWsdlHost()
{
return $this->wsdlHost;
}
private function getWsdlPort()
{
return $this->wsdlPort;
}
private function getWsdlQuery()
{
return $this->wsdlQuery;
}
private function getFunction()
{
return $this->function;
}
private function getSoapAction()
{
return $this->soapAction;
}
private function getWsdl()
{
return $this->getWsdlSchema().$this->getWsdlHost().$this->getWsdlQuery();
}

private function checkConnect()
{
/*
//		 * Testa a conexão antes de tentar buscar dados no WebServices do Correios
*/
$fp = fsockopen($this->getWsdlSock().$this->getWsdlHost(), $this->getWsdlPort(), $errno, $errstr, 5);
if (!$fp) return false;
return true;
}

private function setZipcodeSRC($zipcode)
{
$zipcode = str_replace(array('(', ')', '-', '.', ' '), '', $zipcode);

if (is_numeric($zipcode) & strlen($zipcode) == 8 )
{
$this->zipcodeSRC = $zipcode;
return true;
}
return false;
}
private function getZipcodeSRC()
{
return $this->zipcodeSRC;
}

private function setZipcodeDST($zipcode)
{
$zipcode = str_replace(array('(', ')', '-', '.', ' '), '', $zipcode);

if (is_numeric($zipcode) & strlen($zipcode) == 8 )
{
$this->zipcodeDST = $zipcode;
return true;
}
return false;
}
private function getZipcodeDST()
{
return $this->zipcodeDST;
}

private function setWeight($weight)
{
$weight = doubleval($weight);
if (is_double($weight))
{
$this->weight = $weight;
return true;
}
return false;
}

private function getWeight()
{
return ($this->weight + $this->getWeightAdd()) * 1;	//peso deve ser informado em Kilograma.
}
private function getWeightAdd()
{
return $this->weightAdd;
}

private function setDiameter($diameter)
{
$diameter = doubleval($diameter);
if (is_double($diameter))
{
$this->diameter = $diameter;
return true;
}
return false;
}
private function getDiameter()
{
return $this->diameter;
}

private function setWidth($width)
{
$width = doubleval($width);
if (is_double($width))
{
$this->width = $width;
return true;
}
return false;
}
private function getWidth()
{
return $this->width;
}

private function setLength($length)
{
$length = doubleval($length);
if (is_double($length))
{
$this->length = $length;
return true;
}
return false;
}
public function getLength()
{
return $this->length;
}

private function setHeight($height)
{
$height = doubleval($height);
if (is_double($height))
{
$this->height = $height;
return true;
}
return false;
}
private function getHeight()
{
return $this->height;
}

private function setPrice($price)
{
$price = doubleval($price);
if (is_double($price))
{
$this->price = $price;
return true;
}
return false;
}
private function getPrice()
{
return $this->price;
}

private function getMaoPropria()
{
return $this->maoPropria;
}
private function getFormat()
{
return $this->format;
}
private function getReceipt()
{
return $this->receipt;
}
private function getCost()
{
return $this->cost;
}

private function getTimeProcedure()
{
return $this->timeProcedure;
}

private function reset()
{
$this->width     = 0.00;		//Largura
$this->length    = 0.00;		//Comprimento
$this->height	 = 0.00;		//Altura
$this->diameter  = 0.00;		//Diametro
$this->weight    = 0.00;		//Peso
$this->price     = 0.00;		//Valor Declarado
}

private function getServicesId()
{
$_services = $this->_services;
$_keys = array_keys($_services);

return $_keys;
}

private function getServicesName($code)
{
$_services = $this->_services;
$name      = $_services[$code]['name'];
return $name;
}

private function getServicesCost($code)
{
$_services = $this->_services;
$cost      = $_services[$code]['cost'];
return $cost;
}

private function getServicesTitle($code)
{
$_services = $this->_services;
$name      = $_services[$code]['title'];
return $name;
}

private function getConnect()
{
$wsdl   = $this->getWsdl();
$client = new soap_client($wsdl, true); // true = sem namespace

return $client;
}

private function toDecimal($value)
{
if ($value > 0) return number_format($value, 2, '.', '');
return '0';
}

private function toNumber($value)
{
return number_format($value, 2, ',', '.');
}

private function convertDecimal($value)
{
$l_value = str_replace(".", "", $value);
$l_value = str_replace(",", ".", $l_value);
$l_value = $this->toDecimal(doubleval($l_value));

return $l_value;
}

private function check()
{
$l_weight = $this->getWeight();
if ($l_weight > 0 & $l_weight <= 30) 		{ 			$l_block  = $this->checkConnect();
return $l_block;
}
return false;
}

private function addCost($code, $price)
{
$l_cost  = $price;
$l_price = $this->getPrice();
$v_cost  = $this->getCost();
$v_cost2 = $this->getServicesCost($code);

$v_cost  = $v_cost + $v_cost2;
switch($code)
{
default: $l_cost = ($v_cost * $l_price) + $price; break;
}
return doubleval($l_cost);
}

public function getData()
{
$error   = false;
$check   = $this->check();
if ($check)
{
$client  = $this->getConnect();

$_param  = array (
array (
'nCdEmpresa'	      => $this->getUsername(),
'sDsSenha'		      => $this->getPassword(),
'nCdServico'		  => implode(',', $this->getServicesId()),
'sCepOrigem'	      => $this->getZipcodeSRC(),
'sCepDestino'	      => $this->getZipcodeDST(),
'nVlPeso'		      => $this->toDecimal($this->getWeight()),
'nCdFormato'	      => $this->getFormat(),
'nVlComprimento'      => $this->toDecimal($this->getLength()),
'nVlAltura'           => $this->toDecimal($this->getHeight()),
'nVlLargura'          => $this->toDecimal($this->getWidth()),
'nVlDiametro'         => $this->toDecimal($this->getDiameter()),
'sCdMaoPropria'       => $this->getMaoPropria(),
'nVlValorDeclarado'   => $this->toDecimal($this->getPrice()),
'sCdAvisoRecebimento' => $this->getReceipt()
)
);

$_result = $client->call($this->getFunction(), $_param);

$error   = $client->getError();
if($client->fault) $error = true;

$_data = array();
if (!$error)
{
$_data = $_result[$this->getFunction().'Result']['Servicos']['cServico'];
$_keys = array_keys($_data);
if (!is_numeric($_keys[0])) $_data = array($_data);
}

$this->_data = $_data;
}
return $this;
}

public function getSecure($value)
{
if($value > 0) return 'S'; else return 'N';
}

/*
* Regra de Prazo de Entrega
* Aqui é possível ajustar a sua realidade
*/
private function getDeliveryTime($time)
{
return intval($time)+$this->getTimeProcedure();
}

public function procedure()
{
$_data   = $this->_data;
$l_count = sizeof($_data);
if ($l_count > 0)
{
$x = 0;	//Inicio
while($x < $l_count) 			{ 				$l_value = $this->convertDecimal($_data[$x]['Valor']);
$l_time1 = intval($_data[$x]['PrazoEntrega']);
$l_code  = $_data[$x]['Codigo'];

//Validação dos resultados retornados
//No Manual é possível encontrar mais detalhes sobre os retornos inválidos.
if ($l_code != '' & $l_value > 0.00 & $l_time1 > 0)
{
$l_time = $this->getDeliveryTime($l_time1);

$_data[$x]['Nome']      			 = $this->getServicesName($l_code);
$_data[$x]['Descricao'] 			 = $this->getServicesTitle($l_code);
$_data[$x]['ValorReal'] 			 = $this->convertDecimal($_data[$x]['Valor']);
$_data[$x]['Valor']    				 = $this->convertDecimal($this->toNumber($this->addCost($l_code, $_data[$x]['ValorReal'])));
$_data[$x]['ValorMaoPropria'] 		 = $this->convertDecimal($_data[$x]['ValorMaoPropria']);
$_data[$x]['ValorAvisoRecebimento']  = $this->convertDecimal($_data[$x]['ValorAvisoRecebimento']);
$_data[$x]['ValorValorDeclarado'] 	 = $this->convertDecimal($_data[$x]['ValorValorDeclarado']);
$_data[$x]['ValorTotal'] 			 = $this->toDecimal($_data[$x]['Valor'] + $_data[$x]['ValorMaoPropria'] + $_data[$x]['ValorAvisoRecebimento'] + $_data[$x]['ValorValorDeclarado']);
$_data[$x]['PrazoEntrega'] 			 = $l_time;
$_data[$x]['PrazoEntregaReal']       = $l_time1;
$_data[$x]['Seguro']				 = $this->getSecure($_data[$x]['ValorValorDeclarado']);

//Elimina os resultados que não possuem dados
}else unset($_data[$x]);
$x++;
}
}
else return -1;
return $_data;
}
}
?>