如何捕获 Shopify Webhook 发送的 HTTP POST 请求

Posted

技术标签:

【中文标题】如何捕获 Shopify Webhook 发送的 HTTP POST 请求【英文标题】:How to catch the HTTP POST request sent by a Shopify Webhook 【发布时间】:2012-06-11 19:48:38 【问题描述】:

我是个菜鸟,但我并不害怕承认这一点,我从事这个项目是为了获得更好的 php 和服务器端脚本/ing 处理方面的学习经验。

我正在尝试想出一种方法来使用 Shopify 并在每次从我的 Shopify 购物车中完成订单时同时更新服务器外数据库。例如,有人从我的在线商店购买了东西,我希望它更新我的家庭数据库库存以显示它现在少了一件商品。

我得出的结论是,最好的方法是设置一个webhook notification,将 HTTP POST 请求发送到我的服务器,然后我让我的服务器捕获 POST 并将其解析为XML。然后,我将通过一个 php 脚本读取 XML,该脚本将更新我的数据库。

我的 php 没有问题,但我似乎无法弄清楚如何在我的服务器上捕获 webhook。 Webhook 向我询问发送 POST 请求的 URL,我的问题是;网址是什么?

我做了一些研究,发现您可以通过多种方式捕获 POST 请求,通过 html、php、Access-Control-Allow-Origin 等。但是,由于我还是新手,我不太了解如何执行这些操作。我尝试过使用 HTML 隐藏操作表单,但似乎无法让它捕获 XML。

我想要做的就是让 webhook 发送它的 POST 请求,并将它作为 .xml 捕获。这样我就可以在每天结束时读取 xml,并相应地更新数据库。

如果您能想到更好或更简单的方法来做到这一点,请务必给我您的建议。我希望这是安全的,所以像 Access-Control-Allow-Origin 这样的方法是不可能的。

tl;博士: 我必须在服务器上做什么才能捕获 webhook 通知?我的服务器上应该有什么脚本来提供给 webhook?如何编写回调脚本?

【问题讨论】:

您在使用什么环境/框架?您提到了 PHP,但没有提到 webapp 框架(Cake、Zend 等)的任何细节 Shopify(Ruby on Rails)和 mysql,我实际上只是想要一个脚本来创建一个我可以使用 php 读取的 xml。 【参考方案1】:

在http://example.com/whatever.php 创建一个公共 URL,其中 example.com 是您的域名,whatever.php 是您可以编辑的 PHP 文件。

然后把这段代码放到whatever.php中:

<?php
$webhookContent = "";

$webhook = fopen('php://input' , 'rb');
while (!feof($webhook)) 
    $webhookContent .= fread($webhook, 4096);

fclose($webhook);

error_log($webhookContent);
?>

然后在 Shopify 后台中,您可以创建一个新的 webhook 并将其指向 http://example.com/whatever.php,当您单击 Shopify 后台中的“测试 webhook”按钮时,Shopify 将 POST 到您上面的脚本,该脚本应该依次写入Webhook 的主体到您的 PHP 错误日志。

【讨论】:

如果有人没有工作错误日志文件,那么我们也可以在文本文件中写入所有内容 $content = "some text here".$webhookContent; $fp = fopen($_SERVER['DOCUMENT_ROOT'] . "/myText.txt","wb"); fwrite($fp,$内容); fclose($fp); 您如何解决公开可用的 http url 的安全问题?我的意思是有没有办法只允许 Webhooks 发布到这个 url,并且应该忽略对这个 url 的任何其他点击? 你真是个天才!!数周以来,我一直试图为 Venmo 和 Dwolla 解决这个问题,并从他们的支持团队那里得到了零帮助。谢谢!!!这对 Dwolla 和 Venmo 都有效,本质上是即插即用的!! @RohitGupta 的规范方式是verify the HMAC digest of the POST。或者,您可以在 Shopify 中设置 webhook 时添加一个“秘密”URL 参数,然后让您的脚本检查以确保该参数存在并且具有正确的值。【参考方案2】:

对不起,我没有足够的声誉来发布 cmets,但这里是 Edward Ocampo-Gooding 的回答中的死链接的内容:

带 SimpleXML 的 PHP 示例(PHP 5+)

下面的脚本向您展示了如何将 XML 数据从 Shopify 获取到您的脚本中、归档文件并发送正确的标题...

鉴于 webhook 管理员中的新订单订阅设置为:http://example.com/some-script.php?key=123456789

http://example.com/ 上 some-script.php 的内容:

