验证Laravel中的Woocommerce Web挂钩

时间:2017-08-01 10:54:55

标签: php wordpress laravel woocommerce webhooks

我正在尝试通过来自Woocommerce网络钩子的请求来验证数据,该钩子负责更新Laravel数据库中的产品项目。

我已经创建了一个名为VerifyWoocommerce的中间件,它可以正常启动,正如我在日志中看到的那样。

我有点不确定如何验证传入的请求实际来自Woocommerce。

这是我的VerifyWoocommerce.php

<?php

namespace App\Http\Middleware;

use Closure;
use Request;
use Log;

class VerifyWoocommerce
{

    public function handle($request, Closure $next)
    {
        $signature = Request::header('x-wc-webhook-signature');
        $calculated_hmac = base64_encode(hash_hmac('sha256', $signature, env('WOOCOMMERCE_WEBHOOK_ITEM_UPDATED'), true));

        Log::debug($signature);
        Log::debug($calculated_hmac);


        return $next($request);
    }
}

两个变量都返回不同的值。我比较正确的值吗?

更新

这是Woocommerce发送的正文输出

[2017-08-01 15:12:34] local.DEBUG: array (
  'id' => 38,
  'name' => 'Long Sleeve Tee',
  'slug' => 'long-sleeve-tee',
  'permalink' => 'http://velvetcake.local/product/long-sleeve-tee/',
  'date_created' => '2017-07-31T07:45:31',
  'date_created_gmt' => '2017-07-31T07:45:31',
  'date_modified' => '2017-08-01T15:12:33',
  'date_modified_gmt' => '2017-08-01T15:12:33',
  'type' => 'simple',
  'status' => 'publish',
  'featured' => false,
  'catalog_visibility' => 'visible',
  'description' => '<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>',
  'short_description' => NULL,
  'sku' => NULL,
  'price' => '25',
  'regular_price' => '25',
  'sale_price' => NULL,
  'date_on_sale_from' => NULL,
  'date_on_sale_from_gmt' => NULL,
  'date_on_sale_to' => NULL,
  'date_on_sale_to_gmt' => NULL,
  'price_html' => '<span class="woocommerce-Price-amount amount"><span class="woocommerce-Price-currencySymbol">&#82;</span>21.93</span>',
  'on_sale' => false,
  'purchasable' => true,
  'total_sales' => 0,
  'virtual' => false,
  'downloadable' => false,
  'downloads' => 
  array (
  ),
  'download_limit' => -1,
  'download_expiry' => -1,
  'external_url' => NULL,
  'button_text' => NULL,
  'tax_status' => 'taxable',
  'tax_class' => NULL,
  'manage_stock' => false,
  'stock_quantity' => NULL,
  'in_stock' => true,
  'backorders' => 'no',
  'backorders_allowed' => false,
  'backordered' => false,
  'sold_individually' => false,
  'weight' => NULL,
  'dimensions' => 
  array (
    'length' => NULL,
    'width' => NULL,
    'height' => NULL,
  ),
  'shipping_required' => true,
  'shipping_taxable' => true,
  'shipping_class' => NULL,
  'shipping_class_id' => 0,
  'reviews_allowed' => true,
  'average_rating' => '0.00',
  'rating_count' => 0,
  'related_ids' => 
  array (
    0 => 40,
    1 => 39,
    2 => 41,
  ),
  'upsell_ids' => 
  array (
  ),
  'cross_sell_ids' => 
  array (
  ),
  'parent_id' => 0,
  'purchase_note' => NULL,
  'categories' => 
  array (
    0 => 
    array (
      'id' => 18,
      'name' => 'Tshirts',
      'slug' => 'tshirts',
    ),
  ),
  'tags' => 
  array (
  ),
  'images' => 
  array (
    0 => 
    array (
      'id' => 19,
      'date_created' => '2017-07-31T07:45:31',
      'date_created_gmt' => '2017-07-31T07:45:31',
      'date_modified' => '2017-07-31T07:45:31',
      'date_modified_gmt' => '2017-07-31T07:45:31',
      'src' => 'http://velvetcake.local/wp-content/uploads/2017/07/long-sleeve-tee.jpg',
      'name' => 'Long Sleeve Tee',
      'alt' => NULL,
      'position' => 0,
    ),
  ),
  'attributes' => 
  array (
  ),
  'default_attributes' => 
  array (
  ),
  'variations' => 
  array (
  ),
  'grouped_products' => 
  array (
  ),
  'menu_order' => 0,
  'meta_data' => 
  array (
  ),
)  
[2017-08-01 15:15:05] local.DEBUG: array (
  'id' => 37,
  'name' => 'Hoodie',
  'slug' => 'hoodie',
  'permalink' => 'http://velvetcake.local/product/hoodie/',
  'date_created' => '2017-07-31T07:45:31',
  'date_created_gmt' => '2017-07-31T07:45:31',
  'date_modified' => '2017-08-01T15:15:04',
  'date_modified_gmt' => '2017-08-01T15:15:04',
  'type' => 'simple',
  'status' => 'publish',
  'featured' => true,
  'catalog_visibility' => 'visible',
  'description' => '<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>',
  'short_description' => NULL,
  'sku' => NULL,
  'price' => '42',
  'regular_price' => '45',
  'sale_price' => '42',
  'date_on_sale_from' => NULL,
  'date_on_sale_from_gmt' => NULL,
  'date_on_sale_to' => NULL,
  'date_on_sale_to_gmt' => NULL,
  'price_html' => '<del><span class="woocommerce-Price-amount amount"><span class="woocommerce-Price-currencySymbol">&#82;</span>39.47</span></del> <ins><span class="woocommerce-Price-amount amount"><span class="woocommerce-Price-currencySymbol">&#82;</span>36.84</span></ins>',
  'on_sale' => true,
  'purchasable' => true,
  'total_sales' => 1,
  'virtual' => false,
  'downloadable' => false,
  'downloads' => 
  array (
  ),
  'download_limit' => -1,
  'download_expiry' => -1,
  'external_url' => NULL,
  'button_text' => NULL,
  'tax_status' => 'taxable',
  'tax_class' => NULL,
  'manage_stock' => false,
  'stock_quantity' => NULL,
  'in_stock' => true,
  'backorders' => 'no',
  'backorders_allowed' => false,
  'backordered' => false,
  'sold_individually' => false,
  'weight' => NULL,
  'dimensions' => 
  array (
    'length' => NULL,
    'width' => NULL,
    'height' => NULL,
  ),
  'shipping_required' => true,
  'shipping_taxable' => true,
  'shipping_class' => NULL,
  'shipping_class_id' => 0,
  'reviews_allowed' => true,
  'average_rating' => '0.00',
  'rating_count' => 0,
  'related_ids' => 
  array (
    0 => 35,
    1 => 34,
    2 => 36,
  ),
  'upsell_ids' => 
  array (
  ),
  'cross_sell_ids' => 
  array (
  ),
  'parent_id' => 0,
  'purchase_note' => NULL,
  'categories' => 
  array (
    0 => 
    array (
      'id' => 17,
      'name' => 'Hoodies',
      'slug' => 'hoodies',
    ),
  ),
  'tags' => 
  array (
  ),
  'images' => 
  array (
    0 => 
    array (
      'id' => 18,
      'date_created' => '2017-07-31T07:45:31',
      'date_created_gmt' => '2017-07-31T07:45:31',
      'date_modified' => '2017-07-31T07:45:31',
      'date_modified_gmt' => '2017-07-31T07:45:31',
      'src' => 'http://velvetcake.local/wp-content/uploads/2017/07/hoodie.jpg',
      'name' => 'Hoodie',
      'alt' => NULL,
      'position' => 0,
    ),
  ),
  'attributes' => 
  array (
  ),
  'default_attributes' => 
  array (
  ),
  'variations' => 
  array (
  ),
  'grouped_products' => 
  array (
  ),
  'menu_order' => 0,
  'meta_data' => 
  array (
  ),
)  

