phpwordpresswoocommercepayment-gatewaycoupon

Restrict payment gateways based on applied coupons in WooCommerce displaying a message


I would like to only show e.g. Stripe if coupon code 123 is used. So, I have come up with the code which is working, but I would also like to show a message at the top of the checkout, where the woo notices show. My message isn't showing correctly.

// restrict coupon codes payment method
add_filter('woocommerce_available_payment_gateways', 'unset_gateway_by_applied_coupons');

function unset_gateway_by_applied_coupons($available_gateways) {
    // prevents coupon error in admin
    if( is_admin() ) 
        return $available_gateways;
    
    global $woocommerce;
    $unset = false; // the norm
    
    // names of coupons
    $coupon_codes = array('test123', 'check123');
            
    foreach($coupon_codes as $coupon_code) {
        
        // if code is used in cart
        if(in_array($coupon_code, WC()->cart->get_applied_coupons() )){
            //echo 'found =' .$coupon_code;
            unset($available_gateways['bacs']);
            unset($available_gateways['invoice']);
            // $message = sprintf( __('<br><p class="coupon-code">The coupon code  "%s" can only use the Credit Card payment method.</p>'), $coupon_code);  // <<<<< not working
        }
            
    }
    return $available_gateways;
}

Solution

  • To display a message in checkout when restricting some payment methods conditionally, you can use WooCommerce wc_add_notice() function.

    Also, your code doesn't handle WooCommerce "Order Pay".

    The following will restrict available payment methods based on applied coupons in Checkout page and Order pay page, displaying a message:

    // Restrict available payment methods based on applied coupons
    add_filter('woocommerce_available_payment_gateways', 'restrict_checkout_available_payment_gateways_conditionally');
    function restrict_checkout_available_payment_gateways_conditionally( $available_gateways ) {
        $targeted_coupons = array('test123', 'check123'); // Define here the coupon codes
    
        // Only on checkout and order pay
        if( is_checkout() ) {
            if ( is_wc_endpoint_url('order-pay') ) { // Order pay page
                global $wp;
                $order_id = absint( $wp->query_vars['order-pay'] );
                $order = wc_get_order($order_id);
                $applied_coupons = $order->get_coupon_codes();
            }  elseif ( ! is_wc_endpoint_url() ) { // Checkout page
                $applied_coupons = WC()->cart->get_applied_coupons();
            }
        
            // Check if any defined coupon code is used in cart
            if ( $applied_coupons && array_intersect($targeted_coupons, $applied_coupons ) ) {
                if ( isset($available_gateways['bacs']) ) {
                    unset($available_gateways['bacs']);
                }
                if ( isset($available_gateways['invoice']) ) {
                    unset($available_gateways['invoice']);
                }
                // Display message
                wc_clear_notices();
                wc_add_notice( sprintf( __('You can only use the <strong>Credit Card</strong> payment method with coupon %s "%s".'), 
                    _n('code', 'codes', count($applied_coupons)), implode( '", "', $applied_coupons) ), 'notice');  
            }
        }
        return $available_gateways;
    }
    

    Code goes in functions.php file of your child theme (or in a plugin). Tested and works with WooCommerce Legacy checkout page shortcode. Untested with checkout Blocks. Tested also in "Order pay" page.

    enter image description here