Como fazer integração do Google Maps com AdvPL

Hoje vou mostrar como fazer a integração do Google Maps em um site com PHP e JavaScript consultando informações do Protheus via AdvPL.

Algumas vezes precisamos fazer alguma integração, e recentemente eu tive que fazer uma, onde em um site com PHP e JavaScript ele iria acessar os dados de uma base Protheus e mostrar pinos em uma região conforme a tabela de clientes (SA1).

Essa integração funciona da seguinte forma, em uma página web, é feito uma requisição via SOAP para o Protheus, que analisa e retorna os principais clientes daquela cidade em questão, e nisso a página web monta os pinos conforme os endereços dos clientes.

Caso você tenha cadastrado latitude e longitude, fica mais fácil para fazer a integração, porém como nesse cenário não tinha isso, eu fiz pegando pelo endereço mesmo, então vamos lá ver como é feito.

  1. Crie ou configure uma conta no Google Cloud Platform ( https://cloud.google.com/maps-platform/ ), crie uma API, que contemple as seguintes opções:
  • Maps JavaScript API
  • Maps Embed API
  • Directions API
  • Geocoding API
  • Maps SDK for Android
  • Maps SDK for iOS
  • Maps Static API
  • Street View Publish API
  • Street View Static API
  1. Após criar a API, guarde a chave gerada, geralmente é uma de 40 caracteres, por exemplo XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  2. Agora, configure um AppServer que será o nosso WebService, nesse exemplo nós usaremos SOAP. Para ver como configurar, veja o passo a passo nesse link – https://terminaldeinformacao.com/2019/02/05/como-configurar-um-webservice-em-advpl-utilizando-soap/
  3. Então, nós iremos agora criar um fonte .prw que irá buscar as informações para mostrar no mapa do Google Maps na nossa página web. Esse método abaixo foi construído assim, ele irá receber o Estado, a Cidade e um Token. A partir disso, é verificado os 26 principais clientes dos últimos 6 meses da cidade para mostrar no mapa. Veja o código abaixo:
//Bibliotecas
#Include "Protheus.ch"
#Include "APWebSrv.ch"
#Include "TBIConn.ch"
#Include "TBICode.ch"
#Include "TopConn.ch"
#Include "aarray.ch"
#Include "json.ch"
#Include "shash.ch"

WsService WsSite Description "WebService de exemplo para o site"
	//Atributos
	WsData   cMapRece  as String
	WsData   cMapSend  as String

	//Métodos
	WsMethod RetMapClis       Description "Metodo para retornar os clientes para pinagem em mapa"
EndWsService

/*
	Função fNoAcento
	Função que retira os acentos, foi criado para substituir a FWNoAccent para tirar somente os caracteres de acentuação (sem retirar outros caracteres especiais)
*/

Static Function fNoAcento(cTexto, lTiraAspas, lRetorno)
	Local nAtual        := 0
	Local aTroca        := {}
	Default cTexto      := ""
	Default lTiraAspas  := .T.
	Default lRetorno    := .F.
	
	//ConOut("cTexto:     "+cTexto)
	//ConOut("lTiraAspas: "+cValToChar(lTiraAspas))
	//ConOut("lRetorno:   "+cValToChar(lRetorno))
	
	If ! lRetorno
		aAdd(aTroca, {"ã", "a"})
		aAdd(aTroca, {"á", "a"})
		aAdd(aTroca, {"â", "a"})
		aAdd(aTroca, {"à", "a"})
		aAdd(aTroca, {"ä", "a"})
		aAdd(aTroca, {"é", "e"})
		aAdd(aTroca, {"è", "e"})
		aAdd(aTroca, {"ê", "e"})
		aAdd(aTroca, {"ë", "e"})
		aAdd(aTroca, {"í", "i"})
		aAdd(aTroca, {"ì", "i"})
		aAdd(aTroca, {"î", "i"})
		aAdd(aTroca, {"ï", "i"})
		aAdd(aTroca, {"ó", "o"})
		aAdd(aTroca, {"ò", "o"})
		aAdd(aTroca, {"õ", "o"})
		aAdd(aTroca, {"ô", "o"})
		aAdd(aTroca, {"ö", "o"})
		aAdd(aTroca, {"ú", "u"})
		aAdd(aTroca, {"ù", "u"})
		aAdd(aTroca, {"û", "u"})
		aAdd(aTroca, {"ü", "u"})
		aAdd(aTroca, {"ç", "c"})
	EndIf
	If lTiraAspas
		aAdd(aTroca, {'"', ""})
		aAdd(aTroca, {'“', ""})
		aAdd(aTroca, {'”', ""})
	EndIf
	
	For nAtual := 1 To Len(aTroca)
		cTexto := StrTran(cTexto, aTroca[nAtual][1], aTroca[nAtual][2])
		cTexto := StrTran(cTexto, Upper(aTroca[nAtual][1]), Upper(aTroca[nAtual][2]))
	Next
Return cTexto

/*
	Método RetMapClis
	Funcionalidade que recebe alguns parâmetros e retorna uma lista de clientes
	
	Exemplo do JSON
	{
		"Filtro": {
			"Estado": "SP",
			"Cidade": "Bauru"
    	}
	}
*/

WsMethod RetMapClis WsReceive cMapRece WsSend cMapSend WsService WsSite
	Local lRet      := .T.
	Local cEstado   := ""
	Local cCidade   := ""
	Local cQryCli   := ""
	Local cTokWs    := Alltrim(GetMV('MV_X_TOKEN'))
	Local cSeqAtu   := "A"
	Local cNaoTotal     := "'201','202','206','411','413','551','556','901','903','910','912','914','915','949','913'"
	Local cTiraFilt     := "'901','903','910','915','556','206'"
	Local cTiraFilt2     := "'5411','5413', '5917'"
	Local nMeses    := 6
	Private oJSON   := Nil
	Private oFiltro := Nil
	Private cToken  := ""

	//Deserializando o JSON
	If (FWJsonDeserialize(::cMapRece, @oJSON))
		oFiltro := oJSON:Filtro
		cToken  := Iif(ValAtrib("oJSON:Token") != "U", oJSON:Token, "")
		
		//Se for o mesmo Token
		If cToken == cTokWs
			//Pegando os atributos vindos do JSON
			cEstado  := Upper(Iif(ValAtrib("oFiltro:Estado") != "U", oFiltro:Estado, ""))
			cCidade  := fNoAcento(Upper(Iif(ValAtrib("oFiltro:Cidade") != "U", oFiltro:Cidade, "")))
			
			//Monta a consulta
			cQryCli := "SELECT * FROM (" + CRLF
			cQryCli += " SELECT TOP 26 "                               + CRLF
			cQryCli += " 	A1_COD AS CODIGO, "                        + CRLF
			cQryCli += " 	A1_NOME AS NOME, "                       + CRLF
			cQryCli += " 	A1_NREDUZ AS NREDUZ, "                       + CRLF
			cQryCli += " 	A1_END AS ENDERECO, "                      + CRLF
			cQryCli += " 	A1_BAIRRO AS BAIRRO, "                     + CRLF
			cQryCli += " 	A1_MUN AS CIDADE, "                     + CRLF
			cQryCli += " 	A1_EST AS ESTADO, "                     + CRLF
			cQryCli += " 	A1_CEP AS CEP, "                           + CRLF
			cQryCli += " 	A1_DDD AS DDD, "                           + CRLF
			cQryCli += " 	A1_TEL AS TELEFONE, "                      + CRLF
			cQryCli += " 	A1_EMAIL AS EMAIL, "                       + CRLF
			cQryCli += " 	A1_HPAGE AS SITE, "                       + CRLF
			cQryCli += " 	ISNULL(( "                       + CRLF
			cQryCli += " 		SELECT " + CRLF
			cQryCli += " 			SUM(CASE WHEN SUBSTRING(D2_CF,2,3) NOT IN ("+cNaoTotal+") AND (D2_TIPO NOT IN ('I')) AND ( D2_FILIAL = '01' ) THEN D2_TOTAL ELSE 0.0 END ) AS TOTAL " + CRLF
			cQryCli += " 		FROM " + CRLF
			cQryCli += " 			"+RetSQLName("SD2")+" SD2 WITH (NOLOCK) " + CRLF
			cQryCli += " 			LEFT JOIN "+RetSQLName("SF2")+" SF2 WITH (NOLOCK) ON ( " + CRLF
			cQryCli += " 				D2_FILIAL = F2_FILIAL " + CRLF
			cQryCli += " 				AND F2_DOC = D2_DOC " + CRLF
			cQryCli += " 				AND F2_SERIE = D2_SERIE " + CRLF
			cQryCli += " 				AND SF2.D_E_L_E_T_ = ' ') " + CRLF
			cQryCli += " 		WHERE " + CRLF
			cQryCli += " 			D2_FILIAL = '01' " + CRLF
			cQryCli += " 	        AND D2_CLIENTE = A1_COD "                       + CRLF
			cQryCli += " 	        AND D2_LOJA = A1_LOJA "                       + CRLF
			cQryCli += " 			AND D2_EMISSAO >= '" + dToS(MonthSub(Date(), nMeses)) + "' " + CRLF
			cQryCli += " 			AND SUBSTRING(D2_CF,2,3) NOT IN ("+cTiraFilt+") " + CRLF
			cQryCli += " 			AND D2_CF NOT IN ("+cTiraFilt2+") "	 + CRLF
			cQryCli += " 			AND SD2.D_E_L_E_T_ = ' ' " + CRLF
			cQryCli += " 	), 0) AS VALOR "                       + CRLF
			cQryCli += " FROM "                                        + CRLF
			cQryCli += " 	"+RetSQLName('SA1')+" SA1 WITH (NOLOCK) "  + CRLF
			cQryCli += " WHERE "                                       + CRLF
			cQryCli += " 	A1_FILIAL = '"+FWxFilial('SA1')+"' "       + CRLF
			cQryCli += " 	AND A1_MSBLQL != '1' "                     + CRLF
			If ! Empty(cEstado)
				cQryCli += " 	AND A1_EST = '"+cEstado+"' "           + CRLF
			EndIf
			If !Empty(cCidade)
				cQryCli += " 	AND UPPER(A1_MUN) LIKE '%"+Alltrim(Upper(cCidade))+"%' "      + CRLF
			EndIf
			cQryCli += " 	AND SA1.D_E_L_E_T_ = ' ' "                 + CRLF
			cQryCli += " ORDER BY "                                    + CRLF
			cQryCli += " 	VALOR DESC "                               + CRLF
			cQryCli += " ) TAB_TEMPO "                               + CRLF
			cQryCli += " WHERE "                               + CRLF
			cQryCli += " 	VALOR != 0 "                               + CRLF
			cQryCli += " ORDER BY NREDUZ ASC "               + CRLF
			TCQuery cQryCli New Alias "QRY_CLI"
			
			//Se houver dados
			If ! QRY_CLI->(EoF())
				::cMapSend := '{'                  + CRLF
				::cMapSend +=     '"Clientes": {'
				
				//Enquanto houver dados na consulta
				While ! QRY_CLI->(EoF())
					
					cSite := ''
					If ! ('@' $ cSite .Or. ' ' $ cSite) .And. ('.' $ cSite)
						cSite := Alltrim(QRY_CLI->SITE)
					EndIf
					
					::cMapSend += CRLF
					::cMapSend += '"'+QRY_CLI->CODIGO+'": {'+;
						' "Sequencia":"' +cSeqAtu                              +'", '+;
						' "Codigo":"'    +QRY_CLI->CODIGO                      +'", '+;
						' "Nome":"'      +Alltrim(Capital(QRY_CLI->NOME))      +'", '+;
						' "NomeReduz":"' +Alltrim(Capital(QRY_CLI->NREDUZ))    +'", '+;
						' "Endereco":"'  +Alltrim(Capital(QRY_CLI->ENDERECO))  +'", '+;
						' "Bairro":"'    +Alltrim(Capital(QRY_CLI->BAIRRO))    +'", '+;
						' "Cidade":"'    +Alltrim(Capital(QRY_CLI->CIDADE))    +'", '+;
						' "Estado":"'    +Alltrim(Capital(QRY_CLI->ESTADO))    +'", '+;
						' "CEP":"'       +Alltrim(QRY_CLI->CEP)                +'", '+;
						' "DDD":"'       +Alltrim(QRY_CLI->DDD)                +'", '+;
						' "Telefone":"'  +Alltrim(QRY_CLI->TELEFONE)           +'", '+;
						' "Email":"'     +Alltrim(QRY_CLI->EMAIL)              +'", '+;
						' "Site":"'      +Alltrim(cSite)                       +'"  '+;
						'},'
						
					cSeqAtu := Soma1(cSeqAtu)
					QRY_CLI->(DbSkip())
				EndDo
				
				//Retirando a última vírgula
				::cMapSend := SubStr(::cMapSend, 1, Len(::cMapSend)-1)
				
				::cMapSend +=     '}'              + CRLF
				::cMapSend += '}'                  + CRLF
				
			//Senão monta estrutura vazia
			Else
				::cMapSend := '{'                  + CRLF
				::cMapSend +=     '"Clientes": {'  + CRLF
				::cMapSend +=     '}'              + CRLF
				::cMapSend += '}'                  + CRLF
			EndIf
			QRY_CLI->(DbCloseArea())
			
			//Retira os acentos
			::cMapSend := fNoAcento(::cMapSend, .F., .T.)
			
		//Caso seja um token inválido
		Else
			SetSoapFault('Erro', 'Token invalido!')
			lRet := .F.
		EndIf
		
	//Se houve erro ao deserializar o JSON
	Else
		SetSoapFault('Erro', 'JSON nao deserializado!')
		lRet := .F.
	EndIf

Return lRet

/*
	Função ValAtrib
	Função que verifica se um atributo existe no objeto
*/

Static Function ValAtrib(xAtributo)
Return ( Type(xAtributo) )
  1. No nosso site, iremos criar um arquivo chamado functions.php, que será o responsável por ter o nosso Token e a URL do nosso WebService, veja o código abaixo:
<?php

function getToken() {
	$token = 'SeuToken@TerminalDeInformacao';
	return $token;
}

function getWSProtheus() {
	$wsdl = 'http://localhost:8091/ws/WSSITE.apw?WSDL';
	return $wsdl;
}
?>
  1. Agora iremos montar o nosso site, com o nome index.php. Nessa página, iremos colocar alguns parâmetros em cima, o mapa no meio e uma tabela no final. Nos códigos intermediários, através de PHP e JavaScript iremos fazer as integrações com o Protheus (PHP com WebService SOAP) e com o Google Maps (JavaScript). Ah, no código abaixo, lembre-se de colocar a sua chave da API ao invés do XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX (linhas 22 e 309)
<html>
<head>
	<title>Teste Google Maps x AdvPL</title>
</head>
<style>
table, th, td {
    border: 1px solid black;
}
</style>
<body>

<?php
	
	//Incluindo as funcoes de webservice, colocando uma latitude e longitude padrao e a chave do api do Maps
	include "functions.php";
	$parametroCEP         = "";
	$parametroCidade      = "";
	$parametroEstado      = "";
	$parametroRua         = "";
	$latitudePadrao       = "-22.3430709";
	$longitudePadrao      = "-49.0473996";
	$keyGoogleMaps        = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
	$usuarioPesquisou     = false;
	$cidadeEmBranco       = false;
	$tokenProtheus        = getToken();
	$enderecoParaGoogle   = "";
	$urlGoogleMaps        = "";
	$respostaGoogleMaps   = "";
	$respostaGoogleDecod  = "";
	$clientesProtheus     = null;
	$urlWsdlProtheus      = getWSProtheus();
	$soapClientProtheus   = null;
	$parametrosProtheus   = null;
	$respostaProtheus     = null;
	$jsonClientesProtheus = null;

	//Pegando via POST os parametros, caso eles tenham sido preenchidos
	if(isset($_POST['cep'])) {
		$parametroCEP = $_POST['cep'];
	}
	if(isset($_POST['estado'])) {
		$parametroEstado = $_POST['estado'];

		if (! empty($parametroEstado))
			$parametroEstado = substr($parametroEstado, 0, 2);
	}
	if(isset($_POST['cidade'])) {
		$parametroCidade = $_POST['cidade'];
	}
	if(isset($_POST['rua'])) {
		$parametroRua = $_POST['rua'];
	}

	//Se a cidade estiver em branco, porem algum outro parametro estiver preenchido
	if (empty($parametroCidade) && (!empty($parametroCEP) || !empty($parametroEstado) || !empty($parametroRua))) {
		$usuarioPesquisou = true;
		$cidadeEmBranco = true;
	}
	else {
		
		//Se algum parametro estiver preenchido
		if (!empty($parametroCEP) || !empty($parametroEstado) || !empty($parametroCidade) || !empty($parametroRua)) {
			//Monta a url de pesquisa no Google Maps, sendo Rua + Cidade + Estado + CEP
			$usuarioPesquisou = true;
			$enderecoParaGoogle = str_replace(" ", "+", $parametroRua) . str_replace(" ", "+", $parametroCidade) . "+" . $parametroEstado . "+" . $parametroCEP;
			
			//Faz a pesquisa para achar a posicao que o usuario digitou nos parametros
			$urlGoogleMaps = "https://maps.googleapis.com/maps/api/geocode/json?address=" . $enderecoParaGoogle . "&key=" . $keyGoogleMaps;
			$respostaGoogleMaps = file_get_contents($urlGoogleMaps);
			$respostaGoogleDecod = json_decode($respostaGoogleMaps, true);

			//Se houve uma resposta do Google, altera a latitude e longitude padrao
			if ($respostaGoogleDecod != null) {
				$latitudePadrao  = $respostaGoogleDecod['results'][0]['geometry']['location']['lat'];
				$longitudePadrao = $respostaGoogleDecod['results'][0]['geometry']['location']['lng'];
			}
		}
	}

	//Se o usuario pesquisou e a cidade nao esta em branco
	if ($usuarioPesquisou && ! $cidadeEmBranco) {
		
		//Faz a conexao com o WebService no Protheus
		$soapClientProtheus = new SoapClient($urlWsdlProtheus, ['exceptions' => true]);
		
		//Tenta fazer a conexao com o Protheus e buscar os clientes
		try {
			$parametrosProtheus = array(
				"RETMAPCLIS" => array(
					"CMAPRECE" => 
						'{'.
						'	"Filtro": {'.
						'	   "Estado": "'  . $parametroEstado  . '", '.
						'	   "Cidade": "'  . $parametroCidade  . '" '.
						'	},'.
						'	"Token": "'.$tokenProtheus.'"'.
						'}'
					)
				);
			
			$respostaProtheus = $soapClientProtheus->__soapCall("RETMAPCLIS", $parametrosProtheus);
			
			$jsonClientesProtheus = json_decode($respostaProtheus->RETMAPCLISRESULT);
			if (json_last_error() == 0) {
				$clientesProtheus = $jsonClientesProtheus->Clientes;
			}
			
		} catch (SoapFault $soapException) {
			echo 'Houve um erro no carregamento dos clientes, <b>contate o Administrador</b>. Exception: <br>';
			echo $soapException->getMessage();
			return;
		}
	}

	//Agora cria algumas variaveis em javascript com o conteudo das variaveis em php
	echo '<script>';
	echo 'var jsLatitudeOriginal = ' . $latitudePadrao . ';';
	echo 'var jsLongitudeOriginal = ' . $longitudePadrao . ';';
	echo 'var jsLatitudeMarcadorGoogle = jsLatitudeOriginal;';
	echo 'var jsLongitudeMarcadorGoogle = jsLongitudeOriginal;';
	
	if ($usuarioPesquisou && ! $cidadeEmBranco)
		echo 'var jsUsuarioPesquisou = true;';
	else
		echo 'var jsUsuarioPesquisou = false;';
	
	if ($clientesProtheus != null) 
		echo 'var jsTotalDeClientes = ' . count((array)$clientesProtheus) . ';';
	else
		echo 'var jsTotalDeClientes = 0;';
	
	echo '</script>';
?>

<script>
var jsMapa;
var jsPopupInfoWindow;
var jsSiglas = 'ZYXWVUTSRQPONMLKJIHGFEDCBA';
var jsMensagemPos = 0;
var jsMarcadores = [];
var jsArrayDados = [];
var jsMensagensPopup = [];

//se possui clientes, modifica a lista de siglas caso tenha menos que 26 (de A ate Z)
if (jsTotalDeClientes != 0) {
	jsSiglas = jsSiglas.substring(jsSiglas.length - jsTotalDeClientes, jsSiglas.length);
}

//Definindo nos Cookies a latitude e longitude (caso consiga buscar no navegador)
document.cookie="browserLatitude=";
document.cookie="browserLongitude=";

//Se o site tiver suporte a SSL - HTTPS e o navegador tiver suporte a HTML5 - Geolocalizacao, pergunta para o usuario se ele permite compartilhar a localizacao, e se ele confirmar, altera a latitude e longitude
if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(function(position) {
    	document.cookie="browserLatitude=" + position.coords.latitude;
    	document.cookie="browserLongitude=" + position.coords.longitude;
    }, function() {
		
	});
}
</script>

