You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

添加searchCriteria筛选后Magento 2 API OAuth签名无效求助

Magento 2 API OAuth签名无效问题(添加过滤条件时)

我正在使用Laravel的Illuminate\Support\Facades\Http向Magento 2.4.4版本的API发送请求获取订单,通过OAuth集成凭证认证,已授予全资源权限用于测试。原代码能正常运行,但添加订单状态过滤的查询参数后,就抛出The signature is invalid. Verify and try again.错误,求问题原因和解决方法。

原可正常运行代码

$orderEndpoint = '/rest/V1/orders';

$oauthParams = [
    'oauth_consumer_key' => $clientId,
    'oauth_nonce' => md5(uniqid(rand(), true)),
    'oauth_signature_method' => 'HMAC-SHA256',
    'oauth_timestamp' => time(),
    'oauth_token' => $accessToken,
];

ksort($oauthParams);

$queryParams = [
    'searchCriteria[currentPage]' => 1,
    'searchCriteria[pageSize]' => 10,
];

$baseString = 'GET&' . rawurlencode($baseUrl . $orderEndpoint) . '&' . rawurlencode(http_build_query(array_merge($oauthParams, $queryParams), '', '&', PHP_QUERY_RFC3986));
dump($baseString);

$signatureKey = rawurlencode($consumerSecret) . '&' . rawurlencode($tokenSecret);
$signature = base64_encode(hash_hmac('sha256', $baseString, $signatureKey, true));
dump($signature);

$oauthParams['oauth_signature'] = $signature;

$authorizationHeader = 'OAuth ' . http_build_query($oauthParams, '', ', ', PHP_QUERY_RFC3986);
$fullUrl = $baseUrl . $orderEndpoint . '?' . http_build_query(array_merge($oauthParams, $queryParams));
dump($fullUrl);

$response = Http::withHeaders([
    'Authorization' => $authorizationHeader,
])->get($baseUrl . $orderEndpoint, $queryParams);

if ($response->successful()) {
    $orderData = $response->json();
    dd($orderData);
} else {
    dd($response->json());
}

修改后触发错误的查询参数

$queryParams = [
    'searchCriteria[filter_groups][0][filters][0][field]' => 'status',
    'searchCriteria[filter_groups][0][filters][0][value]' => 'complete',
    'searchCriteria[currentPage]' => 1,
    'searchCriteria[pageSize]' => 10,
];

问题原因与解决方法

问题出在OAuth签名生成时的参数排序逻辑:原代码仅对oauthParams单独排序,合并查询参数后未对所有参与签名的参数整体排序。当添加嵌套结构的过滤参数后,http_build_query生成的参数顺序会和Magento验证端的预期顺序不一致,导致签名校验失败。

具体修正步骤

  1. 合并并排序所有签名参数:将OAuth参数和查询参数合并后,统一按参数名的ASCII码升序排序,确保生成签名的base string参数顺序与Magento端完全匹配。
  2. 保持参数编码一致性:全程使用PHP_QUERY_RFC3986编码规则,避免编码差异导致的签名不匹配。

修正后的完整代码

$orderEndpoint = '/rest/V1/orders';

$oauthParams = [
    'oauth_consumer_key' => $clientId,
    'oauth_nonce' => md5(uniqid(rand(), true)),
    'oauth_signature_method' => 'HMAC-SHA256',
    'oauth_timestamp' => time(),
    'oauth_token' => $accessToken,
];

$queryParams = [
    'searchCriteria[filter_groups][0][filters][0][field]' => 'status',
    'searchCriteria[filter_groups][0][filters][0][value]' => 'complete',
    'searchCriteria[currentPage]' => 1,
    'searchCriteria[pageSize]' => 10,
];

// 合并所有参与签名的参数并整体排序
$allParams = array_merge($oauthParams, $queryParams);
ksort($allParams);

$baseString = 'GET&' . rawurlencode($baseUrl . $orderEndpoint) . '&' . rawurlencode(http_build_query($allParams, '', '&', PHP_QUERY_RFC3986));
dump($baseString);

$signatureKey = rawurlencode($consumerSecret) . '&' . rawurlencode($tokenSecret);
$signature = base64_encode(hash_hmac('sha256', $baseString, $signatureKey, true));
dump($signature);

$oauthParams['oauth_signature'] = $signature;

$authorizationHeader = 'OAuth ' . http_build_query($oauthParams, '', ', ', PHP_QUERY_RFC3986);

$response = Http::withHeaders([
    'Authorization' => $authorizationHeader,
])->get($baseUrl . $orderEndpoint, $queryParams);

if ($response->successful()) {
    $orderData = $response->json();
    dd($orderData);
} else {
    dd($response->json());
}

内容的提问来源于stack exchange,提问作者sjors

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 10:11:27