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

WooCommerce回购自定义插件:如何更新用户钱包余额?

WooCommerce回购计算器插件钱包余额更新问题

我正在开发一款WooCommerce回购计算器插件,核心逻辑如下:

  • 用户正常购买商品且订单完成后,可通过SKU申请回购
  • 回购完成后扣除部分金额,剩余金额存入用户钱包
  • 用户购买新品时,需从钱包余额中抵扣订单金额

目前已实现前端订单总额扣除钱包金额的功能,但数据库中的total_wallet_amount字段未同步更新。

现有代码

创建数据表的函数

function create_buy_back_calculator_table()
{
    global $wpdb;
    $charset_collate = $wpdb->get_charset_collate();
    $table_name = $wpdb->prefix . 'buy_back_calculator';
    $total_wallet_amount = $wpdb->prefix . 'total_wallet_amount';

    // 创建buy_back_calculator表的SQL语句
    $sql = "CREATE TABLE $table_name (
        id INT AUTO_INCREMENT PRIMARY KEY,
        sku VARCHAR(255) NOT NULL,
        user_name VARCHAR(255) NOT NULL,
        user_email VARCHAR(255) NOT NULL,
        user_billing_address VARCHAR(255) NOT NULL,
        user_phone_number VARCHAR(20) NOT NULL,
        date_of_product_purchase DATE NOT NULL,
        date_of_buyback DATE NOT NULL,
        product_price DECIMAL(10, 2) NOT NULL,
        number_of_days INT NOT NULL,
        buy_back_price DECIMAL(10, 2) NOT NULL,
        amount_in_wallet_remaining DECIMAL(10, 2) NOT NULL,
        transit_status VARCHAR(255) NOT NULL,
        image_path VARCHAR(255) NOT NULL
    ) $charset_collate;";

    // 执行创建buy_back_calculator表的SQL查询
    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    dbDelta($sql);

    // 创建total_wallet_amount表的SQL语句
    $sql = "CREATE TABLE $total_wallet_amount (
        id INT AUTO_INCREMENT PRIMARY KEY,
        user_email VARCHAR(255) NOT NULL,
        total_wallet_amount DECIMAL(19, 4) NOT NULL
    ) $charset_collate;";

    // 执行创建total_wallet_amount表的SQL查询
    dbDelta($sql);
}

尝试的扣款函数(仅前端生效)

function adjust_order_total_with_deduction()
{
    if (is_user_logged_in()) {
        global $wpdb;
        $current_user = wp_get_current_user();
        $user_email = $current_user->user_email;
        $total_wallet_amount_table = $wpdb->prefix . 'total_wallet_amount';
        $user_remaining_sum = $wpdb->get_var($wpdb->prepare("SELECT total_wallet_amount FROM $total_wallet_amount_table WHERE user_email = %s", $user_email));

        $deduction_amount = $user_remaining_sum; // 固定扣除金额
        if ($deduction_amount > 0) {
            WC()->cart->add_fee(__('Deduction Amount', 'your-text-domain'), -$deduction_amount);
        }
    }
}
add_action('woocommerce_cart_calculate_fees', 'adjust_order_total_with_deduction');

解决方案

问题出在woocommerce_cart_calculate_fees钩子仅负责修改前端显示的订单金额,不会触发数据库更新。需要在订单完成时同步更新钱包余额,同时优化抵扣逻辑避免异常情况。

修改后的完整代码:

// 前端订单金额扣除钱包余额,存储抵扣金额到会话
function adjust_order_total_with_deduction()
{
    if (is_user_logged_in()) {
        global $wpdb;
        $current_user = wp_get_current_user();
        $user_email = $current_user->user_email;
        $total_wallet_amount_table = $wpdb->prefix . 'total_wallet_amount';
        $user_remaining_sum = $wpdb->get_var($wpdb->prepare("SELECT total_wallet_amount FROM $total_wallet_amount_table WHERE user_email = %s", $user_email));

        // 确保抵扣金额不超过购物车总额,避免出现负数订单
        $cart_total = WC()->cart->get_subtotal();
        $deduction_amount = min(floatval($user_remaining_sum), floatval($cart_total));
        
        if ($deduction_amount > 0) {
            WC()->cart->add_fee(__('钱包余额抵扣', 'your-text-domain'), -$deduction_amount);
            // 将实际抵扣金额存入会话,用于订单完成时更新数据库
            WC()->session->set('wallet_deduction_amount', $deduction_amount);
        } else {
            WC()->session->set('wallet_deduction_amount', 0);
        }
    }
}
add_action('woocommerce_cart_calculate_fees', 'adjust_order_total_with_deduction');

// 订单完成时,更新数据库中的用户钱包余额
function update_wallet_balance_after_order_completion($order_id)
{
    $order = wc_get_order($order_id);
    $user_id = $order->get_user_id();
    
    if ($user_id === 0) return; // 跳过未登录用户的订单
    
    $current_user = get_user_by('id', $user_id);
    $user_email = $current_user->user_email;
    $deduction_amount = WC()->session->get('wallet_deduction_amount');
    
    if ($deduction_amount <= 0) return;
    
    global $wpdb;
    $total_wallet_amount_table = $wpdb->prefix . 'total_wallet_amount';
    
    // 执行数据库更新,扣除对应金额
    $wpdb->query($wpdb->prepare(
        "UPDATE $total_wallet_amount_table SET total_wallet_amount = total_wallet_amount - %f WHERE user_email = %s",
        $deduction_amount,
        $user_email
    ));
    
    // 清除会话中的抵扣金额,避免重复扣除
    WC()->session->__unset('wallet_deduction_amount');
}
add_action('woocommerce_order_status_completed', 'update_wallet_balance_after_order_completion');

关键优化点

  • 通过WC()->session存储抵扣金额,避免用户放弃下单时误更新数据库
  • 添加min()限制抵扣金额不超过购物车总额,防止订单金额为负
  • 仅在订单状态变为completed时更新数据库,确保交易真实完成
  • 处理未登录用户的情况,避免报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 22:57:52