Stoto
Stoto

Reputation: 51

How to auto generate a coupon in WooCommerce and apply it to the cart?

I have scoured the net and many pages here on stackoverflow. I’m trying to set up a WooCommerce abandoned cart flow where an auto generated coupon in WooCommerce can be added to the cart. I have butchered various code that I’ve found. I have it pretty rough but kinda working. I’m not that familiar with PHP so struggling to get this to behave correctly.

I have the coupon auto generating in WooCommerce admin when a product is added to the cart, its also being applied on the cart page. However every time the page is refreshed more coupons are being generated and added to the cart. Also coupons are generated every time a product is added to the cart.

Is there anyway to limit the coupon so that it is only generated and applied once?

I was planning to direct to the WooCommerce shopping cart from a recreated abandoned cart flow in Klaviyo, where all products from a customers abandoned cart will be added. I was planning to append the URL with something like https://example.com/cart?coupon-code=mycoupon

Would it at all be possible to trigger the coupon creation from the URL variable (eg/ mycoupon) ?

Please let me know if this is even possible? Before I waste another day of my life on this project...lol

Heres my code so far.

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 );

    $coupon_codes = $wpdb->get_results($sql);

    if (count($coupon_codes)> 0) {
        return true;
    }
    else {
        return false;
    }
} 

// Utility function that generate a non existing coupon code (as each coupon code has to be unique)
function random_coupon_code() {
    global $wpdb;
    
    // Get an array of all existing coupon codes
    $coupon_codes_check = $wpdb->get_col("SELECT post_name FROM $wpdb->posts WHERE post_type = 'shop_coupon'");
    
    for ( $i = 0; $i < 1; $i++ ) {
        $generated_code = strtolower( wp_generate_password( 15, false ) );
        
        // Check if the generated code doesn't exist yet
        if( in_array( $generated_code, $coupon_codes_check ) ) {
            $i--; // continue the loop and generate a new code
        } else {
            break; // stop the loop: The generated coupon code doesn't exist already
        }
    }
    return $generated_code;
}  

function generate_random_coupon($coupon_generated) {
    
// Set some coupon data by default
    $date_expires     = date('Y-m-d', strtotime('+1 days'));
    $discount_type    = 'fixed_cart'; // 'store_credit' doesn't exist
    $coupon_amount    = '10';

    $coupon = new WC_Coupon();
    
    // Generate a non existing coupon code name
    $coupon_code  = random_coupon_code();
    $coupon->set_code($coupon_generated);
    //the coupon discount type can be 'fixed_cart', 'percent' or 'fixed_product', defaults to 'fixed_cart'
    $coupon->set_discount_type($discount_type);
    //the discount amount, defaults to zero
    $coupon->set_amount($coupon_amount );
    $coupon->set_date_expires( $date_expires );

    //save the coupon
    $coupon->save();

    return $coupon_generated;
}


function hwn_add_programmatically_created_coupon_to_basket( $cart ) {
    
   if ( is_admin() && ! defined( 'DOING_AJAX' ) )
      return;
   if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
      return;
   $coupon_code  = random_coupon_code();
    
   if (!coupon_exists($coupon_code)) {
      generate_random_coupon($coupon_code);
   }        
   $applied_coupons  = $cart->get_applied_coupons();
   if( ! in_array($coupon_code, $applied_coupons)){
      $cart->add_discount( $coupon_code );
      wc_print_notices();
   }
   elseif( in_array($coupon_code, $applied_coupons)){
      $cart->remove_coupon( $coupon_code );
   }    
}
add_action('woocommerce_before_calculate_totals', 'hwn_add_programmatically_created_coupon_to_basket'); 

https://i.sstatic.net/65fZX.png

https://i.sstatic.net/xVGyn.png

https://i.sstatic.net/GX49V.png

Upvotes: 2

Views: 2071

Answers (1)

Bhautik
Bhautik

Reputation: 11282

You can get a coupon code from the URL using the GET method. try the below code. You remove the function random_coupon_code because now you generate coupon code based on URL.

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 );

    $coupon_codes = $wpdb->get_results($sql);

    if ( count( $coupon_codes ) > 0 ) {
        return true;
    } else {
        return false;
    }
} 

function generate_coupon($coupon_generated) {
    
    // Set some coupon data by default
    $date_expires     = date('Y-m-d', strtotime('+1 days'));
    $discount_type    = 'fixed_cart'; // 'store_credit' doesn't exist
    $coupon_amount    = '10';

    $coupon = new WC_Coupon();
    
    $coupon->set_code($coupon_generated);
    //the coupon discount type can be 'fixed_cart', 'percent' or 'fixed_product', defaults to 'fixed_cart'
    $coupon->set_discount_type($discount_type);
    //the discount amount, defaults to zero
    $coupon->set_amount($coupon_amount );
    $coupon->set_date_expires( $date_expires );

    //save the coupon
    $coupon->save();

    return $coupon_generated;
}

function hwn_add_programmatically_created_coupon_to_basket( $cart ) {
    
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;
    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;
    
    $coupon_code = ( isset( $_GET['coupon-code'] ) && $_GET['coupon-code'] != '' ) ? $_GET['coupon-code'] : '' ;

    if( $coupon_code == '' ){
        return;
    }

    $applied_coupons = $cart->get_applied_coupons();

    if( empty( $applied_coupons ) || ! in_array( $coupon_code, $applied_coupons ) ){
        if ( !coupon_exists( $coupon_code ) ) {
            generate_coupon( $coupon_code );
        }   
        $cart->add_discount( $coupon_code );
    }       

}
add_action('woocommerce_before_calculate_totals', 'hwn_add_programmatically_created_coupon_to_basket');

Tested and works

enter image description here

Upvotes: 2

Related Questions