【发布时间】:2017-08-09 02:14:22
【问题描述】:
我找到了一个如何制作 oauth 签名的示例,但遇到了多维哈希问题。我的哈希看起来像这样,使用 Data::Dumper 显示我的哈希,称为 %request:
$VAR1 = { 'Invoice' => { 'Line' => [ { 'Id' => '1', 'SalesItemLineDetail' => { 'ItemRef' => { 'value' => 'SKM2267' }, 'UnitPrice' => '10.00' }, 'DetailType' => 'SalesItemLineDetail', 'LineNum' => 1 }, { 'Id' => '2', 'SalesItemLineDetail' => { 'ItemRef' => { 'value' => 'SKM2292' }, 'UnitPrice' => '20.00' }, 'DetailType' => 'SalesItemLineDetail', 'LineNum' => 2 }, { 'Id' => '3', 'SalesItemLineDetail' => { 'ItemRef' => { 'value' => 'SKM2285' }, 'UnitPrice' => '30.00' }, 'DetailType' => 'SalesItemLineDetail', 'LineNum' => 3 } ], 'DocNumber' => '90210', 'CustomerRef' => \{ 'name' => 'Amazon.com', 'value' => 1 } } };
制作签名的例子包括将上面的 %request 哈希加入一个字符串:
my $string = join('&',map {$_ . '=' . uri_escape($request{$_})} sort keys %request);
但这会产生以下与用作签名不一致的情况:
Invoice=HASH%280x7f254c17b540%29
如何处理此哈希以创建需要传递到我的 oauth 签名字符串的字符串?
运行良好的示例脚本使用以下内容构建 oauth 签名:
my $hmac = Digest::HMAC_SHA1->new($e->{params}{qbo_consumer_secret} . '&' . $e->{params}{qbo_access_token_secret});
$hmac->add('GET&' . uri_escape('https://sandbox-quickbooks.api.intuit.com/v3/company/' . $company_id . '/query') . '&' . uri_escape('oauth_consumer_key=' . $consumer_key . '&oauth_nonce=' . $nonce . '&oauth_signature_method=HMAC-SHA1&oauth_timestamp=' . $time . '&oauth_token=' . $access_token . '&oauth_version=1.0' . '&' . join('&',map {$_ . '=' . uri_escape($params{$_})} sort keys %params)));
与我正在尝试的相比:
my $hmac = Digest::HMAC_SHA1->new($e->{params}{qbo_consumer_secret} . '&' . $e->{params}{qbo_access_token_secret});
$hmac->add('POST&' . uri_escape($server) . '&' . uri_escape('oauth_consumer_key=' . $e->{params}{qbo_consumer_key}) . '&oauth_nonce=' . $nonce . '&oauth_signature_method=HMAC-SHA1&oauth_timestamp=' . $time . '&oauth_token=' . $e->{params}{qbo_access_token} . '&oauth_version=1.0' . '&' . join('&',map {$_ . '=' . uri_escape($request{$_})} sort keys %request));
那么请求包含这个授权头:
my $req = HTTP::Request->new(POST => $server);
$req->header(Authorization =>
'OAuth oauth_consumer_key="' . $e->{qbo_consumer_key}
. '",oauth_nonce="' . $nonce
. '",oauth_signature="' . encode_base64($hmac->digest)
. '",oauth_signature_method="HMAC-SHA1'
. '",oauth_timestamp="' . time();
. '",oauth_token="' . $e->{qbo_access_token}
. '",oauth_version="1.0'
. '"');
$req->content( \%request );
此外,尝试将散列转换为 json 会导致“无法编码对标量的引用”。我试试这个简单的测试脚本:
#!/usr/bin/perl
use strict;
use warnings;
use JSON;
my %hash = { 'Invoice' => { 'Line' => [ { 'Id' => '1', 'SalesItemLineDetail' => { 'ItemRef' => { 'value' => 'SKM2267' }, 'UnitPrice' => '10.00' }, 'DetailType' => 'SalesItemLineDetail', 'LineNum' => 1 }, { 'Id' => '2', 'SalesItemLineDetail' => { 'ItemRef' => { 'value' => 'SKM2292' }, 'UnitPrice' => '20.00' }, 'DetailType' => 'SalesItemLineDetail', 'LineNum' => 2 }, { 'Id' => '3', 'SalesItemLineDetail' => { 'ItemRef' => { 'value' => 'SKM2285' }, 'UnitPrice' => '30.00' }, 'DetailType' => 'SalesItemLineDetail', 'LineNum' => 3 } ], 'DocNumber' => '90210', 'CustomerRef' => \{ 'name' => 'Amazon.com', 'value' => 1 } } };
my $js = encode_json \%hash;
print "$js\n";
在下面产生这个错误,我的哈希有什么问题吗?
Reference found where even-sized list expected at testjson.pl line 8.
{"HASH(0x8db5f3c)":null}
【问题讨论】:
-
您到底想
uri_escape做什么?$request{$_}是一个哈希引用,通常不是你想要字符串化的那种东西。 -
是的,我想我不需要 uri_escape,我下面的示例使用 HMAC 包添加函数来构造 GET 请求的签名,但我正在为这个特定的 Quickbooks API 使用 POST称呼。如何生成字符串也让我感到困惑,但据我了解,该请求必须是 oauth 签名的一部分。我将添加与我正在尝试做的事情相比有效的示例。
-
在工作示例中,签名是由构成 HTTP 请求的元素构成的 - 方法、主机和查询字符串。您如何使用
%request构建$req? -
是的,作为内容,我已经在上面添加了。我没有任何运气使用 JSON 包将哈希转换为 json 字符串。没有使用 $json->encode(%request); 给我整个哈希值。