मेरा लक्ष्य : AJAX का उपयोग करके कार्ट के कुल मूल्य पर 10% की छूट लागू करें।

संदर्भ : यह छूट केवल दी गई वेबसाइट से आने वाले विशिष्ट उपयोगकर्ताओं के लिए ही लागू होनी चाहिए। विचार यह है कि मैंने कार्ट के पेज में जोड़े गए इनपुट फ़ील्ड में उनकी सदस्यता संख्या प्राप्त की है। एक एपीआई के साथ मैं इस नंबर की जांच करूंगा और छूट लागू करूंगा या नहीं (आगे बताए गए मुद्दे पर विचार करते हुए, मैं यहां इस जांच भाग का विवरण नहीं दूंगा और केवल समस्या पर ध्यान केंद्रित करूंगा)।

विचार :

  1. एक प्लगइन बनाएं जो एक सत्यापन बटन के साथ कार्ट के पेज में एक इनपुट फ़ील्ड जोड़ देगा।
  2. बटन क्लिक होने पर AJAX कॉल करें
  3. यदि उपयोगकर्ता सदस्यता संख्या अच्छी है तो छूट लागू करें (मैं यहां एपीआई जांच से नहीं निपटूंगा क्योंकि यह समस्या नहीं है)

समस्या: इसलिए मैं इस नंबर को मान्य करने के लिए AJAX का उपयोग कर रहा हूं और फिर कुल कार्ट की कीमत पर 10% छूट लागू करता हूं। समस्या यह है कि मैं कुल को अपडेट करने का तरीका नहीं ढूंढ सकता।

माई जेएस:

(function($) {
    $("body").on("click", ".updateCart", function(e) {
        e.preventDefault();
        var form = $('#cartAjaxTcs');
        var value = form.serialize();
        $.ajax({
            type:'POST',
            data: {
                action: 'test',
                number: value
            },
            url: ajaxurl,
            success: function(value) {
                jQuery("[name='update_cart']").removeAttr('disabled');
                jQuery("[name='update_cart']").trigger("click");
                console.log(value);
            },
            error:function(){
                console.log('error');
            }
        });
    });
})( jQuery );

मेरा PHP:


<?php

/*
  Plugin Name: discount Plugin
  Description: Apply 10% discount on cart's price
  Author: Aurélien
  Version: 1.0.0
 */

