1) URL pública do QR Code
O QR Code impresso na placa deve apontar para uma URL neste formato:
https://regenerag10.com.br/qrcode/TOKEN
Exemplo:
https://regenerag10.com.br/qrcode/cli_bce3ebfe0cb2aeaca4aea4ee49
TOKEN da URL e consulta o ERP pelo backend.
A api_key nunca deve ficar no JavaScript do navegador.
2) Endpoint do ERP
URL oficial do ERP
POST https://agroecologia.grupoekos.com.br/router/action.php
Parâmetros obrigatórios
| Campo | Obrigatório | Exemplo | Descrição |
|---|---|---|---|
action |
Sim | apiG10 |
Controller do ERP. |
f |
Sim | clientePublicoPorToken |
Função pública para carregar os dados da página. |
token |
Sim | cli_bce3ebfe0cb2aeaca4aea4ee49 |
Token extraído da URL pública. |
api_key |
Sim | SUA_API_KEY |
Chave da página pública para consultar o ERP. Não expor no navegador. |
Exemplo cURL
curl -X POST "https://agroecologia.grupoekos.com.br/router/action.php" \
-H "Content-Type: application/x-www-form-urlencoded; charset=UTF-8" \
--data "action=apiG10&f=clientePublicoPorToken&token=cli_bce3ebfe0cb2aeaca4aea4ee49&api_key=SUA_API_KEY"
3) Dados retornados pela API
A chamada continua a mesma. O que muda é o conteúdo retornado no campo data.
A resposta deve trazer informações do cliente, fotos públicas e geocerca.
Exemplo de resposta esperada
{
"success": true,
"msg": "ok",
"data": {
"api": "Regenera G10",
"publico": true,
"g10": {
"id": 2,
"unidade_referencia": "G10 - 02",
"numero_aplicacoes": 4
},
"cliente": {
"idade_pomar": "8",
"variedade_planta": "Pera Rio",
"porta_enxerto": "Swingle"
},
"resultado": {
"percentual_evolucao": 38.5,
"data_ultima_atualizacao": "2026-06-30",
"data_proxima_atualizacao": "2026-09-30"
},
"fotos": [
{
"id": 12,
"url": "https://agroecologia.grupoekos.com.br/router/action.php?action=apiG10&f=foto_publica&id_foto=12&token=cli_bce3ebfe0cb2aeaca4aea4ee49",
"data_foto": "2026-05-05",
"hora_foto": "10:35:20",
"latitude": "-21.86454000",
"longitude": "-47.49973000",
"observacao": "Foto da área central do talhão",
"tipo_foto": "pomar"
}
],
"geocerca": {
"id": 1,
"descricao": "Talhão 9",
"poligonos": [
{
"latitude": "-21.86456790",
"longitude": "-47.49966836",
"ordem": 1
},
{
"latitude": "-21.86449821",
"longitude": "-47.49988561",
"ordem": 2
},
{
"latitude": "-21.86450567",
"longitude": "-47.50004118",
"ordem": 3
},
{
"latitude": "-21.86466748",
"longitude": "-47.50011628",
"ordem": 4
},
{
"latitude": "-21.86478198",
"longitude": "-47.49977296",
"ordem": 5
}
]
},
"token": {
"usos_agora": 1,
"uso_maximo": null,
"expira_em": null
}
}
}
url aponta para um endpoint controlado do ERP:
foto_publica. Esse endpoint valida o token, valida se a foto pertence ao mesmo cliente/G10,
verifica se está aprovada e se está marcada com
exibir_pagina_publica = 1. Somente depois disso a imagem é entregue.
tipo_foto identifica a categoria da imagem pública.
Valores possíveis: folha, fruto, chao ou pomar.
A página pública deve usar esse campo para filtros e para evitar comparação entre fotos de tipos
diferentes.
4) Como as fotos são exibidas
As fotos ficam armazenadas em uma pasta protegida no ERP. Por isso, a API pública não retorna o arquivo diretamente e também não retorna base64. Ela retorna apenas uma URL controlada.
Formato do link da foto
https://agroecologia.grupoekos.com.br/router/action.php?action=apiG10&f=foto_publica&id_foto=ID_DA_FOTO&token=TOKEN
Exemplo
https://agroecologia.grupoekos.com.br/router/action.php?action=apiG10&f=foto_publica&id_foto=12&token=cli_bce3ebfe0cb2aeaca4aea4ee49
Na página pública, basta usar esse link no atributo src da imagem.
<img
src="https://agroecologia.grupoekos.com.br/router/action.php?action=apiG10&f=foto_publica&id_foto=12&token=cli_bce3ebfe0cb2aeaca4aea4ee49"
alt="Foto do talhão"
>
foto_publica, não a pasta real da imagem.
Assim a pasta continua protegida, e o ERP decide se a foto pode ou não ser exibida.
4) Origem dos dados no ERP
Dados do cliente
Buscar na tabela clientes:
idade_pomar
variedade_planta
porta_enxerto
Fotos públicas
Buscar na tabela g10_fotos somente fotos liberadas para exibição pública:
status = 'aprovada'
exibir_pagina_publica = 1
Campos úteis:
id
arquivo
data_foto
hora_foto
latitude
longitude
observacao
tipo_foto
Geocerca
Buscar em:
g10_geocerca
g10_geocerca_poligonos
A geocerca deve ser retornada com os pontos do polígono ordenados pelo campo
ordem.
Dados do G10
Buscar na tabela g10_participacoes:
id
A página deve montar a unidade de referência usando:
G10 - ID
Exemplo:
G10 - 02
Número de aplicações
Buscar na tabela g10_aplicacoes:
WHERE id_g10_participacao = ID_G10
AND status = 'finalizada'
Quantidade de plantas da área tratada
Buscar na tabela g10_geocerca:
qtde_plantas_area_tratada
Resultado G10
Buscar na tabela g10_resultados_tecnicos somente o resultado ativo mais recente:
percentual_evolucao
data_ultima_atualizacao
data_proxima_atualizacao
WHERE status = 1
ORDER BY data_ultima_atualizacao DESC, id DESC
LIMIT 1
5) Como usar os dados na página pública
A página pública deve exibir os dados de forma simples:
- Mostrar idade do pomar.
- Mostrar variedade da planta.
- Mostrar porta-enxerto.
- Exibir a geocerca no mapa usando os polígonos retornados.
- Exibir as fotos aprovadas em uma galeria.
- Permitir filtro das fotos públicas por
tipo_foto: Folha, Fruto, Chão e Pomar. - Não comparar fotos de tipos diferentes entre si.
- Mostrar unidade de referência:
g10.unidade_referencia. - Mostrar número de aplicações finalizadas:
g10.numero_aplicacoes. - Mostrar quantidade de plantas da área tratada:
geocerca.qtde_plantas_area_tratada. - Mostrar percentual de evolução:
resultado.percentual_evolucao. - Mostrar última atualização:
resultado.data_ultima_atualizacao. - Mostrar próxima atualização:
resultado.data_proxima_atualizacao.
Nenhuma foto pública disponível no momento.
6) Exemplo simples usando Google Maps
O array geocerca.poligonos deve ser convertido para o formato esperado pelo Google Maps:
{ lat: ..., lng: ... }.
HTML
<div id="mapa-geocerca" style="width:100%; height:420px;"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=SUA_GOOGLE_MAPS_KEY&callback=initMap" async defer></script>
JavaScript
let dadosPublicos = null;
async function carregarPaginaPublica() {
const response = await fetch("/api-publica/qrcode/cli_bce3ebfe0cb2aeaca4aea4ee49");
const json = await response.json();
if (!json.success) {
console.error(json.msg || "Erro ao carregar página pública.");
return;
}
dadosPublicos = json.data;
renderizarDadosCliente(dadosPublicos.cliente);
renderizarFotos(dadosPublicos.fotos);
initMap();
}
function renderizarDadosCliente(cliente) {
document.getElementById("idade_pomar").textContent = cliente.idade_pomar || "-";
document.getElementById("variedade_planta").textContent = cliente.variedade_planta || "-";
document.getElementById("porta_enxerto").textContent = cliente.porta_enxerto || "-";
}
function renderizarFotos(fotos) {
const box = document.getElementById("galeria");
box.innerHTML = "";
if (!fotos || fotos.length === 0) {
box.innerHTML = "<p>Nenhuma foto pública disponível no momento.</p>";
return;
}
fotos.forEach(function(foto) {
const card = document.createElement("div");
card.style.display = "inline-block";
card.style.margin = "6px";
card.style.verticalAlign = "top";
const img = document.createElement("img");
img.src = foto.url;
img.alt = "Foto do talhão - " + (foto.tipo_foto || "sem classificação");
img.style.maxWidth = "220px";
img.style.borderRadius = "10px";
const label = document.createElement("div");
label.style.fontSize = "12px";
label.style.marginTop = "4px";
label.textContent = "Tipo: " + (foto.tipo_foto || "sem classificação");
card.appendChild(img);
card.appendChild(label);
box.appendChild(card);
});
}
function initMap() {
if (!dadosPublicos || !dadosPublicos.geocerca) {
return;
}
const poligonos = dadosPublicos.geocerca.poligonos || [];
if (poligonos.length === 0) {
return;
}
const path = poligonos.map(function(p) {
return {
lat: parseFloat(p.latitude),
lng: parseFloat(p.longitude)
};
});
const mapa = new google.maps.Map(document.getElementById("mapa-geocerca"), {
zoom: 18,
center: path[0],
mapTypeId: "satellite"
});
const bounds = new google.maps.LatLngBounds();
path.forEach(function(p) {
bounds.extend(p);
});
const polygon = new google.maps.Polygon({
paths: path,
strokeColor: "#FF0000",
strokeOpacity: 1,
strokeWeight: 3,
fillColor: "#FACC15",
fillOpacity: 0.35,
map: mapa
});
mapa.fitBounds(bounds);
}
carregarPaginaPublica();
7) Exemplo visual da página pública
A página pode ter uma estrutura simples:
<section>
<h2>Informações do Talhão</h2>
<p><b>Idade do pomar:</b> <span id="idade_pomar">-</span></p>
<p><b>Variedade:</b> <span id="variedade_planta">-</span></p>
<p><b>Porta-enxerto:</b> <span id="porta_enxerto">-</span></p>
</section>
<section>
<h2>Geocerca</h2>
<div id="mapa-geocerca" style="width:100%; height:420px;"></div>
</section>
<section>
<h2>Fotos</h2>
<div id="filtros_fotos">
<button type="button" data-tipo="todos">Todas</button>
<button type="button" data-tipo="folha">Folha</button>
<button type="button" data-tipo="fruto">Fruto</button>
<button type="button" data-tipo="chao">Chão</button>
<button type="button" data-tipo="pomar">Pomar</button>
</div>
<div id="galeria"></div>
</section>
8) Respostas de erro
O padrão de erro continua igual:
{
"success": false,
"error": "token_not_found",
"msg": "Token não encontrado.",
"data": {}
}
Possíveis erros:
| Erro | Quando ocorre |
|---|---|
missing_token |
Token não enviado. |
token_not_found |
Token não localizado no ERP. |
token_inactive |
Token inativo. |
token_expired |
Token expirado. |
client_not_found |
Cliente vinculado ao token não localizado. |
db_error |
Erro interno ao consultar o banco. |
9) Recomendações importantes
- A chamada ao ERP deve continuar sendo feita pelo backend da página pública.
- Não colocar
api_keyno JavaScript do navegador. - Retornar somente fotos com
status = aprovadaeexibir_pagina_publica = 1. - Retornar
tipo_fotoem cada foto pública. - Permitir filtro por tipo: Folha, Fruto, Chão e Pomar.
- Não comparar fotos de tipos diferentes entre si.
- Não retornar base64 das fotos no JSON da página pública.
- Não expor o caminho real da pasta protegida das fotos.
- Usar o endpoint
foto_publicapara entregar a imagem de forma controlada. - Ordenar os pontos da geocerca por
ordem. - Se não houver geocerca, a página deve ocultar o mapa ou mostrar mensagem simples.
- Se não houver fotos públicas, a página deve ocultar a galeria ou mostrar mensagem simples.