Eliminação de conta RGPD: guia completo
Instalar, configurar e utilizar a eliminação de conta conforme ao RGPD, com confirmação por e-mail, anonimização que respeita a obrigação contabilística e anulação de subscrição no Mailchimp, Brevo e Mailjet para PrestaShop 8 e 9.
Visão geral
O módulo Eliminação de Conta RGPD dá aos seus clientes a possibilidade de exercerem o direito ao apagamento (artigo 17.º do RGPD) diretamente a partir da área de cliente, sem qualquer intervenção manual da sua parte. Um pedido desencadeia uma cascata: confirmação por e-mail com token criptográfico, anonimização ou eliminação da conta do lado da loja, anulação automática da subscrição no Mailchimp, no Brevo e no Mailjet, e escrita de uma prova de tratamento num registo de auditoria.
Para quem? Qualquer comerciante em PrestaShop 8 ou 9 que trate dados pessoais de cidadãos europeus e queira evitar a gestão manual dos pedidos de eliminação ao abrigo do RGPD. O módulo é entregue em francês, inglês, espanhol e alemão.
O português não está incluído no pacote. Como a página de eliminação e o e-mail de confirmação são vistos pelo cliente num momento sensível, traduza as cadeias em Internacional > Traduções e crie a pasta mails/pt antes de ativar o bloco na área de cliente.
Instalação
- Inicie sessão no back-office do PrestaShop.
- Vá a Módulos → Gestor de módulos, clique em Carregar um módulo e coloque o ZIP
dfaccountdelete-1.0.2.zip. - O módulo é instalado e ativado automaticamente. Clique em Configurar.
A instalação cria duas tabelas: ps_dfad_log (registo RGPD) e ps_dfad_token (tokens de confirmação por e-mail). Regista o módulo no hook displayCustomerAccount, que acrescenta um bloco «Eliminar a minha conta» na área de cliente.
Se tiver muitos templates personalizados, confirme depois da instalação que o bloco «Eliminar a minha conta» aparece mesmo em A minha conta, do lado da loja. O hook displayCustomerAccount tem de ser suportado pelo seu tema, o que acontece no tema nativo Classic e na maioria dos temas comerciais.
Configuração geral
O ecrã de configuração está dividido em quatro painéis: Parâmetros gerais, Mailchimp, Brevo e Mailjet. Cada painel é gravado de forma independente.
Modo de eliminação
Escolha entre dois modos:
- Anonimizar (recomendado): os dados pessoais do cliente (nome, apelido, e-mail, telefone, moradas, data de nascimento) são substituídos por valores anónimos. As encomendas ficam intactas, para respeitar a obrigação de conservação dos documentos durante 10 anos, prevista no artigo 123.º do CIRC e no artigo 52.º do CIVA.
- Eliminar totalmente, se possível: a conta é totalmente apagada se não existir qualquer encomenda. Se existirem encomendas, o módulo passa automaticamente ao modo de anonimização, para não quebrar o histórico legal.
Mesmo em modo «Eliminar totalmente», não pode eliminar uma conta que tenha feito encomendas. É uma obrigação legal portuguesa e europeia: os documentos de suporte da contabilidade têm de ser conservados 10 anos. O módulo trata desta passagem automaticamente e regista no registo RGPD o modo realmente aplicado. O direito ao apagamento do artigo 17.º do RGPD prevê precisamente esta exceção quando o tratamento é necessário para o cumprimento de uma obrigação legal.
Confirmação por e-mail obrigatória
Ativa por predefinição (fortemente recomendada). O cliente tem de clicar numa ligação recebida por e-mail para validar o pedido. Isto impede qualquer eliminação acidental ou provocada por terceiros que tenham acedido a uma sessão aberta.
Validade do token
Em horas. 24 horas por predefinição. Passado esse período, a ligação do e-mail expira e o pedido é automaticamente anulado.
Registos
Ativos por predefinição. O módulo escreve em ps_dfad_log cada pedido apenas com dados pseudonimizados: hash SHA-256 do e-mail, hash SHA-256 do IP, identificador do cliente, modo aplicado, estado, fornecedores contactados, user agent, identificador da loja e data e hora. Não é conservado qualquer dado pessoal em claro.
A tabela ps_dfad_log não é eliminada na desinstalação do módulo. É intencional: constitui a prova do tratamento em caso de fiscalização pela CNPD. Para a eliminar manualmente, execute DROP TABLE ps_dfad_log; depois da desinstalação.
E-mail do administrador notificado
Endereço que receberá uma notificação (apenas o hash do e-mail, nunca o e-mail em claro) a cada eliminação efetiva. Por predefinição, o e-mail da loja.
Configuração dos fornecedores de newsletter
O módulo suporta de origem três plataformas de newsletter. Cada fornecedor está desativado por predefinição. Ative apenas os que utiliza.
Mailchimp
Preencha:
- Chave API: formato
xxxxxxxxxxxx-us21. O sufixo (-us21,-eu1, entre outros) é o datacenter do Mailchimp. O módulo deteta-o automaticamente. - List ID (Audience ID): identificador da sua audiência principal. Encontra-o no Mailchimp em Audience → Settings → Audience name and defaults.
- Eliminação permanente: ativa por predefinição. Usa o endpoint
POST /lists/{list_id}/members/{hash}/actions/delete-permanent, que corresponde ao verdadeiro direito ao esquecimento do RGPD: o e-mail é definitivamente eliminado e o Mailchimp recusará qualquer futura subscrição com esse endereço. Se preferir um simples arquivo (permitindo que o endereço se volte a inscrever mais tarde), desative esta opção.
Clique em Testar a ligação para validar a sua configuração. Se estiver tudo correto, verá o nome da sua audiência.
Brevo (ex-Sendinblue)
Preencha:
- Chave API v3: formato
xkeysib-xxxxxx. Encontra-a no Brevo em A minha conta → SMTP e API → Chaves API. - List ID (opcional): se estiver preenchido, retira o contacto apenas dessa lista. Se ficar vazio, elimina o contacto por completo (recomendado para o RGPD).
Endpoint utilizado: DELETE /v3/contacts/{email} para eliminação total, ou POST /v3/contacts/lists/{id}/contacts/remove para retirada de uma lista.
Mailjet
O Mailjet usa autenticação Basic com duas chaves. Preencha:
- API Key
- API Secret
- Contact List ID (opcional): se estiver preenchido, anula a subscrição apenas dessa lista. Se ficar vazio, elimina o contacto através do endpoint oficial de RGPD do Mailjet.
O fluxo de eliminação do Mailjet tem duas etapas: procura do identificador do contacto através de GET /v3/REST/contact/{email} e depois DELETE /v4/contacts/{id} no endpoint de RGPD. O módulo trata desta mecânica automaticamente.
Se uma plataforma devolver 404 na eliminação, o módulo considera que é um sucesso (o contacto já não existe, idempotência). Não verá qualquer erro nos registos.
Anonimizar ou eliminar: o que escolher?
O RGPD impõe o direito ao apagamento, mas a legislação fiscal portuguesa impõe a conservação dos documentos contabilísticos durante 10 anos (artigo 123.º do CIRC e artigo 52.º do CIVA). As duas obrigações conciliam-se através da anonimização, que é a abordagem habitualmente seguida.
Modo de anonimização
O módulo substitui em ps_customer:
firstname→Anonymizedlastname→Customeremail→anon-{id_customer}-{hash}@anonymized.localpasswd→ hash aleatório (o cliente deixa de poder iniciar sessão)birthday→ NULLnote,website,ip_registration_newsletter→ vazioactive→ 0,deleted→ 1
Nas moradas:
- As moradas não usadas por encomendas são eliminadas por completo.
- As moradas usadas por encomendas são anonimizadas (
firstname,lastname,address1,postcode,city,phone, entre outros, substituídos por valores neutros) e marcadas comdeleted = 1.
Se guarda o NIF do cliente num campo personalizado da morada ou da conta, verifique que também ele é anonimizado: é um dado pessoal e identificador direto. O módulo trata os campos padrão do PrestaShop, não os campos acrescentados por outros módulos.
Modo de eliminação total
Se o cliente não fez qualquer encomenda: eliminação completa das moradas e depois chamada a Customer::delete(). Caso contrário: passagem automática ao modo de anonimização. Não existe opção que permita forçar a eliminação de uma conta com encomendas, o que é intencional por razões legais.
Fluxo completo de um pedido
- O cliente vai a A minha conta e clica no bloco «Eliminar a minha conta».
- Chega a uma página de confirmação com um painel de aviso, um campo «Palavra-passe» e uma caixa «Compreendo que esta ação é irreversível».
- Introduz a palavra-passe e assinala a caixa. O módulo verifica a palavra-passe através da classe
PrestaShop/Core/Crypto/Hashing. - Se a confirmação por e-mail estiver ativa, o módulo gera um token aleatório de 32 bytes (
random_bytes(32)), converte-o em hexadecimal de 64 caracteres, guarda o respetivo hash SHA-256 emps_dfad_tokene envia um e-mail com o token em claro dentro de um URL. - O cliente recebe o e-mail e clica na ligação. O módulo obtém o token do URL, calcula o seu SHA-256 e verifica que existe na tabela, que não expirou e que ainda não foi consumido.
- O token é marcado como consumido (
consumed_at = NOW()), para evitar qualquer reutilização. - Em cada fornecedor ativo (Mailchimp, Brevo, Mailjet), o módulo chama a API de eliminação e regista o resultado (código HTTP, mensagem) no registo.
- O módulo limpa as tabelas do PrestaShop:
ps_emailsubscription,ps_newsletter,ps_cart,ps_cart_product,ps_wishlist,ps_compare,ps_customer_thread,ps_customer_messageeps_guest. - Consoante o modo e a existência de encomendas, a conta é anonimizada ou eliminada.
- É inserida uma linha em
ps_dfad_logcom o estadodone, o modo realmente aplicado e a lista dos resultados dos fornecedores. - É enviado um e-mail de notificação ao administrador configurado (apenas o hash do e-mail).
- O cliente é desautenticado e reencaminhado para uma página de confirmação.
O RGPD prevê que o pedido seja tratado sem demora injustificada e, no máximo, no prazo de um mês. Aqui o tratamento é imediato assim que o cliente confirma, o que cumpre folgadamente o prazo. Guarde ainda assim o registo, que é a sua prova perante a CNPD.
Registo de tratamento RGPD
O ecrã de configuração mostra os 30 últimos pedidos, com:
- ID do pedido
- Hash do e-mail truncado (os 12 primeiros caracteres do SHA-256)
- Modo aplicado (anonymize / delete)
- Estado (awaiting_confirm, done)
- Lista dos fornecedores e o respetivo código de retorno, por exemplo
mailchimp:OK(200) | brevo:OK(204) | mailjet:OK(200) - Data e hora UTC
A tabela completa contém ainda: hash SHA-256 do IP, user agent truncado a 250 caracteres, identificador da loja e notas internas (existência ou não de encomendas).
Para exportar o registo completo em caso de fiscalização, pode consultar diretamente a base de dados: SELECT * FROM ps_dfad_log ORDER BY created_at DESC;. Nunca aparece qualquer dado em claro neste registo.
Testar antes de colocar em produção
Procedimento recomendado antes de ativar o módulo numa loja de produção:
- Teste das ligações aos fornecedores: no back-office do módulo, clique em Testar a ligação em cada plataforma ativa. Deve ver uma mensagem verde com o nome da sua audiência ou conta. Em caso de erro, é apresentada a mensagem HTTP exata devolvida pela API.
- Teste do fluxo completo numa conta de teste:
- Crie uma conta de cliente com um endereço de e-mail real que controle.
- Inscreva-a na sua newsletter do Mailchimp, do Brevo ou do Mailjet manualmente, ou através do formulário da sua loja.
- Confirme que aparece mesmo em cada plataforma.
- Inicie sessão nessa conta do lado da loja e lance o procedimento de eliminação.
- Confirme através do e-mail recebido.
- Confirme em
ps_customerque a conta ficou anonimizada. - Confirme em cada plataforma de newsletter que o e-mail desapareceu.
- Verifique a entrada em
ps_dfad_log.
- Teste do caso «cliente com encomenda»: crie uma conta, faça uma encomenda de teste (1 €) e lance depois a eliminação em modo «Eliminar totalmente». Confirme que o módulo passou mesmo à anonimização e que a encomenda está intacta, mas com uma morada anónima.
Estender: acrescentar um novo fornecedor
A arquitetura segue um padrão Strategy. Acrescentar o Sendgrid, o Mailerlite, o HubSpot, o ActiveCampaign ou qualquer outra plataforma exige apenas a criação de uma classe.
Crie classes/Provider/SendgridProvider.php:
class DfAccountDelete_SendgridProvider extends DfAccountDelete_AbstractProvider
{
public function getKey() { return 'sendgrid'; }
public function isEnabled()
{
return (bool) Configuration::get('DFAD_SG_ENABLED')
&& Configuration::get('DFAD_SG_API_KEY');
}
public function deleteSubscriber($email)
{
$headers = ['Authorization: Bearer ' . Configuration::get('DFAD_SG_API_KEY')];
$url = 'https://api.sendgrid.com/v3/marketing/contacts?emails=' . rawurlencode($email);
$res = $this->http('DELETE', $url, $headers);
return ['ok' => $res['ok'], 'status' => $res['status'], 'message' => $res['message']];
}
public function testConnection()
{
$headers = ['Authorization: Bearer ' . Configuration::get('DFAD_SG_API_KEY')];
$res = $this->http('GET', 'https://api.sendgrid.com/v3/scopes', $headers);
return ['ok' => $res['ok'], 'status' => $res['status'], 'message' => $res['message']];
}
}
Referencie a classe em DfAccountDeleteService::getProviders():
public function getProviders()
{
return [
new DfAccountDelete_MailchimpProvider(),
new DfAccountDelete_BrevoProvider(),
new DfAccountDelete_MailjetProvider(),
new DfAccountDelete_SendgridProvider(), // novo
];
}
E carregue a classe no início de dfaccountdelete.php com um require_once. O resto (painel de configuração no back-office, botão de teste, integração no fluxo de eliminação) deve ser programado de forma semelhante aos fornecedores existentes.
Perguntas frequentes e resolução de problemas
O cliente diz não ter recebido o e-mail de confirmação
Verifique: (1) se a configuração de SMTP do PrestaShop funciona (está a enviar outros e-mails transacionais, como as confirmações de encomenda?); (2) se o e-mail não foi para o spam; (3) se o prazo de expiração já não foi atingido. O cliente pode relançar o procedimento a partir da conta, e o novo token invalida automaticamente os anteriores.
Uma plataforma de newsletter devolve um erro 401
A chave de API é inválida ou expirou. Volte a gerá-la na plataforma em causa e atualize-a na configuração do módulo. Use o botão Testar a ligação para validar de imediato.
Aparece o erro SQL «LIMIT 1 LIMIT 1»
Está numa versão anterior à 1.0.1. Atualize para a última versão: esse erro foi corrigido na 1.0.1.
A conta não parece anonimizada: o nome, o apelido e o e-mail originais continuam visíveis
Está numa versão anterior à 1.0.2. A validação interna do PrestaShop em Validate::isCustomerName() recusava o antigo valor de lastname, que continha o caractere # e algarismos, o que fazia falhar silenciosamente a atualização. Atualize para a 1.0.2: a atualização automática repara também as contas mal anonimizadas nas versões anteriores.
Como eliminar o registo RGPD na desinstalação?
A tabela ps_dfad_log é propositadamente conservada na desinstalação (prova do tratamento). Para a eliminar manualmente depois da desinstalação: DROP TABLE ps_dfad_log; DROP TABLE ps_dfad_token;.
O módulo é compatível com o meu módulo de RGPD existente (gdpr, psgdpr)?
Sim, os dois módulos podem coexistir. O módulo oficial do PrestaShop psgdpr serve sobretudo para a exportação dos dados e a gestão dos consentimentos; o dfaccountdelete serve para a eliminação efetiva das contas, com integração da newsletter. Não entram em conflito.
O cliente pode desistir depois de clicar no botão?
Sim, enquanto não clicar na ligação do e-mail de confirmação. O token expira automaticamente ao fim do período configurado (24 horas por predefinição). Durante essa janela, a conta mantém-se plenamente ativa. Se não fizer nada, o pedido é anulado.
Como acrescentar o bloco de eliminação fora de A minha conta?
Pode criar uma ligação direta para {shop_url}/{lang}/module/dfaccountdelete/delete a partir de qualquer página (rodapé, página de condições gerais, entre outras). Se o visitante não tiver sessão iniciada, é reencaminhado para a página de início de sessão e regressa à página de eliminação depois de se autenticar.
Um bom lugar para essa ligação é a sua política de privacidade, na secção dedicada aos direitos do titular dos dados: dá ao cliente uma via direta e demonstra que o direito é efetivamente exercível.
Versões e registo de alterações
1.0.2, correção crítica
- Correção:
anonymizeCustomer()usavaCustomer::update(), que passa porValidate::isCustomerName(). Essa validação proíbe algarismos e o caractere#em firstname e lastname, o que fazia falhar silenciosamente a anonimização do registops_customer. Substituído por umUPDATEem SQL direto, que contorna a validação. - A atualização
upgrade-1.0.2.phprepara retroativamente as contas tratadas pelas versões anteriores que tinham ficado por anonimizar.
1.0.1, correção
- Correção:
tableExists()usavaDb::getValue(), que acrescenta automaticamenteLIMIT 1. A consultaSHOW TABLES LIKE 'xxx' LIMIT 1é SQL inválido em MariaDB. Substituído porexecuteS().
1.0.0, versão inicial
- Compatibilidade com PrestaShop 8.0 a 9.x
- Modo de anonimização e modo de eliminação total
- Confirmação por e-mail com token SHA-256
- Integrações com Mailchimp, Brevo e Mailjet
- Registo de tratamento RGPD
- Interface e modelos de e-mail em FR, EN, ES e DE