WordPress单产品页自定义按钮控制COD支付网关显示问题排查
问题分析与代码修正
原代码的核心问题
结账页COD禁用逻辑失效:
原代码通过$_POST['custom_field_name']判断是否隐藏COD,但结账页面是独立的HTTP请求,添加购物车时的POST数据不会保留到结账环节,导致该判断永远不成立。自定义字段验证逻辑矛盾:
validate_custom_field函数中的条件isset($_POST['custom_field_name']) && !empty($_POST['custom_field_name']) && empty(trim($_POST['custom_field_name']))存在逻辑冲突——!empty($_POST['custom_field_name'])和empty(trim($_POST['custom_field_name']))无法同时满足,导致字段为空时不会触发错误提示。过时钩子兼容性问题:
woocommerce_add_order_item_meta钩子已被WooCommerce弃用,继续使用可能导致订单项元数据无法正确保存。后台订单显示参数错误:
woocommerce_admin_order_data_after_order_details钩子的参数为$order,但原函数错误地接收$item_id, $item, $product,导致无法读取订单项的自定义元数据。
修正后的完整代码
// 显示自定义按钮和字段 function display_customize_button_and_field() { echo '<p id="customize-instruction" style="margin-bottom: 5px;">' . __('If you want to customize the product, click here:', 'woocommerce') . '</p>'; echo '<button id="customize-button" type="button" style="margin-bottom: 10px;">' . __('Customize', 'woocommerce') . '</button>'; echo '<div id="custom-field-container" style="display:none;">'; woocommerce_form_field( 'custom_field_name', array( 'type' => 'textarea', 'class' => array('custom-field-class form-row-wide'), 'label' => __('Message', 'woocommerce'), 'placeholder' => __('Write Details here', 'woocommerce'), ), '' ); echo '</div>'; } add_action( 'woocommerce_before_add_to_cart_button', 'display_customize_button_and_field' ); // 验证自定义字段(修正逻辑) function validate_custom_field($passed, $product_id, $quantity) { // 当用户点击自定义并提交空内容时触发验证 if ( isset($_POST['custom_field_name']) && empty(trim($_POST['custom_field_name'])) ) { wc_add_notice( __('Please enter a value for the custom field.'), 'error' ); return false; } return $passed; } add_filter('woocommerce_add_to_cart_validation', 'validate_custom_field', 10, 3); // 保存自定义字段到购物车项 function save_custom_field($cart_item_data, $product_id) { if (isset($_POST['custom_field_name']) && !empty(trim($_POST['custom_field_name']))) { $cart_item_data['custom_field_name'] = sanitize_textarea_field($_POST['custom_field_name']); // 添加唯一键确保购物车中相同商品的自定义项被视为独立条目 $cart_item_data['unique_key'] = md5(microtime().rand()); } return $cart_item_data; } add_filter('woocommerce_add_cart_item_data', 'save_custom_field', 10, 2); // 在购物车页面显示自定义字段 function display_custom_field_in_cart($item_data, $cart_item) { if (isset($cart_item['custom_field_name'])) { $item_data[] = array( 'name' => __('Custom Field'), 'value' => $cart_item['custom_field_name'] ); } return $item_data; } add_filter('woocommerce_get_item_data', 'display_custom_field_in_cart', 10, 2); // 保存自定义字段到订单项(使用新钩子) function add_custom_field_to_order_meta($item, $cart_item_key, $values, $order) { if (isset($values['custom_field_name'])) { $item->add_meta_data(__('Custom Field'), $values['custom_field_name']); } } add_action('woocommerce_checkout_create_order_line_item', 'add_custom_field_to_order_meta', 10, 4); // 在后台订单页面显示自定义字段(修正参数) function display_custom_field_in_admin_order($order) { echo '<h3>' . __('Customized Products', 'woocommerce') . '</h3>'; foreach ($order->get_items() as $item) { if ($custom_field_value = $item->get_meta(__('Custom Field'))) { echo '<p><strong>' . $item->get_name() . ':</strong> ' . $custom_field_value . '</p>'; } } } add_action('woocommerce_admin_order_data_after_order_details', 'display_custom_field_in_admin_order', 10, 1); // 加载自定义脚本 function enqueue_custom_script() { if ( is_product() ) { wp_enqueue_script( 'customize-product', get_template_directory_uri() . '/js/customize-product.js', array('jquery'), null, true ); } } add_action( 'wp_enqueue_scripts', 'enqueue_custom_script' ); // 结账页禁用COD(修正判断逻辑) function disable_cod_for_customized_product_on_checkout($available_gateways) { // 仅在结账页执行 if ( !is_checkout() || is_wc_endpoint_url() ) return $available_gateways; // 遍历购物车项,检查是否有自定义字段 foreach (WC()->cart->get_cart() as $cart_item) { if (isset($cart_item['custom_field_name']) && !empty($cart_item['custom_field_name'])) { // 存在自定义商品,隐藏COD unset($available_gateways['cod']); break; // 只要有一个自定义商品就停止遍历 } } return $available_gateways; } add_filter('woocommerce_available_payment_gateways', 'disable_cod_for_customized_product_on_checkout');
关键修正说明
- COD禁用逻辑:改为遍历当前购物车的所有商品,检查是否存在
custom_field_name字段,只要有一个自定义商品就隐藏COD。 - 字段验证:简化条件,当用户提交空的自定义字段时触发错误提示。
- 订单项元数据保存:使用
woocommerce_checkout_create_order_line_item钩子替代过时的woocommerce_add_order_item_meta,确保元数据正确保存。 - 后台订单显示:修正钩子参数,遍历订单的所有订单项,显示每个商品的自定义内容。
- 购物车唯一键:添加
unique_key确保相同商品的自定义版本在购物车中被视为独立条目,避免覆盖。
内容的提问来源于stack exchange,提问作者Muhammad zubair Ahmad
相关产品推荐
相关产品推荐

