这是我的代码:
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不匹配。
我做错了什么?
答案 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×tamp=112242913';
$ver_hmac = hash_hmac('sha256',$str,env('SHOPIFY_SECRET'),false);
if($ver_hmac==$hmac)
{
return 'hmac verified';
}
return ':( no';
}