在 Laravel 中验证 Woocommerce 网络挂钩
Verify Woocommerce web hook in Laravel
我正在尝试通过来自负责更新我的 Laravel 数据库中的产品项目的 Woocommerce 网络挂钩的请求来验证传入的数据。
我创建了一个名为 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);
}
}
两个变量 return 不同的值。我比较的是正确的值吗?
更新
这是 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">R</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">R</span>39.47</span></del> <ins><span class="woocommerce-Price-amount amount"><span class="woocommerce-Price-currencySymbol">R</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 (
),
)
您实际上已经非常接近正确了。我会给你一个高层次的 overview/pseudocode 需要发生的事情(或者我最终会写代码,见下文)。
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;
}
}
这是我的最终解决方案
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()
我正在尝试通过来自负责更新我的 Laravel 数据库中的产品项目的 Woocommerce 网络挂钩的请求来验证传入的数据。
我创建了一个名为 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);
}
}
两个变量 return 不同的值。我比较的是正确的值吗?
更新
这是 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">R</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">R</span>39.47</span></del> <ins><span class="woocommerce-Price-amount amount"><span class="woocommerce-Price-currencySymbol">R</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 (
),
)
您实际上已经非常接近正确了。我会给你一个高层次的 overview/pseudocode 需要发生的事情(或者我最终会写代码,见下文)。
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;
}
}
这是我的最终解决方案
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()