PS PrestaShop Beginner

Accountverwijdering volgens de AVG: volledige gids

Installatie, configuratie en gebruik van de AVG-conforme accountverwijdering met e-mailbevestiging, anonimisering die de boekhoudplicht respecteert en uitschrijving bij Mailchimp, Brevo en Mailjet voor PrestaShop 8 en 9.

Bijgewerkt Moduleversie 1.0.2

Overzicht

De module Accountverwijdering AVG geeft uw klanten de mogelijkheid hun recht op gegevenswissing (artikel 17 van de AVG) direct vanuit hun klantaccount uit te oefenen, zonder handmatige tussenkomst van uw kant. Een verzoek zet een keten in gang: e-mailbevestiging met cryptografisch token, anonimisering of verwijdering van het account aan winkelzijde, automatische uitschrijving bij Mailchimp, Brevo en Mailjet, en het wegschrijven van een verwerkingsbewijs in een auditlogboek.

Voor wie? Elke PrestaShop 8- of 9-verkoper die persoonsgegevens van Europese burgers verwerkt en het handmatige beheer van AVG-verwijderingsverzoeken wil vermijden. De module wordt geleverd in het Frans, Engels, Spaans en Duits.

Installatie

  1. Log in op de PrestaShop back-office.
  2. Ga naar Modules → Module Manager, klik op Een module uploaden en sleep de ZIP dfaccountdelete-1.0.2.zip erin.
  3. De module wordt automatisch geïnstalleerd en geactiveerd. Klik op Configureren.

De installatie maakt twee tabellen aan: ps_dfad_log (AVG-logboek) en ps_dfad_token (bevestigingstokens per e-mail). Ze registreert de module op de hook displayCustomerAccount, die een blok “Mijn account verwijderen” aan het klantaccount toevoegt.

Controleer bij veel aangepaste templates na de installatie of het blok “Mijn account verwijderen” daadwerkelijk verschijnt in Mijn Account aan winkelzijde. De hook displayCustomerAccount moet door uw thema worden ondersteund — dat is het geval bij het native Classic-thema en de meeste commerciële thema’s.

Algemene configuratie

Het configuratiescherm is verdeeld in vier panelen: Algemene instellingen, Mailchimp, Brevo, Mailjet. Elk paneel wordt onafhankelijk opgeslagen.

Verwijderingsmodus

Kies tussen twee modi:

  • Anonimiseren (aanbevolen): de persoonsgegevens van de klant (naam, voornaam, e-mailadres, telefoon, adressen, geboortedatum) worden vervangen door anonieme waarden. De bestellingen blijven intact om te voldoen aan de wettelijke bewaarplicht van boekhoudstukken.
  • Volledig verwijderen indien mogelijk: het account wordt volledig gewist als er geen enkele bestelling bestaat. Bestaan er bestellingen, dan schakelt de module automatisch over op de anonimiseringsmodus om de wettelijke historiek niet te breken.

Zelfs in de modus “Volledig verwijderen” kunt u geen account verwijderen dat bestellingen heeft geplaatst. Dat is een wettelijke verplichting (bewaring van boekhoudstukken, in Frankrijk 10 jaar volgens artikel L123-22 van de Code de Commerce). De module beheert deze omschakeling automatisch en legt in het AVG-logboek de daadwerkelijk toegepaste modus vast.

Verplichte e-mailbevestiging

Standaard ingeschakeld (zeer sterk aanbevolen). De klant moet op een per e-mail ontvangen link klikken om zijn verzoek te valideren. Dat voorkomt elke onbedoelde verwijdering of verwijdering door een derde die toegang had tot een open sessie.

Geldigheidsduur van het token

In uren. Standaard 24 uur. Daarna verloopt de link in de e-mail en wordt het verzoek automatisch geannuleerd.

Logs

Standaard ingeschakeld. De module schrijft in ps_dfad_log elk verzoek weg met uitsluitend gepseudonimiseerde gegevens: SHA-256-hash van het e-mailadres, SHA-256-hash van het IP, klantidentifier, toegepaste modus, status, gecontacteerde providers, user agent, winkelidentifier, tijdstempel. Er wordt geen enkel persoonsgegeven in klare tekst bewaard.

De tabel ps_dfad_log wordt bij het deïnstalleren van de module niet verwijderd. Dat is opzettelijk: ze vormt het bewijs van de verwerking bij een audit van de toezichthouder. Voer om haar handmatig te verwijderen DROP TABLE ps_dfad_log; uit na de deïnstallatie.