2 个答案:

答案 0 :(得分:0)

你实际上非常接近于做到这一点。我将为您提供需要发生的事情的高级概述/伪代码(或者我最终会编写代码,见下文)。

public function handle(Request $request, Closure $next)
    {
    // Get the HMAC value from request/header from the Woocommerce request, whatever the hmac value you want is called
    $hmac = $request->get('hmac');

    // Get the signature - your secret
    $signature = Request::header('x-wc-webhook-signature');

    /* Get the woocommerce URL
    * They should give you a code or some kind of ID and also a TIMESTAMP (this is important in your HMAC Calculation) in the request
    * You'd need to figure out this bit
    */
    $woocommerceData = $request->get('woocomerceData');

    // Calculate the HMAC
    $calculatedHmac = hash_hmac('sha256', $woocommerceData, $secret, true);

    // encode the calculated HMAC
    $calculatedHmac = base64_encode($calculatedHmac)

    // Check if the HMAC and Calculated HMAC Match, if they do continue
    if ($hmac == $calculatedHmac) {
        return $next($request);
    }
    // If they don't stop processing
    else {
        return false;
    }
}

答案 1 :(得分:0)

这是我的最终解决方案

public function handle($request, Closure $next)
{
    $signature = Request::header('x-wc-webhook-signature');

    $payload = Request::getContent();
    $calculated_hmac = base64_encode(hash_hmac('sha256', $payload, env('WOOCOMMERCE_WEBHOOK_ITEM_UPDATED'), true));

    if($signature != $calculated_hmac) {
        return false;
    }

    return $next($request);
}

hash_hmac函数的第二个参数需要请求体作为字符串,我从Request :: getContent()获取