首页 > 解决方案 > 验证嵌入式应用设置页面访问是否来自 PHP 中的 Shopify

问题描述

当客户安装应用程序时,他们可以选择单击/admin/apps页面上应用程序列表中的应用程序名称。

当他们单击该页面时,我的应用程序的 PHP 索引文件会收到这些$_GET变量:

hmac = some_long_alphanumaeric_hmac
locale = en
protocol = https://
shop = example-shop.myshopify.com
timestamp = 1535609063

为了验证 Shopify 的 webhook,我成功地使用了这个:

function verify_webhook($data, $hmac_header, $app_api_secret) {
    $calculated_hmac = base64_encode(hash_hmac('sha256', $data, $app_api_secret, true));
    return ($hmac_header == $calculated_hmac);
}

// Set vars for Shopify webhook verification
$hmac_header = $_SERVER['HTTP_X_SHOPIFY_HMAC_SHA256'];
$data = file_get_contents('php://input');
$verified = verify_webhook($data, $hmac_header, MY_APP_API_SECRET);

是否可以验证应用管理页面访问来自安装了应用的 Shopify 客户端?

PS:我已经查看了Embedded Apps API(但我不知道这是否是正确的文档,或者我做错了什么),以及提供的GitHub 示例(没有关于如何验证嵌入式应用程序管理页面访问)。

更新:

我尝试了其他各种方法,一路上发现了一些荒谬的问题,但仍然没有运气。

  1. 我理解的方法应该用于验证 Shopify HMAC 类似于以下内容:

    function verify_hmac($hmac = NULL, $shopify_app_api_secret) {
        $params_array = array();
        $hmac = $hmac ? $hmac : $_GET['hmac'];
        unset($_GET['hmac']);
    
        foreach($_GET as $key => $value){
            $key = str_replace("%","%25",$key);
            $key = str_replace("&","%26",$key);
            $key = str_replace("=","%3D",$key);
            $value = str_replace("%","%25",$value);
            $value = str_replace("&","%26",$value);
            $params_array[] = $key . "=" . $value;
        }
    
        $params_string = join('&', $params_array);
        $computed_hmac = hash_hmac('sha256', $params_string, $shopify_app_api_secret);
    
        return hash_equals($hmac, $computed_hmac);
    }
    

但是该行通过编码为...$params_string = join('&', $params_array);导致了一个烦人的问题。使用结果同样荒谬。在这里发现其他人有同样的问题。基本上通过编码as来解决,到达.&timestampxtamphttp_build_query($params_array)&&$params_string = join('&', $params_array);

  1. 我的最终版本是这样的,但仍然无法正常工作(所有注释代码都是我尝试过的其他代码无济于事):

    function verify_hmac($hmac = NULL, $shopify_app_api_secret) {
        $params_array = array();
        $hmac = $hmac ? $hmac : $_GET['hmac'];
        unset($_GET['hmac']);
    //  unset($_GET['protocol']);
    //  unset($_GET['locale']);
    
        foreach($_GET as $key => $value){
            $key = str_replace("%","%25",$key);
            $key = str_replace("&","%26",$key);
            $key = str_replace("=","%3D",$key);
            $value = str_replace("%","%25",$value);
            $value = str_replace("&","%26",$value);
            $params_array[] = $key . "=" . $value;
    //  This commented out method below was an attempt to see if 
    //  the imporperly encoded query param characters were causing issues
    /*
            if (!isset($params_string) || empty($params_string)) {
                $params_string = $key . "=" . $value;
            }
            else {
                $params_string = $params_string . "&" . $key . "=" . $value;
            }
    */
        }
    
    //  $params_string = join('&', $params_array);
    //  echo $params_string;
    //  $computed_hmac =  base64_encode(hash_hmac('sha256', $params_string, $shopify_app_api_secret, true));
    //  $computed_hmac =  base64_encode(hash_hmac('sha256', $params_string, $shopify_app_api_secret, false));
    //  $computed_hmac =  hash_hmac('sha256', $params_string, $shopify_app_api_secret, false);
    //  $computed_hmac =  hash_hmac('sha256', $params_string, $shopify_app_api_secret, true);
        $computed_hmac = hash_hmac('sha256', http_build_query($params_array), $shopify_app_api_secret);
    
        return hash_equals($hmac, $computed_hmac);
    }
    

标签: phpshopifyhmac

解决方案


如果您从 Shopify 中获得成功,您要做的第一件事就是检查您的持久层是否已注册商店。如果你这样做了,并且你有某种设置的会话,你可以自由地将你的应用程序呈现给那个商店。如果您没有持久化商店,则通过 oAuth 周期获取要在商店上使用的身份验证令牌,该令牌与商店和新会话一起保留。

对于您商店中接收 webhook 的任何路由或端点,这些请求当然没有会话,因此您使用 HMAC 安全方法来确定要做什么。因此,您的问题显然跨越了两个不同的概念,每个概念的处理方式都不同。该文档非常清楚地说明了这些差异。


推荐阅读