Te notificeren beheerders-e-mailadres

Adres dat bij elke effectieve verwijdering een notificatie ontvangt (alleen de hash van het e-mailadres, nooit het adres in klare tekst). Standaard het e-mailadres van de winkel.

Configuratie van de nieuwsbriefproviders

De module ondersteunt standaard drie nieuwsbriefplatforms. Elke provider is standaard uitgeschakeld. Activeer alleen de providers die u gebruikt.

Mailchimp

Vul in:

  • API-sleutel: formaat xxxxxxxxxxxx-us21. Het achtervoegsel (-us21, -eu1, enzovoort) is het Mailchimp-datacenter. De module detecteert het automatisch.
  • List ID (Audience ID): identifier van uw hoofdaudience. Te vinden in Mailchimp via Audience → Settings → Audience name and defaults.
  • Permanente verwijdering: standaard ingeschakeld. Gebruikt het endpoint POST /lists/{list_id}/members/{hash}/actions/delete-permanent, dat overeenkomt met het echte AVG-recht op vergetelheid: het e-mailadres wordt definitief verwijderd en Mailchimp weigert elke toekomstige opt-in met dit adres. Geeft u de voorkeur aan een eenvoudige archivering (het adres kan zich dan later opnieuw inschrijven), schakel deze optie dan uit.

Klik op Verbinding testen om uw configuratie te valideren. Is alles correct, dan ziet u de naam van uw audience.

Brevo (voorheen Sendinblue)

Vul in:

  • API-sleutel v3: formaat xkeysib-xxxxxx. Te vinden in Brevo via Mijn account → SMTP & API → API-sleutels.
  • List ID (optioneel): indien ingevuld wordt het contact alleen uit deze lijst verwijderd. Indien leeg wordt het contact volledig verwijderd (aanbevolen voor de AVG).

Gebruikt endpoint: DELETE /v3/contacts/{email} voor volledige verwijdering, of POST /v3/contacts/lists/{id}/contacts/remove voor verwijdering uit één lijst.

Mailjet

Mailjet gebruikt Basic-authenticatie met twee sleutels. Vul in:

  • API Key
  • API Secret
  • Contact List ID (optioneel): indien ingevuld wordt alleen uit deze lijst uitgeschreven. Indien leeg wordt het contact verwijderd via het officiële GDPR-endpoint van Mailjet.

De Mailjet-verwijderingsflow verloopt in twee stappen: lookup van de contactidentifier via GET /v3/REST/contact/{email}, daarna DELETE /v4/contacts/{id} op het GDPR-endpoint. De module handelt dit mechanisme automatisch af.

Geeft een platform bij de verwijdering een 404 terug, dan beschouwt de module dat als een succes (het contact bestaat niet meer, idempotentie). U ziet dan geen fout in de logs.

Anonimiseren of verwijderen: wat kiezen?

De AVG legt het recht op gegevenswissing op, maar de wettelijke bewaarplicht van boekhoudstukken vereist dat facturatiegegevens jarenlang bewaard blijven. Beide verplichtingen worden verzoend door de anonimisering, de door de toezichthouders aanbevolen aanpak.

Anonimiseringsmodus

De module vervangt in ps_customer:

  • firstnameAnonymized
  • lastnameCustomer
  • emailanon-{id_customer}-{hash}@anonymized.local
  • passwd → willekeurige hash (de klant kan niet meer inloggen)
  • birthday → NULL
  • note, website, ip_registration_newsletter → leeg
  • active → 0, deleted → 1

Voor de adressen:

  • Adressen die niet door bestellingen worden gebruikt, worden volledig verwijderd.
  • Adressen die door bestellingen worden gebruikt, worden geanonimiseerd (firstname, lastname, address1, postcode, city, phone, enzovoort vervangen door neutrale waarden) en gemarkeerd met deleted = 1.

Modus volledige verwijdering

Heeft de klant geen enkele bestelling geplaatst: volledige verwijdering van de adressen en daarna aanroep van Customer::delete(). Anders: automatische omschakeling naar de anonimiseringsmodus. Geen enkele optie laat toe de verwijdering van een account met bestellingen te forceren — dat is opzettelijk om juridische redenen.