<?php
	//Se a pesquisa no Protheus retornou clientes, usuario pesquisou e tiver cidade digitada
	if (($clientesProtheus != null) && ($usuarioPesquisou) && ! $cidadeEmBranco) {
		
		//Percorrendo todos os clientes
		foreach ( $clientesProtheus as $clienteAtual ) {
			
			//Busca dados do cliente no Google
			$enderecoParaGoogle = str_replace(" ", "+", $clienteAtual->Endereco) . "+" . str_replace(" ", "+", $clienteAtual->Cidade) . "+" . $clienteAtual->Estado . "+" . $clienteAtual->CEP;
			
			$urlGoogleMaps = "https://maps.googleapis.com/maps/api/geocode/json?address=" . $enderecoParaGoogle . "&key=" . $keyGoogleMaps;
			$respostaGoogleMaps = file_get_contents($urlGoogleMaps);
			$respostaGoogleDecod = json_decode($respostaGoogleMaps, true);
			
			//Se encontrou informacoes, pega latitude e longitude do cliente, adiciona no array de informacoes
			if ($respostaGoogleDecod != null) {
				$clienteLatitude  = $respostaGoogleDecod['results'][0]['geometry']['location']['lat'];
				$clienteLongitude = $respostaGoogleDecod['results'][0]['geometry']['location']['lng'];

				echo '<script>jsArrayDados.unshift({lat: ' . $clienteLatitude . ', lng: ' . $clienteLongitude . '});</script>';
			}
			else {
				echo '<script>jsArrayDados.unshift({lat: jsLatitudeOriginal, lng: jsLongitudeOriginal});</script>';
			}
			
			//Adicionando mensagem do Popup que aparece ao clicar no marcador do cliente
			$atualizaPopupMarcadores =  '<script>jsMensagensPopup.push("' ;
			$atualizaPopupMarcadores .= '<b>' . $clienteAtual->NomeReduz . '</b><br>' ;
			$atualizaPopupMarcadores .= '<b>Razão Social: </b>' . $clienteAtual->Nome . '<br>' ;
			$atualizaPopupMarcadores .= '<b>Endereço: </b>' . $clienteAtual->Endereco . ' - ' . $clienteAtual->Bairro . '<br>' ;
			$atualizaPopupMarcadores .= '<b>CEP: </b>' . $clienteAtual->CEP . '<br>' ;
			if (! empty($clienteAtual->Telefone))
				$atualizaPopupMarcadores .= '<b>Telefone: </b> (' . $clienteAtual->DDD . ') ' . $clienteAtual->Telefone . '<br>' ;
			if (! empty($clienteAtual->Email))
				$atualizaPopupMarcadores .= '<b>e-Mail: </b>' . $clienteAtual->Email . '<br>' ;
			if (! empty($clienteAtual->Site))
				$atualizaPopupMarcadores .= '<b>Site: </b>' . $clienteAtual->Site . '' ;
			$atualizaPopupMarcadores .= '")</script>';
			echo $atualizaPopupMarcadores;

		}

		//Busca o endereco digitado pelo usuario
		$enderecoParaGoogle = str_replace(" ", "+", $parametroRua) . "+" . str_replace(" ", "+", $parametroCidade) . "+" . $parametroEstado . "+" . $parametroCEP;
		$urlGoogleMaps = "https://maps.googleapis.com/maps/api/geocode/json?address=" . $enderecoParaGoogle . "&key=" . $keyGoogleMaps;
		$respostaGoogleMaps = file_get_contents($urlGoogleMaps);
		$respostaGoogleDecod = json_decode($respostaGoogleMaps, true);
		
		//Se encontrar, o mapa ira comecar da localizacao do usuario
		if ($respostaGoogleDecod != null) {
			$clienteLatitude = $respostaGoogleDecod['results'][0]['geometry']['location']['lat'];
			$clienteLongitude = $respostaGoogleDecod['results'][0]['geometry']['location']['lng'];

			echo '<script>jsLatitudeMarcadorGoogle = ' . $clienteLatitude . ';</script>';
			echo '<script>jsLongitudeMarcadorGoogle = ' . $clienteLongitude . ';</script>';
		}
	}
