You may delete or change orders that are final, as that is prohibited by law, but you should probably have to tell the customer you need to save that information for a limited amount of time (7 years in EU countries).
Printable View
As the only core team member residing in the EU, thought I would offer my thoughts here.
First, as mentioned in a previous post, be wary of scaremongers, especially when they are consultants looking to make some money from you.
The first steps in compliance is to make sure your Privacy and Conditions of use tell the customer exactly what data you are collecting, what use it is put to, and how to contact you if they have concerns or want you to amend/delete their data.
Another big issue is consent. Using Agree to terms on both sign up and checkout will help here. Also remember that any consent should be opt in, don't automatically check those checkboxes.
Zen Cart by default does not have a Cookie consent pop up, although there are modules that you can install.
When you are collecting information, make sure you are only collecting information you really need. Do you really need a customers telephone number, their date of birth etc. If you are collecting that information then tell the customer why you need it.
On the right to forget, there are obviously some conflicts here. While its easy to delete a customers record, if they have made orders then personal info is also stored in the order. However as a general principle, the tax requirements to keep order information for n years will override the GDPR requirements. Again this fact should be shared with the customer in your privacy policy.
On encryption. The actual section in the wonderful GDPR documentation does not make it an absolute necessity, at least as far as database encryption is concerned. However no store now should ever operate without SSL, and as a general principle should use SSL site wide and not just for admin/checkout.
Finally, I am not a lawyer. My advice above is based on my reading of GDPR, and my experience working with Zen Cart for many many years :)
I never took close look on the customers tables and all that stuff.
I was thinking about creating a new table that could save the customers agreement in the new gdpr laws. But there's a beautiful table called customers_info, that could hold this extra info.
My concern is on future zencart updates. I belive in principle that it will update tables without removing extra columns , right ?
About the 7 years. I believe this depends if one is using zencart as a accounting software.
This has been the operation of ZC for as far back as I have seen the install/upgrade process work. In fact there was discussion that one of the ZC provided tables had a field in it that was never used in core code (final_price as found in the customers_basket table). Removal of that field (from the install script and from the database in the upgrade process) was under review for nearly a year. Now, this was a direction to affect a field within a table that was generated by core Zen Cart code. Otherwise, the process has been to still generally leave other fields and tables alone to be controlled by some other process. So, provided the path forward continues to be one of Zen Cart taking care of its own tables and fields with any other modifications made to be addressed by an applicable process, you can yes use the customers_info table to track this additional field.
Thanks !
I see now that I was inventing the wheel. The zencart terms and conditions configuration, can handle this bit at the registration page! Cool!
Edit:
Not so cool! However it seems that it's not inserting this data anywhere...
I'm glad our volume of sales exempts us from all/Most of this.
I guess something like bbc.com , where you can control what cookies are in place. So one could stop analytics or whatever to run before user consent.
However zencart uses IP from visitors, and IP are now considered personal information.
A lot of issues here.
I've given some thought to how to implement the 'right to be forgotten'. Some years ago Kuroi highlighted a potential fraud issue with allowing customers to delete their own accounts. So given that I'm unlikely to have to deal with many account deletions I've gone down the road of having a customer request that their account be deleted - click on a button and it sends me an email requesting such. In case anyone's interested:
I added a link in the customers Account page (\includes\templates\my_template\templates\tpl_account_default.php) pointing to a 'Delete My Account' page.
I created 3 new files:
\includes\languages\english\my_template\account_delete.php
\includes\templates\my_template\templates\tpl_account_delete_default.phpCode:define('HEADING_TITLE', 'Delete My Account');
define('NAVBAR_TITLE_1', 'My Account');
define('NAVBAR_TITLE_2', 'Delete Account');
define('TEXT_SUCCESS_ACCOUNT_DELETE', 'Your request for your account to be deleted has been successfully sent and will be actioned as soon as possible.');
define('ACCOUNT_DELETE_INFORMATION', 'Do you wish to delete your account? Please confirm by clicking the button below. <br/><br/>This will notify us of your request and we will delete your account as soon as possible (by law we must action your request within one month).<br/><br/>Please note that this will permanently remove all of your personal information, including order history, from our system.');
define('EMAIL_SUBJECT', 'Website Enquiry from ' . STORE_NAME);
define('ENTRY_NAME', 'Full Name:');
define('ENTRY_EMAIL', 'Email Address:');
define('ENTRY_ENQUIRY', 'Message:');
define('MESSAGE_BODY', 'Please permanently delete my account');
define('MESSAGE_CUSTOMERS_ID', 'customers_id: ');
\includes\modules\pages\account_delete\header_php.phpCode:<article id="main">
<header><h1><?php echo HEADING_TITLE; ?></h1>
</header>
<section class="wrapper style5">
<div class="inner">
<?php echo zen_draw_form('account_delete', zen_href_link(FILENAME_ACCOUNT_DELETE, 'action=send', 'SSL')); ?>
<?php
if (isset($_GET['action']) && ($_GET['action'] == 'success')) {
?>
<div class="mainContent success"><?php echo TEXT_SUCCESS_ACCOUNT_DELETE; ?></div>
<br class="clearBoth" />
<div class="buttonRow"><?php echo zen_back_link() . zen_image_button(BUTTON_IMAGE_BACK, BUTTON_BACK_ALT) . '</a>'; ?></div>
<?php
} else {
?>
<?php echo zen_draw_input_field('contactname', $name, 'style="visibility:hidden; display:none;"'); ?>
<?php echo zen_draw_input_field('email', ($email_address), 'style="visibility:hidden; display:none;"'); ?>
<?php echo zen_draw_input_field('enquiry', $enquiry, 'style="visibility:hidden; display:none;"'); ?>
<fieldset class="accountDelete">
<legend><?php echo HEADING_TITLE; ?></legend>
<?php echo ACCOUNT_DELETE_INFORMATION; ?>
</fieldset>
<div class="buttonRow forward"><?php echo zen_image_submit(BUTTON_IMAGE_CONFIRM,BUTTON_CONFIRM_DELETE_ALT); ?></div>
<div class="buttonRow back"><?php echo '<a href="' . zen_href_link(FILENAME_ACCOUNT, '', 'SSL') . '">' . zen_image_button(BUTTON_IMAGE_BACK, BUTTON_BACK_ALT) . '</a>'; ?></div>
<?php
}
?>
</form>
<br class="clearBoth" />
</div>
</section>
</article>
and added a line to:Code:$zco_notifier->notify('NOTIFY_HEADER_START_ACCOUNT_DELETE');
if (!$_SESSION['customer_id']) {
$_SESSION['navigation']->set_snapshot();
zen_redirect(zen_href_link(FILENAME_LOGIN, '', 'SSL'));
}
require(DIR_WS_MODULES . zen_get_module_directory('require_languages.php'));
$error = false;
if (isset($_GET['action']) && ($_GET['action'] == 'send')) {
$name = zen_db_prepare_input($_POST['contactname']);
$email_address = zen_db_prepare_input($_POST['email']);
$enquiry = zen_db_prepare_input(strip_tags($_POST['enquiry']));
$sql = "SELECT customers_id, customers_firstname, customers_lastname, customers_password, customers_email_address, customers_default_address_id
FROM " . TABLE_CUSTOMERS . "
WHERE customers_id = :customersID";
$sql = $db->bindVars($sql, ':customersID', $_SESSION['customer_id'], 'integer');
$check_customer = $db->Execute($sql);
$customer_email= $check_customer->fields['customers_email_address'];
$customer_name= $check_customer->fields['customers_firstname'] . ' ' . $check_customer->fields['customers_lastname'];
$send_to_email = trim(EMAIL_FROM);
$send_to_name = trim(STORE_NAME);
// Prepare extra-info details
$extra_info = email_collect_extra_info($name, $email_address, $customer_name, $customer_email);
// Prepare Text-only portion of message
$text_message = OFFICE_FROM . "\t" . $name . "\n" .
OFFICE_EMAIL . "\t" . $email_address . "\n\n" .
'------------------------------------------------------' . "\n\n" .
strip_tags($_POST['enquiry']) . "\n\n" .
'------------------------------------------------------' . "\n\n" .
$extra_info['TEXT'];
// Prepare HTML-portion of message
$html_msg['EMAIL_MESSAGE_HTML'] = strip_tags($_POST['enquiry']);
$html_msg['CONTACT_US_OFFICE_FROM'] = OFFICE_FROM . ' ' . $name . '<br />' . OFFICE_EMAIL . '(' . $email_address . ')';
$html_msg['EXTRA_INFO'] = $extra_info['HTML'];
// Send message
zen_mail($send_to_name, $send_to_email, EMAIL_SUBJECT, $text_message, $name, $email_address, $html_msg,'contact_us');
zen_redirect(zen_href_link(FILENAME_ACCOUNT_DELETE, 'action=success', 'SSL'));
} // end action==send
// default email and name if customer is logged in
if($_SESSION['customer_id']) {
$sql = "SELECT customers_id, customers_firstname, customers_lastname, customers_password, customers_email_address, customers_default_address_id
FROM " . TABLE_CUSTOMERS . "
WHERE customers_id = :customersID";
$sql = $db->bindVars($sql, ':customersID', $_SESSION['customer_id'], 'integer');
$check_customer = $db->Execute($sql);
$email_address = $check_customer->fields['customers_email_address'];
$name= $check_customer->fields['customers_firstname'] . ' ' . $check_customer->fields['customers_lastname'];
$customers_id = $check_customer->fields['customers_id'];
$enquiry = MESSAGE_BODY . ' (' . MESSAGE_CUSTOMERS_ID . $customers_id . ')';
}
$breadcrumb->add(NAVBAR_TITLE_1, zen_href_link(FILENAME_ACCOUNT, '', 'SSL'));
$breadcrumb->add(NAVBAR_TITLE_2, zen_href_link(FILENAME_ACCOUNT_DELETE, '', 'SSL'));
// This should be last line of the script:
$zco_notifier->notify('NOTIFY_HEADER_END_ACCOUNT_DELETE_PROCESS');
\includes\languages\english\my_template\button_names.php
All this gives give meCode:define('BUTTON_CONFIRM_DELETE_ALT', 'Yes, Delete My Account');
Attachment 17789
A click on the button gives a 'message received and understood' page and an email is sent to the address in the admin > configuration > e-mail options > Email Address (sent FROM) field.
This is just a copy and paste job (so there are probably plenty of errors/omissions/redundant code).
Edit: forgot to say that I've posted the full code from the three files so there'll be some custom HTML tags that won't relate to the standard ZC template
And just for my curiosity, as I don't need to implement this (yet)
What data do you actually delete when you decide to go ahead with their request?