WooCommerce custom price using get_price() functio

2019-03-22 05:32发布

问题:

I've currently been playing around with using multiple prices/currencies based on user location. I'm going through the whole ordering process and I'm almost there.

I'm using the get_price() function to hook with woocommerce_get_price (located in class-wc-product.php, line 822) and then find custom field amounts that i have set (gb_price, us_price etc) from the product.

All works fine in the shop, single product view, cart, checkout but when placing order it all falls back to the default base cost and currency. I've noticed that this only fails when hooking in via functions.php. If I amend the function itself directly in the class file, everything works perfectly.

I really don't want to hack away at the core of WC so can someone have a look and tell me why it fails? Here's my code...

class-wc-product.php

function get_price() {  
    return apply_filters( 'woocommerce_get_price', $this->price, $this );
}

functions.php

add_filter('woocommerce_get_price', 'return_custom_price', $product, 2); 
function return_custom_price($price, $product) {    
    global $post, $woocommerce;
    // Grab the product id
    $post_id = $product->id; 
    // Get user's ip location and correspond it to the custom field key
    $user_country = $_SESSION['user_location'];
    $get_user_currency = strtolower($user_country.'_price');
    // If the IP detection is enabled look for the correct price
    if($get_user_currency!=''){
        $new_price = get_post_meta($post_id, $get_user_currency, true);
        if($new_price==''){
            $new_price = $price;
        }
    }
    return $new_price;
}   

So this works everywhere except the order confirmation. If I simply move the function from functions.php to the class itself within get_price(), it works perfectly.

回答1:

Here is the code I now use, it's not perfect by any means but should help people get on the right track. (Not tested with WC2.0 yet, I'm almost certain it will not work out of box for 2.) Please note, any sessions used are for IP driven testing and are not integral to the functionality. I adapted it from before to be used as a plugin. In products in WP I use custom fields for the price i.e 'us_price', 'gb_price' etc, this is how the ip detection hooks in.

// 1. Change the amount
function return_custom_price($price, $product) {
    global $post, $woocommerce;
    $post_id = $post->ID;
    // Prevent conflicts with order pages and products, peace of mind.
    if($post_id == '9' || $post_id == '10' || $post_id == '17' || $post_id == '53' || $post_id == ''){
        // cart, checkout, , order received, order now
        $post_id = $product->id;
    }
    $user_country = $_SESSION['user_location'];
    $get_user_currency = strtolower($user_country.'_price');
    // If the IP detection is enabled look for the correct price
    if($get_user_currency!=''){
        $new_price = get_post_meta($post_id, $get_user_currency, true);
        if($new_price==''){
            $new_price = $price;
        }
    }
    if( is_admin() && $_GET['post_type']=='product' ){
        return $price;
    } else {
        return $new_price;
    }
}
add_filter('woocommerce_get_price', 'return_custom_price', $product, 2);

// 2. Update the order meta with currency value and the method used to capture it
function update_meta_data_with_new_currency( $order_id ) {
    if($_SESSION['user_order_quantity']>=2){
        update_post_meta( $order_id, 'group_ticket_amount', $_SESSION['user_order_quantity'] );
        update_post_meta( $order_id, 'master_of', '' );

    }
    update_post_meta( $order_id, 'currency_used', $_SESSION['user_currency'] );
    update_post_meta( $order_id, 'currency_method', $_SESSION['currency_method'] );
}
add_action( 'woocommerce_checkout_update_order_meta', 'update_meta_data_with_new_currency' );