Search code examples
javascriptemailwoocommercecoupon

Woocommerce: JS Button to send email with description from coupon page


I would like to be able to add a JS button to the coupon page to be able to send an email with the coupon description in it. I'm unfortunately not very knowledgeable in JS. I can see in the console that the data is correctly fed to the request (if that makes sense), but I always get 400 bad request, here is the code:

// Add the meta box
function add_coupon_email_meta_box() {
  add_meta_box( 'coupon-email', __( 'Send Email', 'woocommerce' ), 'coupon_email_meta_box_callback', 'shop_coupon', 'side' );
}
add_action( 'add_meta_boxes', 'add_coupon_email_meta_box' );


// Meta box callback function
function coupon_email_meta_box_callback( $post ) {
  ?>
  <form>
      <input type="hidden" name="coupon-id" value="<?=  $post->ID ?>" />
      <input type="hidden" name="security" value="<?= wp_create_nonce( 'coupon_email_nonce' ); ?>" />
      <input type="button" id="send-coupon-email" class="button button-primary" value="<?=  __( 'Send Email', 'woocommerce' ); ?>" />
  </form>

  <script>
    jQuery(document).ready(function($) {
        $('#send-coupon-email').on('click', function(e) {
            e.preventDefault();
            var couponId = $('input[name="coupon-id"]').val();
            var security = $('input[name="security"]').val();
            $.ajax({
                type: 'POST',
                url: ajaxurl,
                data: {
                    action: 'send_coupon_email',
                    coupon_id: couponId,
                    security: security
                },
                success: function(response) {
                    console.log(response);
                    // Do something on success
                },
                error: function(XMLHttpRequest, textStatus, errorThrown) {
                    console.log(XMLHttpRequest);
                    console.log(textStatus);
                    console.log(errorThrown);
                    // Do something on error
                }
            });
        });
    });

  </script>
  <?php
}


// Send coupon email
function send_coupon_email() {
    error_log('function send_coupon_email');
    // Validate the nonce
    check_ajax_referer( 'coupon_email_nonce', 'security', false );  
    
    // Get the coupon ID from the form data
    $coupon_id = intval( $_POST['coupon_id'] );
    
    // Make sure the coupon exists
    $coupon = new WC_Coupon( $coupon_id );
    if ( ! $coupon->get_id() ) {
        wp_send_json_error( __( 'Coupon not found.', 'woocommerce' ) );
    }
    
    // Get the customer ID from the coupon's metadata
    $customer_id = $coupon->get_meta( 'customer_id' );
    
    // Get the customer email from the customer ID
    $customer = get_user_by( 'id', $customer_id );
    $customer_email = $customer ? $customer->user_email : '';
    
    // Validate the customer email
    if ( ! is_email( $customer_email ) ) {
        wp_send_json_error( __( 'Invalid email address.', 'woocommerce' ) );
    }
    
    // Get the coupon code
    $coupon_code = $coupon->get_code();
    
    // Get the coupon description
    $coupon_description = $coupon->get_description();
    
    // Prepare the email data
    $to = $customer_email;
    $subject = __( 'Your coupon code', 'woocommerce' );
    $message = $coupon->get_description();
    $headers = array( 'Content-Type: text/html; charset=UTF-8' );
    
    // Send the email
    if ( wp_mail( $to, $subject, $message, $headers ) ) {       
        add_settings_error( 'coupon_email_sent', esc_attr( 'settings_updated' ), __( 'Email sent successfully.', 'woocommerce' ), 'updated' );
    } else {
        add_settings_error( 'coupon_email_not_sent', esc_attr( 'settings_updated' ), __( 'Email could not be sent.', 'woocommerce' ), 'error' );
    }
    
    wp_send_json_success();
}

What do I need to make this work?

(StackOverflow claims I need to add more details for me to be able to post since it's mostly code so here you go! X))


Solution

  • Okay, so:

    At the end of the day, I made it a bit more complex than what I'm posting right now so it's not impossible that by removing what was superfluous for something else than my specific case, I broke it a little but here we go. Note that as it is, this code implies that you have added a field to select an existing customer from where we're getting the email:

    function coupon_email_meta_box_callback( $post ) {
      ?>    
      <form>
        <h4>Select message type:</h4>
          <input type="hidden" name="coupon-id" value="<?=  $post->ID ?>" />
          <input type="hidden" name="security" value="<?= wp_create_nonce( 'coupon_email_nonce' ); ?>" />
          <input type="button" id="send-coupon-email" class="button button-primary" value="<?=  __( 'Send Email', 'woocommerce' ); ?>" />
      </form>
    
      <script>
        jQuery(document).ready(function($) {
            $('#send-coupon-email').click(function(){
                var coupon_id = $('input[name=coupon-id]').val();
    
                var data = {
                    'action': 'send_coupon_email',
                    'security': $('input[name=security]').val(),
                    'coupon_id': coupon_id,
                };
    
                $.post(ajaxurl, data, function(response) {
                    alert(response);
                });
            });
        });
      </script>
      <?php
    }
    
    
    
    // Sends email
    function send_coupon_email( $post_id ) {
        if(!wp_verify_nonce($_POST['security'], 'coupon_email_nonce')){
            wp_die('Security check failed.');
        }
        $coupon = new WC_Coupon($_POST['coupon_id']);
        $coupon_code = $coupon->get_code();
        $coupon_description = $coupon->get_description();
        $customer_name = '';
        $customer_id =  $coupon->get_meta('customer_id');   
        
        if($customer_id !== "none") {
            $customer = get_userdata( $customer_id );
            $customer_email = $customer->user_email;
            $customer_name = $customer->first_name;
        }
    
        // Send email to customer   
        // Define the message body          
    
        $website_title = html_entity_decode(get_bloginfo('name'), ENT_QUOTES, 'UTF-8');
        $title = __('Your deposit has been credited', 'lockoloop-customizer');  
        $subject = sprintf('[%s] %s', $website_title, $title );     
        $headers = "Content-Type: text/html\r\n";
        $mailer = WC()->mailer();
        $message = $mailer->wrap_message(
            $title,
            $saved_message
        );
        
        if (!empty($customer_email) && !empty($saved_message) ) {
            $mailer->send( $customer_email, $subject, $message, $headers );
            echo 'Email sent successfully.';
        } else {    
            echo 'Could not send the email due to missing information, check error log.';
        }
        wp_die();
    }
    
    add_action('wp_ajax_send_coupon_email', 'send_coupon_email');
    add_action('wp_ajax_nopriv_send_coupon_email', 'send_coupon_email');