我的目标:使用AJAX对购物车总价应用10%的折扣。
上下文:此折扣必须仅适用于来自给定网站的特定用户。我的想法是在我在购物车页面中添加的输入字段中获取其会员编号。使用API时,我将检查此号码并是否应用折扣(考虑到进一步解释的问题,在此我将不详细介绍此检查部分,而仅关注问题)。
想法:
问题:因此,我使用AJAX验证此数字,然后对购物车总价施加10%的折扣。问题是我找不到如何更新总数。
我的JS:
(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
}
因此,这项工作需要支付negatif费用,但是在加载页面时,这并不是我想要的,因为我想在触发更新购物车按钮时应用负费用,所以这个想法是将 add_action 集成到我的 AJAX动作函数中,如下所示:
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 。我的两个标志都显示在chrome控制台中,因此这意味着我的动作函数已正确调用。所以我的问题是:如何使这个add_action在我的action函数中起作用?
答案 0 :(得分:1)
您错过了使用WC Session变量设置某些数据并将其用于折扣函数的用法……下面的第一个函数可处理您的设置,并且已在其他函数的任何地方加载。
// 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.' <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 / Ajax代码:
// 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 WordPress Ajax接收器功能:
// 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. 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. 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文件中。经过测试,可以正常工作。
相似线程: