繁体   English   中英

shopify hmac 验证 php

[英]shopify hmac verification php

这是我的代码:

function verifyRequest($request, $secret) {
  // Per the Shopify docs:
  // Everything except hmac and signature...

  $hmac = $request['hmac'];
  unset($request['hmac']);
  unset($request['signature']);

  // Sorted lexilogically...
  ksort($request);

  // Special characters replaced...
  foreach ($request as $k => $val) {
    $k = str_replace('%', '%25', $k);
    $k = str_replace('&', '%26', $k);
    $k = str_replace('=', '%3D', $k);
    $val = str_replace('%', '%25', $val);
    $val = str_replace('&', '%26', $val);
    $params[$k] = $val;
  }

  echo $http = "protocol=". urldecode("https://").http_build_query( $params) ;
  echo $test = hash_hmac("sha256", $http , $secret);

  // enter code hereVerified when equal
  return $hmac === $test;
}

shopi 的 hmac 和从我的代码创建的 hmac 不匹配。

我究竟做错了什么?

您只需要在创建键值对列表时包含请求参数 - 不需要“protocol=https://”。

https://help.shopify.com/api/getting-started/authentication/oauth#verification

您需要对 http_build_query() 的结果进行 urldecode()。 它返回一个 url 编码的查询字符串。

http://php.net/manual/en/function.http-build-query.php

代替:

 echo $http = "protocol=". urldecode("https://").http_build_query( $params) ;
 echo $test = hash_hmac("sha256", $http , $secret);

像这样的东西:

 $http = urldecode(http_build_query($params));
 $test = hash_hmac('sha256', $http, $secret);

可以使用 sha256 加密算法在任何编程语言中计算 hmac。

然而,shopify 提供了 hmac 验证的文档,但应用程序开发人员仍然对如何正确实施它感到困惑。

这是php中用于hmac验证的代码。 参考 http://code.codify.club

<?php

function verifyHmac()
{
  $ar= [];
  $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);

    $ar[] = $key."=".$value;
  }

  $str = join('&',$ar);
  $ver_hmac =  hash_hmac('sha256',$str,"YOUR-APP-SECRET-KEY",false);

  if($ver_hmac==$hmac)
  {
    echo 'hmac verified';
  }

}
?>

请注意,对于App Proxy等其他请求,不会预设 HMAC,因此您需要计算签名。 这里有一个函数可以满足包括 webhooks 在内的两种类型的请求:

public function authorize(Request $request)
{
    if( isset($request['hmac']) || isset($request['signature']) ){
        try {
            $signature = $request->except(['hmac', 'signature']);

            ksort($signature);

            foreach ($signature as $k => $val) {
                $k = str_replace('%', '%25', $k);
                $k = str_replace('&', '%26', $k);
                $k = str_replace('=', '%3D', $k);
                $val = str_replace('%', '%25', $val);
                $val = str_replace('&', '%26', $val);
                $signature[$k] = $val;
            }

            if(isset($request['hmac'])){
                $test = hash_hmac('sha256', http_build_query($signature), env('SHOPIFY_API_SECRET'));

                if($request->input('hmac') === $test){
                    return true;
                }
            } elseif(isset($request['signature'])){
                $test = hash_hmac('sha256', str_replace('&', '', urldecode(http_build_query($signature))), env('SHOPIFY_API_SECRET'));

                if($request->input('signature') === $test){
                    return true;
                }
            }
        } catch (Exception $e) {
            Bugsnag::notifyException($e);
        }
    } else { // If webhook
        $calculated_hmac = base64_encode(hash_hmac('sha256', $request->getContent(), env('SHOPIFY_API_SECRET'), true));

        return hash_equals($request->server('HTTP_X_SHOPIFY_HMAC_SHA256'), $calculated_hmac);
    }

    return false;
}

上面的例子使用了一些 Laravel 函数,所以如果你使用不同的框架,你可能想要替换它们。

我有以下几点来做到这一点:

// Remove the 'hmac' parameter from the query string
$query_string_rebuilt = removeParamFromQueryString($_SERVER['QUERY_STRING'], 'hmac');
// Check the HMAC
if(!checkHMAC($_GET['hmac'], $query_string_rebuilt, $shopify_api_secret_key)) {
    // Error code here
}

/**
 * @param string $comparison_data
 * @param string $data
 * @param string $key
 * @param string $algorithm
 * @param bool $binary
 * @return bool
 */
function checkHMAC($comparison_data, $data, $key, $algorithm = 'sha256', $binary=false) {
    // Check the HMAC
    $hash_hmac = hash_hmac($algorithm, $data, $key, $binary);
    // Return true if there's a match
    if($hash_hmac === $comparison_data) {
        return true;
    }
    return false;
}

/**
 * @param string $query_string
 * @param string $param_to_remove
 * @return string
 */
function removeParamFromQueryString(string $query_string, string $param_to_remove) {
    parse_str($query_string, $query_string_into_array);
    unset($query_string_into_array[$param_to_remove]);
    return http_build_query($query_string_into_array);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM