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
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.