You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为WooCommerce程序化创建的订单添加费用和优惠券?

Fixing Fees and Coupons for Programmatically Created WooCommerce Orders/Subscriptions

Got it, let's break down your issues and fix them step by step:

1. Why add_fee() is adding a fee with no amount

The add_fee() method expects the amount to be a float value (not an integer), and while operation order can affect totals, the core issue here is likely parameter type mismatch. Also, structuring your order creation flow to add products first helps give context for total calculations.

Update your fee line to explicitly use a float:

$order->add_fee( 'Sign Up Fee', 1500.00, false ); // Third param = taxable (false by default, included for clarity)

If 1500 was meant to be cents (e.g., $15 USD), use 15.00 instead—WooCommerce uses the store's currency unit (not cents) for this method.

2. Why add_discount() is crashing your function

The add_discount() method belongs to the WC_Cart object, not WC_Order. For orders, you need to use apply_coupon() with a valid coupon object. First, confirm the coupon NOFEE exists in your WooCommerce admin and is active, then replace your discount line with this:

// Validate and apply the coupon
$coupon_code = 'NOFEE';
$coupon = new WC_Coupon( $coupon_code );

if ( ! is_wp_error( $coupon ) ) {
    $order->apply_coupon( $coupon );
} else {
    // Optional: Log invalid coupon errors for debugging
    error_log( 'Failed to apply coupon ' . $coupon_code . ': ' . $coupon->get_error_message() );
}

Full Modified Function

Here's your updated function with these fixes, plus robustness improvements to avoid unexpected crashes:

function give_user_subscription($companyId, $productId, $companyName) {
    // Get the primary contact ID for the company
    $primaryUser = get_users( array(
        'fields' => array('ID'),
        'meta_query' => array(
            'relation' => 'AND',
            array(
                'key' => 'company_id',
                'value' => $companyId,
                'compare' => '='
            ),
            array(
                'key' => 'primary_contact',
                'value' => 1,
                'compare' => '='
            )
        ),
    ) );

    // Guard clause: Exit if no primary user found
    if ( empty( $primaryUser ) ) {
        error_log( 'No primary contact found for company ID: ' . $companyId );
        return;
    }

    $userId = $primaryUser[0]->ID;
    $user = get_user_by('ID', $userId);

    $address = array(
        'first_name' => $user->first_name,
        'last_name' => $user->last_name,
        'email' => $user->user_email,
        'phone' => get_user_meta($userId, 'mobile', true),
        'address_1' => get_user_meta($userId, 'address_line_1', true),
        'address_2' => get_user_meta($userId, 'address_line_2', true),
        'city' => get_user_meta($userId, 'town', true),
        'postcode' => get_user_meta($userId, 'postcode', true),
        'country' => get_user_meta($userId, 'country', true),
        'company' => $companyName
    );

    // Order object
    $order = wc_create_order(array( 'customer_id' => $userId ));
    $order->set_address($address, 'billing');

    // Add product first for calculation context
    $product = wc_get_product($productId);
    if ( ! $product ) {
        error_log( 'Invalid product ID: ' . $productId );
        return;
    }
    $order->add_product($product, 1);

    // Add sign-up fee with float amount
    $order->add_fee( 'Sign Up Fee', 1500.00, false );

    // Apply coupon correctly
    $coupon_code = 'NOFEE';
    $coupon = new WC_Coupon( $coupon_code );
    if ( ! is_wp_error( $coupon ) ) {
        $order->apply_coupon( $coupon );
    } else {
        error_log( 'Failed to apply coupon ' . $coupon_code . ': ' . $coupon->get_error_message() );
    }

    // Set payment gateway (check if gateway exists first)
    $payment_gateways = WC()->payment_gateways->payment_gateways();
    if ( isset( $payment_gateways['bacs'] ) ) {
        $order->set_payment_method( $payment_gateways['bacs'] );
    }

    $order->calculate_totals(); // Update order taxes and totals
    $note = __('Manually added order and subscription.');
    $order->update_status('completed', $note, true); // Set order status and save

    // Create subscription
    $subscription = wcs_create_subscription(array(
        'status' => 'pending',
        'order_id' => $order->get_id(),
        'customer_id' => $userId,
        'billing_period' => WC_Subscriptions_Product::get_period($product),
        'billing_interval' => WC_Subscriptions_Product::get_interval($product),
    ));

    if ( is_wp_error( $subscription ) ) {
        error_log( 'Subscription creation failed: ' . $subscription->get_error_message() );
        return;
    }

    $start_date = gmdate('Y-m-d H:i:s');
    $subscription->add_product($product, 1);

    $dates = array(
        'trial_end' => WC_Subscriptions_Product::get_trial_expiration_date( $product, $start_date ),
        'next_payment' => WC_Subscriptions_Product::get_first_renewal_payment_date( $product, $start_date ),
        'end' => WC_Subscriptions_Product::get_expiration_date( $product, $start_date ),
    );
    $subscription->update_dates($dates);
    $subscription->set_address($address, 'billing');
    $subscription->calculate_totals();

    // Update subscription status
    $subscription->update_status('active', $note, true);
}

Key Notes

  • Guard clauses (like checking for valid users/products) prevent unexpected crashes and make debugging easier.
  • WooCommerce order methods differ from cart methods—always refer to WC_Order documentation when working with orders directly.
  • Ensure your coupon is properly configured (active, valid for the target product, not expired) in the WooCommerce admin.

内容的提问来源于stack exchange,提问作者Reece

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 09:27:36