?>

<script>
//Funcao para inicializar o map
function initMap() {

	//Inicializa o mapa com a latitude e longitude
	jsMapa = new google.maps.Map(document.getElementById('GoogleMaps'), {
		center: {lat: jsLatitudeOriginal, lng: jsLongitudeOriginal},
		zoom: 13
	});
	jsPopupInfoWindow = new google.maps.InfoWindow;

	//Percorre agora a lista de clientes, e adiciona um marcador com a letra de cada cliente
	for (var jsPosicaoAtual = jsArrayDados.length - 1; jsPosicaoAtual >= 0; jsPosicaoAtual--) {
		addMarker(jsArrayDados[jsPosicaoAtual], jsSiglas[jsPosicaoAtual]);
	}

	//Adiciona um marcador com a posicao atual na cor azul
	jsMensagensPopup.push("Minha localização");
	addMarker({lat: jsLatitudeMarcadorGoogle, lng: jsLongitudeMarcadorGoogle}, "blu-blank");
	jsMapa.setCenter({lat: jsLatitudeMarcadorGoogle, lng: jsLongitudeMarcadorGoogle});
	
	//Se o site tiver SSL - HTTPS, tenta pegar a localizacao atual
	if ((navigator.geolocation) && ! (jsUsuarioPesquisou)) {
		navigator.geolocation.getCurrentPosition(function(position) {
			var jsPosition = {
				lat: position.coords.latitude,
				lng: position.coords.longitude
			};

			jsPopupInfoWindow.setPosition(jsPosition);
			jsPopupInfoWindow.setContent('Localização encontrada');
			jsPopupInfoWindow.open(jsMapa);
			jsMapa.setCenter(jsPosition);
		}, function() {
		//handleLocationError(true, jsPopupInfoWindow, jsMapa.getCenter());
		});
	} else {
		// Browser doesn't support Geolocation
		//handleLocationError(false, jsPopupInfoWindow, jsMapa.getCenter());
	}
	
}

