EmailVerify LogoEmailVerify

WooCommerce

Email checker for WooCommerce. Verify emails at checkout and in WordPress forms.

Añade verificación de correo electrónico a tu tienda WooCommerce para reducir entregas fallidas, prevenir fraude y mejorar la comunicación con los clientes.

Métodos de Integración

MétodoMejor ParaComplejidad
PluginConfiguración rápidaBaja
Hook de CheckoutVerificación en tiempo realMedia
Procesamiento de PedidosVerificación en segundo planoMedia
REST APISoluciones personalizadasAlta

Método 1: Plugin de WordPress

Si ya has configurado el plugin de EmailVerify para WordPress, la integración con WooCommerce es automática.

Activar Soporte para WooCommerce

  1. Ve a AjustesEmailVerify
  2. Marca Activar Integración con WooCommerce
  3. Configura las opciones:
    • ✓ Verificar al finalizar compra
    • ✓ Bloquear correos desechables
    • ✓ Mostrar estado de verificación en pedidos

Método 2: Validación en Checkout

Añade verificación de correo electrónico al proceso de checkout de WooCommerce.

Validación del Lado del Servidor

<?php
// functions.php o plugin personalizado

/**
 * Verificar email al finalizar compra en WooCommerce
 */
add_action('woocommerce_checkout_process', 'emailverify_checkout_validation');

function emailverify_checkout_validation() {
    $email = sanitize_email($_POST['billing_email']);

    if (empty($email)) {
        return;
    }

    $result = emailverify_verify_email($email);

    if (!$result['success']) {
        // Error de API - permitir que continúe el checkout
        return;
    }

    $data = $result['data'];

    // Bloquear correos inválidos
    if ($data['status'] === 'invalid') {
        wc_add_notice(
            __('Por favor, introduce una dirección de correo válida para completar tu pedido.', 'your-theme'),
            'error'
        );
    }

    // Bloquear correos desechables (opcional)
    if (get_option('emailverify_block_disposable', true)) {
        if ($data['result']['disposable'] ?? false) {
            wc_add_notice(
                __('No se aceptan direcciones de correo temporales. Por favor, usa un correo permanente.', 'your-theme'),
                'error'
            );
        }
    }
}

/**
 * Función auxiliar para llamadas a la API de EmailVerify
 */
function emailverify_verify_email($email) {
    $api_key = get_option('emailverify_api_key');

    // Verificar caché primero
    $cache_key = 'bv_email_' . md5($email);
    $cached = get_transient($cache_key);

    if ($cached !== false) {
        return $cached;
    }

    $response = wp_remote_post('https://api.emailverify.ai/v1/verify', [
        'headers' => [
            'Authorization' => 'Bearer ' . $api_key,
            'Content-Type' => 'application/json',
        ],
        'body' => json_encode(['email' => $email]),
        'timeout' => 10,
    ]);

    if (is_wp_error($response)) {
        return ['success' => false, 'error' => $response->get_error_message()];
    }

    $body = json_decode(wp_remote_retrieve_body($response), true);
    $result = ['success' => true, 'data' => $body];

    // Cachear durante 24 horas
    set_transient($cache_key, $result, DAY_IN_SECONDS);

    return $result;
}

Validación AJAX en Tiempo Real

Añade retroalimentación instantánea mientras los clientes escriben su correo electrónico.

<?php
// Encolar scripts
add_action('wp_enqueue_scripts', 'emailverify_wc_scripts');

function emailverify_wc_scripts() {
    if (!is_checkout()) {
        return;
    }

    wp_enqueue_script(
        'emailverify-checkout',
        get_template_directory_uri() . '/js/emailverify-checkout.js',
        ['jquery'],
        '1.0.0',
        true
    );

    wp_localize_script('emailverify-checkout', 'bv_checkout', [
        'ajax_url' => admin_url('admin-ajax.php'),
        'nonce' => wp_create_nonce('emailverify_checkout'),
    ]);
}

