Complete Bank Account Management with Encryption for JetFormBuilder

PHP

Difficulty Level:

Snippet Description

/**
 * Complete Bank Account Management with Encryption
 * Consolidated snippet for JetFormBuilder bank account handling
 */

// ===================================================================
// 1. ENCRYPTION HELPER FUNCTIONS
// ===================================================================

/**
 * Get encryption key from wp-config.php
 */
function get_encryption_key() {
    if (!defined('BANK_DATA_ENCRYPTION_KEY')) {
        error_log('BANK_DATA_ENCRYPTION_KEY not defined in wp-config.php');
        return false;
    }
    return BANK_DATA_ENCRYPTION_KEY;
}

/**
 * Encrypt sensitive bank data
 */
function encrypt_bank_data($data) {
    $encryption_key = get_encryption_key();
    if (!$encryption_key) {
        return false;
    }
    
    $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
    $encrypted = openssl_encrypt(
        $data,
        'aes-256-cbc',
        $encryption_key,
        1,  // Using integer 1 instead of OPENSSL_RAW_OUTPUT
        $iv
    );
    
    if ($encrypted === false) {
        error_log('Encryption failed for bank data');
        return false;
    }
    
    return base64_encode($iv . $encrypted);
}

/**
 * Decrypt sensitive bank data
 */
function decrypt_bank_data($encrypted_data) {
    $encryption_key = get_encryption_key();
    if (!$encryption_key || empty($encrypted_data)) {
        return false;
    }
    
    $data = base64_decode($encrypted_data);
    $iv_length = openssl_cipher_iv_length('aes-256-cbc');
    $iv = substr($data, 0, $iv_length);
    $encrypted = substr($data, $iv_length);
    
    $decrypted = openssl_decrypt(
        $encrypted,
        'aes-256-cbc',
        $encryption_key,
        1,  // Using integer 1 instead of OPENSSL_RAW_OUTPUT
        $iv
    );
    
    if ($decrypted === false) {
        error_log('Decryption failed for bank data');
        return false;
    }
    
    return $decrypted;
}

/**
 * Mask account numbers for display
 */
function mask_account_number($account_number) {
    if (strlen($account_number) <= 4) {
        return str_repeat('*', strlen($account_number));
    }
    return str_repeat('*', strlen($account_number) - 4) . substr($account_number, -4);
}

// ===================================================================
// 2. ENCRYPT DATA ON FORM SUBMISSION
// ===================================================================

/**
 * 2. ENCRYPT DATA ON FORM SUBMISSION
 * Encrypts sensitive bank account data before saving to database
 */
function encrypt_bank_account_before_save($handler) {
    // Only apply to bank account form (update form_id to match your form)
    if ($handler->form_id != 1616) {
        return $handler;
    }
    
    // Get the form data from the handler
    $request_data = isset($handler->action_handler->request_data) ? $handler->action_handler->request_data : array();
    
    // Encrypt account number if present
    if (isset($request_data['account_number']) && !empty($request_data['account_number'])) {
        $encrypted_account = encrypt_bank_data($request_data['account_number']);
        if ($encrypted_account) {
            $handler->action_handler->request_data['account_number'] = $encrypted_account;
        }
    }
    
    // Encrypt routing number if present
    if (isset($request_data['routing_number']) && !empty($request_data['routing_number'])) {
        $encrypted_routing = encrypt_bank_data($request_data['routing_number']);
        if ($encrypted_routing) {
            $handler->action_handler->request_data['routing_number'] = $encrypted_routing;
        }
    }
    
    // Check for duplicate bank accounts
    $user_id = get_current_user_id();
    if ($user_id) {
        global $wpdb;
        $table_name = $wpdb->prefix . 'jet_cct_bank_accounts';
        
        $existing_accounts = $wpdb->get_results($wpdb->prepare(
            "SELECT account_number, routing_number FROM $table_name WHERE _user_id = %d",
            $user_id
        ));
        
        foreach ($existing_accounts as $account) {
            $decrypted_account = decrypt_bank_data($account->account_number);
            $decrypted_routing = decrypt_bank_data($account->routing_number);
            
            if ($decrypted_account === $request_data['account_number'] && 
                $decrypted_routing === $request_data['routing_number']) {
                wp_send_json_error(array(
                    'message' => 'This bank account already exists.'
                ));
                exit;
            }
        }
    }
    
    return $handler;
}
add_filter('jet-form-builder/form-handler/before-send', 'encrypt_bank_account_before_save', 5, 1);


// ===================================================================
// 3. DEFAULT BANK ACCOUNT LOGIC
// ===================================================================

/**
 * Handle default bank account logic after form submission
 * Hooked to: jet-form-builder/custom-action/bank_account_added
 */
