Trying to trace error for why email is not sending

2020-04-08 13:41发布

问题:

I am trying to see why sometimes the webhook seems to fire and sometimes it doesn't after a purchase in Woocommerce.

There is a custom plugin that is supposed to add in a custom topic to the woocommerce plugin webhook is my understanding which is added with the following code (I will be placing the entire code below)

function add_new_webhook_topics( $topics ) {
    // New topic array to add to the list, must match hooks being created.
    $new_topics = array( 
        'order.gift_card' => __( 'Order Gift Card', 'woocommerce' ),
        );
    return array_merge( $topics, $new_topics );
 }
 add_filter( 'woocommerce_webhook_topics', 'add_new_webhook_topics' );

There are two files one is the plugin, which all I can tell is it does currently is add the custom topic to the webhook dropdown options so that we can then fire a webhook when an order is successfully placed. However sometimes it will fire the webhook and sometimes not as far as I can tell. The reason I say that is because a email is supposed to be fired from the webhook after a payload is sent to a gift card platform and then the giftcard are returned and the email is sent.

First here is the plugin PHP code. I think the additional enqueued scripts are planned features but still not sure.

<?php


 // Get grouped product ID from child product ID
 function get_parent_grouped_id( $children_id ){
     global $wpdb;
     $results = $wpdb->get_col("SELECT post_id FROM {$wpdb->prefix}postmeta
         WHERE meta_key = '_children' AND meta_value LIKE '%$children_id%'");
     // Will only return one product Id or false if there is zero or many
     return sizeof($results) == 1 ? reset($results) : false;
 }
 /**
  * add_new_topic_hooks will add a new webhook topic hook. 
  * @param array $topic_hooks Esxisting topic hooks.
  */
 function add_new_topic_hooks( $topic_hooks ) {
    // Array that has the topic as resource.event with arrays of actions that call that topic.
    $new_hooks = array(
        'order.gift_card' => array(
            'order_gift_card_filter',
            ),
        );
    return array_merge( $topic_hooks, $new_hooks );
 }
 add_filter( 'woocommerce_webhook_topic_hooks', 'add_new_topic_hooks' );
 /**
  * add_new_topic_events will add new events for topic resources.
  * @param array $topic_events Existing valid events for resources.
  */
 function add_new_topic_events( $topic_events ) {
    // New events to be used for resources.
    $new_events = array(
        'gift_card',
        );
    return array_merge( $topic_events, $new_events );
 }
 add_filter( 'woocommerce_valid_webhook_events', 'add_new_topic_events' );
 /**
  * add_new_webhook_topics adds the new webhook to the dropdown list on the Webhook page.
  * @param array $topics Array of topics with the i18n proper name.
  */
 function add_new_webhook_topics( $topics ) {
    // New topic array to add to the list, must match hooks being created.
    $new_topics = array( 
        'order.gift_card' => __( 'Order Gift Card', 'woocommerce' ),
        );
    return array_merge( $topics, $new_topics );
 }
 add_filter( 'woocommerce_webhook_topics', 'add_new_webhook_topics' );
 /**
  * my_order_item_check will check an order when it is created through the checkout form,
  * if it has product ID 1030 as one of the items, it will fire off the action `order_gift_card_filter`
  * 
  * @param  int    $order_id    The ID of the order that was just created.
  * @param  array  $posted_data Array of all of the data that was posted through checkout form.
  * @param  object $order       The order object.
  * @return null
  */
  function my_order_item_check( $order_id, $posted_data, $order ) {
    $order = wc_get_order( $order_id );
    $order_status = $order->status;
    $items = $order->get_items();
    //$picnic_ordered_bool = false;
    foreach ( $items as $item ) {

        if ( is_a( $item, 'WC_Order_Item_Product' ) ) {

            if ( 1457 === $item->get_product_id() ) {

          $item_data = $item->get_data();
          $item_meta_data_group = $item_data['meta_data'];
          $gift_card_data = array();
          foreach ( $item_meta_data_group as $item_meta_data ) {
            $gift_card_data[$item_meta_data->key] = $item_meta_data->value;
          }

          do_action( 'order_gift_card_filter', $order_id, $posted_data, $order );

            }
        /*if ( '1611' === get_parent_grouped_id( $item->get_product_id() ) ) {

          $item_data = $item->get_data();
          $item_order_id = $item_data['order_id'];

          $picnic_ordered_bool = true;

        }*/

        }
    }
  }
 /**
  *  The two below actions are what the order.created webhook is tied into, it is up to you to use these if you wish. 
  */
  //add_action( 'woocommerce_payment_complete', 'my_order_item_check', 10, 4 );
  add_action( 'woocommerce_checkout_order_processed', 'my_order_item_check', 10, 3 );
  //add_action( 'woocommerce_process_shop_order_meta', 'my_order_item_check', 10, 2 );

add_action( 'wp_enqueue_scripts', 'add_ajax_script' );
function add_ajax_script() {
  wp_enqueue_script( 'check-balance', plugins_url( '/check-balance.js', __FILE__ ), array('jquery'), '1.0', true );
  wp_enqueue_script( 'secure-register', plugins_url( '/secure-register.js', __FILE__ ), array('jquery'), '1.0', true );
  wp_localize_script( 'check-balance', 'gi_check_balance', array( 'ajax_url' => admin_url('admin-ajax.php') ) );
  wp_localize_script( 'secure-register', 'gi_secure_register', array( 'ajax_url' => admin_url('admin-ajax.php') ) );
}

add_action( 'wp_ajax_nopriv_gi_check_balance', 'gi_check_balance' );
add_action( 'wp_ajax_gi_check_balance', 'gi_check_balance' );
function gi_check_balance() {
  $gx_url_1 = 'gift-card.com';
  $gx_url_2 = 'gift-card-1.com';
  $gx_port_1 = 54643;
  $gx_port_2 = 432141;
  $gx_post_url_1 = $gx_url_1 . ':' . $gx_port_1;
  $gx_post_url_2 = $gx_url_2 . ':' . $gx_port_2;
  $gx_user = '341241';
  $gx_password = '432141';

  $gx_card_number = $_POST['gx_card_number'];
  /*$gx_card_pin = $_POST['gx_card_pin'];
  if( empty($gx_card_pin) ) {
    $gx_card_pin = 'XXXX';
  }*/

  $data = array(
    'method' => '994',
    'params' => [
      'en',
      'rc1',
      //null,
      $gx_user,
      $gx_password,
      $gx_card_number,
      $gx_card_pin,
      null
    ],
    'id' => 'test'
  );

  $options = array(
    'http' => array(
      'method' => 'POST',
      'header' => 'Content-Type: application/json',
      'content' => json_encode( $data )
    )
  );

  $context  = stream_context_create( $options );
  $result = file_get_contents( $gx_post_url_1, false, $context );
  if ( $result == false ) {
    $result = file_get_contents( $gx_post_url_2, false, $context );
  }
  $response = json_decode( $result );

  echo $result;
  //echo json_encode($result) ;
  //var_dump( $response );
  //echo $response;

  die();
}

Now I can't tell if this is actually sending a payload to the gift-card platform or if the webhook is doing all that work. I am confused because the gift-card platform is called in the webhook and in this plugin, hopefully someone can help clarify what is going on in this plugin beyond firing the webhook based off of the topic.

And here is the webhook

  <?php 
    // required headers
    header("Access-Control-Allow-Origin: *");
    header("Content-Type: application/json; charset=UTF-8");

    $passed = false;
    $request_body = file_get_contents('php://input');
    $secret = 'secret452323';
    $sig = base64_encode(hash_hmac('sha256', $request_body, $secret, true));

    if( !function_exists('apache_request_headers') ) {
      function apache_request_headers() {
        $headers = array();
        foreach($_SERVER as $key => $value) {
            if (substr($key, 0, 5) <> 'HTTP_') {
                continue;
            }
            $header = str_replace(' ', '-', ucwords(str_replace('_', ' ', strtolower(substr($key, 5)))));
            $headers[$header] = $value;
        }
        return $headers;
      }
    }
    $header = apache_request_headers(); 
    foreach ( $header as $headers => $value ) {
      if( $headers == 'X-Wc-Webhook-Signature' ) {
        if ( $value == $sig ) {
          $passed = true;
        }
      }
    }

    if( $passed !== true ) {
      header("Location: https://dev-site.com");
    } else {

    /*$gx_url = 'https://dev-gift-card.com';
    $gx_port = 50104;
    $gx_post_url = $gx_url . ':' . $gx_port;
    $gx_user = '423523';
    $gx_password = 'hfja98eshj98234j';*/
    $gx_url_1 = 'giftcard.com';
    $gx_url_2 = 'giftcard-1.com';
    $gx_port_1 = 45353;
    $gx_port_2 = 43214;
    $gx_post_url_1 = $gx_url_1 . ':' . $gx_port_1;
    $gx_post_url_2 = $gx_url_2 . ':' . $gx_port_2;
    $gx_user = '3424';
    $gx_password = '38234287';

    $data = json_decode(file_get_contents('php://input'), true);

    foreach( $data['line_items'] as $item ) {
      if( $item['product_id'] == 1457 ) {
        $item_meta_data_group = $item['meta_data'];
        $gift_card_data = array();
        foreach( $item_meta_data_group as $item_meta_data ) {
          $gift_card_data[$item_meta_data['key']] = $item_meta_data['value'];
        }

        $data_modified = array(
          'method' => '904',
          'params' => [
            'en',
            null,
            $gx_user,
            $gx_password,
            str_replace(array(',', '$', ' '), '', $gift_card_data['gift-card-amount']),
            null,
            null,
            null
          ],
          'id' => 'test'
        );

        $options = array(
          'http' => array(
            'method' => 'POST',
            'header' => 'Content-Type: application/json',
            'content' => json_encode( $data_modified )
          )
        );

        $context  = stream_context_create( $options );
        //$result = file_get_contents( $gx_post_url, false, $context );
        $result = file_get_contents( $gx_post_url_1, false, $context );
        if ( $result == false ) {
          $result = file_get_contents( $gx_post_url_2, false, $context );
        }
        $response = json_decode( $result );
        $response_reference = explode(':', $response->result[2]);
        //echo $result;

        //$to = 'example@gmail.com';
        $to = $gift_card_data['recipient_email'];
        $subject_decoded = 'You received a gift card for Place | Deane House';
        $subject = '=?UTF-8?B?' . base64_encode( $subject_decoded ) . '?=';
        $message = '<table border="0" cellspacing="0" cellpadding="0" width="100%" style="width: 100%; border-collapse: collapse;"><tbody><tr><td style="padding: 40px 40px 20px; background-color: #f9f9f9;" align="center"><table border="0" cellspacing="0" cellpadding="0" width="600" style="border-collapse: collapse;"><tbody>';
        $message .= '<tr><td align="center" valign="bottom" style="padding: 0 0 20px;">';
        $message .= '<img src="https://website.com/wp-content/uploads/2019/05/RCDH-ComLogo.png" alt="Place;"

 width="600" height="87" style="vertical-align: bottom;" />';
        $message .= '</td></tr>';
        $message .= '<tr><td align="center" style="padding: 10px 40px 20px; background-color: #ffffff; color: #676767; font-family: Helvetica, Arial, sans-serif;">';
        $message .= '<h2 style="font-family: Garamond, serif; font-size: 28px; font-weight: 600; color: #444444;">' . (!empty($gift_card_data['recipient_name']) ? $gift_card_data['recipient_name'] : 'Whoa') . ', you&rsquo;ve got ' . $gift_card_data['gift-card-amount'] . ' to spend at place</h2>';
        $message .= '<p style="color: #676767;">' . (!empty($gift_card_data['sender']) ? $gift_card_data['sender'] : 'Someone') . ' sent you a gift card' . (!empty($gift_card_data['message']) ? ' with the following message:' : '.') . '</p>';
        if( !empty($gift_card_data['message']) ) {
          $message .= '<p style="color: #676767;"><i><br />' . nl2br($gift_card_data['message']) . '<br /><br /></i></p>';
        }
        $message .= '<img src="https://dev.website.com/wp-content/uploads/2019/06/rdch-gc.jpg" alt="" width="520" height="334" />';
        //$message .= '<img src="https://www.barcodesinc.com/generator/image.php?code=' . $response->result[3] . '&style=68&type=C39&width=300&height=50&xres=1&font=4" alt="" />';
        // barcode generator website: https://www.barcodesinc.com/generator/index.php
        $message .= '<p style="color: 676767; font-size: 1.25em;"><b>Card Number:</b> ' . $response->result[3] . '<br /> <b>PIN:</b> ' . $response_reference[1] . '<br /> <b>Card Amount:</b> ' . $response->result[4] . '<br /> <b>Reference Number:</b> ' . $response_reference[0] . '</p>';
        $message .= '</td></tr>';
        $message .= '<tr><td align="center" style="padding: 20px 0 0;">';
        $message .= '<p style="color: #676767;"><b>We look forward to you dining with us!</b></p>';  
        $message .= '</td></tr>';
        $message .= '</tbody></table></td></tr></tbody></table>';
        $headers = "From: Gift Cards <noreply@website.com>\r\n";
        $headers .= "Reply-To: noreply@website.com\r\n";
        $headers .= "MIME-Version: 1.0\r\n";
        $headers .= "Content-Type: text/html; charset=ISO-8859-1\r\n";
        mail($to, $subject, $message, $headers);
      }
    } // end foreach

    } // end if else '$passed !== true'
    ?>

Now here is where my issue lies. I can't tell if the reason the mail($to, $subject, $message, $headers); never gets sent is because the webhook is failing to submit to the gift-card server and is getting a error on the gift card server end, or if it's this webhook failing to send the email. Or if this webhook is never fired.

Now to help debug If the mail function for this webhook never get's sent, which it get's sent about half the time I can get it to send by changing the order status from processing to completed. However that should only be for internal we do want the gift card info sent automatically, I would like to however have a way to have a custom action to resend this webhook from the order page in woocommerce. Like a button or something that says resend gift card email.

So what I am trying to understand where is the real payload being submitted to the gift-card server, in the webhook or in the plugin? and why does the webhook email only submit half the time and then will submit the other half when I change the order status in woocommerce.

Here are the JS scripts as well, but I don't think they do anything at the moment.

check-balance.js

jQuery(document).ready(function($) {

  // checks card balance
  $('.gi-check-balance').submit(function() {

    var gx_card_number = $(this).find('[name=card-number]').val()
    var gx_card_pin = $(this).find('[name=card-pin]').val()

    $.ajax({
      url: gi_check_balance.ajax_url,
      type: 'post',
      data: {
        action: 'gi_check_balance',
        gx_card_number: gx_card_number,
        gx_card_pin: gx_card_pin
      },
      dataType: 'json',
      success: function(response) {
        console.log(response)
        $('.gi-check-balance-result').text(response['result'][2])
        //$('.gi-check-balance-result').text(JSON.stringify(response))
        $('.gi-check-balance-result').show()
      }
    })

    return false

  })

})

secure-register.js

jQuery(document).ready(function($) {

  // registers gift card
  $('.gi-secure-register').submit(function() {

    var gx_register_amount = $(this).find('[name=register-amount]').val()

    $.ajax({
      url: gi_secure_register.ajax_url,
      type: 'post',
      data: {
        action: 'gi_secure_register',
        gx_register_amount: gx_register_amount
      },
      dataType: 'json',
      success: function(response) {
        //$('.gi-secure-register-result').html('Reference Number: ' + response['result'][2] + '<br>' + 'Card Number: ' + response['result'][3] + '<br>' + 'Card Amount: ' + response['result'][4])
        $('.gi-secure-register-result').text(response)
        $('.gi-secure-register-result').show()
      }
    })

    return false

  })

})

Here is a error log I was getting that had anything to do with the webhook.php file

[10-Nov-2019 21:42:59 UTC] PHP   1. {main}() /Users/anderskitson/Local Sites/river-cafe/app/public/wp-content/plugins/givex-integrate/webhook.php:0
[10-Nov-2019 21:42:59 UTC] PHP   2. file_get_contents() /Users/anderskitson/Local Sites/river-cafe/app/public/wp-content/plugins/givex-integrate/webhook.php:86
[10-Nov-2019 21:42:59 UTC] PHP Warning:  file_get_contents(): Failed to enable crypto in /Users/anderskitson/Local Sites/river-cafe/app/public/wp-content/plugins/givex-integrate/webhook.php on line 86
[10-Nov-2019 21:42:59 UTC] PHP Stack trace:
[10-Nov-2019 21:42:59 UTC] PHP   1. {main}() /Users/anderskitson/Local Sites/river-cafe/app/public/wp-content/plugins/givex-integrate/webhook.php:0
[10-Nov-2019 21:42:59 UTC] PHP   2. file_get_contents() /Users/anderskitson/Local Sites/river-cafe/app/public/wp-content/plugins/givex-integrate/webhook.php:86
[10-Nov-2019 21:42:59 UTC] PHP Warning:  file_get_contents(https://dev-dataconnect.givex.com:50104): failed to open stream: operation failed in /Users/anderskitson/Local Sites/river-cafe/app/public/wp-content/plugins/givex-integrate/webhook.php on line 86
[10-Nov-2019 21:42:59 UTC] PHP Stack trace:
[10-Nov-2019 21:42:59 UTC] PHP   1. {main}() /Users/anderskitson/Local Sites/river-cafe/app/public/wp-content/plugins/givex-integrate/webhook.php:0
[10-Nov-2019 21:42:59 UTC] PHP   2. file_get_contents() /Users/anderskitson/Local Sites/river-cafe/app/public/wp-content/plugins/givex-integrate/webhook.php:86
[10-Nov-2019 21:42:59 UTC] PHP Notice:  Trying to get property 'result' of non-object in /Users/anderskitson/Local Sites/river-cafe/app/public/wp-content/plugins/givex-integrate/webhook.php on line 92
[10-Nov-2019 21:42:59 UTC] PHP Stack trace:
[10-Nov-2019 21:42:59 UTC] PHP   1. {main}() /Users/anderskitson/Local Sites/river-cafe/app/public/wp-content/plugins/givex-integrate/webhook.php:0
[10-Nov-2019 21:42:59 UTC] PHP Notice:  Trying to get property 'result' of non-object in /Users/anderskitson/Local Sites/river-cafe/app/public/wp-content/plugins/givex-integrate/webhook.php on line 112
[10-Nov-2019 21:42:59 UTC] PHP Stack trace:
[10-Nov-2019 21:42:59 UTC] PHP   1. {main}() /Users/anderskitson/Local Sites/river-cafe/app/public/wp-content/plugins/givex-integrate/webhook.php:0
[10-Nov-2019 21:42:59 UTC] PHP Notice:  Trying to get property 'result' of non-object in /Users/anderskitson/Local Sites/river-cafe/app/public/wp-content/plugins/givex-integrate/webhook.php on line 112
[10-Nov-2019 21:42:59 UTC] PHP Stack trace:
[10-Nov-2019 21:42:59 UTC] PHP   1. {main}() /Users/anderskitson/Local Sites/river-cafe/app/public/wp-content/plugins/givex-integrate/webhook.php:0
[10-Nov-2019 21:42:59 UTC] PHP Notice:  Undefined variable: mail in /Users/anderskitson/Local Sites/river-cafe/app/public/wp-content/plugins/givex-integrate/webhook.php on line 124
[10-Nov-2019 21:42:59 UTC] PHP Stack trace:
[10-Nov-2019 21:42:59 UTC] PHP   1. {main}() /Users/anderskitson/Local Sites/river-cafe/app/public/wp-content/plugins/givex-integrate/webhook.php:0

回答1:

Checking your log output in line 86 the Warning starts with:

file_get_contents(): Failed to enable crypto...

That message indicates that you use secure connection so try adding the following to your request headers.

    $options = array(
      'ssl'=>array(
        'verify_peer'=>false,
        'verify_peer_name'=>false
      ),
      'http' => array(
        'method' => 'POST',
        'header' => 'Content-Type: application/json',
        'content' => json_encode( $data_modified )
      )
    );

In addition it is better to use empty() on checking $result

    if ( empty($result) ) {
      $result = file_get_contents( $gx_post_url_2, false, $context );
    }

EDIT: Since it is not safe to not verify peer. Try the following, but also take a look to SSL context options for more information.

    $options = array(
      'ssl'=>array(
        'verify_peer'=>true,
        'verify_peer_name'=>true,
        'cafile'=>'path/to/cafile.pem',
        'CN_match'=>'demo.com',
        'chiphers'=>'HIGH:!SSLv2:!SSLv3',
        'disable_compression'=>true
      ),
      'http' => array(
        'method' => 'POST',
        'header' => 'Content-Type: application/json',
        'content' => json_encode( $data_modified )
      )
    );