/**
* Check if WooCommerce is active
**/
if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {

    class Discount_Plugin{

        public static function init() {

            add_action('wp_enqueue_scripts',  __CLASS__ .'::callback_for_setting_up_scripts');

            //Add input field
            add_action('woocommerce_cart_collaterals', __CLASS__.'::order_comments_custom_cart_field');

        }

        public static function callback_for_setting_up_scripts() {
            $path = '/wp-content/plugins/discount-plugin/assets/css/style.css';
            wp_register_style( 'discountStyle', $path );
            wp_enqueue_style( 'discountStyle' );
            wp_enqueue_script( 'ajax-script', plugins_url( 'assets/js/discount-plugin.js', __FILE__ ), array('jquery'), '1.0', true );
            wp_localize_script( 'ajax-script', 'ajaxurl', admin_url( 'admin-ajax.php' ) );
        }

        public static function order_comments_custom_cart_field() {
            ?>
            <form id="cartAjaxTcs" class="discount_input_wrapper" method="post" action="/wp-admin/admin-post.php">
                <div class="discount_form_field">
                    <input type="text" name="number" id="number" placeholder="<?php echo 'My number, ie : 4GG524G42';?>">
                    <label for="number"><?php echo 'Membership number';?></label>
                </div>
                <button class="updateCart" type="submit"><?php echo 'Update cart';?></button>
            </form>
            <?php

        }

 

    Discount_Plugin::init();
    add_action( 'wp_ajax_test', 'test' );
    add_action( 'wp_ajax_nopriv_test', 'test' );

    function test()
    {
      //Solution 1 or solution 2
    }

}

मेरा पहला समाधान: मैंने इस तरह कुल कीमत को सीधे कम करने का प्रयास किया। यह कुल कीमत को बदल देता है लेकिन इसे प्रदर्शित नहीं करता है, यहां तक ​​कि बैकएंड कार्ट की रिपोर्ट में भी जहां कुल कीमत अभी भी छूट से पहले समान है।

function test()
{
    //This is displayed in console
    echo 'test-init';

    if (!DOING_AJAX){
        return;
    }

    $total = (int) WC()->cart->get_totals()['total']; 
    $total *= 0.9;
    WC()->cart->set_total($total);

    wp_die();
}


मेरा दूसरा समाधान: मैंने "अपडेट कार्ट" बटन (पहले से ही पेज पर मौजूद) को ट्रिगर करने की कोशिश की और कीमत को अपडेट करने के लिए woocommerce_before_calculate_totals हुक का उपयोग किया, लेकिन इसे कॉल भी नहीं किया गया।

जाहिर है, मेरे AJAX के एक्शन फ़ंक्शन के अंदर कोई हुक या फ़िल्टर नहीं निकाला गया है। मैंने शरीर में कक्षा जोड़ने के लिए एक साधारण फ़िल्टर के साथ परीक्षण किया है और यह मेरे एक्शन फ़ंक्शन के अंदर काम नहीं करता है लेकिन पूरी तरह से बाहर काम करता है। मैंने यह देखने के लिए कुछ झंडे लगाए कि क्या मेरा कार्य AJAX द्वारा बुलाया गया था और यह है!

//This works well! If I put the same filter in my 'test' function it doesn't work
add_filter( 'body_class', function( $classes ) {
    return array_merge( $classes, array( 'test-class' ) );
} );

function test()
{
    //This is displayed in console
    echo'test-init';

    if (!DOING_AJAX){
        return;
    }
    
    //This does't work
    add_filter( 'body_class', function( $classes ) {
      return array_merge( $classes, array( 'test-class2' ) );
    } );
    
    //The callback function isn't called
    add_action( 'woocommerce_before_calculate_totals', 'update_price' );

    //This is displayed in console
    echo 'test';

    wp_die();
}

//Not called
function update_price(){
    echo 'update';
}

संपादित करें:

मैंने अतिरिक्त कोड के साथ उन्हें थोड़ा और समझने योग्य बनाने के लिए अपने स्पष्टीकरण दोबारा लिखे:

woocommerce_cart_calculate_fees हुक का उपयोग करके ऋणात्मक शुल्क के साथ कुछ प्रयास यहां दिए गए हैं:

यदि मैं अपने AJAX क्रिया फ़ंक्शन के बाहर add_action का उपयोग इस प्रकार करता हूं, तो woocommerce_cart_calculate_fees हुक का कॉलबैक फ़ंक्शन पूरी तरह से कार्य करता है:

add_action( 'wp_ajax_test', 'test' );
add_action( 'wp_ajax_nopriv_test', 'test' );

add_action( 'woocommerce_cart_calculate_fees','woocommerce_custom_surcharge' );
function woocommerce_custom_surcharge() {
    global $woocommerce;

    if ( ( is_admin() && ! defined( 'DOING_AJAX' )))
        return;

    $percentage = 0.1;
    $surcharge = ( $woocommerce->cart->cart_contents_total + $woocommerce->cart->shipping_total ) * $percentage;
    $woocommerce->cart->add_fee( 'discount', -$surcharge, true, '' );

}

function test(){
   
   //My AJAX action function

}

तो यह काम, नकारात्मक शुल्क लागू किया जाता है, लेकिन जब पृष्ठ लोड होता है और यह वह नहीं है जो मैं चाहता हूं क्योंकि जब मैं अपडेट कार्ट बटन ट्रिगर करता हूं, तो मैं नकारात्मक शुल्क लागू करना चाहता हूं, इसलिए विचार एकीकृत करना है मेरे AJAX क्रिया समारोह के अंदर add_action इस तरह:

add_action( 'wp_ajax_test', 'test' );
add_action( 'wp_ajax_nopriv_test', 'test' );

function woocommerce_custom_surcharge() {
    global $woocommerce;

    if ( ( is_admin() && ! defined( 'DOING_AJAX' )))
        return;

    $percentage = 0.1;
    $surcharge = ( $woocommerce->cart->cart_contents_total + $woocommerce->cart->shipping_total ) * $percentage;
    $woocommerce->cart->add_fee( 'discount', -$surcharge, true, '' );

}

//My AJAX action function
function test(){

   echo 'test1'; //flag 1
   add_action( 'woocommerce_cart_calculate_fees','woocommerce_custom_surcharge' );
   echo 'test2'; //flag 2
}

कॉलबैक फ़ंक्शन woocommerce_custom_surcharge को बिल्कुल भी कॉल नहीं किया जाता है। मेरे दोनों झंडे क्रोम कंसोल में प्रदर्शित होते हैं, इसलिए इसका मतलब है कि मेरा एक्शन फंक्शन सही ढंग से कहा जाता है। तो मेरा सवाल है: इस ऐड_एक्शन को मेरे एक्शन फंक्शन के अंदर कैसे काम करें?

2
Aurélien 31 जुलाई 2020, 11:36

1 उत्तर

सबसे बढ़िया उत्तर

आप कुछ डेटा सेट करने और इसे अपने डिस्काउंट फ़ंक्शन में उपयोग करने के लिए WC सत्र चर का उपयोग करने से चूक गए… नीचे दिया गया पहला फ़ंक्शन आपकी सेटिंग्स को संभालता है और यह अन्य कार्यों पर हर जगह लोड होता है।

// Settings
function get_membership_settings(){
    $discount_percentage = 1; // the discount percentage: 1% here

    return array(
        'percentage'       => $discount_percentage,
        'field_key'        => 'membership_number', // Field "name" key (or id)
        'field_type'       => 'text',
        'field_label'      =>  __('Membership number', 'woocommerce'),
        'button_text'      =>  __('Apply membership number', 'woocommerce'),
        'discount_text'    =>  sprintf( __('Membership discount%s', 'woocommerce'), ' ('.$discount_percentage.' %)' ), // for negative fee
        'valid_message'    => __('Number is valid (text message).', 'woocommerce'),
        'unvalid_message'  => __('Number not valid (text message).', 'woocommerce'),
        'empty_field_text' => __('Please enter your membership number.', 'woocommerce'),
     );
}

// Settings + Membership number
function get_membership_data(){
    $settings      = get_membership_settings();// Load settings
    $field_key     = $settings['field_key']; // The field Id

    $user_value    = get_user_meta( get_current_user_id(), $field_key, true ); // Get "membership number" from user data
    $session_value = WC()->session->get($field_key); // Get "membership number" from session variable

    // Set "membership number" in the array
    $settings['field_value'] = empty($session_value) ? $user_value : $session_value;

    return $settings;
}

कार्ट पर प्रदर्शित फ़ील्ड (अंत में स्क्रीनशॉट देखें):

// Display a text input field on cart (+ javascript)
add_action('woocommerce_cart_contents', 'display_field_membership_number', 100 );
function display_field_membership_number(){
    extract(get_membership_data()); // Load data and settings

    echo '<tr><td colspan="6" class="membership" style="padding:0;border-top:16px solid #FFF;">
        <style>.message.off,label.hidden{display:none}.membership .message{margin-left:20px}</style>
        <div id="'.$field_key.'-wrapper">
            <label for="'.$field_key.'" class="hidden"> '.$field_label.'&nbsp;<abbr class="required" title="required">*</abbr></label>
            <input type="'.$field_type.'" class="input-'.$field_type.'" name="'.$field_key.'" id="'.$field_key.'" placeholder="'.$field_label.'" value="'.$field_value.'">
            <button type="button" class="button">'.$button_text.'</button>
            <span class="message off"></span>
        </div>
    </td></tr>
    <tr><td colspan="6" style="padding:0"></td></tr>';
}

JQuery/अजाक्स कोड:

// Function that send the Ajax request | jQuery + Ajax
add_action('wp_footer', 'membership_number_js_script');
function membership_number_js_script() {
    if( ! is_cart() ) return; // Only on cart

    $field_key = get_membership_settings()['field_key']; // Load field key id

    // jQuery Ajax code
    ?>
    <script type="text/javascript">
    jQuery( function($){
        if (typeof woocommerce_params === 'undefined')
            return false;

        var s = '#<?php echo $field_key; ?>-wrapper';

        $(s+' button').click( function(){
            var value = $(s+' input').val();

            // Function that handle the display of the message
            function handleDisplayMessage( selector, response, error = false ) {
                if ( ! error ) {
                    $.each( $.parseJSON(response), function(index, value){
                        displayMessage( selector, value, index );
                    });
                } else {
                    displayMessage( selector, response, 0 );
                }
            }

            // Function that display a message
            function displayMessage( selector, response, type ) {
                $(selector).hide('0').removeClass('off').html(response).css('color', (type == 1 ? '#03C03C' : '#DC143C')).show();
                setTimeout(function() {
                    $(selector).hide();
                }, 3000 );
            }

            $.ajax({
                type: 'POST',
                url: wc_cart_params.ajax_url,
                data: {
                    'action': '<?php echo $field_key; ?>',
                    '<?php echo $field_key; ?>': value,
                },
                success: function (response) {
                    handleDisplayMessage( (s+' .message'), response );
                    $(document.body).trigger("added_to_cart"); // refresh cart
                },
                error:function(error){
                    handleDisplayMessage( (s+' .message'), ('A problem occured (error: '+error+')'), true );
                }
            });
        });
    });
    </script>
    <?php
}

PHP वर्डप्रेस अजाक्स रिसीवर फ़ंक्शन:

// Get the ajax request and set value to WC session (and the field validation)
add_action( 'wp_ajax_membership_number', 'set_membership_number_and_validation' );
add_action( 'wp_ajax_nopriv_membership_number', 'set_membership_number_and_validation' );
function set_membership_number_and_validation() {
    extract(get_membership_settings()); // Load and extract settings

    if( isset($_POST[$field_key]) && ! empty($_POST[$field_key]) ) {

        ## HERE BELOW, SET YOUR CODE (that checks membership number for validation)

        $validation = true; // "true" when validated (or false if not)

        // Set membership number to a WC session variable
        WC()->session->set($field_key, $_POST[$field_key]);

        // Send response back
        echo json_encode( ($validation ? [1 => $valid_message] : [0 => $unvalid_message]) );
    } else {
        // Send response back
        echo json_encode( [0 => $empty_field_text] );
    }
    die();
}

छूट वाला हिस्सा:

छूट बनाने के कई तरीके हैं (यहां दो अलग-अलग हुक का उपयोग करके दिए गए हैं):

1. डिस्काउंट आधारित कार्ट सबटोटल + शिपिंग टोल (नकारात्मक शुल्क):

// 1. Percentage discount for Membership (with a negative fee)
add_action( 'woocommerce_cart_calculate_fees', 'add_membership_discount' );
function add_membership_discount( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    extract(get_membership_data()); // Load and extract settings + membership numver

    if( ! empty($field_value) ) {
        // Calculation
        $discount = ( $cart->get_cart_contents_total() + $cart->get_shipping_total() ) * $percentage / 100;

        $cart->add_fee( $discount_text, -$discount ); // Add a discount
    }
}

2. कार्ट आइटम की कीमत पर छूट:

// 2. Percentage discount for Membership (on cart items price)
add_action( 'woocommerce_before_calculate_totals', 'add_membership_cart_item_discount' );
function add_membership_cart_item_discount( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;

    extract(get_membership_data()); // Load and extract settings + membership numver

    if( ! empty($field_value) ) {

        // Loop through cart items
        foreach( $cart->get_cart() as $cart_item ){
            // Get the real WC_Product Object
            $product = wc_get_product($cart_item['data']->get_id());

            $price = $product->get_price(); // The real product price

            $discounted_price = $price * ( 1 - ( $percentage / 100 ) ); // Calculation

            $cart_item['data']->set_price($discounted_price); // Set the discounted price
        }
    }
}

सभी कोड आपके सक्रिय चाइल्ड थीम (या सक्रिय थीम) के functions.php फ़ाइल में जाते हैं। परीक्षण और काम करता है।

enter image description here


इसी तरह के धागे:

1
LoicTheAztec 3 अगस्त 2020, 17:43