//Funcao para mostrar o erro caso nao encontre a localizacao
function handleLocationError(jsBrowserHasGeolocation, jsPopupInfoWindow, jsPosition) {
	jsPopupInfoWindow.setPosition(jsPosition);
	jsPopupInfoWindow.setContent(jsBrowserHasGeolocation ?
	                  'Erro: A localização falhou, verifique configurações do Navegador.' :
	                  'Erro: Seu Navegador não tem suporte a localização.');
	jsPopupInfoWindow.open(jsMapa);
}

//Funcao para adicionar marcador no mapa
function addMarker(jsLocation, jsLetter) {
	//Monta a URL com a letra
	let jsURLIcone = "http://maps.google.com/mapfiles/kml/paddle/";
    jsURLIcone += jsLetter + ".png";
	
	//Adiciona o marcador e a mensagem
	var jsMarker = new google.maps.Marker({
		position: jsLocation,
		label: {
		},
		map: jsMapa,
		icon: {
          url: jsURLIcone,
      	}
	});
	jsMarcadores.push(jsMarker);
	addInfoWindow(jsMarker, jsMensagensPopup[jsMensagemPos++]);
}

//Funcao para adicionar um Popup no marcador
function addInfoWindow(jsMarker, jsMensagem) {
    var jsPopupInfoWindow = new google.maps.InfoWindow({
        content: jsMensagem
    });

    google.maps.event.addListener(jsMarker, 'click', function () {
        jsPopupInfoWindow.open(jsMapa, jsMarker);
    });
}
</script>

