ZC 1.5.6c, OPC (One Page Checkout, although not active on production site yet), Japanese (multilingual) language customizations, PHP 7.3.15, MariaDB 10.3.22
https://www.proteawines.jp/shop/

I implemented an age check for purchases, since our shop is selling alcohol. Japanese regulations specify that the age check must be a text box for users to type in their age in digits, not a scrollbar. And that this check must be there regardless of whether user registration is limited to users above age 20 (the legal age for purchase of alcohol in Japan).

In additions, notice of the age restriction must be included on customer emails pertaining to the order, and on the invoice and packing slip (deliveries must be accepted by a person above the legal limit for purchase of alcohol).

So here is what I have done, in case it helps others to do something similar, or elicits feedback on improvements.

Step1
Add age_check to table orders in your database:
Code:
ALTER TABLE orders ADD order_age_check int(3) NOT NULL;
Step 2
Prepare some language definitions for wording used in age check conditions.
First, in your override language checkout_payment.php file
includes/languages/LANGUAGE/YOURTEMPLATE/checkout_payment.php for the box in the display:
Code:
define('TEXT_AGE_CHECK_DESCRIPTION','<span class="termsdescription">The Japanese tax office requires confirmation of legal age for the purchase of alcohol, by entering your age when confirming your purchase.</span>');
define('TEXT_AGE_CHECK','Enter your age in English numerals.');
Note, if using OPC, add this to your checkout_one.php file.

Second, in your override general language file
includes/languages/YOURTEMPLATE/LANGUAGE.php add definitions for validation errors:
Code:
define('ERROR_AGE_CHECK_INPUT', 'You must be over 20 years of age to purchage alcohol from our store.');
define('ERROR_AGE_CHECK_INPUT_INHUMAN', 'We do expect humans over this age.');
Third, to enable outputing a notice of age restriction in emails, and on the order invoice/packing slip, set definitions in
languages/LANGUAGE/YOURTEMPLATE/checkout_process.php as follows:
Code:
define('EMAIL_AGE_CHECK_HEADER','Restriction:');
define('EMAIL_AGE_CHECK','Sales and delivery of alcohol is prohibited by law to persons under 20 years of age.');
Step 3
Add use of the age_check fields to your includes/classes/order.php. Note this is a core file edit.
Code:
1. function query($order_id)
   $this->info = array(...
              'age_check' => $order->fields['order_age_check'], // age check

2. function cart()
   $this->info = array(...
              'age_check' => $_SESSION['age_check'], // age check

3. function create($zf_ot_modules, $zf_mode = 2)
   $sql_data_array = array(...
                  'order_age_check' => $this->info['age_check'], // age check

4. $email_order ...
   $email_order .= "\n" . EMAIL_AGE_CHECK_HEADER . "\n" .
   ...
   EMAIL_AGE_CHECK . "\n";
The first three are additions to arrays, the fourth an output for the email being sent.

Step 4
Add processing of the age_check to your checkout_payment page as follows.
Note these are core file edits (I am not sure if overrides for individual pages are possible).
First, add the following to
includes/modules/pages/checkout_payment/header_php.php
Code:
// age check
if (isset($_SESSION['age_check'])) {
    $age_check = $_SESSION['age_check'];
}
Second, add the following to
includes/modules/pages/checkout_payment/jscript_main.js:
Code:
window.onload = function resetAgeCheck()
{
    //var x=document.getElementsByTagName("input");
    var x = document.getElementById("age_check");
    x.value = "";
}
The code is there to check whether the check has already been set, if the user is returned to this page by another error.
Note, if using OPC, add this to your checkout_one page header file along with other customizations as described in the OPC instructions.

Step 5
Add validation to your checkout_payment_confirmation page as follows.
Note these are core file edits (I am not sure if overrides for individual pages are possible).
includes/modules/pages/checkout_payment_confirmation/header_php.php
This checks the input to the age_check box is digits and within acceptable ranges (above minimum, below silly).
Code:
// age check
if (zen_not_null($_POST['age_check'])) {
    $_SESSION['age_check'] = zen_db_prepare_input($_POST['age_check']);
}
$age_check = $_SESSION['age_check'];
...
// age check required even if not null
$min_age=20; // legal age for purchase and consumption of alcohol (Japan)
$max_age=122; // oldest human known!
if (filter_var($age_check, FILTER_VALIDATE_INT, array("options" => array("min_range"=>$min_age, "max_range"=>$max_age))) === false) {
    if ($age_check <= $max_age) {
        $messageStack->add_session('checkout_payment', ERROR_AGE_CHECK_INPUT,'error');
    } else {
        $messageStack->add_session('checkout_payment', ERROR_AGE_CHECK_INPUT_INHUMAN,'error');
    }
}
Note, if using OPC, add this to your checkout_one_confirmation page header file.

Step 6
Add the age check box to the conditions section of your override template file
includes/templates/YOURTEMPLATE/templates/tpl_checkout_payment_default.php so that is appears something like this:
Code:
<?php
  if (DISPLAY_CONDITIONS_ON_CHECKOUT == 'true') {
?>
<fieldset>
<legend><?php echo TABLE_HEADING_CONDITIONS; ?></legend>
<div><?php echo TEXT_CONDITIONS_DESCRIPTION;?></div>
<?php echo  zen_draw_checkbox_field('conditions', '1', false, 'id="conditions"');?>
<label class="checkboxLabel" for="conditions"><?php echo TEXT_CONDITIONS_CONFIRM; ?></label>
<!-- Age verification input field as required by Japanese tax office -->
<div><?php echo TEXT_AGE_CHECK_DESCRIPTION;?></div>
<?php echo  zen_draw_input_field('age_check', '', 'id="age_check" pattern="[0-9]*" required minlength="2" maxlength="3" size="3" placeholder="00"', 'text');?>
<label class="inputAgeLabel" for="conditions"><?php echo TEXT_AGE_CHECK; ?></label>
</fieldset>
<?php
  }
?>
Note, if using OPC, add this to your override of tpl_modules_opc_conditions.php.

Add styling to your override stylesheet
includes/templates/YOURTEMPLATE/css/stylesheet.css:
Code:
LABEL.inputAgeLabel {width:15em;margin:0.5em 0.3em;}
input[type=text]#age_check {width:3em;margin-left:20px;font-size:120%;margin-top:5px;}