简体   繁体   English

在 WooCommerce 中将结帐自定义字段数据添加到运输包裹中进行计算

[英]Add checkout custom fields data to shipping packages for calculations in WooCommerce

I'm creating a plugin that will calculate custom shipping variants with API. I have a jQuery script that calculates postal and fias codes based on an entered address.我正在创建一个插件,它将使用 API 计算自定义运输变体。我有一个 jQuery 脚本,它根据输入的地址计算邮政和 fias 代码。

$("#billing_address_1").suggestions({
        serviceUrl: "https://suggestions.dadata.ru/suggestions/api/4_1/rs",
        token: php_vars.dadata_suggest_token,
        type: "ADDRESS",
        count: 5,
        onSelect: function (suggestion) {
            $("#billing_city").val(suggestion.data.city);
            $("#billing_state").val(suggestion.data.region);
            $("#billing_postcode").val(suggestion.data.postal_code);
            if (suggestion.data.settlement_fias_id)
                $("#billing_fias_code").val(suggestion.data.settlement_fias_id);
            else if (suggestion.data.city_fias_id)
                $("#billing_fias_code").val(suggestion.data.city_fias_id);
            else
                $("#billing_fias_code").val('');
        }
    }); 

To store the fias code, I created custom field.为了存储 fias 代码,我创建了自定义字段。

add_filter( 'woocommerce_checkout_fields' , array( $this, 'custom_checkout_fields' ));
add_action( 'woocommerce_checkout_update_order_meta', array( $this, 'shipping_apartment_update_order_meta') ); 
function custom_checkout_fields( $fields ) {
        $fields['shipping']['shipping_fias_code'] = array(
            'type' => 'text',
            'label' => __('FIAS', 'woocommerce'),
            'placeholder' => _x('Код', 'placeholder', 'woocommerce'),
            'required' => false,
            'class' => array('form-row-wide'),
            'clear' => true
        );
        $fields['billing']['billing_fias_code'] = array(
            'type' => 'text',
            'label' => __('FIAS', 'woocommerce'),
            'placeholder' => _x('Код', 'placeholder', 'woocommerce'),
            'required' => false,
            'class' => array('form-row-wide'),
            'clear' => true
        );
        
        return $fields;
    }

    function shipping_apartment_update_order_meta( $order_id ) {
        if ( ! empty( $_POST['shipping_fias_code'] ) ) {
            update_post_meta( $order_id, 'shipping_fias_code', sanitize_text_field( $_POST['shipping_fias_code'] ) );
        }
        if ( ! empty( $_POST['billing_fias_code'] ) ) {
            update_post_meta( $order_id, 'billing_fias_code', sanitize_text_field( $_POST['billing_fias_code'] ) );
        }
    }

The calculate_shipping() method in WC_Shipping_Method in woocommerce calculates shipping options using the $ package variable, which has an 'destination' array field with information about the shipping address. woocommerce 中 WC_Shipping_Method 中的 calculate_shipping() 方法使用 $ package 变量计算运输选项,该变量有一个“目的地”数组字段,其中包含有关送货地址的信息。 The postal code is passed into this array by default.默认情况下,邮政编码会传递到此数组中。 But I also need to pass my custom field inside $package.但我还需要在 $package 中传递我的自定义字段。

As I understand it, the field that I created will save the information added there via the jQuery script, only after the form is posted.据我了解,我创建的字段将保存通过 jQuery 脚本添加到那里的信息,只有在发布表单后。 But other fields included in $package['destination'] are saved immediately after adding information to them.但是 $package['destination'] 中包含的其他字段在向它们添加信息后会立即保存。

How do I add data from a custom field in the checkout form to the $package['destination'] variable?如何将结帐表单中自定义字段的数据添加到$package['destination']变量?

I can't test (or modify) your jQuery code, so you will have to handle it yourself, maybe making some changes to it.我无法测试(或修改)您的 jQuery 代码,因此您必须自己处理它,也许要对其进行一些更改。 I have revisited completely all your code (except your jQuery code) and everything works as you expect.我已经完全重新访问了您的所有代码(除了您的 jQuery 代码)并且一切都如您所愿。

So $package['destination'] will have an additional entry for 'fias_code' .所以$package['destination']将有一个额外的'fias_code'条目。

The commented code:评论的代码:

// Add billing and shipping fields
add_filter( 'woocommerce_billing_fields' , 'custom_billing_fields' );
add_filter( 'woocommerce_shipping_fields' , 'custom_shipping_fields' );

function custom_shipping_fields( $fields ) {
    $fields['shipping_fias_code'] = array(
        'type' => 'text',
        'label' => __('FIAS', 'woocommerce'),
        'placeholder' => _x('Код', 'placeholder', 'woocommerce'),
        'required' => false,
        'class' => array('form-row-wide'),
        'clear' => true
    );

    return $fields;
}

function custom_billing_fields( $fields ) {
    $fields['billing_fias_code'] = array(
        'type' => 'text',
        'label' => __('FIAS', 'woocommerce'),
        'placeholder' => _x('Код', 'placeholder', 'woocommerce'),
        'required' => false,
        'class' => array('form-row-wide'),
        'clear' => true
    );
    return $fields;
}

// Ajax sender
add_action( 'wp_footer', 'checkout_send_fias_code_via_ajax_js' );
function checkout_send_fias_code_via_ajax_js() {
    if ( is_checkout() && ! is_wc_endpoint_url() ) :
    ?><script type="text/javascript">
    jQuery( function($){
        if (typeof wc_checkout_params === 'undefined')
            return false;

        // Function that send the Ajax request
        function sendAjaxRequest( value, fieldset = 'billing' ) {
            $.ajax({
                type: 'POST',
                url: wc_checkout_params.ajax_url,
                data: {
                    'action': 'fias_code',
                    'fias_code': value,
                    'fieldset' : fieldset
                },
                success: function (result) {
                    $(document.body).trigger('update_checkout'); // Update checkout processes
                    console.log( result ); // For testing (output data sent)
                }
            });
        }

        // Billing fias code change & input events
        $(document.body).on( 'change input', 'input[name=billing_fias_code]', function() {
            sendAjaxRequest( $(this).val() );
        });

        // Shipping fias code change & input events
        $(document.body).on( 'change input', 'input[name=shipping_fias_code]', function() {
            sendAjaxRequest( $(this).val(), 'shipping' );
        });
    });
    </script>
    <?php
    endif;
}

// The Wordpress Ajax PHP receiver (set data to a WC_Session variable)
add_action( 'wp_ajax_fias_code', 'set_fias_code_to_wc_session' );
add_action( 'wp_ajax_nopriv_fias_code', 'set_fias_code_to_wc_session' );
function set_fias_code_to_wc_session() {
    $field_key = 'fias_code';
    if ( isset($_POST[$field_key]) && isset($_POST['fieldset']) ){
        // Get data from custom session variable
        $values = (array) WC()->session->get($field_key);

        // Initializing when empty
        if( ! empty($values) ) {
            $values = array(
                'billing' => WC()->customer->get_meta('billing_'.$field_key),
                'shipping' => WC()->customer->get_meta('shipping_'.$field_key)
            );
        }

        // Sanitizing data sent
        $fieldset  = esc_attr($_POST['fieldset']);
        $fias_code = sanitize_text_field($_POST[$field_key]);

        // Set / udpate custom WC_Session variable
        $values[$fieldset] = $fias_code;
        WC()->session->set($field_key, wc_clean($values));

        // Send back to javascript the data received as an array (json encoded)
        echo json_encode(array($fieldset.'_'.$field_key => $fias_code));
        wp_die(); // always use die() or wp_die() at the end to avoird errors
    }
}

// Update checkout fields 'fias_code' values from custom WC_session variable
add_filter('woocommerce_checkout_get_value', 'update_fias_code_checkout_fields_values', 10, 2 );
function update_fias_code_checkout_fields_values( $value, $input ) {
    $field_key = 'fias_code';

    // Get data from custom session variable
    $values = (array) WC()->session->get($field_key);

    if ( ! empty($values) ) {
        if ( 'billing_'.$field_key === $input ) {
            $value = $values['billing'];
        }
        if ( 'shipping_'.$field_key === $input ) {
            $value = $values['shipping'];
        }
    }
    return $value;
}

// Add 'fias_code' data to destination shipping packages
add_filter( 'woocommerce_cart_shipping_packages', 'add_fias_code_to_destination_shipping_package' );
function add_fias_code_to_destination_shipping_package( $packages ) {
    $customer   = WC()->customer; // The WC_Customer Object

    // Get 'fias_code' data from customer meta data
    $main_key   = 'fias_code';
    $meta_value = $customer->get_meta('shipping_'.$main_key);
    $meta_value = empty($meta_value) ? $customer->get_meta('billing_'.$main_key) : $meta_value;

    // Get data from custom session variable
    $values = (array) WC()->session->get($main_key);

    if ( ! empty($values) ) {
        $session_value = $values['shipping'];

        if ( $session_value === $meta_value ) {
            $session_value = $values['billing'];

            if ( $session_value !== $meta_value ) {
                $meta_value = $values['billing'];
            }
        } else {
            $meta_value = $session_value;
        }
    }

    // Loop through shipping packages
    foreach ( $packages as $key => $package ) {
        // Set to destination package the "fias_code"
        $packages[$key]['destination'][$main_key] = $meta_value;
    }
    return $packages;
}