<!--Script de carregamento do Google Maps-->
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&callback=initMap">
</script>

<?php
	//Se o usuario fez a pesquisa
	if (! $usuarioPesquisou) {
		//Se estiver em branco a longitude e latitude do navegador, coloca por padrao a cidade de Bauru
		if (empty($_COOKIE['browserLatitude']) && empty($_COOKIE['browserLongitude'])) {
			$parametroCEP    = "";
			$parametroCidade = "Bauru";
			$parametroEstado = "SP";
			$parametroRua    = "";
			$longitudePadrao = "-49.0473996";
			$latitudePadrao  = "-22.3430709";
		}
		//Senao, busca as informacoes conforme pesquisa do usuario para preencher os parametros
		else {
			$longitudePadrao = $_COOKIE['browserLongitude'];
			$latitudePadrao  = $_COOKIE['browserLatitude'];
			$urlGoogleMaps = "https://maps.googleapis.com/maps/api/geocode/json?latlng=" . $latitudePadrao . "," . $longitudePadrao . "&key=" . $keyGoogleMaps;
			$respostaGoogleMaps = file_get_contents($urlGoogleMaps);
			$respostaGoogleDecod = json_decode($respostaGoogleMaps, true);
			
			//Se tiver uma resposta do Google
			if ($respostaGoogleDecod != null) {
				//Percorre todos os componentes que o Google enviou para achar detalhes do endereco
				foreach($respostaGoogleDecod['results'][0]['address_components'] as $componentesEndereco) {
					if($componentesEndereco["types"][0]=="administrative_area_level_1") {
						$parametroEstado = $componentesEndereco["short_name"];
					}   
					if($componentesEndereco["types"][0]=="administrative_area_level_2") {
						$parametroCidade = $componentesEndereco["long_name"];
					}
					if($componentesEndereco["types"][0]=="postal_code") {
						$parametroCEP = $componentesEndereco["long_name"];
					}
					if($componentesEndereco["types"][0]=="route") {
						$parametroRua = $componentesEndereco["long_name"];
					}
				}
			}
		}
	}
