EmailVerify LogoEmailVerify

WooCommerce

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

WooCommerce 스토어에 이메일 검증을 추가하여 배송 실패를 줄이고, 사기를 방지하고, 고객 커뮤니케이션을 개선하세요.

통합 방법

방법적합 대상복잡도
플러그인빠른 설정낮음
결제 훅실시간 검증중간
주문 처리백그라운드 검증중간
REST API커스텀 솔루션높음

방법 1: WordPress 플러그인

EmailVerify WordPress 플러그인을 이미 설정했다면 WooCommerce 통합이 자동으로 됩니다.

WooCommerce 지원 활성화

  1. 설정EmailVerify로 이동
  2. Enable WooCommerce Integration 체크
  3. 옵션 구성:
    • ✓ 결제 시 검증
    • ✓ 일회용 이메일 차단
    • ✓ 주문에서 검증 상태 표시

방법 2: 결제 검증

WooCommerce 결제 과정에 이메일 검증을 추가합니다.

서버 측 검증

<?php
// functions.php or custom plugin

/**
 * Verify email at WooCommerce checkout
 */
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']) {
        // API error - allow checkout to proceed
        return;
    }

    $data = $result['data'];

    // Block invalid emails
    if ($data['status'] === 'invalid') {
        wc_add_notice(
            __('Please enter a valid email address to complete your order.', 'your-theme'),
            'error'
        );
    }

    // Block disposable emails (optional)
    if (get_option('emailverify_block_disposable', true)) {
        if ($data['result']['disposable'] ?? false) {
            wc_add_notice(
                __('Temporary email addresses are not accepted. Please use a permanent email.', 'your-theme'),
                'error'
            );
        }
    }
}

/**
 * EmailVerify API call helper
 */
function emailverify_verify_email($email) {
    $api_key = get_option('emailverify_api_key');

    // Check cache first
    $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];

    // Cache for 24 hours
    set_transient($cache_key, $result, DAY_IN_SECONDS);

    return $result;
}

실시간 AJAX 검증

고객이 이메일을 입력할 때 즉각적인 피드백을 추가합니다.

<?php
// Enqueue 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'),
    ]);
}

// AJAX handler
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' => 'Email is required']);
    }

    $result = emailverify_verify_email($email);

    if ($result['success']) {
        wp_send_json_success($result['data']);
    } else {
        wp_send_json_error(['message' => 'Verification failed']);
    }
}
// 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> Verifying...').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> Email verified')
                            .addClass('valid')
                            .removeClass('invalid');
                    } else if (data.status === 'invalid') {
                        $status
                            .html('<span class="dashicons dashicons-no"></span> Please enter a valid email')
                            .addClass('invalid')
                            .removeClass('valid');
                    } else if (data.result && data.result.disposable) {
                        $status
                            .html('<span class="dashicons dashicons-warning"></span> Please use a permanent email')
                            .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); }
}

방법 3: 주문 처리

주문 생성 후 이메일을 검증하고 결과를 저장합니다.

검증 데이터 저장

<?php
/**
 * Verify email after order is created
 */
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'];

        // Store verification data as order meta
        $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();

        // Add order note
        if ($data['status'] === 'invalid') {
            $order->add_order_note(
                sprintf(
                    __('Warning: Customer email %s failed verification (Status: %s)', 'your-theme'),
                    $email,
                    $data['status']
                )
            );
        }
    }
}

/**
 * Display verification status in order details
 */
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>' . __('Email Verification', 'your-theme') . '</h3>';
    echo '<p><strong>' . __('Status:', 'your-theme') . '</strong> ';
    echo '<mark class="order-status ' . esc_attr($status_class) . '">' . esc_html(ucfirst($status)) . '</mark></p>';

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

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

    echo '</div>';
}

주문 목록 컬럼 추가

<?php
/**
 * Add email status column to orders list
 */
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'] = __('Email', '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="Not verified"></span>';
        return;
    }

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

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

방법 4: REST API 통합

헤드리스 WooCommerce 또는 커스텀 결제 플로우용.

커스텀 REST 엔드포인트

