【问题标题】:Woocommerce: Pay half (50%) on Cash on delivery using ajaxWoocommerce:使用 ajax 货到付款支付一半 (50%)
【发布时间】:2018-03-25 11:08:52
【问题描述】:

我正在尝试制作一个 ajax 功能,让用户以自定义货到付款方式支付总金额的一半。当用户选择是或否单选按钮时,总金额会相应更改。

这个:Link 是一个很好的例子,我正在尝试遵循,但我需要将其作为 ajax 调用。

以下是我在付款阻止前添加新字段的方法:

add_action("woocommerce_review_order_before_payment", "new_buttons");
function new_buttons(){
 echo '<div id="cash-on-delivery-wrap" class="cash-on-delivery-wrap">';
 echo '<h5>Cash on delivery: </h5><div style="clear:both"></div>';
 echo '<h6>Pay half 50%</h6><div style="clear:both"></div>';
 echo '<div class="cod_button_wrap">';
 echo '<label><input type=radio value="no" name="new-cod" checked/>No</label>';
 echo '<label><input type=radio value="yes" name="new-cod" />Yes</label>';
 echo '</div>';
 echo '</div>';
}

这里是 JS:

jQuery(document).ready(function(){
  jQuery("form.checkout").on("change", "#cash-on-delivery-wrap input", 
   function(){
     var data = {
        action: 'change_cod',
        security: wc_checkout_params.update_order_review_nonce,
        post_data: jQuery( 'form.checkout' ).serialize()
     };

     jQuery.post( ajaxurl, data, function( response )
     {
        jQuery( 'body' ).trigger( 'update_checkout' );
     });
   });
});

函数如下:

function custom_cart_total() {
 $current_state = $_POST['post_data'];
 if ( is_admin() && ! defined( 'DOING_AJAX' ) )
 return;
 if($current_state=='yes'){
    WC()->cart->total *= 0.50;
 }else{
    WC()->cart->total;
 }
 exit;
}
add_action( 'wp_ajax_nopriv_change_cod', 'custom_cart_total' );
add_action( 'wp_ajax_change_cod', 'custom_cart_total' ); 

似乎无法让它工作,我在这里错过了什么。