?>

<center>
	<!--Div principal da navegação-->
	<div style="max-width: 800px; font: caption;">
		<!--Div dos filtros-->
		<div style="text-align: left;">
			<center>
				<h3>Filtros</h3>
			</center>
			<p><em><strong>Obs.:</strong> Se o navegador perguntar, permita acesso à sua localização, e depois clique em <strong>Procurar</strong></em></p>
			<br>

			<form action="" method="post">
				<label for="cep"><span>CEP: </span><input type="text" name="cep" id="cep" value=<?php echo '"'.$parametroCEP.'"' ?> style="width: 100px;"/></label><br>
				<label for="cidade"><span>Cidade: </span><input type="text" name="cidade" id="cidade" value=<?php echo '"'.$parametroCidade.'"' ?> style="width: 40%;" /></label><br>
				<label for="rua"><span>Endereço: </span><input type="text" name="rua" id="rua" value=<?php echo '"'.$parametroRua.'"' ?> style="width: 60%;"/></label><br>
				<label for="estado"><span>Estado: </span>
					<select name="estado" id="estado">
						<option <?php if (empty($parametroEstado)) echo 'selected="selected"'; ?>></option>
						<option <?php if ($parametroEstado == "AC") echo 'selected="selected"'; ?>>AC - Acre</option>
						<option <?php if ($parametroEstado == "AL") echo 'selected="selected"'; ?>>AL - Alagoas</option>
						<option <?php if ($parametroEstado == "AP") echo 'selected="selected"'; ?>>AP - Amapá</option>
						<option <?php if ($parametroEstado == "AM") echo 'selected="selected"'; ?>>AM - Amazonas</option>
						<option <?php if ($parametroEstado == "BA") echo 'selected="selected"'; ?>>BA - Bahia</option>
						<option <?php if ($parametroEstado == "CE") echo 'selected="selected"'; ?>>CE - Ceará</option>
						<option <?php if ($parametroEstado == "DF") echo 'selected="selected"'; ?>>DF - Distrito Federal</option>
						<option <?php if ($parametroEstado == "ES") echo 'selected="selected"'; ?>>ES - Espírito Santo</option>
						<option <?php if ($parametroEstado == "GO") echo 'selected="selected"'; ?>>GO - Goiás</option>
						<option <?php if ($parametroEstado == "MA") echo 'selected="selected"'; ?>>MA - Maranhão</option>
						<option <?php if ($parametroEstado == "MT") echo 'selected="selected"'; ?>>MT - Mato Grosso</option>
						<option <?php if ($parametroEstado == "MS") echo 'selected="selected"'; ?>>MS - Mato Grosso do Sul</option>
						<option <?php if ($parametroEstado == "MG") echo 'selected="selected"'; ?>>MG - Minas Gerais</option>
						<option <?php if ($parametroEstado == "PA") echo 'selected="selected"'; ?>>PA - Pará</option>
						<option <?php if ($parametroEstado == "PB") echo 'selected="selected"'; ?>>PB - Paraíba</option>
						<option <?php if ($parametroEstado == "PR") echo 'selected="selected"'; ?>>PR - Paraná</option>
						<option <?php if ($parametroEstado == "PE") echo 'selected="selected"'; ?>>PE - Pernambuco</option>
						<option <?php if ($parametroEstado == "PI") echo 'selected="selected"'; ?>>PI - Piauí</option>
						<option <?php if ($parametroEstado == "RJ") echo 'selected="selected"'; ?>>RJ - Rio de Janeiro</option>
						<option <?php if ($parametroEstado == "RN") echo 'selected="selected"'; ?>>RN - Rio Grande do Norte</option>
						<option <?php if ($parametroEstado == "RS") echo 'selected="selected"'; ?>>RS - Rio Grande do Sul</option>
						<option <?php if ($parametroEstado == "RO") echo 'selected="selected"'; ?>>RO - Rondônia</option>
						<option <?php if ($parametroEstado == "RR") echo 'selected="selected"'; ?>>RR - Roraima</option>
						<option <?php if ($parametroEstado == "SC") echo 'selected="selected"'; ?>>SC - Santa Catarina</option>
						<option <?php if ($parametroEstado == "SP") echo 'selected="selected"'; ?>>SP - São Paulo</option>
						<option <?php if ($parametroEstado == "SE") echo 'selected="selected"'; ?>>SE - Sergipe</option>
						<option <?php if ($parametroEstado == "TO") echo 'selected="selected"'; ?>>TO - Tocantins</option>
					</select>
				</label><br>
				<center>
					<input type="submit" value="Procurar" style="font-size: x-large;"/>
				</center>
			</form>
			
		</div>
		<!--Div do Mapa-->
		<div>
			<center>
			<div id="GoogleMaps" style="max-height:500px;max-width:900px;margin-top:5%;min-height:500px;min-width:200px;"></div>
			</center>
		</div>
		<br>
		<!--Div da Tabela-->
		<div>
			<table id="tabela">
				<thead style="background: aliceblue;">
					<tr>
						<th width="10%">Sequencia</th>
						<th>Local</th>
					</tr>
				</thead>
				<tbody>
					<?php
					//Se nao tiver clientes, apenas mostra 3 pontos
					if ($clientesProtheus == null) {
						echo '<tr>';
						echo '	<td>...</td>';
						echo '	<td>...</td>';
						echo '</tr>';
					}
					//Porem, se existir o array de clientes existir, mas nao tiver conteudos, mostra outra mensagem
					else if (count((array)$clientesProtheus) == 0) {
						echo '<tr>';
						echo '	<td colspan="2" style="text-align: center;font-weight: bold;">Não foi possível encontrar dados com o(s) filtro(s) informado(s)!</td>';
						echo '</tr>';
					}
					//Se nao, entao existem dados e sera percorrido os clientes
					else {
						foreach ( $clientesProtheus as $clienteAtual ) {
							//Monta o link para ver a distância no Google
							$linkDistancia = "https://www.google.com/maps/dir/" . str_replace(" ", "+", $parametroRua) . ",+" . str_replace(" ", "+", $parametroCidade) . "+-+" . $parametroEstado . ",+" . str_replace(" ", "", $parametroCEP);
							$linkDistancia .= "/";
							$linkDistancia .= str_replace(" ", "+", $clienteAtual->Endereco) . ' - ' . str_replace(" ", "+", $clienteAtual->Bairro) . ",+" . str_replace(" ", "+", $parametroCidade)  . "+-+" . $parametroEstado ."," . str_replace(" ", "", $clienteAtual->CEP) . "/";
							
							echo '<tr>';
							
							//Coluna para ver a distância
							echo '	<td style="text-align: center;">' . $clienteAtual->Sequencia . '<br><br>';
							echo '<a href="'. $linkDistancia . '" target="_blank" rel="noopener noreferrer">';
							echo 'Ver Distância';
							echo '</a>';
							echo '</td>';
							
							//Coluna com os dados do cliente
							echo '	<td>';
							echo '<b>' . $clienteAtual->NomeReduz . '</b><br>';
							echo '<b>Razão Social:</b> ' . $clienteAtual->Nome . '<br>';
							echo '<b>Endereço: </b>' . $clienteAtual->Endereco . ' - ' . $clienteAtual->Bairro . '<br>';
							echo '<b>CEP: </b>' . $clienteAtual->CEP . '<br>';
							if (! empty($clienteAtual->Telefone))
								echo '<b>Telefone: <a href="tel:' . $clienteAtual->DDD . $clienteAtual->Telefone . '"></b> (' . $clienteAtual->DDD . ') ' . $clienteAtual->Telefone . '</a><br>';
							if (! empty($clienteAtual->Email))
								echo '<b>e-Mail: <a href="mailto:' . $clienteAtual->Email . '"></b>' . $clienteAtual->Email . '</a><br>';
							if (! empty($clienteAtual->Site))
								echo '<b>Site: <a href="' . $clienteAtual->Site . '"></b>' . $clienteAtual->Site . '</a>';
							echo '	</td>';
							
							echo '</tr>';
						}
					}
					?>
				</tbody>
			</table>
		</div>
	</div>