// Manejador AJAX
add_action('wp_ajax_verify_checkout_email', 'emailverify_ajax_checkout_verify');
add_action('wp_ajax_nopriv_verify_checkout_email', 'emailverify_ajax_checkout_verify');

function emailverify_ajax_checkout_verify() {
    check_ajax_referer('emailverify_checkout', 'nonce');

    $email = sanitize_email($_POST['email'] ?? '');

    if (empty($email)) {
        wp_send_json_error(['message' => 'El correo electrónico es requerido']);
    }

    $result = emailverify_verify_email($email);

    if ($result['success']) {
        wp_send_json_success($result['data']);
    } else {
        wp_send_json_error(['message' => 'La verificación falló']);
    }
}
// js/emailverify-checkout.js
jQuery(function($) {
    var $billingEmail = $('#billing_email');
    var verifyTimeout;
    var $status = $('<span class="bv-status"></span>');

    $billingEmail.after($status);

    $billingEmail.on('blur change', function() {
        var email = $(this).val();

        if (!email || !isValidEmailFormat(email)) {
            $status.html('').removeClass('valid invalid verifying');
            return;
        }

        clearTimeout(verifyTimeout);

        verifyTimeout = setTimeout(function() {
            verifyEmail(email);
        }, 500);
    });

    function verifyEmail(email) {
        $status.html('<span class="spinner"></span> Verificando...').addClass('verifying');

        $.ajax({
            url: bv_checkout.ajax_url,
            method: 'POST',
            data: {
                action: 'verify_checkout_email',
                nonce: bv_checkout.nonce,
                email: email
            },
            success: function(response) {
                $status.removeClass('verifying');

                if (response.success) {
                    var data = response.data;

                    if (data.status === 'valid') {
                        $status
                            .html('<span class="dashicons dashicons-yes"></span> Correo verificado')
                            .addClass('valid')
                            .removeClass('invalid');
                    } else if (data.status === 'invalid') {
                        $status
                            .html('<span class="dashicons dashicons-no"></span> Por favor, introduce un correo válido')
                            .addClass('invalid')
                            .removeClass('valid');
                    } else if (data.result && data.result.disposable) {
                        $status
                            .html('<span class="dashicons dashicons-warning"></span> Por favor, usa un correo permanente')
                            .addClass('invalid')
                            .removeClass('valid');
                    }
                }
            },
            error: function() {
                $status.html('').removeClass('verifying valid invalid');
            }
        });
    }

    function isValidEmailFormat(email) {
        return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
    }
});
/* style.css */
.bv-status {
    display: block;
    margin-top: 5px;
    font-size: 13px;
}

.bv-status.verifying {
    color: #666;
}

.bv-status.valid {
    color: #28a745;
}

.bv-status.invalid {
    color: #dc3545;
}

.bv-status .spinner {
    display: inline-block;
    width: 12px;
    height: 12px;
    border: 2px solid #ccc;
    border-top-color: #333;
    border-radius: 50%;
    animation: spin 1s linear infinite;
}

@keyframes spin {
    to { transform: rotate(360deg); }
}

Método 3: Procesamiento de Pedidos

Verifica correos electrónicos después de realizar el pedido y guarda los resultados.

Guardar Datos de Verificación

<?php
/**
 * Verificar email después de crear el pedido
 */
add_action('woocommerce_checkout_order_created', 'emailverify_verify_order_email');

