You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为WooCommerce访客购物者分配自定义Customer Code

问题描述

我正在开发一个电商项目,需要为所有购买商品的顾客(包括访客)分配基于姓名与序号的Customer Code,供会计软件使用。现有代码仅对注册用户生效,无法为访客生成代码。希望将该信息存储到wp_wc_customer_lookup表(该表记录所有顾客,无论是否注册),同时在WooCommerce客户标签页显示该代码。

现有代码

用户资料字段与注册用户代码生成

add_action( 'show_user_profile', 'ipx_user_profile_fields' );
add_action( 'edit_user_profile', 'ipx_user_profile_fields' );

function ipx_user_profile_fields( $user ) { ?>
    <h3><?php _e("IPX", "blank"); ?></h3>

    <table class="form-table">
    <tr>
        <th><label for="ipx_customer_code"><?php _e("Customer Code"); ?></label></th>
        <td>
            <input type="text" name="ipx_customer_code" id="ipx_customer_code" value="<?php echo esc_attr( get_the_author_meta( 'ipx_customer_code', $user->ID ) ); ?>" class="regular-text" /><br />
            <span class="description"><?php _e("This field should contain only the IPX Customer Code."); ?></span>
        </td>
    </tr>
    </table>
<?php }

add_action( 'personal_options_update', 'save_ipx_user_profile_fields' );
add_action( 'edit_user_profile_update', 'save_ipx_user_profile_fields' );

function save_ipx_user_profile_fields( $user_id ) {
    if ( !current_user_can( 'edit_user', $user_id ) ) { 
        return false; 
    }
    update_user_meta( $user_id, 'ipx_customer_code', $_POST['ipx_customer_code'] );
}

/**
 * Generate customer code based on user's first name, last name and a sequential number
 */
function generate_customer_code($user_id) {
    $user = get_userdata($user_id);
    $first_name = $user->first_name;
    $last_name = $user->last_name;

    // Get the current sequential number for the customer code
    $sequential_number = get_user_meta($user_id, 'sequential_customer_code', true);
    if (!$sequential_number) {
        $sequential_number = 0;
    }

    // Loop until a unique customer code is generated
    do {
        $sequential_number++;
        // Generate the customer code
        $customer_code = strtoupper(substr($first_name, 0, 4) . substr($last_name, 0, 4) . sprintf('%02d', $sequential_number));
        // Check if the customer code already exists
        $user_query = new WP_User_Query(array(
            'meta_key' => 'ipx_customer_code',
            'meta_value' => $customer_code
        ));
    } while (!empty($user_query->results));

    // Save the customer code and sequential number as separate custom fields
    update_user_meta($user_id, 'ipx_customer_code', $customer_code);
    update_user_meta($user_id, 'sequential_customer_code', $sequential_number);
}
add_action('user_register', 'generate_customer_code');

订单关联客户代码

add_action( 'woocommerce_checkout_update_order_meta', 'include_customer_code_on_order', 10, 2 );

function include_customer_code_on_order( $order_id, $posted_data ) {
    $order = wc_get_order( $order_id );
    $user_id = $order->get_user_id();

    if ( $user_id ) {
        $customer_code = get_user_meta( $user_id, 'ipx_customer_code', true );
        if ( $customer_code ) {
            $order->update_meta_data( 'ipx_customer_code', $customer_code );
            $order->save();
        }
    }
}

解决方案

1. 为wp_wc_customer_lookup表新增客户代码字段

首先需要在WooCommerce的统一顾客表中添加存储字段:

// 初始化时检查并新增字段
add_action('init', 'ipx_add_customer_code_column');
function ipx_add_customer_code_column() {
    global $wpdb;
    $table_name = $wpdb->prefix . 'wc_customer_lookup';
    $column_exists = $wpdb->get_var("SHOW COLUMNS FROM $table_name LIKE 'ipx_customer_code'");
    
    if (!$column_exists) {
        $wpdb->query("ALTER TABLE $table_name ADD COLUMN ipx_customer_code VARCHAR(20) NULL DEFAULT ''");
    }
}

2. 通用唯一客户代码生成逻辑

重构生成逻辑,同时支持注册用户和访客:

// 注册用户注册时生成代码
add_action('user_register', 'ipx_generate_customer_code_for_user');
function ipx_generate_customer_code_for_user($user_id) {
    $user = get_userdata($user_id);
    $first_name = $user->first_name;
    $last_name = $user->last_name;
    
    $customer_code = ipx_generate_unique_customer_code($first_name, $last_name);
    
    // 同步更新用户meta和customer_lookup表
    update_user_meta($user_id, 'ipx_customer_code', $customer_code);
    ipx_update_customer_lookup_code($user_id, $customer_code);
}

// 访客下单时生成代码
add_action('woocommerce_checkout_create_order', 'ipx_generate_customer_code_for_guest', 20, 2);
function ipx_generate_customer_code_for_guest($order, $data) {
    if (!$order->get_user_id()) { // 判断为访客订单
        $first_name = $order->get_billing_first_name();
        $last_name = $order->get_billing_last_name();
        
        $customer_code = ipx_generate_unique_customer_code($first_name, $last_name);
        
        // 更新customer_lookup表(WooCommerce会自动为访客创建该表记录)
        ipx_update_customer_lookup_code($order->get_customer_id(), $customer_code);
        
        // 将代码存入订单元数据
        $order->update_meta_data('ipx_customer_code', $customer_code);
    }
}

