尝试跟踪错误以了解为什么应在woocommerce中触发Webhook之后为何电子邮件未发送 - php

我试图了解为什么有时在Woocommerce中购买后Webhook似乎启动,而有时却不启动。

我的理解是应该向woocommerce插件webhook中添加custom topic的自定义插件,其中添加了以下代码(我将在下面放置整个代码)

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' );

有两个文件,一个是插件,我所能告诉的是它当前所做的就是将自定义主题添加到webhook下拉选项中,以便我们可以在成功下订单后触发一个webhook。但是有时它会触发webhook,有时甚至不尽人意。我之所以这样说,是因为在将有效载荷发送到礼品卡平台后,应该从Webhook发出电子邮件,然后将礼品卡退回并发送电子邮件。

首先是插件PHP代码。我认为其他排队脚本是计划的功能,但仍不确定。

<?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();
}

现在,我无法确定这是否实际上是在向礼品卡平台发送有效载荷,或者网络挂钩是否正在完成所有工作。我很困惑,因为礼品卡平台是在Webhook和此插件中调用的,希望有人可以帮助阐明该插件中发生的事情,而不是根据主题触发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 = '[email protected]';
        $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 <[email protected]>\r\n";
        $headers .= "Reply-To: [email protected]\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'
    ?>

现在这是我的问题所在。我不知道邮件的原因($ to,$ subject,$ message,$ headers);永远不会发送是因为Webhook无法提交到礼品卡服务器,并且在礼品卡服务器端出现错误,或者是因为此Webhook无法发送电子邮件。或者,如果此webhook从未触发过。

现在可以帮助调试如果此Webhook的邮件功能从未发送过,那么通过将订单状态从处理更改为完成就可以发送它的一半时间。但是,这仅应用于内部,我们确实希望自动发送礼品卡信息,但是我希望有一种方法可以执行自定义操作,以从woocommerce的订购页面重新发送该Webhook。就像一个按钮或说重新发送礼品卡电子邮件的内容。

因此,我想了解的是,在Webhook或插件中,真正的有效负载在哪里提交给了礼品卡服务器?以及为什么当我在woocommerce中更改订单状态时,webhook电子邮件只提交一半时间,然后又提交另一半时间。

这里也有JS脚本,但是我现在不认为它们有任何作用。

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

  })

})

这是我得到的与webhook.php文件有关的错误日志

[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

参考方案

检查第86行的日志输出,警告开始于:

file_get_contents():无法启用加密...

该消息表明您使用了安全连接,因此请尝试将以下内容添加到请求标头中。

    $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 )
      )
    );

此外,最好在检查empty()时使用$result

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

编辑:由于不验证对等体是不安全的。请尝试以下操作,但也请参阅SSL context options以获取更多信息。

    $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 )
      )
    );

故障排除“警告:session_start():无法发送会话高速缓存限制器-标头已发送” - php

我收到警告:session_start()[function.session-start]:无法发送会话缓存限制器-标头已发送(错误输出开始如果我将表单数据提交到其他文件进行处理,则可以正常工作。但是,如果我将表单数据提交到同一页面,则会出现此错误。请建议<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0…

使用PHP包含时的淡入淡出过渡 - php

我正在尝试使用jQuery或CSS(或其他方式!)在DIV中包含的php页面上创建淡入淡出或滑动过渡。我四处搜寻,发现了很多淡入淡出过渡的示例,这些实例彼此淡入淡出div或隐藏内容淡入淡出,但是这种情况略有不同。我有一个DIV,其内容由导航栏控制。选中后,每个页面都可以使用PHP成功地包含在div中,但我想使内容淡入和淡出。关于如何在页面更改之间进行漂亮过渡…

AJAX调用只能与$(document).on('click')一起使用 - php

我有一个显示数据库条目的表。用户能够为每一行打开一个弹出菜单。选项之一是删除数据库条目,并且该表应通过AJAX调用相应地刷新。只要有人单击#delete-toggle中的table-popup,我就会在HTML页面上进行AJAX调用(table-popup是div,当有人单击每行中存在的表中的table-edit-button时出现的表): <div …

将输入类型复选框关联到输入类型文本 - php

我有一个问题,我需要将输入类型复选框与输入类型文本关联。情况如下:从数据库中提取数据。 PK数据是复选框的值。当复选框选择输入类型的文本时,您可以在其中输入特定数字。现在的问题是,选中所有类型的复选框输入文本都会被激活。我希望通过选择复选框输入,仅启用与复选框相关联的输入。我的HTML代码(此代码创建一个输入复选框,并为数据库中的每个记录输入文本,而我要激活…

PHP PDO组按列名称查询结果 - php

以下PDO查询返回以下结果:$db = new PDO('....'); $sth = $db->prepare('SELECT ...'); 结果如下: name curso ABC stack CDE stack FGH stack IJK stack LMN overflow OPQ overflow RS…