WooCommerce优惠券生成问题求助:需为每个用户生成唯一券且会话内不重复
问题与解决方案
需求概述
用户访问类似example.com/cart/?coupon-code=mycoupon的链接时,需实现:
- 自动为每个用户生成唯一优惠券
- 会话内(用户未关闭浏览器/清除会话)刷新页面不再生成新券
- 避免重复生成优惠券、叠加应用的问题
现有代码的核心问题
- 每次触发
woocommerce_before_calculate_totals都会生成新优惠券码,未利用会话存储用户已生成的券 generate_random_coupon函数逻辑混乱:参数$coupon_generated未被使用,反而重新调用random_coupon_code生成新码- 未判断URL中的
coupon-code触发参数,导致所有购物车访问都触发生成 - 优惠券应用/移除逻辑错误,导致刷新时重复添加券
修正后的代码
// 检查优惠券是否存在 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
相关产品推荐
相关产品推荐

