How to allow re-submission of a form without requiring a page refresh for new token generation?

I have implemented a security system for a WordPress site form that involves generating a unique token for every form submission. The current flow is:

When a user goes to the website with the form, several security measures kick in, including the generation of a unique token.
Once the form is submitted, a new token isn’t generated. This means that if a user made some errors or wants to re-submit for any reason, they’d need to refresh the entire page to generate a new token.
Given the following code logic for token generation, validation, and cleanup:

Database Table Creation for Storing Tokens:

function create_token_table() {
    global $wpdb;
    $charset_collate = $wpdb->get_charset_collate();
    $sql = "CREATE TABLE IF NOT EXISTS `{$wpdb->base_prefix}CF7_unique_tokens` (
        id mediumint(9) NOT NULL AUTO_INCREMENT,
        token varchar(255) NOT NULL,
        salt varchar(16) NOT NULL,
        timestamp datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
        PRIMARY KEY  (id)
    ) $charset_collate;";
    require_once ABSPATH . 'wp-admin/includes/upgrade.php';
    dbDelta($sql);
}
add_action('init', 'create_token_table');

Generating a Unique Token:

function generate_token() {
    if (!function_exists('random_bytes') || !function_exists('openssl_encrypt') || !defined('AUTH_KEY')) {
        return false;
    }
    $token = bin2hex(random_bytes(32));
    $salt = random_bytes(8);
    $salt_hex = bin2hex($salt);
    $encrypted_token = openssl_encrypt($token, 'aes-256-cbc', AUTH_KEY, 0, $salt_hex);
    global $wpdb;
    $success = $wpdb->insert($wpdb->prefix . 'CF7_unique_tokens', [
        'token' => $encrypted_token,
        'salt' => $salt_hex,
        'timestamp' => current_time('mysql'),
    ]);
    return $success ? $encrypted_token : false;
}

Cleaning Up Old Tokens:

function cleanup_old_tokens() {
    global $wpdb;
    $expiration = date('Y-m-d H:i:s', strtotime('-24 hours'));
    $wpdb->query($wpdb->prepare("DELETE FROM `{$wpdb->prefix}CF7_unique_tokens` WHERE timestamp < %s", $expiration));
}
add_action('init', 'cleanup_old_tokens');

Adding the Generated Token to Form as a Hidden Field:

function add_token_hidden_field($hidden_fields) {
    $token = generate_token();
    if (!$token) {
        return $hidden_fields;
    }
    $hidden_fields['form_token'] = $token;
    $hidden_fields['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
    return $hidden_fields;
}
add_filter('wpcf7_form_hidden_fields', 'add_token_hidden_field');

Validating the Submitted Token:

function validate_token_and_keywords($spam) {
    global $wpdb;
    if (!isset($_POST['form_token'])) {
        return true;
    }
    $token = $_POST['form_token'];
    if (!is_token_valid($token, $wpdb)) {
        return true;
    }
    delete_token($token, $wpdb);
    return $spam;
}

Deleting a Token from the Database:

function delete_token($token, $wpdb) {
    $wpdb->delete("{$wpdb->prefix}CF7_unique_tokens", array('token' => $token));
}

Checking Token’s Validity:

function is_token_valid($token, $wpdb) {
    $result = $wpdb->get_row($wpdb->prepare("SELECT * FROM `{$wpdb->prefix}CF7_unique_tokens` WHERE token = %s", $token));
    if (!$result) {
        return false;
    }
    return true;
}

I’d like to address two main concerns:

  • How can I prevent the user from needing to refresh the entire page?
  • How can I ensure that the user can submit the form again (after the first submission) without token-related issues?
    In essence, I want the form to be user-friendly by allowing re-submissions without a full page refresh but also ensure it remains secure against spam or malicious attacks. Any recommendations on the best approach or adjustments to the current logic would be greatly appreciated.