function handle_bank_account_added($request) {
    global $wpdb;
    $user_id = get_current_user_id();
    
    if (!$user_id) {
        return;
    }
    
    $table_name = $wpdb->prefix . 'jet_cct_bank_accounts';
    
    // Count user's bank accounts
    $account_count = $wpdb->get_var($wpdb->prepare(
        "SELECT COUNT(*) FROM {$table_name} WHERE user_id = %d",
        $user_id
    ));
    
    // Get the most recently added account
    $latest_account = $wpdb->get_row($wpdb->prepare(
        "SELECT _ID, is_default FROM {$table_name} 
         WHERE user_id = %d 
         ORDER BY _ID DESC 
         LIMIT 1",
        $user_id
    ));
    
    if (!$latest_account) {
        return;
    }
    
    // If this is the first account, set it as default
    if ($account_count == 1) {
        $wpdb->update(
            $table_name,
            array('is_default' => 1),
            array('_ID' => $latest_account->_ID),
            array('%d'),
            array('%d')
        );
    }
    // If user explicitly set this as default, unset others
    elseif ($latest_account->is_default == 1) {
        // Unset all other accounts as default
        $wpdb->query($wpdb->prepare(
            "UPDATE {$table_name} SET is_default = 0 
             WHERE user_id = %d AND _ID != %d",
            $user_id,
            $latest_account->_ID
        ));
    }
}
add_action('jet-form-builder/custom-action/bank_account_added', 'handle_bank_account_added');

// ===================================================================
// 4. FORM VALIDATION
// ===================================================================

/**
 * 4. FORM VALIDATION
 * Validate bank account form submission
 */
function validate_bank_account_form($handler) {
    // Check if this is the bank account form (update form_id to match your form)
    if (!isset($handler->form_id) || $handler->form_id != 1616) {
        return $handler;
    }
    
    // Get form data from the handler object
    $request_data = isset($handler->action_handler->request_data) 
        ? $handler->action_handler->request_data 
        : array();
    
    // Validate required fields
    $account_holder = isset($request_data['account_holder_name']) ? sanitize_text_field($request_data['account_holder_name']) : '';
    $bank_name = isset($request_data['bank_name']) ? sanitize_text_field($request_data['bank_name']) : '';
    $account_number = isset($request_data['account_number']) ? sanitize_text_field($request_data['account_number']) : '';
    $routing_number = isset($request_data['routing_number']) ? sanitize_text_field($request_data['routing_number']) : '';
    
    $errors = array();
    
    if (empty($account_holder)) {
        $errors[] = 'Account holder name is required';
    }
    
    if (empty($bank_name)) {
        $errors[] = 'Bank name is required';
    }
    
    if (empty($account_number)) {
        $errors[] = 'Account number is required';
    } elseif (!preg_match('/^[0-9]{8,17}$/', $account_number)) {
        $errors[] = 'Account number must be 8-17 digits';
    }
    
    if (empty($routing_number)) {
        $errors[] = 'Routing number is required';
    } elseif (!preg_match('/^[0-9]{9}$/', $routing_number)) {
        $errors[] = 'Routing number must be exactly 9 digits';
    }
    
    // If there are validation errors, stop the form submission
    if (!empty($errors)) {
        wp_die(implode('<br>', $errors), 'Validation Error', array('response' => 400, 'back_link' => true));
    }
    
    return $handler;
}
add_filter('jet-form-builder/form-handler/before-send', 'validate_bank_account_form', 1, 1);

// ===================================================================
// 5. DECRYPT DATA WHEN RETRIEVING
// ===================================================================

/**
 * Get user's default bank account with decrypted data
 * Usage: $default_account = get_user_default_bank_account($user_id);
 */
function get_user_default_bank_account($user_id) {
    global $wpdb;
    $table_name = $wpdb->prefix . 'jet_cct_bank_accounts';
    
    $account = $wpdb->get_row($wpdb->prepare(
        "SELECT * FROM {$table_name} 
         WHERE user_id = %d AND is_default = 1 
         LIMIT 1",
        $user_id
    ));
    
    if (!$account) {
        return null;
    }
    
    // Decrypt sensitive fields
    if (!empty($account->account_number_encrypted)) {
        $decrypted_account = decrypt_bank_data($account->account_number_encrypted);
        $account->account_number_masked = $decrypted_account ? mask_account_number($decrypted_account) : '****';
    }
    
    if (!empty($account->routing_number_encrypted)) {
        $decrypted_routing = decrypt_bank_data($account->routing_number_encrypted);
        $account->routing_number_masked = $decrypted_routing ? mask_account_number($decrypted_routing) : '****';
    }
    
    return $account;
}

Usage Instructions

Table of Contents