function emailverify_verify_order_email($order) {
    $email = $order->get_billing_email();

    if (empty($email)) {
        return;
    }

    $result = emailverify_verify_email($email);

    if ($result['success']) {
        $data = $result['data'];

        // Guardar datos de verificación como meta del pedido
        $order->update_meta_data('_email_verification_status', $data['status']);
        $order->update_meta_data('_email_verification_score', $data['score'] ?? '');
        $order->update_meta_data('_email_is_disposable', $data['result']['disposable'] ? 'yes' : 'no');
        $order->update_meta_data('_email_verified_at', current_time('mysql'));
        $order->save();

        // Añadir nota al pedido
        if ($data['status'] === 'invalid') {
            $order->add_order_note(
                sprintf(
                    __('Advertencia: El correo del cliente %s falló la verificación (Estado: %s)', 'your-theme'),
                    $email,
                    $data['status']
                )
            );
        }
    }
}

/**
 * Mostrar estado de verificación en detalles del pedido
 */
add_action('woocommerce_admin_order_data_after_billing_address', 'emailverify_show_order_email_status');

function emailverify_show_order_email_status($order) {
    $status = $order->get_meta('_email_verification_status');

    if (empty($status)) {
        return;
    }

    $score = $order->get_meta('_email_verification_score');
    $disposable = $order->get_meta('_email_is_disposable');

    $status_class = $status === 'valid' ? 'status-completed' : 'status-on-hold';

    echo '<div class="email-verification-status">';
    echo '<h3>' . __('Verificación de Correo', 'your-theme') . '</h3>';
    echo '<p><strong>' . __('Estado:', 'your-theme') . '</strong> ';
    echo '<mark class="order-status ' . esc_attr($status_class) . '">' . esc_html(ucfirst($status)) . '</mark></p>';

    if ($score) {
        echo '<p><strong>' . __('Puntuación:', 'your-theme') . '</strong> ' . esc_html($score) . '</p>';
    }

    if ($disposable === 'yes') {
        echo '<p><span class="dashicons dashicons-warning" style="color: #d63638;"></span> ';
        echo __('Correo desechable detectado', 'your-theme') . '</p>';
    }

    echo '</div>';
}

Añadir Columna en Lista de Pedidos

<?php
/**
 * Añadir columna de estado de correo a la lista de pedidos
 */
add_filter('manage_edit-shop_order_columns', 'emailverify_orders_column');

function emailverify_orders_column($columns) {
    $new_columns = [];

    foreach ($columns as $key => $value) {
        $new_columns[$key] = $value;

        if ($key === 'order_status') {
            $new_columns['email_status'] = __('Correo', 'your-theme');
        }
    }

    return $new_columns;
}

add_action('manage_shop_order_posts_custom_column', 'emailverify_orders_column_content', 10, 2);

function emailverify_orders_column_content($column, $post_id) {
    if ($column !== 'email_status') {
        return;
    }

    $order = wc_get_order($post_id);
    $status = $order->get_meta('_email_verification_status');

    if (empty($status)) {
        echo '<span class="dashicons dashicons-minus" title="No verificado"></span>';
        return;
    }

    if ($status === 'valid') {
        echo '<span class="dashicons dashicons-yes-alt" style="color: #28a745;" title="Válido"></span>';
    } else {
        echo '<span class="dashicons dashicons-dismiss" style="color: #dc3545;" title="Inválido"></span>';
    }

    $disposable = $order->get_meta('_email_is_disposable');
    if ($disposable === 'yes') {
        echo '<span class="dashicons dashicons-warning" style="color: #d63638;" title="Desechable"></span>';
    }
}

Método 4: Integración con REST API

Para WooCommerce headless o flujos de checkout personalizados.

Endpoint REST Personalizado

<?php
/**
 * Registrar endpoint de REST API para verificación de correo
 */
add_action('rest_api_init', 'emailverify_register_wc_endpoint');

function emailverify_register_wc_endpoint() {
    register_rest_route('emailverify/v1', '/verify-checkout', [
        'methods' => 'POST',
        'callback' => 'emailverify_rest_verify_checkout',
        'permission_callback' => '__return_true',
        'args' => [
            'email' => [
                'required' => true,
                'type' => 'string',
                'format' => 'email',
                'sanitize_callback' => 'sanitize_email',
            ],
        ],
    ]);
}

