如何让WooCommerce新增账单字段数据纳入官方账单结构?
WooCommerce自定义账单字段纳入官方地址结构解决方案
我在WooCommerce的「我的账户」账单地址页面添加了两个仅对administrator角色可见的字段:
- 标签为「我有附加费」的复选框(需在邮件中显示)
- 标签为「NIF/CIF」的公司税号输入字段
目前这两个字段可在账户编辑页(my-account/edit-address/billing/)和结账页编辑,但数据仅在邮件的地址区域外显示,且无法在生成的发票中展示。以下是将其纳入WooCommerce官方账单地址结构的安全实现方案:
一、调整「我有附加费」复选框字段
将字段改为WooCommerce标准账单字段,让系统自动将其纳入地址渲染流程(含邮件、发票):
// 添加管理员可见的复选框到账单字段 add_filter( 'woocommerce_billing_fields', 'custom_checkbox_below_billing_company' ); function custom_checkbox_below_billing_company( $fields ) { if ( user_can( wp_get_current_user(), 'administrator' ) ) { $fields['billing_surcharge'] = array( 'type' => 'checkbox', 'label' => __( '我有附加费', 'woocommerce' ), 'class' => array('form-row-wide'), 'priority' => 30, 'required' => false, 'clear' => true, 'default' => 0, 'show_in_email' => true, 'show_in_address' => true, ); } return $fields; } // 保存复选框值到用户meta add_action( 'woocommerce_customer_save_address', 'save_billing_surcharge_checkbox', 10, 2 ); function save_billing_surcharge_checkbox( $customer_id, $load_address ) { $value = isset( $_POST['billing_surcharge'] ) ? sanitize_text_field( $_POST['billing_surcharge'] ) : '0'; update_user_meta( $customer_id, 'billing_surcharge', $value ); } // 同步字段值到订单meta(供发票/订单详情读取) add_action( 'woocommerce_checkout_create_order', 'sync_billing_surcharge_to_order', 10, 2 ); function sync_billing_surcharge_to_order( $order, $data ) { if ( user_can( $order->get_user_id(), 'administrator' ) ) { $surcharge_value = get_user_meta( $order->get_user_id(), 'billing_surcharge', true ); $order->update_meta_data( '_billing_surcharge', $surcharge_value ); } } // 让字段显示在邮件的客户详情地址区域 add_filter( 'woocommerce_email_customer_details_fields', 'include_surcharge_in_email_address', 10, 3 ); function include_surcharge_in_email_address( $fields, $sent_to_admin, $order ) { if ( user_can( $order->get_user_id(), 'administrator' ) ) { $surcharge_value = $order->get_meta( '_billing_surcharge' ) ?: get_user_meta( $order->get_user_id(), 'billing_surcharge', true ); $fields['billing_surcharge'] = array( 'label' => __( '我有附加费', 'woocommerce' ), 'value' => $surcharge_value ? '是' : '否', ); } return $fields; } // 让字段显示在后台订单页的账单地址区域 add_filter( 'woocommerce_admin_billing_fields', 'include_surcharge_in_admin_address' ); function include_surcharge_in_admin_address( $fields ) { if ( user_can( get_current_user_id(), 'administrator' ) ) { $fields['billing_surcharge'] = array( 'label' => __( '我有附加费', 'woocommerce' ), 'show' => true, ); } return $fields; }
修改说明:
- 字段名改为
billing_surcharge,遵循WooCommerce账单字段命名规范 - 添加
show_in_email/show_in_address标记,让系统识别为地址结构的一部分 - 新增订单meta同步逻辑,确保发票、订单详情能读取到字段值
- 保留管理员权限控制,避免普通用户访问
二、调整NIF/CIF税号字段
同样改为标准账单字段,替换原有自定义meta逻辑:
// 添加管理员可见的NIF/CIF字段到账单字段 add_filter( 'woocommerce_billing_fields', 'add_custom_billing_nif_field' ); function add_custom_billing_nif_field( $fields ) { $user = wp_get_current_user(); if ( ! empty( $user ) && in_array( 'administrator', (array) $user->roles ) ) { $fields['billing_nif'] = array( 'label' => __( 'NIF/CIF', 'woocommerce' ), 'placeholder' => __( 'B12345678', 'woocommerce' ), 'required' => true, 'clear' => false, 'type' => 'text', 'default' => get_user_meta( $user->ID, 'billing_nif', true ), 'class' => array('form-row-wide'), 'priority' => 25, 'show_in_email' => true, 'show_in_address' => true, ); } return $fields; } // 保存字段值到用户meta add_action( 'woocommerce_customer_save_address', 'save_billing_nif_field', 10, 2 ); function save_billing_nif_field( $customer_id, $load_address ) { if ( isset( $_POST['billing_nif'] ) ) { update_user_meta( $customer_id, 'billing_nif', wc_clean( $_POST['billing_nif'] ) ); } } // 同步字段值到订单meta add_action( 'woocommerce_checkout_create_order', 'sync_billing_nif_to_order', 10, 2 ); function sync_billing_nif_to_order( $order, $data ) { $user_id = $order->get_user_id(); if ( $user_id && user_can( $user_id, 'administrator' ) ) { $nif_value = get_user_meta( $user_id, 'billing_nif', true ); if ( $nif_value ) { $order->update_meta_data( '_billing_nif', $nif_value ); } } } // 在订单详情页、感谢页显示字段 add_action( 'woocommerce_order_details_after_order_table', 'show_billing_nif_in_order_details', 20 ); add_action( 'woocommerce_thankyou', 'show_billing_nif_in_order_details' ); function show_billing_nif_in_order_details( $order ) { if ( is_a( $order, 'WC_Order' ) ) { $nif_value = $order->get_meta( '_billing_nif' ) ?: get_user_meta( $order->get_user_id(), 'billing_nif', true ); } else { $user_id = get_post_meta( $order, '_customer_user', true ); $nif_value = get_post_meta( $order, '_billing_nif', true ) ?: get_user_meta( $user_id, 'billing_nif', true ); } if ( $nif_value ) { echo '<p><strong>' . __( 'NIF/CIF:', 'woocommerce' ) . '</strong> ' . esc_html( $nif_value ) . '</p>'; } } // 在后台订单页的账单地址区域显示字段 add_filter( 'woocommerce_admin_billing_fields', 'include_nif_in_admin_billing' ); function include_nif_in_admin_billing( $fields ) { if ( user_can( get_current_user_id(), 'administrator' ) ) { $fields['billing_nif'] = array( 'label' => __( 'NIF/CIF', 'woocommerce' ), 'show' => true, ); } return $fields; }
修改说明:
- 替换原有
woocommerce_checkout_fields钩子为woocommerce_billing_fields,确保字段在账户地址编辑页和结账页都能显示 - 字段名改为
billing_nif,遵循官方命名规范 - 移除自定义邮件显示逻辑,
show_in_email标记会让系统自动将字段纳入邮件地址区域 - 用
wc_clean()、esc_html()确保输入输出安全,防止XSS攻击
关键注意事项
- 命名规范:自定义账单字段必须以
billing_开头,WooCommerce才会将其识别为官方地址结构的一部分,自动支持邮件、发票(含官方PDF发票插件)渲染 - 数据同步:必须将用户meta同步到订单meta,因为发票、订单详情优先读取订单层面的元数据
- 权限控制:全程保留管理员角色判断,避免普通用户看到或修改这些字段
- 安全处理:所有用户输入必须经过清洗,输出必须经过转义,确保站点安全
内容的提问来源于stack exchange,提问作者gemita
相关产品推荐
相关产品推荐

