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

WooCommerce优惠券生成问题求助:需为每个用户生成唯一券且会话内不重复

问题与解决方案

需求概述

用户访问类似example.com/cart/?coupon-code=mycoupon的链接时,需实现:

  • 自动为每个用户生成唯一优惠券
  • 会话内(用户未关闭浏览器/清除会话)刷新页面不再生成新券
  • 避免重复生成优惠券、叠加应用的问题

现有代码的核心问题

  1. 每次触发woocommerce_before_calculate_totals都会生成新优惠券码,未利用会话存储用户已生成的券
  2. generate_random_coupon函数逻辑混乱:参数$coupon_generated未被使用,反而重新调用random_coupon_code生成新码
  3. 未判断URL中的coupon-code触发参数,导致所有购物车访问都触发生成
  4. 优惠券应用/移除逻辑错误,导致刷新时重复添加券

修正后的代码

// 检查优惠券是否存在
function coupon_exists($coupon_code) {
    global $wpdb;
    $sql = $wpdb->prepare( "SELECT post_name FROM $wpdb->posts WHERE post_type = 'shop_coupon' AND post_name = %s", $coupon_code );
    return $wpdb->get_var($sql) ? true : false;
} 

// 生成唯一不重复的优惠券码
function random_coupon_code() {
    global $wpdb;
    $existing_codes = $wpdb->get_col("SELECT post_name FROM $wpdb->posts WHERE post_type = 'shop_coupon'");
    
    do {
        $generated_code = strtolower( wp_generate_password( 15, false ) );
    } while (in_array($generated_code, $existing_codes));
    
    return $generated_code;
}  

// 生成优惠券并保存
function generate_random_coupon($coupon_code) {
    // 优惠券默认设置
    $date_expires     = date('Y-m-d', strtotime('+1 days'));
    $discount_type    = 'fixed_cart';
    $coupon_amount    = '10';

    $coupon = new WC_Coupon();
    $coupon->set_code($coupon_code);
    $coupon->set_discount_type($discount_type);
    $coupon->set_amount($coupon_amount);
    $coupon->set_date_expires($date_expires);
    $coupon->save();

    return $coupon_code;
}


function hwn_add_programmatically_created_coupon_to_basket( $cart ) {
    // 后台非AJAX请求直接返回
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;
    // 避免重复触发
    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;

    // 1. 检查URL是否携带coupon-code触发参数
    if ( ! isset( $_GET['coupon-code'] ) )
        return;

    // 2. 初始化WooCommerce会话
    if ( ! WC()->session->has_session() ) {
        WC()->session->set_customer_session_cookie( true );
    }

    // 3. 从会话中获取用户已生成的优惠券码
    $user_coupon_code = WC()->session->get( 'user_unique_coupon' );

    // 4. 如果会话中没有优惠券码,生成并保存到会话
    if ( empty( $user_coupon_code ) ) {
        $user_coupon_code = random_coupon_code();
        // 确保优惠券不存在才生成
        if ( ! coupon_exists( $user_coupon_code ) ) {
            generate_random_coupon( $user_coupon_code );
        }
        // 把优惠券码存入会话
        WC()->session->set( 'user_unique_coupon', $user_coupon_code );
    }

    // 5. 处理优惠券的应用与移除逻辑
    $applied_coupons = $cart->get_applied_coupons();
    // 如果优惠券未应用,添加到购物车
    if ( ! in_array( $user_coupon_code, $applied_coupons ) ) {
        $cart->add_discount( $user_coupon_code );
    }
    // 移除其他可能存在的优惠券(确保只应用当前用户的唯一券)
    foreach ( $applied_coupons as $coupon ) {
        if ( $coupon !== $user_coupon_code ) {
            $cart->remove_coupon( $coupon );
        }
    }
}
add_action('woocommerce_before_calculate_totals', 'hwn_add_programmatically_created_coupon_to_basket'); 

关键修改说明

  • 会话存储:使用WooCommerce内置会话WC()->session存储用户的唯一优惠券码,确保同一会话内刷新不会重新生成
  • 触发条件判断:仅当URL携带coupon-code参数时才执行逻辑,避免无意义触发
  • 修正生成逻辑:generate_random_coupon直接使用传入的优惠券码,不再重复生成,避免逻辑冲突
  • 去重处理:循环生成优惠券码直到找到未存在的,确保全局唯一;同时移除其他优惠券,避免叠加应用
  • 性能优化:coupon_exists改用get_var直接获取结果,比get_results更高效

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 06:04:50