function emailverify_rest_verify_checkout($request) {
    $email = $request->get_param('email');

    // Limitación de tasa
    $ip = $_SERVER['REMOTE_ADDR'];
    $rate_key = 'bv_rate_' . md5($ip);
    $rate_count = get_transient($rate_key) ?: 0;

    if ($rate_count >= 20) {
        return new WP_Error(
            'rate_limited',
            'Demasiadas solicitudes de verificación',
            ['status' => 429]
        );
    }

    set_transient($rate_key, $rate_count + 1, MINUTE_IN_SECONDS);

    // Verificar correo
    $result = emailverify_verify_email($email);

    if (!$result['success']) {
        return new WP_Error(
            'verification_failed',
            'La verificación del correo falló',
            ['status' => 503]
        );
    }

    $data = $result['data'];

    return new WP_REST_Response([
        'valid' => $data['status'] === 'valid',
        'status' => $data['status'],
        'disposable' => $data['result']['disposable'] ?? false,
        'score' => $data['score'] ?? null,
    ], 200);
}

Uso en Frontend

// Verificación de correo en checkout headless
async function verifyCheckoutEmail(email) {
    const response = await fetch('/wp-json/emailverify/v1/verify-checkout', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({ email }),
    });

    if (!response.ok) {
        if (response.status === 429) {
            throw new Error('Demasiadas solicitudes. Por favor, espera.');
        }
        throw new Error('La verificación falló');
    }

    return response.json();
}

// Uso
try {
    const result = await verifyCheckoutEmail('customer@example.com');

    if (!result.valid) {
        showError('Por favor, introduce una dirección de correo válida');
    } else if (result.disposable) {
        showError('Por favor, usa una dirección de correo permanente');
    } else {
        proceedToPayment();
    }
} catch (error) {
    // Permitir checkout en caso de error
    proceedToPayment();
}

Verificación Masiva de Clientes

Verifica clientes existentes en tu base de datos.

Comando WP-CLI

<?php
/**
 * Comando WP-CLI para verificación masiva de clientes
 */
