shopify hmac验证php

时间:2017-11-17 10:02:06

标签: php validation shopify hmac

这是我的代码:

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不匹配。

我做错了什么?

5 个答案:

答案 0 :(得分:1)

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

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

你需要urldecode()http_build_query()的结果。它返回一个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);

答案 1 :(得分:1)

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

然而,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';
  }

}
?>

答案 2 :(得分:0)

对于其他请求(例如App Proxy),HMAC不会被预先通知,因此您需要计算签名。这里的函数可以同时满足两种类型的请求:

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) {
        }
    }

    return false;
}

如果您不使用Laravel,请不要忘记替换->except函数。

答案 3 :(得分:0)

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

// 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);
}

答案 4 :(得分:-1)

这应该是完美的:D

function verify_hmac()
        {
          $hmac='5aee2efb4ec03885bd41123549df267a540388e5f248db8a2a7e24532a156e';
          $str ='locale=en&shop=appName.myshopify.com&timestamp=112242913';
          $ver_hmac =  hash_hmac('sha256',$str,env('SHOPIFY_SECRET'),false);

                if($ver_hmac==$hmac)
                {
                   return 'hmac verified';
                }
                return ':( no';

        }