Search code examples
phpwordpresswoocommerceorderscoupon

Creating a WooCommerce promo code after order completion


On a WooCommerce website I'm selling a gift voucher where the client can input the amount he wants to gift himself, I'd like after an order is paid that a WooCommerce promo code is created with the corresponding amount.

This is the code I came up with, but does not seem to work whatsoever.

add_action('woocommerce_order_status_completed', 'custom_promo_code_creation', 10, 1);
function custom_promo_code_creation($order_id) {
    $order = wc_get_order($order_id);
    $specific_product_id = 2081;
    $specific_product_price = 0;

    foreach ($order->get_items() as $item_id => $item) {
        $product_id = $item->get_product_id();
        if ($product_id === $specific_product_id) {
            $specific_product_price = $item->get_total();
            break;
        }
    }

    if ($specific_product_price > 0) {
        $coupon_code = generate_unique_voucher_code();
        $expiration_date = strtotime('+3 months'); // Set the expiration to 3 months from now

        $coupon = array(
            'post_title' => $coupon_code,
            'post_content' => '',
            'post_status' => 'publish',
            'post_author' => 1,
            'post_type' => 'shop_coupon'
        );

        $new_coupon_id = wp_insert_post($coupon);

        if ($new_coupon_id) {
            update_post_meta($new_coupon_id, 'discount_type', 'fixed_cart');
            update_post_meta($new_coupon_id, 'coupon_amount', $specific_product_price);
            update_post_meta($new_coupon_id, 'individual_use', 'yes');
            update_post_meta($new_coupon_id, 'product_ids', '');
            update_post_meta($new_coupon_id, 'exclude_product_ids', '');
            update_post_meta($new_coupon_id, 'usage_limit', 1);
            update_post_meta($new_coupon_id, 'expiry_date', $expiration_date);
        }
    }
}

The order is coming through normaly but no coupon is created


Solution

  • First, please enable WP_DEBUG as explained in: How to debug in WooCommerce 3+

    I rewrote your code in the right way, using WooCommerce CRUD methods instead of using WordPress functions (old outdated way). I have added some debug points, to allow you to check if everything works as it should:

    add_action( 'woocommerce_order_status_completed', 'custom_promo_code_creation', 10, 2 );
    function custom_promo_code_creation( $order_id, $order ) {
        $targeted_product_id = 2081;
        $item_total = 0;
    
        foreach ( $order->get_items() as $item ) {
            $product_id = $item->get_product_id();
            if ( in_array( $targeted_product_id, [$item->get_product_id(), $item->get_variation_id()]) ) {
                $item_total = $item->get_total();
                error_log('Item Found with a total amount of '.$item_total); // For testing
                break;
            }
        }
    
        if ( $item_total > 0 ) {
            $coupon_code = generate_unique_voucher_code();
            $coupon = new WC_Coupon();
            $coupon->set_code( $coupon_code );
            $coupon->set_status( 'publish' );
            $coupon->set_amount( $item_total );
            $coupon->set_discount_type( 'fixed_cart' );
            $coupon->set_description( sprintf(__('Generated coupon code from order #%s'), $order_id ) );
            $coupon->set_individual_use( 1 );
            $coupon->set_usage_limit( 1 );
            $coupon->set_date_expires( strtotime('+3 months') ); 
            $coupon->save();
    
            error_log('Generated coupon code: '.$coupon_code); // For testing
            error_log(print_r($coupon, true)); // For testing
        }
    }
    

    It should work.

    Once coupon will be generated, you can remove all 3 error_log() lines from the code, and disable back WP_DEBUG.