Verificação de idade no PrestaShop: janela bloqueante para CBD, álcool, vape e profissionais de saúde
Documentação completa do módulo dfagegate: instalação, configuração dos modos (padrão para CBD, álcool, vape e armaria, e médico), personalização multi-idioma, conformidade com o RGPD e diagnóstico.
O módulo dfagegate acrescenta à sua loja PrestaShop 8 ou 9 uma janela de verificação de idade bloqueante. Cobre dois mercados distintos: o modo padrão, para produtos com restrição de idade (CBD, álcool, vape, armaria, isqueiros, produtos para maiores de 18 anos), e o modo médico, para dispositivos médicos reservados a profissionais de saúde.
Compatibilidade: PrestaShop 1.7.7+, 8.x e 9.0. PHP 7.4 no mínimo, 8.1+ recomendado. Multiloja e multi-idioma (FR/EN/ES/DE pré-preenchidos na instalação).
Leia primeiro, se vende em Portugal. Este módulo foi desenhado a partir do quadro legal francês, e vários pontos não se transpõem tal como estão. O modo médico refere-se ao artigo L5122-9 do Código da Saúde Pública francês e ao número RPPS/ADELI, que não existem em Portugal, onde a identificação profissional é a cédula das respetivas Ordens e a publicidade de dispositivos médicos é regulada pelo Decreto-Lei n.º 145/2009, sob supervisão do Infarmed. O exemplo do CBD também não se aplica diretamente: a venda de produtos com canabidiol está fortemente restringida em Portugal e nem todos os formatos são comercializáveis. Antes de configurar, valide o seu catálogo com um advogado: o módulo é uma ferramenta técnica, não um parecer jurídico.
Instalação
A instalação segue o fluxo normal do PrestaShop. Depois da compra na DataFirefly, recebe um ficheiro ZIP dfagegate-X.Y.Z.zip.
Pelo back-office (recomendado)
- Inicie sessão no back-office do PrestaShop
- Vá a Módulos → Catálogo de módulos
- Clique em Carregar um módulo, no canto superior direito
- Selecione o ZIP
dfagegate-X.Y.Z.zip - Terminado o carregamento, clique em Instalar
Por FTP
- Descomprima o ZIP localmente
- Envie a pasta
dfagegate/paramodules/do seu PrestaShop - Vá a Módulos → Catálogo de módulos
- Procure «DataFirefly Age Gate» e clique em Instalar
Importante: depois da instalação, o módulo fica desativado por predefinição. É intencional, para lhe permitir configurar os textos e o modo antes de bloquear a loja. Vá à configuração do módulo e ative o interruptor no separador Geral quando tiver tudo definido.
Primeira configuração
Aceda à configuração em Módulos → Módulos instalados → DataFirefly Age Gate → Configurar.
A configuração está organizada em 6 separadores:
- Geral: ativação, modo, tipo de verificação, idade mínima
- Conteúdo: textos multi-idioma (título, mensagem, botões, menções legais)
- Aspeto: logótipo, cores, desfocagem do fundo
- Comportamento: cookie, redirecionamento, exceções
- Modo médico: profissões e número profissional (só aparece no modo médico)
- Registos e RGPD: registo e diagnóstico
Separador Geral
É aqui que configura o comportamento principal do módulo.
- Ativar o módulo: interruptor Sim/Não, que controla a apresentação global da janela
- Modo: Padrão (CBD, álcool, vape, armaria) ou Médico (profissionais de saúde)
- Tipo de verificação: Botão sim/não, Data de nascimento ou Declaração de profissão
- Idade mínima: 18 por predefinição, 21 em certos mercados
Que tipo de verificação escolher? O botão sim/não serve para a maioria dos casos, por ser rápido, de baixo atrito e suficientemente dissuasor. A data de nascimento é mais exigente e recomendável para armaria ou líquidos com nicotina. A declaração de profissão destina-se ao modo médico.
Em Portugal, a idade mínima é 18 anos tanto para as bebidas alcoólicas como para os produtos do tabaco e cigarros eletrónicos, incluindo os líquidos sem nicotina. A venda a menores é proibida e a fiscalização cabe à ASAE. Mantenha o valor em 18, a não ser que venda para outro país com um limiar mais alto.
Separador Conteúdo
Cada idioma ativo no seu PrestaShop tem o seu bloco de textos. Os valores predefinidos vêm preenchidos em FR, EN, ES e DE. Em cada idioma pode configurar:
- Título: aparece em destaque no topo da janela
- Mensagem: texto explicativo principal, com as quebras de linha preservadas
- Botão de confirmação: designação do botão positivo (por predefinição, «Tenho 18 anos ou mais»)
- Botão de recusa: designação do botão negativo
- Menção legal: texto no fundo da janela
- Mensagem em caso de recusa: ecrã apresentado quando o utilizador recusa, antes do redirecionamento
O português não está entre os quatro idiomas pré-preenchidos: escreva todos estes textos antes de ativar o módulo, porque a janela é a primeira coisa que o visitante vê. Para a menção legal do álcool, a formulação corrente em Portugal é «Se for grávida, evite o consumo de álcool. Seja responsável, beba com moderação», e a venda a menores de 18 anos é proibida. No caso do tabaco e dos cigarros eletrónicos, a Lei n.º 37/2007 restringe a publicidade e a promoção: escreva a menção com prudência e faça-a validar.
HTML: o conteúdo é limpo na gravação (apenas texto simples). As quebras de linha são convertidas em etiquetas <br> na apresentação, por um filtro nl2br automático.
Separador Aspeto
Personalize o visual da janela para que combine com a sua identidade gráfica:
- Logótipo: PNG, JPG, SVG ou WEBP, até 2 MB, apresentado no topo da janela
- Cor de fundo: cor do cartão principal (branco por predefinição)
- Cor primária: título e botão principal (preto #111111 por predefinição)
- Cor do texto: corpo da mensagem
- Cor da sobreposição: véu por trás da janela, que aceita os formatos CSS
rgba()e hexadecimal (por predefinição,rgba(15,15,20,0.85)) - Desfocagem do fundo: efeito de desfoque no plano de fundo
Separador Comportamento
Controla a persistência da escolha e os casos de exclusão.
- Duração do cookie: em dias (90 por predefinição). Ponha
0para um cookie de sessão, eliminado ao fechar o navegador - URL de redirecionamento em caso de recusa: deixe vazio para mostrar apenas a mensagem de recusa, ou indique um URL externo
- Exceção por IP: lista de IP (uma por linha) para os quais a janela não aparece. É ideal para si e para a sua equipa durante os testes
- Exceções por URL: caminhos parciais excluídos. Vem preenchido com
/legal,/contact,/cgv,/mentions-legalese/politique-confidentialite - Exceção para clientes com sessão iniciada: se ativo, os clientes com sessão iniciada não veem a janela
As exceções por URL vêm com caminhos franceses, que não correspondem à sua loja portuguesa. Substitua-os pelos seus: /termos-e-condicoes, /politica-de-privacidade, /contacto, /avisos-legais. Sem isso, as suas páginas legais ficam atrás da janela bloqueante, o que é exatamente o contrário do que se pretende: essas páginas devem estar sempre acessíveis.
Separador Modo médico
Este separador só se aplica se o modo estiver em Médico e o tipo de verificação em Declaração de profissão.
- Lista de profissões: uma por linha. Por predefinição, traz médico, farmacêutico, enfermeiro, fisioterapeuta, dentista, veterinário e outro profissional de saúde. É personalizável conforme o seu público
- Número profissional obrigatório: se ativo, aparece um campo na janela. A validação é feita por uma expressão regular que aceita 9 a 11 dígitos. O número não é guardado, servindo apenas para a validação do lado do servidor
Adaptação portuguesa indispensável. O campo foi pensado para o RPPS e o ADELI franceses. Em Portugal, o equivalente é a cédula profissional emitida pela Ordem respetiva (Ordem dos Médicos, Ordem dos Farmacêuticos, Ordem dos Enfermeiros e outras), cujos formatos não coincidem com a regra de 9 a 11 dígitos: um número de cédula pode ser bem mais curto. Duas opções: desative a obrigatoriedade do número e fique-se pela declaração de honra da profissão, ou peça uma adaptação da expressão regular. Ative o campo tal como está e arrisca-se a bloquear profissionais legítimos.
Conformidade jurídica. A referência ao artigo L5122-9 do Código da Saúde Pública é francesa. Em Portugal, a publicidade de dispositivos médicos é regulada pelo Decreto-Lei n.º 145/2009 e pela legislação europeia aplicável, com o Infarmed como autoridade competente, e há dispositivos cuja publicidade é reservada a profissionais. Este módulo não dispensa uma revisão jurídica do seu catálogo por um advogado. A declaração de honra materializa a restrição de acesso; não a legitima por si só.
Separador Registos e RGPD
Registo opcional e informações de conformidade.
- Registar as recusas: guarda cada recusa na tabela
ps_dfagegate_log, com o IP em hash SHA-256 (nunca em claro), a data e o motivo
Este separador mostra também um lembrete de RGPD:
- Cookie depositado:
dfagegate_ok - Categoria: estritamente necessário (conformidade legal de acesso)
- Dados: valor «1», duração configurável, SameSite=Lax e Secure em HTTPS
Configurar conforme o seu mercado
Seguem algumas configurações típicas, a título de inspiração.
Loja de bebidas espirituosas ou vinhos
- Modo: Padrão
- Tipo de verificação: Data de nascimento
- Idade mínima: 18
- URL de redirecionamento: uma página oficial de informação sobre consumo responsável
- Menção legal: a formulação portuguesa de consumo responsável, com a proibição de venda a menores de 18 anos
Loja de vape e líquidos com nicotina
- Modo: Padrão
- Tipo de verificação: Data de nascimento (fortemente recomendado)
- Idade mínima: 18
- Registar as recusas: Sim (útil numa inspeção da ASAE)
Loja de armaria
- Modo: Padrão
- Tipo de verificação: Data de nascimento (obrigatório)
- Idade mínima: 18
- Exceções por URL: acrescente as suas páginas de regulamentação e de licenças
- Registar as recusas: Sim
A venda de armas e munições em Portugal está sujeita à Lei n.º 5/2006 e exige licença e, em regra, registo da transação: a janela de idade é uma primeira barreira, não o cumprimento das obrigações de venda. Trate-a como complemento do seu procedimento de verificação, não como substituto.
Loja de material médico (dispositivos profissionais)
- Modo: Médico
- Tipo de verificação: Declaração de profissão
- Lista de profissões: adapte-a ao seu catálogo, com as designações portuguesas
- Número profissional obrigatório: ver o aviso acima sobre o formato da cédula
- Exceção para clientes com sessão iniciada: Sim, se já valida a profissão no registo
Como funciona a verificação por data de nascimento
Ao contrário de um simples botão, a verificação por data de nascimento faz o cálculo do lado do servidor, e não no navegador. O percurso completo é este:
- O visitante introduz o dia, o mês e o ano na janela
- O JavaScript envia esses valores ao controlador AJAX
DfagegateAjaxModuleFrontController - O PHP valida a data com
checkdate()e calcula depois a idade comDateTimeImmutable::diff() - Se a idade for inferior ao limiar configurado, o servidor devolve uma resposta JSON com
success=false, denied=truee a mensagem de erro - A janela mostra a mensagem de recusa e redireciona ao fim de 2 segundos
- Se a idade for igual ou superior, o cookie
dfagegate_oké depositado e a janela fecha
Porquê do lado do servidor? Um controlo puramente em JavaScript é contornável pelas ferramentas de programador em menos de dez segundos. O cálculo no servidor garante que um utilizador abaixo da idade legal não acede ao site, mesmo com conhecimentos técnicos. É o que sustenta a sua posição numa inspeção.
Note que a data de nascimento nunca é guardada: é usada durante o cálculo e esquecida a seguir. Só fica a validação binária (aceite ou recusado), através do cookie.
Como funciona o modo médico
O modo médico segue uma lógica parecida, mas com campos diferentes:
- A janela mostra uma lista de profissões (configurável) e, eventualmente, um campo de número profissional
- Existe uma caixa de declaração de honra, de preenchimento obrigatório
- O controlador AJAX valida que a profissão foi selecionada
- Se o número profissional for obrigatório, o servidor valida o formato através de uma expressão regular que aceita 9 a 11 dígitos consecutivos
- Não há qualquer armazenamento: nem a profissão nem o número ficam na base de dados, e o cookie
dfagegate_okmaterializa apenas a passagem bem-sucedida
Opção de conceção: a abordagem é de conformidade mínima viável, ou seja, pede-se a declaração, valida-se formalmente, regista-se a recusa se a opção estiver ativa, e não se recolhe qualquer dado pessoal desnecessário. Uma verificação em tempo real contra um registo profissional é um desenvolvimento à parte. Em Portugal, essa verificação passaria pelos serviços das Ordens profissionais, e não por um registo nacional único.
Multiloja
O módulo é totalmente compatível com multiloja. Todas as configurações (modo, tipo de verificação, textos multi-idioma, cores, exceções) ficam guardadas por contexto de loja, através de id_shop_group e id_shop. Pode assim ter, no mesmo PrestaShop:
- Uma loja de bebidas PT em modo padrão com 18 anos e textos em português
- Uma loja de vape UK em modo padrão com 18 anos e textos em inglês
- Uma loja de material médico DE em modo médico e textos em alemão
Para configurar uma loja específica:
- No seletor de contexto, no topo do back-office, escolha a loja pretendida
- Abra a configuração do módulo
- Altere os valores, que ficam guardados apenas para essa loja
Os hooks são registados em todas as lojas no momento da instalação, através de Shop::getCompleteListOfShopsID(), o que evita a armadilha clássica do módulo que só funciona na loja atual.
Compatibilidade com temas personalizados
O módulo usa o hook padrão displayBeforeBodyClosingTag para injetar a janela imediatamente antes do fecho da etiqueta body. Este hook deveria ser universal no PrestaShop 1.7.5+.
Infelizmente, alguns temas personalizados não chamam este hook no seu layout. Para esse caso, o dfagegate traz um recurso em JavaScript:
- O PHP prepara todo o HTML da janela e passa-o ao JS através de
Media::addJsDef - No
DOMContentLoaded, o script verifica se o elemento com o IDdfagegate-modalexiste no DOM - Se existir, está tudo bem: o hook funcionou
- Se não existir, o próprio script injeta a janela com
insertAdjacentHTML('beforeend', ...) - Uma mensagem
console.infoconfirma a ativação do recurso
Resultado prático: o módulo funciona em qualquer tema PrestaShop 1.7.5+, incluindo temas personalizados incompletos, sem ter de alterar o layout. Pode implementá-lo sem coordenação com a agência do tema.
Diagnóstico e depuração
Uma vez ativo, o dfagegate acrescenta um comentário HTML na etiqueta head de cada página do front-office, na forma «dfagegate v1.0.3 enabled=1 should_display=1».
Esse comentário é o seu primeiro ponto de diagnóstico. Consulte o código-fonte de uma página do front-office (Ctrl+U ou Cmd+U) e procure «dfagegate».
| Comentário | Interpretação |
|---|---|
| Nenhum comentário | O hook displayHeader não está registado: confirme que o módulo está instalado e ativo |
enabled=0 |
O interruptor «Ativar o módulo» está em Não, no separador Geral |
enabled=1 should_display=0 |
Está ativa uma exceção: o seu IP está na lista, o URL atual corresponde a um caminho excluído, ou tem sessão iniciada com a exceção ativa |
enabled=1 should_display=1 |
Está tudo bem do lado do servidor. Se a janela não aparecer, veja a consola do navegador, à procura de uma mensagem do recurso em JS ou de um erro |
A janela continua a não aparecer
Lista de verificação rápida:
- O comentário de diagnóstico está presente com
should_display=1? Se não, corrija a configuração - Abra a loja em navegação privada. O cookie
dfagegate_okpode ter ficado de uma sessão anterior - Verifique o seu IP nas exceções do separador Comportamento
- Abra a consola do navegador (F12) e procure
[dfagegate], à procura de mensagens de injeção ou de erro - Consulte os registos do PrestaShop em Parâmetros avançados → Registos, filtrando por «dfagegate»
- Limpe a cache do PrestaShop depois de cada alteração de configuração, em Parâmetros avançados → Desempenho → Limpar a cache
Repor o cookie do lado do navegador
Para voltar a testar a janela sem mudar de IP:
- Abra as ferramentas de programador (F12)
- Separador Application (Chrome) ou Storage (Firefox)
- Secção Cookies → o seu domínio
- Elimine a linha
dfagegate_ok - Recarregue a página
Conformidade com o RGPD
O módulo foi concebido para ser conforme ao RGPD por predefinição.
O cookie dfagegate_ok
- Tipo: estritamente necessário ao cumprimento de uma obrigação legal de acesso
- Base legal: em Portugal, a Lei n.º 41/2004 dispensa de consentimento prévio o armazenamento estritamente necessário à prestação do serviço expressamente pedido pelo utilizador, o que abrange este caso
- Valor: binário (
1significa confirmado) - Duração: configurável (90 dias por predefinição), ou de sessão se puser 0
- Atributos:
SameSite=Lax,Secureautomático em HTTPS ePath=/
Na prática: não precisa de acrescentar este cookie à sua faixa de consentimento. Entra na mesma categoria do cookie de sessão do PrestaShop ou do cookie CSRF, ou seja, necessário ao funcionamento legal do site e, por isso, dispensado. Mencione-o na sua política de cookies, na secção dos cookies necessários.
Os registos de recusa
Se ativar a opção Registar as recusas, cada recusa é guardada na tabela ps_dfagegate_log com:
id_shop: loja em causareason: motivo da recusa (user_refusedoudob_under_age)age: idade declarada, quando aplicávelprofession: profissão declarada, quando aplicávelip_hash: SHA-256 do IP, nunca o IP em clarodate_add: data e hora
O hash SHA-256 torna o IP não reversível, mas permite eliminar duplicados nas tentativas, já que um mesmo IP produz sempre o mesmo hash. Inscreva este tratamento no seu registo de atividades e fixe-lhe uma duração de conservação, sob supervisão da CNPD.
Os dados de verificação
- A data de nascimento passa por AJAX para o cálculo, mas nunca é guardada
- O número profissional é validado no servidor e depois esquecido, sem qualquer armazenamento
- Só a validação binária é conservada, através do cookie
Estrutura técnica e integração
Para quem programa e queira ir mais longe ou integrar o módulo num fluxo próprio.
Hooks utilizados
displayHeader: injeta o comentário de diagnósticoactionFrontControllerSetMedia: regista o CSS e o JS, e passa ao JS a configuração e o HTML preparado da janeladisplayBeforeBodyClosingTag: apresenta a janela do lado do servidor (com recurso em JS se faltar no tema)
Pontos de entrada AJAX
O controlador AJAX responde no URL /module/dfagegate/ajax e aceita duas ações:
action=confirm: com os parâmetros próprios do tipo de verificação (nenhum no sim/não, day/month/year na data de nascimento, profession/rpps no modo médico)action=refuse: regista a recusa e devolve o URL de redirecionamento
As respostas vêm em JSON. Uma confirmação devolve success=true. Uma recusa por idade insuficiente devolve success=false, denied=true e a mensagem de erro adequada. Um erro de validação devolve success=false com a mensagem. Uma recusa do utilizador devolve success=true e redirect_url com o URL de redirecionamento configurado.
Esquema da base de dados
É criada uma única tabela, ps_dfagegate_log. Contém as colunas id_log (chave primária com incremento automático), id_shop, reason (varchar 64), age (anulável), profession (varchar 128 anulável), ip_hash (char 64, para o SHA-256) e date_add (datetime). Dois índices secundários otimizam as consultas de relatório: idx_shop_date em (id_shop, date_add) e idx_reason em reason.
Desinstalação
Há dois níveis de desinstalação:
Desativar sem eliminar
Módulos → Módulos instalados → DataFirefly Age Gate → Desativar. A configuração é conservada, e a tabela de registos também. Pode reativar a qualquer momento sem voltar a configurar.
Desinstalar por completo
Módulos → Módulos instalados → DataFirefly Age Gate → Desinstalar. Esta ação:
- Elimina a tabela
ps_dfagegate_log - Elimina todas as entradas de configuração (18 chaves simples e 6 chaves multi-idioma)
- Remove o registo dos hooks
- Retira o módulo do sistema
Atenção: a desinstalação é irreversível. Se quiser conservar o histórico dos registos de recusa, por exemplo para uma auditoria, exporte a tabela antes.
Suporte e atualizações
Cada licença inclui:
- 12 meses de atualizações: compatibilidade com o PrestaShop, correções e melhorias
- Suporte técnico por e-mail: resposta em 24 horas úteis, em francês e inglês
- Reembolso em 30 dias
- Código-fonte não cifrado: pode adaptar o módulo às suas necessidades
Para qualquer questão técnica ou comunicação de erro, contacte-nos a partir da sua conta DataFirefly. Indique a versão do PrestaShop, a versão do PHP, a versão do módulo (visível no topo do ecrã de configuração) e, se possível, o comentário de diagnóstico presente na etiqueta head da sua loja.