【问题讨论】:

    标签: php jquery ajax wordpress woocommerce


    【解决方案1】:

    注意:链接答案中的代码仅更改购物车和结帐中显示的总金额,但不会真正更改。

    这个答案也改变了显示的结帐总额。我们需要在订单创建过程中挂接另一个函数来更新总金额。

    对于 Wordpress Ajax,您需要在一个外部 JS 文件中注册您的脚本,该文件将上传到您的活动主题文件夹中的 js 子文件夹中。假设这个外部文件名将是 pay_half.js

    1) 以下是进行注册并启用 WordPress Ajax 功能的函数:

    add_action( 'wp_enqueue_scripts', 'ajax_change_shipping' );
    function ajax_change_shipping() {
        // Only on front-end and checkout page
        if( is_admin() || ! is_checkout() ) return;
    
        // Get the Path to the active theme or child theme or plugin folder
        # $path = plugin_dir_url( __FILE__ ); // A plugin
        # $path = get_template_directory_uri(); // A Normal theme
        $path = get_stylesheet_directory_uri(); // A child theme
    
        // Define the subfolder name
        $subfolder = 'js';
    
        // Define the file name
        $filename = 'pay_half.js';
    
        // Reference name of the script (should be unique)
        $handle = 'pay-half';
    
        // Set the ajaxurl parameter used in your script
        $data = array(
            'ajaxurl' => admin_url( 'admin-ajax.php' ),
        );
    
        // The variable name whichwill contain the data
        $name = 'pay_half';
    
        // Registering the javascript file and enqueues it.
        wp_enqueue_script( $handle, $path."/$subfolder/$filename", array( 'jquery' ), '1.0', true );
    
        // Localizing the registered script (Here using Ajax)
        wp_localize_script( $handle, $name, $data );
    }
    

    代码进入您的活动子主题(或主题)的 function.php 文件或任何插件文件中。


    2) 现在是 Javascript/jQuery 外部文件 (named: pay_half.js):

    jQuery(document).ready(function ($) {
        var selectHalf = '#cash-on-delivery-wrap input[type="radio"]',
            paymentMethod = 'input[name^="payment_method"]',
            codWrap = $('.cash-on-delivery-wrap'),
            cartGTotal = $('input#cart_gtotal').val(),
            codPartial;
    
        // Detecting payment method on load to show/hide cod custom options
        if( $(paymentMethod+':checked').val() == 'cod' )
            codWrap.show("fast");
        else
            codWrap.hide("fast");
    
        // Live detecting choosen payment method to show/hide cod custom options
        $( 'form.checkout' ).on( 'change', 'input[name^="payment_method"]', function() {
            if ( $(paymentMethod+':checked').val() == 'cod' ) {
                codWrap.show("fast");
            } else {
                codWrap.hide("fast");
                $('#cash-on-delivery-wrap input#cod-options_no').prop('checked', true);
            }
            $(document.body).trigger("update_checkout");
            // console.log($(paymentMethod+':checked').val());
        });
    
        // The "Cod" custom options (ajax)
        $(selectHalf).click(function(){
            if($(selectHalf+':checked' ).val() == 'yes' ) codPartial = 'yes';
            else codPartial = 'no';
    
            $.ajax({ // This does the ajax request
                url: pay_half.ajaxurl,
                type : 'post',
                data: {
                    'action':'cod_partial_payment', // Name of the php function
                    'cod_partial' : codPartial       // Passing this variable to the PHP function
                },
                success:function(data) {
                    // Displaying the price (Ajax)
                    $( 'table.shop_table > tfoot > tr.order-total > td > strong > span' ).html(data.price_html);
                    if(codPartial == 'yes')
                        $('input#cart_remaining').val(data.price_remaining);
                    else
                        $('input#cart_remaining').val(0);
                    $(document.body).trigger("wc_fragment_refresh");
                    console.log(data);
                },
                error: function(error){
                    console.log(error);
                }
            });
        });
    });
    

    3) 自定义字段的显示(重新访问)

    我添加了 2 个隐藏字段,其中包含总金额和要支付的剩余金额。

    add_action( 'woocommerce_review_order_before_payment', 'cod_payment_options', 10 );
    function cod_payment_options(){
        echo '<style>.cod-button-options label{display:inline-block; margin:0 6px;}</style>
        <div id="cash-on-delivery-wrap" class="cash-on-delivery-wrap">
            <h3>' . __( 'Cash on delivery option' ) . '</h3>';
    
        woocommerce_form_field( 'cod-options', array(
            'type'      => 'radio',
            'class'     => array('form-row-wide', 'cod-button-options'),
            'label'     => __( '<b>Pay half (50%): </b>' ),
            'required' => false,
            'options' => array(
                'no'  => __( 'No' ),
                'yes' => __( 'Yes' ),
            )
        ), 'no' );
    
        // Some additional hidden fields
        echo '<input type="hidden" id="cart_gtotal" name="cart_gtotal" value="'. WC()->cart->total .'">
            <input type="hidden" id="cart_remaining" name="cart_remaining" value="0" />
            </div>';
    }
    

    代码进入您的活动子主题(或主题)的 function.php 文件或任何插件文件中。


    4) 驱动的php函数(Wordpress Ajax):

    add_action( 'wp_ajax_nopriv_cod_partial_payment', 'cod_partial_payment' );
    add_action( 'wp_ajax_cod_partial_payment', 'cod_partial_payment' );
    function cod_partial_payment() {
        if( ! isset($_POST['cod_partial']) ) return;
    
        $current_state = $_POST['cod_partial'];
        $remaining = 0;
    
        if( $current_state == 'yes' ){
            WC()->cart->total /= 2;
        }
        WC()->session->set( 'total', WC()->cart->total );
    
        $response = array(
            'price_html'        => wc_price( WC()->cart->total ),
            'price_remaining'   => WC()->cart->total,
        );
    
        header( 'Content-Type: application/json' );
        echo json_encode( $response );
    
        die(); // Always (to avoid an error 500)
    }
    

    代码进入您的活动子主题(或主题)的 function.php 文件或任何插件文件中。


    5) 所有其他 php 功能(更新订单金额、保存元数据、显示消息):

    // Replacing the total amount when COD option is enabled
    add_action( 'woocommerce_checkout_create_order', 'cod_options_change_order_total_ammount', 10, 2 );
    function cod_options_change_order_total_ammount( $order, $data ) {
        if ( ! empty( $_POST['cod-options'] ) && $_POST['cod-options'] == 'yes' ) {
            $remaining = sanitize_text_field( $_POST['cart_remaining'] );
            $total = WC()->cart->total - floatval($remaining);
            WC()->session->set( 'total', $total );
            $order->set_total( $total );
        }
    }
    
    
    // Updating order meta data for Cod selected option
    add_action( 'woocommerce_checkout_update_order_meta', 'cod_options_update_order_meta', 10, 1 );
    function cod_options_update_order_meta( $order_id ) {
        if ( ! empty( $_POST['cod-options'] ) && $_POST['cod-options'] == 'yes' ) {
            update_post_meta( $order_id, '_cod_remaining_amount', sanitize_text_field( $_POST['cart_remaining'] ) );
            update_post_meta( $order_id, '_cod_partial_paid_amount', sanitize_text_field( $_POST['cart_gtotal'] - $_POST['cart_remaining'] ) );
        }
        update_post_meta( $order_id, '_cod_partial_payment_option', sanitize_text_field( $_POST['cod-options'] ) );
    }
    
    // Displaying the remaining amount to pay in a custom message on Order received page (thank you)
    add_action( 'woocommerce_thankyou_cod', 'cod_options_woocommerce_thankyou', 10, 1 );
    function cod_options_woocommerce_thankyou( $order_id ) {
        if( get_post_meta( $order_id, '_cod_partial_payment_option', true ) == 'yes' ){
            $ra = '<span style="color:#96588a;">'.wc_price( get_post_meta( $order_id, '_cod_remaining_amount', true )).'</span>';
            ?>
                <ul class="woocommerce-order-overview woocommerce-thankyou-cod-options order_details">
                    <li class="woocommerce-order-overview__remaining_total order">
                    <strong><?php echo __("There is a remaining amount of $ra to pay on this order."); ?></strong>
                    </li>
                </ul>
            <?php
        }
    }
    

    代码进入您的活动子主题(或主题)的 function.php 文件或任何插件文件中。

    此代码在 Woocommerce 3+ 上经过测试并且可以正常工作。

    【讨论】:

      猜你喜欢
      • 2017-05-31
      • 2014-07-18
      • 2015-07-01
      • 2021-01-26
      • 1970-01-01
      • 2017-05-17
      • 2017-02-07
      • 2019-04-25
      • 1970-01-01
      相关资源
      最近更新 更多