// 生成唯一客户代码的核心函数
function ipx_generate_unique_customer_code($first_name, $last_name) {
    global $wpdb;
    $table_name = $wpdb->prefix . 'wc_customer_lookup';
    
    // 提取姓名前缀(最多4位)
    $first_prefix = strtoupper(substr($first_name ?: '', 0, 4));
    $last_prefix = strtoupper(substr($last_name ?: '', 0, 4));
    
    $sequential_number = 0;
    do {
        $sequential_number++;
        $customer_code = $first_prefix . $last_prefix . sprintf('%02d', $sequential_number);
        
        // 检查customer_lookup表中是否已存在该代码
        $exists = $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM $table_name WHERE ipx_customer_code = %s",
            $customer_code
        ));
    } while ($exists > 0);
    
    return $customer_code;
}

// 更新customer_lookup表的客户代码
function ipx_update_customer_lookup_code($customer_id, $customer_code) {
    global $wpdb;
    $table_name = $wpdb->prefix . 'wc_customer_lookup';
    
    $wpdb->update(
        $table_name,
        array('ipx_customer_code' => $customer_code),
        array('customer_id' => $customer_id),
        array('%s'),
        array('%d')
    );
}

3. 在WooCommerce客户列表显示客户代码

添加自定义列并填充数据:

// 为客户列表添加自定义列
add_filter('manage_edit-shop_customer_columns', 'ipx_add_customer_code_column_to_list');
function ipx_add_customer_code_column_to_list($columns) {
    $columns['ipx_customer_code'] = __('Customer Code', 'woocommerce');
    return $columns;
}

// 填充客户列表的自定义列数据
add_action('manage_shop_customer_posts_custom_column', 'ipx_populate_customer_code_column', 10, 2);
function ipx_populate_customer_code_column($column, $customer_id) {
    if ($column === 'ipx_customer_code') {
        global $wpdb;
        $table_name = $wpdb->prefix . 'wc_customer_lookup';
        
        // 从customer_lookup表获取代码
        $customer_code = $wpdb->get_var($wpdb->prepare(
            "SELECT ipx_customer_code FROM $table_name WHERE customer_id = %d",
            $customer_id
        ));
        
        // 兼容旧数据:如果注册用户没有在lookup表找到,从用户meta读取
        if (!$customer_code && get_userdata($customer_id)) {
            $customer_code = get_user_meta($customer_id, 'ipx_customer_code', true);
        }
        
        echo esc_html($customer_code ?: '-');
    }
}

4. 更新订单关联代码逻辑

替换原有函数,同时支持注册用户和访客:

add_action('woocommerce_checkout_update_order_meta', 'ipx_include_customer_code_on_order', 10, 2);
function ipx_include_customer_code_on_order($order_id, $posted_data) {
    $order = wc_get_order($order_id);
    $user_id = $order->get_user_id();
    $customer_id = $order->get_customer_id();
    
    $customer_code = '';
    
    if ($user_id) {
        // 注册用户优先从customer_lookup表获取
        global $wpdb;
        $table_name = $wpdb->prefix . 'wc_customer_lookup';
        $customer_code = $wpdb->get_var($wpdb->prepare(
            "SELECT ipx_customer_code FROM $table_name WHERE user_id = %d",
            $user_id
        ));
        
        // 兼容旧数据
        if (!$customer_code) {
            $customer_code = get_user_meta($user_id, 'ipx_customer_code', true);
        }
    } else {
        // 访客直接从订单meta获取(生成时已存入)
        $customer_code = $order->get_meta('ipx_customer_code');
    }
    
    if ($customer_code) {
        $order->update_meta_data('ipx_customer_code', $customer_code);
        $order->save();
    }
}

5. 保留注册用户个人资料编辑功能

修改原有资料字段函数,适配新的存储来源:

add_action('show_user_profile', 'ipx_user_profile_fields');
add_action('edit_user_profile', 'ipx_user_profile_fields');

function ipx_user_profile_fields($user) {
    global $wpdb;
    $table_name = $wpdb->prefix . 'wc_customer_lookup';
    
    // 优先从customer_lookup表获取代码
    $customer_code = $wpdb->get_var($wpdb->prepare(
        "SELECT ipx_customer_code FROM $table_name WHERE user_id = %d",
        $user->ID
    ));
    
    // 兼容旧数据
    if (!$customer_code) {
        $customer_code = get_user_meta($user->ID, 'ipx_customer_code', true);
    }
    ?>
    <h3><?php _e("IPX", "blank"); ?></h3>

    <table class="form-table">
    <tr>
        <th><label for="ipx_customer_code"><?php _e("Customer Code"); ?></label></th>
        <td>
            <input type="text" name="ipx_customer_code" id="ipx_customer_code" value="<?php echo esc_attr($customer_code); ?>" class="regular-text" /><br />
            <span class="description"><?php _e("This field should contain only the IPX Customer Code."); ?></span>
        </td>
    </tr>
    </table>
    <?php
}

add_action('personal_options_update', 'save_ipx_user_profile_fields');
add_action('edit_user_profile_update', 'save_ipx_user_profile_fields');

function save_ipx_user_profile_fields($user_id) {
    if (!current_user_can('edit_user', $user_id)) { 
        return false; 
    }
    
    $customer_code = sanitize_text_field($_POST['ipx_customer_code']);
    
    // 同步更新用户meta和customer_lookup表
    update_user_meta($user_id, 'ipx_customer_code', $customer_code);
    ipx_update_customer_lookup_code($user_id, $customer_code);
}

内容的提问来源于stack exchange,提问作者AbandonedHope

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 20:37:02