if (defined('WP_CLI') && WP_CLI) {
    WP_CLI::add_command('emailverify verify-customers', function($args, $assoc_args) {
        $batch_size = $assoc_args['batch'] ?? 100;
        $dry_run = isset($assoc_args['dry-run']);

        global $wpdb;

        // Obtener clientes sin estado de verificación
        $customers = $wpdb->get_results("
            SELECT DISTINCT pm.meta_value as email, pm.post_id as order_id
            FROM {$wpdb->postmeta} pm
            LEFT JOIN {$wpdb->postmeta} pm2 ON pm.post_id = pm2.post_id
                AND pm2.meta_key = '_email_verification_status'
            WHERE pm.meta_key = '_billing_email'
            AND pm.meta_value != ''
            AND pm2.meta_id IS NULL
            LIMIT {$batch_size}
        ");

        if (empty($customers)) {
            WP_CLI::success('¡Todos los clientes están verificados!');
            return;
        }

        WP_CLI::log(sprintf('Se encontraron %d clientes para verificar', count($customers)));

        $progress = \WP_CLI\Utils\make_progress_bar('Verificando', count($customers));

        $stats = ['valid' => 0, 'invalid' => 0, 'error' => 0];

        foreach ($customers as $customer) {
            $result = emailverify_verify_email($customer->email);

            if ($result['success']) {
                $status = $result['data']['status'];
                $stats[$status === 'valid' ? 'valid' : 'invalid']++;

                if (!$dry_run) {
                    update_post_meta($customer->order_id, '_email_verification_status', $result['data']['status']);
                    update_post_meta($customer->order_id, '_email_verification_score', $result['data']['score'] ?? '');
                }
            } else {
                $stats['error']++;
            }

            $progress->tick();

            // Limitación de tasa
            usleep(100000); // Retraso de 100ms
        }

        $progress->finish();

        WP_CLI::success(sprintf(
            'Verificación completa: %d válidos, %d inválidos, %d errores',
            $stats['valid'],
            $stats['invalid'],
            $stats['error']
        ));
    });
}

Uso

# Verificar 100 clientes (por defecto)
wp emailverify verify-customers

# Verificar 500 clientes
wp emailverify verify-customers --batch=500

# Prueba en seco (sin cambios en la base de datos)
wp emailverify verify-customers --dry-run

Prevención de Fraude

Usa la verificación de correo como parte de la detección de fraude.

<?php
/**
 * Marcar pedidos de alto riesgo según la verificación de correo
 */
add_action('woocommerce_checkout_order_processed', 'emailverify_fraud_check', 10, 3);

function emailverify_fraud_check($order_id, $posted_data, $order) {
    $risk_score = 0;
    $risk_reasons = [];

    $email = $order->get_billing_email();
    $result = emailverify_verify_email($email);

    if ($result['success']) {
        $data = $result['data'];

        // Correo inválido = alto riesgo
        if ($data['status'] === 'invalid') {
            $risk_score += 50;
            $risk_reasons[] = 'Dirección de correo inválida';
        }

        // Correo desechable = alto riesgo
        if ($data['result']['disposable'] ?? false) {
            $risk_score += 40;
            $risk_reasons[] = 'Correo desechable detectado';
        }

        // Puntuación baja = riesgo medio
        if (($data['score'] ?? 1) < 0.5) {
            $risk_score += 20;
            $risk_reasons[] = 'Puntuación de correo baja';
        }

        // Correo basado en rol = riesgo leve
        if ($data['result']['role'] ?? false) {
            $risk_score += 10;
            $risk_reasons[] = 'Dirección de correo basada en rol';
        }
    }

    // Guardar evaluación de riesgo
    $order->update_meta_data('_fraud_risk_score', $risk_score);
    $order->update_meta_data('_fraud_risk_reasons', $risk_reasons);

    // Marcar pedidos de alto riesgo para revisión manual
    if ($risk_score >= 50) {
        $order->set_status('on-hold', __('Alto riesgo de fraude - revisión manual requerida', 'your-theme'));

        // Notificar al administrador
        $admin_email = get_option('admin_email');
        wp_mail(
            $admin_email,
            sprintf(__('Pedido de Alto Riesgo #%s Requiere Revisión', 'your-theme'), $order_id),
            sprintf(
                __("El pedido #%s ha sido marcado como de alto riesgo.\n\nPuntuación de Riesgo: %d\nRazones:\n- %s\n\nPor favor, revisa el pedido.", 'your-theme'),
                $order_id,
                $risk_score,
                implode("\n- ", $risk_reasons)
            )
        );
    }

    $order->save();
}

Mejores Prácticas

1. Degradación Elegante

// Siempre permitir checkout si la API falla
$result = emailverify_verify_email($email);

if (!$result['success']) {
    error_log('Error de API de EmailVerify: ' . ($result['error'] ?? 'Desconocido'));
    return; // No bloquear el checkout
}

2. Resultados en Caché

// Cachear resultados de verificación para reducir llamadas a la API
$cache_key = 'bv_email_' . md5($email);
$cached = get_transient($cache_key);

if ($cached !== false) {
    return $cached;
}

// ... hacer llamada a la API ...

set_transient($cache_key, $result, DAY_IN_SECONDS);

3. Mensajes de Error Claros

// Proporcionar mensajes de error útiles y no técnicos
$messages = [
    'invalid' => __('Esta dirección de correo parece ser inválida. Por favor, verifica e inténtalo de nuevo.', 'your-theme'),
    'disposable' => __('Las direcciones de correo temporales no se pueden usar para pedidos. Por favor, usa tu correo habitual.', 'your-theme'),
];

Recursos Relacionados

On this page