<?php
/**
 * Register REST API endpoint for email verification
 */
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');

    // Rate limiting
    $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',
            'Too many verification requests',
            ['status' => 429]
        );
    }

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

    // Verify email
    $result = emailverify_verify_email($email);

    if (!$result['success']) {
        return new WP_Error(
            'verification_failed',
            'Email verification failed',
            ['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);
}

프론트엔드 사용

// Headless checkout verification
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('Too many requests. Please wait.');
        }
        throw new Error('Verification failed');
    }

    return response.json();
}

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

    if (!result.valid) {
        showError('Please enter a valid email address');
    } else if (result.disposable) {
        showError('Please use a permanent email address');
    } else {
        proceedToPayment();
    }
} catch (error) {
    // Allow checkout on error
    proceedToPayment();
}

대량 고객 검증

데이터베이스의 기존 고객을 검증합니다.

WP-CLI 명령

<?php
/**
 * WP-CLI command for bulk customer verification
 */
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;

        // Get customers without verification status
        $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('All customers are verified!');
            return;
        }

        WP_CLI::log(sprintf('Found %d customers to verify', count($customers)));

        $progress = \WP_CLI\Utils\make_progress_bar('Verifying', 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();

            // Rate limiting
            usleep(100000); // 100ms delay
        }

        $progress->finish();

        WP_CLI::success(sprintf(
            'Verification complete: %d valid, %d invalid, %d errors',
            $stats['valid'],
            $stats['invalid'],
            $stats['error']
        ));
    });
}

사용법

# Verify 100 customers (default)
wp emailverify verify-customers

# Verify 500 customers
wp emailverify verify-customers --batch=500

# Dry run (no database changes)
wp emailverify verify-customers --dry-run

사기 방지

이메일 검증을 사기 감지의 일부로 사용합니다.

<?php
/**
 * Flag high-risk orders based on email verification
 */
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'];

        // Invalid email = high risk
        if ($data['status'] === 'invalid') {
            $risk_score += 50;
            $risk_reasons[] = 'Invalid email address';
        }

        // Disposable email = high risk
        if ($data['result']['disposable'] ?? false) {
            $risk_score += 40;
            $risk_reasons[] = 'Disposable email detected';
        }

        // Low score = medium risk
        if (($data['score'] ?? 1) < 0.5) {
            $risk_score += 20;
            $risk_reasons[] = 'Low email score';
        }

        // Role-based email = slight risk
        if ($data['result']['role'] ?? false) {
            $risk_score += 10;
            $risk_reasons[] = 'Role-based email address';
        }
    }

    // Store risk assessment
    $order->update_meta_data('_fraud_risk_score', $risk_score);
    $order->update_meta_data('_fraud_risk_reasons', $risk_reasons);

    // Flag high-risk orders for manual review
    if ($risk_score >= 50) {
        $order->set_status('on-hold', __('High fraud risk - manual review required', 'your-theme'));

        // Notify admin
        $admin_email = get_option('admin_email');
        wp_mail(
            $admin_email,
            sprintf(__('High-Risk Order #%s Needs Review', 'your-theme'), $order_id),
            sprintf(
                __("Order #%s has been flagged as high risk.\n\nRisk Score: %d\nReasons:\n- %s\n\nPlease review the order.", 'your-theme'),
                $order_id,
                $risk_score,
                implode("\n- ", $risk_reasons)
            )
        );
    }

    $order->save();
}

모범 사례

1. 그레이스풀 디그레이데이션

// Always allow checkout if API fails
$result = emailverify_verify_email($email);

if (!$result['success']) {
    error_log('EmailVerify API error: ' . ($result['error'] ?? 'Unknown'));
    return; // Don't block checkout
}

2. 결과 캐싱

// Cache verification results to reduce API calls
$cache_key = 'bv_email_' . md5($email);
$cached = get_transient($cache_key);

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

// ... make API call ...

set_transient($cache_key, $result, DAY_IN_SECONDS);

3. 명확한 오류 메시지

// Provide helpful, non-technical error messages
$messages = [
    'invalid' => __('This email address appears to be invalid. Please check and try again.', 'your-theme'),
    'disposable' => __('Temporary email addresses cannot be used for orders. Please use your regular email.', 'your-theme'),
];

관련 리소스

On this page