我找到了一个如何制作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 hash加入到字符串中:
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}
答案 0 :(得分:0)
首先,如果你阅读了JSON模块文档,它就会清楚地说明encode
方法只需要一个标量,所以传递一个哈希不会起作用。当您将类似的哈希值传递给函数时,它会获取每个键和值并单独传递它们。
my %hash=("a" => 1,"b" => 2);
my_func(%hash);
# The above function call is the same as the one below
my_func("b",2,"a",1);
它传递的每个键/值配对的顺序是随机的,因为您通常会使用哈希找到它。它甚至会引发错误,告诉您如何使用它,或者至少在我尝试测试您的代码时已安装的版本。
相反,你真正想要做的就是像这样传入hashref
$json->encode(\%request);
返回的值是您需要传递给$req->content()
并在签名中使用的值。我不知道Quickbooks API的任何内容,无法知道您是按原样传递JSON数据还是将其用作CGI参数的值。它应该是我希望在他们的文档中告诉你的东西。