<?     
// Protect URL from rogue attacks/exploits/spiders
// Grab from GET variable as given in Shopify admin URL
// for the webhook
//
// NOTE: This is not necessary, just a simple verification
//
// A digital signature is also passed along from Shopify,
// as is the shop's domain name, so you can use one or both of those
// to ensure a random person isn't jacking with your script (or some
// spider just randomly hitting it to see what's there).
//
// If $key doesn't matched what should be passed in from the
// webhook url, the script simply exits
$key = $_GET['key']; 

if ($key != '123456789') 
  header('HTTP/1.0 403 Forbidden');
  exit();


// Variables used for processing/saving
$xmlString = ;  // Used to get data from Shopify into script
$name = ;  // Saves the billing address name to be used for later ...
$email = ;  // Save the email address of the user to be used for later ...
$productTitles = array();  // Saves all titles of products purchased to be used for later ... 

// Get XML data and read it into a string for use with SimpleXML
// Thanks to David Oxley (http://www.numeriq.co.uk) for help with this
$xmlData = fopen('php://input' , 'rb'); 
while (!feof($xmlData))  $xmlString .= fread($xmlData, 4096); 
fclose($xmlData);

// Save order XML in file in orders directory
// This creates a file, write the xml for archival purposes, and closes the file ...
// If the file already exists, it appends the data ... this should create a separate
// file for every order but if two orders are processed the same second, they'll both
// be in the same file
file_put_contents('orders/order' . date('m-d-y') . '-' . time() . '.xml', $xmlString, FILE_APPEND);

// Use SimpleXML to get name, email, and product titles
// SimpleXML allows you to use the $xml object to easily
// retrieve the data ...
// Please note, if hyphens are used in the xml node, you must
// surround the call to that member with 'member-name' as is
// shown below when getting the billing-address name & the
// line items
$xml = new SimpleXMLElement($xmlString);

$name = trim($xml->'billing-address'->name);
$email = trim($xml->email);

// Create productTitles array with titles from products
foreach ($xml->'line-items'->'line-item' as $lineItem) 
  array_push($productTitles, trim($lineItem->title));


// You would then go on using $name, $email, $productTitles in your script
// to do whatever the heck you please ...

// Once you are done doing what you need to do, let Shopify know you have 
// the data and all is well!
header('HTTP/1.0 200 OK');
exit();

// If you want to tell Shopify to try sending the data again, i.e. something
// failed with your processing and you want to try again later
header('HTTP/1.0 400 Bad request');
exit();
?>

【讨论】:

【参考方案3】:

听起来你对PHP最熟悉,所以我会根据这个来回答。

您需要一个可作为公共 URL 访问的 PHP 脚本/页面,该 URL 可以获取 Shopify 发送给您的 HTTP POST 中发送的数据并将其转换为您的数据库所需的形式。

以下是 PHP 脚本的示例:http://wiki.shopify.com/WebHook#PHP_Example_w.2F_SimpleXML_.28PHP_5.2B.29

【讨论】:

说实话,我最熟悉 Java 和 C#,我从来没有处理过 Web 开发,一直坚持软件。这是我从 software 进入 web 的第一次真正的冒险 我仍然不明白如何实际创建 .xml,它似乎永远不会工作。 您是否掌握了 Web/PHP 知识,可以在公共 URL 上生成“Hello, world”页面? 哈哈是的,我的知识很基础,但不是那么基础。【参考方案4】:

要回答有关 URL 的问题,这是您服务器上将处理接收 webhook 的端点。这对于大多数 Web 框架来说设置非常简单,它只需要处理 post 请求并以 200 OK 响应。

一旦您在服务器上设置了端点,您就可以在 shopify 上创建 webhook,并将 URL 作为网络服务器上的端点。

【讨论】:

【参考方案5】:

Shopify webhook 不使用常见的 GET 或 POST 请求方法传递数据。您可以在 PHP 中使用 fopen() 方法并传入 php://input 流。

假设您为购物车更新创建一个 webhook 并设置 URL http://example.com/cart_update_hook.php 然后将以下代码放入 cart_update_hook.php 以获取 shopify webhook 发送的数据。

<?php
$webhookContent = "";
$webhook = fopen('php://input' , 'rb');
while (!feof($webhook)) 
    $webhookContent .= fread($webhook, 4096);

fclose($webhook);
$data = json_decode($webhookContent, true);
//do whatever you want with the data
?>

【讨论】:

以上是关于如何捕获 Shopify Webhook 发送的 HTTP POST 请求的主要内容,如果未能解决你的问题,请参考以下文章

在NestJS 中添加对Shopify 的WebHook 验证

Shopify 在 Scala 中验证 webhook 调用

python 用于Shopify Webhook的HMAC验证的Python视图装饰器。

如何在shopify联系表格中捕获网站网址[重复]

我可以用其他可以创建 webhook 来捕获钩子的东西替换 zapier

卸载shopify应用程序的任何回调或设置