我试图使用用户在产品页面的自定义字段中输入的值动态设置 WooCommerce 产品价格。
一切正常,除了,我无法将自定义字段数据显示到管理订单详细信息和电子邮件中。
我不知道如何获取调试结果,因为它不会在 Ajax 响应中返回任何内容。要么结帐页面完成并重新加载到“已完成订单”页面,要么收到错误 500。
这是我陷入困境的代码:
// Get cart item custom data and update order item meta and display in orders and emails
add_action( 'woocommerce_checkout_create_order_line_item', 'save_order_item_custom_meta_data', 10, 2 );
function save_order_item_custom_meta_data( $item, $values ) {
$domain = 'woocommerce';
$owner = $values['custom_data']['share_owner'] ?? '';
$getAmount = $values['custom_data']['dynamic_amount'] ?? '';
// $pmType = '';
// $pmAmount = '';
// if($owner && $getAmount){
// $pmType = __('Payment Breakdown', $domain );
// $pmAmount = '30€ + ( '. number_format((int) $getAmount) .' × 0.05€ )';
// }else{
// $pmType = __('Donation Amount', $domain );
// $pmAmount = number_format((int) $getAmount) . '€';
// }
$item->update_meta_data( $owner, $getAmount ); //returns empty string
}
我的其余相关代码(用于测试自定义价格):
// Display custom input fields in single product page
add_action( 'woocommerce_before_add_to_cart_button', 'add_product_custom_fields', 20 );
function add_product_custom_fields(){
$domain = 'woocommerce';
printf( '<div id="owner"><div class="lined-up"><input type="radio" id="yes" name="share_owner" value="1"><label for="yes">%s</label></div><div class="lined-up"><input type="radio" id="no" name="share_owner" value="0"><label for="no">%s</label></div></div>', __( 'I own share', $domain ), __( 'I do not own share', $domain ), );
$value = isset( $_POST['dynamic_amount'] ) ? sanitize_key( $_POST['dynamic_amount'] ) : '';
printf( '<div id="dyn_amount" style="display:none;"><label for="dynamic_amount">%s</label><input name="dynamic_amount" id="dynamic_amount" value="%s" min="30" type="number"/></div>', __( 'Amount', $domain ), esc_attr( $value ) );
}
// Add custom fields data to cart items and make price calculation
add_filter( 'woocommerce_add_cart_item_data', 'custom_add_cart_item_data', 20, 2 );
function custom_add_cart_item_data( $cart_item, $product_id ){
if( isset( $_POST['share_owner'] ) ){
$cart_item['custom_data']['share_owner'] = (int) sanitize_key( $_POST['share_owner'] );
}
if( isset( $_POST['dynamic_amount'] ) ){
$cart_item['custom_data']['dynamic_amount'] = sanitize_key( $_POST['dynamic_amount'] );
}
// Make calculation and save calculated price
if( isset( $_POST['share_owner'] ) && isset( $_POST['dynamic_amount'] ) ){
$own_share = (int) sanitize_key( $_POST['share_owner'] );
$dynamic_amount = (int) sanitize_key( $_POST['dynamic_amount'] );
//If selected share owner we need to calculate price according to input value
if( $own_share ){
// calculating the amount (share amount * 0.05) + 30
$total_price = ( ( $dynamic_amount * 0.05 ) + 30.0 );
$cart_item['custom_data']['price'] = round($total_price, 2);
} else{
//Otherwise its a donation, no calculation needed
$total_price = $dynamic_amount;
$cart_item['custom_data']['price'] = round($total_price, 2);
}
}
return $cart_item;
}
// Display custom data in cart and checkout pages
add_filter( 'woocommerce_get_item_data', 'udaac_display_custom_cart_item_data', 10, 2 );
function udaac_display_custom_cart_item_data( $cart_data, $cart_item ) {
$domain = 'woocommerce';
$input_amount = $cart_item['custom_data']['dynamic_amount'] ?? '';
if ( isset( $cart_item['custom_data']['share_owner'] ) ){
$owner = (int) $cart_item['custom_data']['share_owner'];
$paymentType = '';
$paymentOrShareAmount = '';
if($owner){
$paymentType = __('Payment Breakdown', $domain );
$paymentOrShareAmount = '30€ + ( '. number_format((int) $input_amount) .' × 0.05€ )';
}else{
$paymentType = __('Donation Amount', $domain );
$paymentOrShareAmount = number_format((int) $input_amount) . '€';
}
$cart_data[] = array(
'name' => $paymentType,
'value' => $paymentOrShareAmount
);
}
return $cart_data;
}
// Set the new calculated price replacing cart item price
add_action( 'woocommerce_before_calculate_totals', 'udaac_set_cart_item_calculated_price', 20, 1 );
function udaac_set_cart_item_calculated_price( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ){
if( ! isset( $cart_item['custom_data']['price'] ) ){
continue;
}
if( $cart_item['custom_data']['price'] > 0 ){
// Set the calculated item price (if there is one)
$cart_item['data']->set_price( (float) $cart_item['custom_data']['price'] );
}
}
}
您的代码中有一些错误。
请尝试以下操作(未经测试),这会将必要的数据保存为自定义订单项元数据,并使用正确的
meta_keys
,并将用可读的标签字符串替换显示的元键:
// Utility function: Convert label string to a correct meta key
function sanitize_meta_key( $label ) {
return str_replace('-','_',sanitize_title($label));
}
// Save custom cart item data as order item meta and display this meta data
// on orders line item(s) in admin order pages, emails and customer orders.
add_action( 'woocommerce_checkout_create_order_line_item', 'save_order_item_custom_meta_data', 10, 4 );
function save_order_item_custom_meta_data( $item, $cart_item_key, $values, $order ) {
if ( isset($values['custom_data']['share_owner']) && isset($values['custom_data']['dynamic_amount']) ) {
$domain = 'woocommerce';
$custom_data = $values['custom_data'];
$share_owner = $custom_data['share_owner'];
$dynamic_amount = (int) $custom_data['dynamic_amount'];
if( $share_owner ){
$label = __('Payment Breakdown', $domain );
$meta_value = '30€ + ( '. number_format($dynamic_amount) .' × 0.05€ )';
} else {
$label = __('Donation Amount', $domain );
$meta_value = number_format((int) $dynamic_amount) . '€';
}
$item->update_meta_data( sanitize_meta_key($label), $meta_value );
}
}
// Add readable "meta key" label name replacement
add_filter('woocommerce_order_item_display_meta_key', 'filter_wc_order_item_display_meta_key', 10, 3 );
function filter_wc_order_item_display_meta_key( $display_key, $meta, $item ) {
if( $item->get_type() === 'line_item' ) {
$domain = 'woocommerce';
$label1 = __('Payment Breakdown', $domain );
$label2 = __('Donation Amount', $domain );
if( $meta->key === sanitize_meta_key( $label1 ) ) {
$display_key = $label1;
} elseif( $meta->key === sanitize_meta_key( $label2 ) ) {
$display_key = $label2 ;
}
}
return $display_key;
}
现在应该可以更好地工作了。您可能需要对我的代码进行一些更改,因为我试图猜测您想要做什么。
注意:您还应该为第一个输入单选按钮添加
checked
属性,以使其默认处于选中状态。