Volledige flow van een verzoek

  1. De klant gaat naar Mijn Account en klikt op het blok “Mijn account verwijderen”.
  2. Hij komt op een bevestigingspagina met een waarschuwingskader, een veld “Wachtwoord” en een selectievakje “Ik begrijp dat deze actie onomkeerbaar is”.
  3. Hij voert zijn wachtwoord in en vinkt het vakje aan. De module controleert het wachtwoord via de klasse PrestaShop/Core/Crypto/Hashing.
  4. Als de e-mailbevestiging is ingeschakeld, genereert de module een willekeurig token van 32 bytes (random_bytes(32)), zet het om in hexadecimaal op 64 tekens, slaat de SHA-256-hash ervan op in ps_dfad_token, en verstuurt een e-mail met het token in klare tekst in een URL.
  5. De klant ontvangt de e-mail en klikt op de link. De module haalt het token uit de URL, berekent de SHA-256 ervan, en controleert of het in de tabel bestaat, niet is verlopen en niet al is gebruikt.
  6. Het token wordt als gebruikt gemarkeerd (consumed_at = NOW()) om elk hergebruik te voorkomen.
  7. Voor elke ingeschakelde provider (Mailchimp, Brevo, Mailjet) roept de module de verwijderings-API aan en registreert ze het resultaat (HTTP-code, bericht) in het logboek.
  8. De module schoont de PrestaShop-tabellen op: ps_emailsubscription, ps_newsletter, ps_cart, ps_cart_product, ps_wishlist, ps_compare, ps_customer_thread, ps_customer_message, ps_guest.
  9. Afhankelijk van de modus en de aanwezigheid van bestellingen wordt het account geanonimiseerd of verwijderd.
  10. Er wordt een regel ingevoegd in ps_dfad_log met de status done, de daadwerkelijk toegepaste modus en de lijst met providerresultaten.
  11. Er wordt een notificatie-e-mail verstuurd naar de geconfigureerde beheerder (alleen de hash van het e-mailadres).
  12. De klant wordt uitgelogd en doorgestuurd naar een bevestigingspagina.

AVG-verwerkingslogboek

Het configuratiescherm toont de laatste 30 verzoeken met:

  • ID van het verzoek
  • Afgekapte e-mailhash (eerste 12 tekens van de SHA-256)
  • Toegepaste modus (anonymize / delete)
  • Status (awaiting_confirm, done)
  • Lijst met providers en hun retourcode, bijvoorbeeld mailchimp:OK(200) | brevo:OK(204) | mailjet:OK(200)
  • Datum en tijd in UTC

De volledige tabel bevat verder: SHA-256-hash van het IP, user agent afgekapt op 250 tekens, winkelidentifier, interne notities (al dan niet aanwezigheid van bestellingen).

Om het volledige logboek te exporteren bij een audit kunt u de database direct bevragen: SELECT * FROM ps_dfad_log ORDER BY created_at DESC;. In dit logboek verschijnt nooit enig gegeven in klare tekst.

Testen vóór productie

Aanbevolen procedure voordat u de module op een productiewinkel activeert:

  1. Test van de providerverbindingen: klik in de BO van de module op Verbinding testen voor elk ingeschakeld platform. U moet een groen bericht zien met de naam van uw audience/account. Bij een fout wordt het exacte HTTP-bericht van de API getoond.
  2. Test van de volledige flow op een testaccount:
    • Maak een klantaccount aan met een echt e-mailadres dat u beheert.
    • Schrijf het handmatig in op uw Mailchimp/Brevo/Mailjet-nieuwsbrief, of via het formulier van uw winkel.
    • Controleer of het in elk platform verschijnt.
    • Log in op dit account aan winkelzijde en start de verwijderingsprocedure.
    • Bevestig via de ontvangen e-mail.
    • Controleer in ps_customer of het account daadwerkelijk is geanonimiseerd.
    • Controleer in elk nieuwsbriefplatform of het e-mailadres is verdwenen.
    • Controleer de vermelding in ps_dfad_log.
  3. Test van het geval “klant met bestelling”: maak een account aan, plaats een testbestelling (1 €), en start dan de verwijdering in de modus “Volledig verwijderen”. Controleer of de module daadwerkelijk is overgeschakeld op anonimisering en of de bestelling intact is maar met een anoniem adres.

Uitbreiden: een nieuwe provider toevoegen

De architectuur volgt een Strategy-patroon. Sendgrid, Mailerlite, HubSpot, ActiveCampaign of elk ander platform toevoegen vergt alleen het aanmaken van een klasse.

Maak classes/Provider/SendgridProvider.php aan:

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']];
    }
}

Registreer de klasse in DfAccountDeleteService::getProviders():

public function getProviders()
{
    return [
        new DfAccountDelete_MailchimpProvider(),
        new DfAccountDelete_BrevoProvider(),
        new DfAccountDelete_MailjetProvider(),
        new DfAccountDelete_SendgridProvider(), // nieuw
    ];
}

En laad de klasse bovenaan dfaccountdelete.php met een require_once. De rest (BO-configuratiepaneel, testknop, integratie in de verwijderingsflow) codeert u naar analogie met de bestaande providers.

FAQ en probleemoplossing

De klant zegt de bevestigingsmail niet te hebben ontvangen

Controleer: (1) werkt de SMTP-configuratie van PrestaShop (verstuurt u andere transactionele e-mails zoals orderbevestigingen?), (2) zit de e-mail niet in de spam, (3) is de verlooptermijn niet verstreken. De klant kan de procedure vanuit zijn account opnieuw starten — het nieuwe token maakt de vorige automatisch ongeldig.

Een nieuwsbriefplatform geeft een 401-fout terug

De API-sleutel is ongeldig of verlopen. Regenereer haar in het betreffende platform en werk haar bij in de moduleconfiguratie. Gebruik de knop Verbinding testen om direct te valideren.

De SQL-fout “LIMIT 1 LIMIT 1” verschijnt

U gebruikt een versie ouder dan 1.0.1. Werk bij naar de nieuwste versie: deze bug is gecorrigeerd in 1.0.1.

Het account lijkt niet geanonimiseerd: de oorspronkelijke naam/voornaam/e-mail zijn nog zichtbaar

U gebruikt een versie ouder dan 1.0.2. De interne PrestaShop-validatie Validate::isCustomerName() weigerde de oude lastname-waarde met het teken # en cijfers, waardoor de update stilzwijgend mislukte. Werk bij naar 1.0.2: de automatische upgrade repareert ook de slecht geanonimiseerde accounts van vorige versies.

Hoe verwijder ik het AVG-logboek bij het deïnstalleren?

De tabel ps_dfad_log wordt bij het deïnstalleren bewust bewaard (bewijs van de verwerking). Om haar na de deïnstallatie handmatig te verwijderen: DROP TABLE ps_dfad_log; DROP TABLE ps_dfad_token;.

Is de module compatibel met mijn bestaande AVG-module (gdpr, psgdpr)?

Ja, beide modules kunnen naast elkaar bestaan. De officiële PrestaShop-module psgdpr dient vooral voor gegevensexport en toestemmingsbeheer; dfaccountdelete dient voor de effectieve accountverwijdering met nieuwsbriefintegratie. Ze zitten elkaar niet in de weg.

Kan de klant annuleren na op de knop te hebben geklikt?

Ja, zolang hij niet op de link in de bevestigingsmail heeft geklikt. Het token verloopt automatisch na de geconfigureerde duur (standaard 24 uur). Tijdens dit venster blijft het account volledig actief. Doet hij niets, dan wordt het verzoek geannuleerd.

Hoe voeg ik het verwijderingsblok elders toe dan in Mijn Account?

U kunt vanaf elke pagina (footer, pagina met algemene voorwaarden, enzovoort) een directe link maken naar {shop_url}/{lang}/module/dfaccountdelete/delete. Is de bezoeker niet ingelogd, dan wordt hij doorgestuurd naar de inlogpagina en na authenticatie teruggebracht naar de verwijderingspagina.

Versies en changelog

1.0.2 — kritieke correctie

  • Fix: anonymizeCustomer() gebruikte Customer::update(), dat via Validate::isCustomerName() loopt. Deze validatie verbiedt cijfers en het teken # in firstname/lastname, waardoor de anonimisering van het ps_customer-record stilzwijgend mislukte. Vervangen door een directe SQL-UPDATE die de validatie omzeilt.
  • De upgrade upgrade-1.0.2.php repareert met terugwerkende kracht de door vorige versies verwerkte accounts die niet-geanonimiseerd waren gebleven.

1.0.1 — correctie

  • Fix: tableExists() gebruikte Db::getValue(), dat automatisch LIMIT 1 toevoegt. De query SHOW TABLES LIKE 'xxx' LIMIT 1 is ongeldige SQL in MariaDB. Vervangen door executeS().

1.0.0 — eerste versie

  • Compatibiliteit met PrestaShop 8.0 tot 9.x
  • Anonimiseringsmodus en modus volledige verwijdering
  • E-mailbevestiging met SHA-256-token
  • Integraties Mailchimp, Brevo, Mailjet
  • AVG-verwerkingslogboek
  • Interface en e-mailsjablonen in FR, EN, ES, DE
Was deze pagina nuttig?

Loopt u nog vast? Neem contact op met support