// Remove custom WC_Session variable once order has been created (before thankyou)
add_action( 'woocommerce_checkout_order_created', 'remove_fias_code_custom_wc_session_variable' );
function remove_fias_code_custom_wc_session_variable() {
    // Remove the custom WC_Session variable
    WC()->session->__unset('fias_code');
}

This code goes in functions.php file of the active child theme (or active theme).此代码进入活动子主题(或活动主题)的 functions.php 文件。 Tested and works.测试和工作。


Important notes:重要笔记:

Displaying and save fias_code checkout fields:显示和保存fias_code结帐字段:
I am using woocommerce_billing_fields and woocommerce_shipping_fields filter hooks instead of woocommerce_checkout_fields as that way the data is saved itself as order meta data and user meta data.我正在使用woocommerce_billing_fieldswoocommerce_shipping_fields过滤器钩子而不是woocommerce_checkout_fields ,因为这样数据就被保存为订单元数据和用户元数据。 So your last function is not required anymore.所以你最后的 function 不再需要了。
The order meta keys start with an underscore like all billing and shipping order metadata.订单元键以下划线开头,就像所有账单和运输订单元数据一样。
The fields will be displayed on My account edit addresses… So if you want to avoid that you will need to add a condition to both related hooks.这些字段将显示在我的帐户编辑地址上......因此,如果您想避免这种情况,您需要为两个相关的挂钩添加一个条件。

Regarding my jQuery code:关于我的 jQuery 代码:
You should better copy it to an external file and register/enqueue it in a clean WordPress way, restricting output to checkout page only.您最好将其复制到外部文件并以干净的 WordPress 方式注册/排队,将 output 限制为仅结帐页面。 Then you will remove the related action hook and the hooked function…然后你将删除相关的动作钩子和钩子函数......

Regarding action and filter hooks:关于动作和过滤器挂钩:
You will have to change all add_action() and add_filter() for your plugin like:您必须为您的插件更改所有add_action()add_filter() ,例如:

add_filter( 'woocommerce_billing_fields' , array($this, 'custom_billing_fields') );
add_filter( 'woocommerce_shipping_fields' , array($this, 'custom_shipping_fields') );
add_action( 'wp_footer', array($this, 'checkout_send_fias_code_via_ajax_js') );
add_action( 'wp_ajax_fias_code', array($this, 'set_fias_code_to_wc_session') );
add_action( 'wp_ajax_nopriv_fias_code', array($this, 'set_fias_code_to_wc_session') );
add_filter('woocommerce_checkout_get_value', array($this, 'update_fias_code_checkout_fields_values'), 10, 2 );
add_filter( 'woocommerce_cart_shipping_packages', array($this, 'add_fias_code_to_destination_shipping_package') );
add_action( 'woocommerce_checkout_order_created', array($this, 'remove_fias_code_custom_wc_session_variable') );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 根据WooCommerce统一运费方式的自定义字段计算添加交货时间 - Add a delivery time based on custom fields calculations for WooCommerce Flat rate Shipping method 在结帐页面和 WooCommerce 数据字段中添加取货地点自定义字段 - Add pickup locations custom field on checkout page and in WooCommerce data fields Woocommerce 结帐页面中的运输承运人自定义字段验证 - Shipping carrier custom fields validation in Woocommerce checkout page 有条件地将自定义结帐字段添加到 WooCommerce 中的运输部分 - Add conditionally a custom checkout field to shipping section in WooCommerce 在WooCommerce中清理自定义结帐字段数据 - Sanitize custom checkout fields data in WooCommerce 清空所有 WooCommerce 运输结帐字段 - Blank all WooCommerce shipping checkout fields 清除WooCommerce Checkout中的shipping_ *字段 - Clear shipping_*fields in WooCommerce Checkout 在 WooCommerce 中禁用可下载产品的运输结帐字段 - Disable shipping checkout fields for downloadable products in WooCommerce 在 WooCommerce 中隐藏特定运输方式的结帐运输字段部分 - Hide checkout shipping fields section for specific shipping method in WooCommerce 结帐后以编程方式添加送货方式 - WooCommerce - Add shipping method programatically after checkout - WooCommerce
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM