I recently had to modify a WooCommerce installation to accept gift cards by entering the gift card as a WooCommerce coupon. The gift card validity had to be checked via a SOAP call to an external API, in other words the coupons did not exist in WooCommerce. So I needed to hook into the point the coupon is added in the cart or checkout. There is a woocommerce_coupon_is_valid filter but it only runs after checking if the coupon exists in WooCommerce, and so will never run in our case.
By looking through the codex, I found a little known filter woocommerce_get_shop_coupon_data which allows developers to bypass the retrieval of the coupon from the database and create one programmatically. If our hook code returns an array with the coupon properties, WooCommerce will apply the coupon to the cart and calculate the correct discounts.
For some scenarios, we don’t need to create the coupon in the WordPress database at all. However, if we need to check usage limits we will need to create a database record so that WooCommerce can keep track of how many times it has been used. Since the woocommerce_get_shop_coupon_data is triggered several times in the cart, we need to first check if we’ve already created the coupon:
add_filter ( 'woocommerce_get_shop_coupon_data', 'mp_create_coupon', 10, 2 ); function mp_create_coupon( $data, $code ) { // Check if the coupon has already been created in the database global $wpdb; $sql = $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_title = %s AND post_type = 'shop_coupon' AND post_status = 'publish' ORDER BY post_date DESC LIMIT 1;", $code ); $coupon_id = $wpdb->get_var( $sql ); if ( empty( $coupon_id ) ) { // Create a coupon with the properties you need $data = array( 'discount_type' => 'fixed_cart', 'coupon_amount' => 100, // value 'individual_use' => 'no', 'product_ids' => array(), 'exclude_product_ids' => array(), 'usage_limit' => '', 'usage_limit_per_user' => '1', 'limit_usage_to_x_items' => '', 'usage_count' => '', 'expiry_date' => '2018-09-01', // YYYY-MM-DD 'free_shipping' => 'no', 'product_categories' => array(), 'exclude_product_categories' => array(), 'exclude_sale_items' => 'no', 'minimum_amount' => '', 'maximum_amount' => '', 'customer_email' => array() ); // Save the coupon in the database $coupon = array( 'post_title' => $code, 'post_content' => '', 'post_status' => 'publish', 'post_author' => 1, 'post_type' => 'shop_coupon' ); $new_coupon_id = wp_insert_post( $coupon ); // Write the $data values into postmeta table foreach ($data as $key => $value) { update_post_meta( $new_coupon_id, $key, $value ); } } return $data; }
Thank you for sharing this tutorial. I am trying to add a custom coupon code but having an error. Can you help me out to resolve my issue. I have seen the code in this tutorial https://www.cloudways.com/blog/create-woocommerce-coupon-code/ . It’s not working for my store.
add_action( ‘woocommerce_before_cart’, ‘sh_coupons_matched’ );
function sh_coupons_matched() {
global $woocommerce;
$sh_coupon = ‘OnlineShop’;
if ( $woocommerce->cart->has_discount( $sh_coupon ) ) return;
foreach ( $woocommerce->cart->cart_contents as $key => $values ) {
$autocoupon = array( 65 );
if( in_array( $values[‘product_id’], $autocoupon ) ) {
$woocommerce->cart->add_discount( $cw_coupon );
wc_print_notices();
}
}
}
Thanks four sharing this code. That is what I was looking for dynamic coupon validation.