</center>
	
<?php
	//Se a cidade estiver em branco, mostra um alerta para o usuario
	if ($cidadeEmBranco) {
		echo '<script>';
		echo 'alert("Preencha a Cidade!");';
		echo '</script>';
	}
?>
</html>
  1. Teste o carregamento da página, e ela irá mostrar basicamente uma página sem muitas informações, apenas com o que a gente criou.

Página criada antes de fazer a pesquisa

  1. Agora, preencha as informações acima de filtro (se o navegador tiver suporte a geolocalização, basta usuário clicar em permitir e recarregar a página), e em seguida clique em pesquisar. Com isso será feito uma pesquisa no nosso WebService criado no passo 4, e se tiver dados irá retornar um JSON para o PHP se comunicar com o JavaScript e montar os pinos no Google, inclusive com opção de clicar nos pinos e mostrar informações para o usuário

Verificando os pinos mostrados no Google Maps vindos do Protheus

Bom pessoal, por hoje é só.

Abraços e até a próxima.

Dan (Daniel Atilio)
Cristão de ramificação protestante. Especialista em Engenharia de Software pela FIB, graduado em Banco de Dados pela FATEC Bauru e técnico em informática pelo CTI da Unesp. Entusiasta de soluções Open Source e blogueiro nas horas vagas. Autor e mantenedor do portal Terminal de Informação.

4 Responses

  1. Almir Bandina disse:

    Atilio, muito interessante a matéria. obrigado por compartilhar

  2. George disse:

    Muito legal Atílio, obrigado ae!

Deixe uma resposta para Dan_AtilioCancelar resposta

Terminal de Informação